2015-10-27 5 views
10

के साथ स्प्रिंग बैच सीरियलाइजेशन समस्याएं मेरे पास स्प्रिंग-बैच एप्लिकेशन है जो जॉबएक्सक्यूशन कॉन्टेक्स्ट में कई जावा 8 टाइम ऑब्जेक्ट्स संग्रहीत करता है। मैं अपने जॉब रेस्पोजिटरी के लिए डिफ़ॉल्ट सीरिएलाइज़र का उपयोग कर रहा हूं। BATCH_STEP_EXECUTION_CONTEXT तालिका में लिखे गए डेटा को वापस पार्स करते समय मुझे अपवाद का सामना करना पड़ रहा है। मैं एक LocalDateTime कि के रूप में जमा किया जा रहा है:जावा 8 टाइम पैकेज

{ 
    "@resolves-to": "java.time.Ser", 
    "byte": [5, 
    8, 
    18, 
    8, 
    45, 
    50], 
    "int": [2015, 
    10000000] 
} 

यह एक अपवाद की ओर जाता है जब मैं पिछले JobExecution डेटा से पढ़ने की कोशिश:

Caused by: java.lang.ClassCastException: java.lang.Byte cannot be cast to java.lang.Integer 
at com.thoughtworks.xstream.core.util.CustomObjectInputStream.readInt(CustomObjectInputStream.java:144) ~[xstream-1.4.8.jar:1.4.8] 
at java.time.LocalDate.readExternal(LocalDate.java:2070) ~[na:1.8.0_45] 
at java.time.LocalDateTime.readExternal(LocalDateTime.java:2002) ~[na:1.8.0_45] 
at java.time.Ser.readInternal(Ser.java:259) ~[na:1.8.0_45] 
at java.time.Ser.readExternal(Ser.java:246) ~[na:1.8.0_45] 
at com.thoughtworks.xstream.converters.reflection.ExternalizableConverter.unmarshal(ExternalizableConverter.java:167) ~[xstream-1.4.8.jar:1.4.8] 
at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) ~[xstream-1.4.8.jar:na] 
... 97 common frames omitted 

मैं वसंत बैच 3.0.5 का उपयोग कर रहा हूँ। विज्ञप्ति। मैंने xstream (1.4.8) और जेटीसन (1.3.7) के नवीनतम संस्करणों में अपग्रेड करने का भी प्रयास किया है, लेकिन मुझे एक ही अपवाद मिलता है।

यह एक्सस्ट्रीम (link) के साथ एक ज्ञात समस्या प्रतीत होता है। सुझाव XStream के भीतर एक कस्टम कनवर्टर रजिस्टर करना था। हालांकि, एक कनवर्टर पंजीकृत करने के लिए वसंत-बैच वास्तविक एक्सस्ट्रीम ऑब्जेक्ट का पर्दाफाश नहीं करता है। आगे बढ़ने के बारे में कोई सुझाव?

+0

क्या आपने कॉन्फ़िगरेशन क्लास पर @EnableBatchProcessing एनोटेशन जोड़ा है? –

उत्तर

3

वसंत बैच आप ExecutionContextSerializer इंटरफ़ेस को लागू करने और JobRepositoryFactoryBean में यह इंजेक्शन लगाने के द्वारा ExecutionContext के लिए अपने स्वयं के serializer कॉन्फ़िगर करने के लिए अनुमति देता है।

आप सही हैं कि हम आपको वर्तमान में अपने स्वयं के एक्सस्ट्रीम उदाहरण को इंजेक्ट करने की अनुमति नहीं देते हैं (हालांकि यह इस मुद्दे को दिए गए उचित विस्तार बिंदु की तरह लगता है)। अभी के लिए, आपको या तो XStreamExecutionContextStringSerializer का विस्तार या प्रतिलिपि बनाना होगा और अपने स्वयं के एक्सस्ट्रीम उदाहरण का उपयोग करना होगा।

+0

मैंने अपना खुद का ग्राहक धारावाहिक जोड़ा है। हालांकि, 'JobRepositoryFactoryBean' अभी भी डिफ़ॉल्ट' XStreamExecutionContextStringSerializer' का उपयोग कर रहा है, जो इस तरह के अपवादों का कारण बन रहा है जब मैं 'जॉबएक्सप्लोरर': –

+0

' से नौकरी डेटा पढ़ने का प्रयास करता हूं: com.thoughtworks.xstream.converters.ConversionException: नई readObject()/writeObject() विधियों के साथ ऑब्जेक्ट को deserialize नहीं कर सकते हैं '---- डीबगिंग जानकारी ----' 'वर्ग: java.time.LocalDate' ' आवश्यक प्रकार: java.time.LocalDate' 'कनवर्टर-टाइप: com.thoughtworks.xstream.converters.reflection.SerializableConverter' –

+0

