title: How to use Spring RestTemplate and JAXB marshalling on a URL that returns multiple types of XML
body: <p>I need to make a Rest POST to a service that returns either a <code>&lt;job/&gt;</code> or an <code>&lt;exception/&gt;</code> and always status code <code>200</code>. (lame 3rd party product!).</p>
  
  <p>I have code like:</p>
  
  <pre><code>Job job = getRestTemplate().postForObject(url, postData, Job.class);
  </code></pre>
  
  <p>And my applicationContext.xml looks like: </p>
  
  <pre><code>&lt;bean id="restTemplate" class="org.springframework.web.client.RestTemplate"&gt;
      &lt;constructor-arg ref="httpClientFactory"/&gt;
  
      &lt;property name="messageConverters"&gt;
          &lt;list&gt;
              &lt;bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter"&gt;
                  &lt;property name="marshaller" ref="jaxbMarshaller"/&gt;
                  &lt;property name="unmarshaller" ref="jaxbMarshaller"/&gt;
              &lt;/bean&gt;
              &lt;bean class="org.springframework.http.converter.FormHttpMessageConverter"/&gt;
              &lt;bean class="org.springframework.http.converter.StringHttpMessageConverter"/&gt;
          &lt;/list&gt;
      &lt;/property&gt;
  &lt;/bean&gt;
  
  &lt;bean id="jaxbMarshaller" class="org.springframework.oxm.jaxb.Jaxb2Marshaller"&gt;
      &lt;property name="classesToBeBound"&gt;
          &lt;list&gt;
              &lt;value&gt;domain.fullspec.Job&lt;/value&gt;
              &lt;value&gt;domain.fullspec.Exception&lt;/value&gt;
          &lt;/list&gt;
      &lt;/property&gt;
  &lt;/bean&gt;
  </code></pre>
  
  <p>When I try to make this call and the service fails, I get: </p>
  
  <pre><code> Failed to convert value of type 'domain.fullspec.Exception' to required type 'domain.fullspec.Job'
  </code></pre>
  
  <p>In the postForObject() call, I am asking for a Job.class and not getting one and it is getting upset.</p>
  
  <p>I am thinking I need to be able to do something along the lines of: </p>
  
  <pre><code>Object o = getRestTemplate().postForObject(url, postData, Object.class);
  if (o instanceof Job.class) {
     ...
  else if (o instanceof Exception.class) {
  }
  </code></pre>
  
  <p>But this doesnt work because then JAXB complains that it doesnt know how to marshal to Object.class - not surprisingly.</p>
  
  <p>I have attempted to create subclass of MarshallingHttpMessageConverter and override readFromSource()</p>
  
  <p>protected Object readFromSource(Class clazz, HttpHeaders headers, Source source) {</p>
  
  <pre><code>    Object o = null;
      try {
          o = super.readFromSource(clazz, headers, source);
      } catch (Exception e) {
          try {
              o = super.readFromSource(MyCustomException.class, headers, source);
          } catch (IOException e1) {
              log.info("Failed readFromSource "+e);
          }
      }
  
      return o;
  }
  </code></pre>
  
  <p>Unfortunately, this doesnt work because the underlying inputstream inside source has been closed by the time I retry it.</p>
  
  <p>Any suggestions gratefully received, </p>
  
  <p>Tom</p>
  
  <p><strong>UPDATE: I have got this to work by taking a copy of the inputStream</strong></p>
  
  <pre><code>protected Object readFromSource(Class&lt;?&gt; clazz, HttpHeaders headers, Source source) {
      InputStream is = ((StreamSource) source).getInputStream();
  
      // Take a copy of the input stream so we can use it for initial JAXB conversion
      // and if that fails, we can try to convert to Exception
      CopyInputStream copyInputStream = new CopyInputStream(is);
  
      // input stream in source is empty now, so reset using copy
      ((StreamSource) source).setInputStream(copyInputStream.getCopy());
  
      Object o = null;
      try {
          o = super.readFromSource(clazz, headers, source);
        // we have failed to unmarshal to 'clazz' - assume it is &lt;exception&gt; and unmarshal to MyCustomException
  
      } catch (Exception e) {
          try {
  
              // reset input stream using copy
              ((StreamSource) source).setInputStream(copyInputStream.getCopy());
              o = super.readFromSource(MyCustomException.class, headers, source);
  
          } catch (IOException e1) {
              e1.printStackTrace();  
          }
          e.printStackTrace();
      }
      return o;
  
  }
  </code></pre>
  
  <p>CopyInputStream is taken from <a href="http://www.velocityreviews.com/forums/t143479-how-to-make-a-copy-of-inputstream-object.html">http://www.velocityreviews.com/forums/t143479-how-to-make-a-copy-of-inputstream-object.html</a>, i'll paste it here.</p>
  
  <pre><code>import java.io.ByteArrayInputStream;
  import java.io.ByteArrayOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  
  public class CopyInputStream
  {
  private InputStream _is;
  private ByteArrayOutputStream _copy = new ByteArrayOutputStream();
  
  /**
   * 
   */
  public CopyInputStream(InputStream is)
  {
      _is = is;
  
      try
      {
          copy();
      }
      catch(IOException ex)
      {
          // do nothing
      }
  }
  
  private int copy() throws IOException
  {
      int read = 0;
      int chunk = 0;
      byte[] data = new byte[256];
  
      while(-1 != (chunk = _is.read(data)))
      {
          read += data.length;
          _copy.write(data, 0, chunk);
      }
  
      return read;
  }
  
  public InputStream getCopy()
  {
      return (InputStream)new ByteArrayInputStream(_copy.toByteArray());
  }
  }
  </code></pre>