Reputation: 694
I'm using Spring 3.1.1 with their OXM stuff, using the RestTemplate to post a request to another server. I'm using a class called ClassTermCollection as both the request and response sides of this, and it's annotated with @XmlRootElement, etc. and has been working fine for this until today. But suddenly we are getting the following error when JAXB is trying to create the request (that is, this error is thrown on the client side, before the http call to the server is ever made).
Google reveals next to nothing useful about this particular error, and - even worse - Sun apparently do not ship the source to the class where the exception is being thrown, with the JDK... so I can't even debug all the way down to the root of this to identify exactly what's happening.
Edit: (see additional comments below stacktrace)
[ERROR] org.springframework.http.converter.HttpMessageNotWritableException: Could not write [pmt.model.collections.ClassTermCollection@6576fac]; nested exception is org.springframework.oxm.MarshallingFailureException: JAXB marshalling exception; nested exception is javax.xml.bind.MarshalException: unsupported javax.xml.parser.transform.Result parameter [ERROR] at org.springframework.http.converter.xml.MarshallingHttpMessageConverter.writeToResult(MarshallingHttpMessageConverter.java:134) [ERROR] at org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter.writeInternal(AbstractXmlHttpMessageConverter.java:66) [ERROR] at org.springframework.http.converter.AbstractHttpMessageConverter.write(AbstractHttpMessageConverter.java:179) [ERROR] at org.springframework.web.client.RestTemplate$HttpEntityRequestCallback.doWithRequest(RestTemplate.java:588) [ERROR] at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:436) [ERROR] at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:409) [ERROR] at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:287) [ERROR] at com.pmt.fe.server.InvestmentServiceImpl.saveTerms(InvestmentServiceImpl.java:306) [ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) [ERROR] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) [ERROR] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) [ERROR] at java.lang.reflect.Method.invoke(Method.java:601) [ERROR] at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:569) [ERROR] at com.google.gwt.user.server.rpc.RPC.invokeAndEncodeResponse(RPC.java:551) [ERROR] at com.pmt.fe.server.RemoteServiceDispatcher.invokeAndEncodeResponse(RemoteServiceDispatcher.java:115) [ERROR] at com.pmt.fe.server.RemoteServiceDispatcher.processCall(RemoteServiceDispatcher.java:75) [ERROR] at com.google.gwt.user.server.rpc.RemoteServiceServlet.processPost(RemoteServiceServlet.java:248) [ERROR] at com.google.gwt.user.server.rpc.AbstractRemoteServiceServlet.doPost(AbstractRemoteServiceServlet.java:62) [ERROR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) [ERROR] at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) [ERROR] at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487) [ERROR] at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362) [ERROR] at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216) [ERROR] at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181) [ERROR] at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:729) [ERROR] at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:405) [ERROR] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) [ERROR] at org.mortbay.jetty.handler.RequestLogHandler.handle(RequestLogHandler.java:49) [ERROR] at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152) [ERROR] at org.mortbay.jetty.Server.handle(Server.java:324) [ERROR] at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505) [ERROR] at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:843) [ERROR] at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:647) [ERROR] at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:205) [ERROR] at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380) [ERROR] at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395) [ERROR] at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:488) [ERROR] Caused by: org.springframework.oxm.MarshallingFailureException: JAXB marshalling exception; nested exception is javax.xml.bind.MarshalException: unsupported javax.xml.parser.transform.Result parameter [ERROR] at org.springframework.oxm.jaxb.Jaxb2Marshaller.convertJaxbException(Jaxb2Marshaller.java:758) [ERROR] at org.springframework.oxm.jaxb.Jaxb2Marshaller.marshal(Jaxb2Marshaller.java:597) [ERROR] at org.springframework.oxm.jaxb.Jaxb2Marshaller.marshal(Jaxb2Marshaller.java:580) [ERROR] at org.springframework.http.converter.xml.MarshallingHttpMessageConverter.writeToResult(MarshallingHttpMessageConverter.java:131) [ERROR] ... 36 more [ERROR] Caused by: javax.xml.bind.MarshalException: unsupported javax.xml.parser.transform.Result parameter [ERROR] at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.createXmlOutput(MarshallerImpl.java:221) [ERROR] at com.sun.xml.internal.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:236) [ERROR] at org.springframework.oxm.jaxb.Jaxb2Marshaller.marshal(Jaxb2Marshaller.java:593) [ERROR] ... 38 more
OK, found the source1 for com.sun.xml.internal.bind.v2.runtime.MarshallerImpl online, and now I see (sort of) what's happening. That code looks at the Result instance and, if it's StreamResult (as it is in my case) it tries to dereference the outputstream, writer and then systemId fields of the StreamResult, and it uses those values to construct a Writer. IF all of them are null, it falls through into the bottom of the method and throws the "unsupported format" exception, which is happening here.
Above that, in the Spring org.springframework.http.converter.xml.AbstractXmlHttpMessageConverter class, we get to this line, which constructs the StreamResult, passing the result of outputMessage.getBody() to the StreamResult constructor. I'm getting null here, and hence the problem bubbling up from below.
@Override protected final void writeInternal(T t, HttpOutputMessage outputMessage) throws IOException { writeToResult(t, outputMessage.getHeaders(), new StreamResult(outputMessage.getBody())); }
Got this working... I forget all the details of what it turned out to be; but it was basically a crazy situation where a coworker added some code that subclassed one of the HttpClient classes, and his class didn't fulfill the contract of the interface exactly, and when called by my code, it caused this error. It was one of those weird situations where it looks like a JAXB error, but it turns out to have nothing to do with JAXB at all.
Upvotes: 0
Views: 5696
Reputation: 65
Your problem is that when you instantiate your StreamResult you must provide it a means to store the data that will be written to it. You should do something along the lines:
StreamResult res=new StreamResult(new ByteArrayOutputStream());
The ByteArrayOutputStream will grow as needed.
Upvotes: 4
Reputation: 200168
Looking at Spring's source code, Marshaller complains that it doesn't support the StreamResult object. It definitely supports this object, but what you may be experiencing is a classloading issue where a StreamResult loaded from the wrong JAR, or by the wrong classloader, is being used.
Upvotes: 1