यह भी प्रतीत होता है कि स्प्रिंग बैच व्यवस्थापक UI पर पुनरारंभ बटन को मारना' जॉबएक्सक्यूशन कंट्रोलर.स्टार्ट 'ट्रिगर करता है, जो डिफ़ॉल्ट' XStreamExecutionContextStringSerializer 'के साथ क्रमबद्ध करने का प्रयास कर रहा है। । मुझे उस परिदृश्य में एक ही अपवाद मिलते हैं (और मेरे स्टैक ट्रेस में मेरे कस्टम सीरिएलाइज़र की बजाय XStreamExecutionContextStringSerializer शामिल है)। –

1

चरण निष्पादन संदर्भ से LocalDate deserializing जबकि मुझे एक ही समस्या थी।

public class DateConverter implements Converter { 

    private static final String   DEFAULT_DATE_PATTERN = "yyyy-MM-dd"; 
    private static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_DATE_PATTERN); 

    public DateConverter() { 
     super(); 
    } 

    public boolean canConvert(Class clazz) { 
     return LocalDate.class.isAssignableFrom(clazz); 
    } 

    /** 
    * Convert LocalDate to String 
    */ 
    public void marshal(Object value, HierarchicalStreamWriter writer, MarshallingContext context) { 
     LocalDate date = (LocalDate) value; 
     String result = date.format(DEFAULT_DATE_FORMATTER); 
     writer.setValue(result); 
    } 

    /** 
    * convert Xml to LocalDate 
    */ 
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 
     LocalDate result = LocalDate.parse(reader.getValue(), DEFAULT_DATE_FORMATTER); 
     return result; 
    } 
} 

कि मैं अपने कनवर्टर का उपयोग कर

/** 
* My XStreamExecutionContextStringSerializer 
* @since 1.0 
*/ 
public class MyXStreamExecutionContextStringSerializer implements ExecutionContextSerializer, InitializingBean { 

    private ReflectionProvider reflectionProvider = null; 

    private HierarchicalStreamDriver hierarchicalStreamDriver; 

    private XStream xstream; 

    public void setReflectionProvider(ReflectionProvider reflectionProvider) { 
     this.reflectionProvider = reflectionProvider; 
    } 

    public void setHierarchicalStreamDriver(HierarchicalStreamDriver hierarchicalStreamDriver) { 
     this.hierarchicalStreamDriver = hierarchicalStreamDriver; 
    } 

    @Override 
    public void afterPropertiesSet() throws Exception { 
     init(); 
    } 

    public synchronized void init() throws Exception { 
     if (hierarchicalStreamDriver == null) { 
      this.hierarchicalStreamDriver = new JettisonMappedXmlDriver(); 
     } 
     if (reflectionProvider == null) { 
      xstream = new XStream(hierarchicalStreamDriver); 
     } 
     else { 
      xstream = new XStream(reflectionProvider, hierarchicalStreamDriver); 
     } 

     // Convert LocalDate 
     xstream.registerConverter(new DateConverter()); 
    } 

    /** 
    * Serializes the passed execution context to the supplied OutputStream. 
    * 
    * @param context 
    * @param out 
    * @see Serializer#serialize(Object, OutputStream) 
    */ 
    @Override 
    public void serialize(Map<String, Object> context, OutputStream out) throws IOException { 
     Assert.notNull(context); 
     Assert.notNull(out); 

     out.write(xstream.toXML(context).getBytes()); 
    } 

    /** 
    * Deserializes the supplied input stream into a new execution context. 
    * 
    * @param in 
    * @return a reconstructed execution context 
    * @see Deserializer#deserialize(InputStream) 
    */ 
    @SuppressWarnings("unchecked") 
    @Override 
    public Map<String, Object> deserialize(InputStream in) throws IOException { 
     BufferedReader br = new BufferedReader(new InputStreamReader(in)); 

     StringBuilder sb = new StringBuilder(); 

     String line; 
     while ((line = br.readLine()) != null) { 
      sb.append(line); 
     } 

     return (Map<String, Object>) xstream.fromXML(sb.toString()); 
    } 
} 

अंतिम चरण फ़ाइल में MyXStreamExecutionContextStringSerializer रजिस्टर करने के लिए है के लिए मेरे उचित XStreamExecutionContextStringSerializer बनाने के लिए करने के बाद:

तो मैं अपने उचित कनवर्टर करना है निष्पादन-संदर्भ.एक्सएमएल जो बीन जॉब पंजीकरण करता है रिपॉजिटरी

<bean id="jobRepository" 
    class="org.springframework.batch.core.repository.support.JobRepositoryFactoryBean"> 
    <property name="dataSource" ref="dataSource" /> 
    <property name="transactionManager" ref="transactionManager" /> 
    <property name="tablePrefix" value="${batch.table.prefix:BATCH.BATCH_}" /> 
    <property name="serializer"> <bean class="com.batch.config.MyXStreamExecutionContextStringSerializer"/> </property> 
</bean> 
संबंधित मुद्दे