Announcement Announcement Module
Collapse
No announcement yet.
sharing non - Serializable objects among Steps Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • sharing non - Serializable objects among Steps

    I have a job that calls a web service using Spring-WS. I call the service in the first step and get back an org.springframework.ws.soap.SoapMessage that I'd like to put into the ExecutionContext for subsequent steps to play with -- to do things like read the SOAP header and body and extract the message attachments, writing some things to a database and some things to disk.

    Unfortunately, SoapMessage and the implementation I'm currently using -- SaajSoapMessage; might switch to AxiomSoapMessage though -- are not Serializable, so Spring Batch throws an exception when I try to put() the SoapMessage in the ExecutionContext, because it can't serialize the object. I thought maybe I could wrap the SoapMessage in another object that has the message as a transient member and implements writeObject(ObjectOutputStream) to convert the SoapMessage to a byte[] member which can be serialized. I think I have code that could do that below. Deserializing the byte[] back into the SoapMessage inside readObject(ObjectInputStream) looks like it's going to be a pain in the butt, though.

    I'm wondering if I'm going about this all wrong. (I *am* new to Spring Batch.) Can someone suggest a better way of sharing a SoapMessage -- or any non-Serializable objects for that matter -- among steps in a job?

    Or if someone has a better way to serialize/deserialize a SoapMessage, please let me know. I may post something similar in the Spring-WS forum. Here's my code currently, which obviously still needs some getters/setters and a constructor:

    Code:
    public class SerializableSoapMessage implements Serializable {
      private static final long serialVersionUID = -6443726973648223066L;
      private static final String AXIOM = "axiom";
      private static final String SAAJ = "saaj";
    
      private transient SoapMessage soapMessage;  // Won't try to serialize this automatically.
      private byte[] soapMessageBytes;            // Raw byte representation of the soap message.
      private String type;                        // Stores which type of Spring SoapMessage implementation we are using.
      
      private void writeObject(ObjectOutputStream out) throws IOException {
        // Convert the unserializable SoapMessage into a field that can be serialized.
        if (soapMessage instanceof SaajSoapMessage) {
          type = SAAJ;
          SaajSoapMessage saajMessage = (SaajSoapMessage) soapMessage;
          ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
          try {
            saajMessage.getSaajMessage().writeTo(byteOut);
            soapMessageBytes = byteOut.toByteArray();
          } catch (SOAPException e) {
            throw new IOException("Couldn't write SAAJ SOAP message to byte array because of SOAPException: "+e.getMessage());
          }
        } else if (soapMessage instanceof AxiomSoapMessage) {
          type = AXIOM;
          AxiomSoapMessage axiomMessage = (AxiomSoapMessage) soapMessage;
          ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
          try {
            axiomMessage.getAxiomMessage().serialize(byteOut);
            soapMessageBytes = byteOut.toByteArray();
          } catch (XMLStreamException e) {
            throw new IOException("Couldn't write Axiom SOAP message to byte array because of SOAPException: "+e.getMessage());
          }
        } else {
          throw new RuntimeException("Unexpected soap message instance type.");
        }
        out.defaultWriteObject(); // Now serialize normally.
      }
      
      private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
        in.defaultReadObject();  // Deserialize normally.
        // Now reconstruct the SoapMessage.
        if (type.equals(SAAJ)) {
          // Not sure what to do here.
          // SOAPMessage saajMessage = 
        } else if (type.equals(AXIOM)) {
          // Not sure what to do here.
        } else {
          throw new RuntimeException("Unexpected type value for soap message.");
        }
      }
      
    }
Working...
X