0

I've got a set of JAX-RS endpoints that are accessed asynchronously from an AngularJS-based application.

About the project...

  • Apache CXF JAX-RS, Non-Spring Servlet Implementation: 2.7.7
  • Hibernate JPA: 4.3.5.Final
  • EclipseLink Moxy: 2.5.1
  • Spring: 4.2.1.RELEASE
  • Tomcat 7

MOXy is currently configured by registering the org.eclipse.persistence.jaxb.rs.MOXyJsonProvider class to the JAX-RS Application, with a jaxb.properties file included in the JPA Entity classes' package; the contents of the file: javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

If I access an endpoint by itself, everything functions as expected.

If I access the Angular client via the browser on my Windows-based localhost, everything functions as expected.

However, as soon as I test the application in a Linux-based test environment, I sometimes get exceptions, such as the following:

10:57:38.390 [tomcat-http--27] WARN  o.a.c.j.i.WebApplicationExceptionMapper - javax.ws.rs.WebApplicationException: javax.xml.bind.MarshalException
 - with linked exception:
[java.lang.NullPointerException]
        at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.java:842)
        at org.apache.cxf.jaxrs.utils.JAXRSUtils.writeMessageBody(JAXRSUtils.java:1317)
        at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.serializeMessage(JAXRSOutInterceptor.java:282)
        at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.processResponse(JAXRSOutInterceptor.java:155)
        at org.apache.cxf.jaxrs.interceptor.JAXRSOutInterceptor.handleMessage(JAXRSOutInterceptor.java:86)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
        at org.apache.cxf.interceptor.OutgoingChainInterceptor.handleMessage(OutgoingChainInterceptor.java:77)
        at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
        at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:121)
        at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:239)
        at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:248)
        at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:222)
        at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:153)
        at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:167)
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:286)
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:211)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
        at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
        at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
        at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
        at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
        at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
        at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
        at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
        at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:947)
        at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
        at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
        at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1009)
        at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
        at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:744)
Caused by: javax.xml.bind.MarshalException
 - with linked exception:
[java.lang.NullPointerException]
        at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:457)
        at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.writeTo(MOXyJsonProvider.java:840)
        ... 33 more
Caused by: java.lang.NullPointerException
        at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.marshal(XMLCompositeObjectMappingNodeValue.java:145)
        at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
        at org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
        at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:401)
        at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:240)
        at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
        at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
        at org.eclipse.persistence.internal.oxm.XMLCompositeCollectionMappingNodeValue.marshalSingleValue(XMLCompositeCollectionMappingNodeValue.java:328)
        at org.eclipse.persistence.internal.oxm.XMLCompositeCollectionMappingNodeValue.marshal(XMLCompositeCollectionMappingNodeValue.java:108)
        at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:149)
        at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
        at org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
        at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:401)
        at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:240)
        at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
        at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
        at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.marshalSingleValue(XMLCompositeObjectMappingNodeValue.java:249)
        at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.marshal(XMLCompositeObjectMappingNodeValue.java:150)
        at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
        at org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
        at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:401)
        at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:240)
        at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
        at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
        at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.marshalSingleValue(XMLCompositeObjectMappingNodeValue.java:249)
        at org.eclipse.persistence.internal.oxm.XMLCompositeObjectMappingNodeValue.marshal(XMLCompositeObjectMappingNodeValue.java:150)
        at org.eclipse.persistence.internal.oxm.NodeValue.marshal(NodeValue.java:102)
        at org.eclipse.persistence.internal.oxm.record.ObjectMarshalContext.marshal(ObjectMarshalContext.java:59)
        at org.eclipse.persistence.internal.oxm.XPathNode.marshal(XPathNode.java:401)
        at org.eclipse.persistence.internal.oxm.XPathObjectBuilder.buildRow(XPathObjectBuilder.java:240)
        at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:118)
        at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.buildRow(TreeObjectBuilder.java:1)
        at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:751)
        at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:571)
        at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshalStreamOrWriter(XMLMarshaller.java:1107)
        at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:919)
        at org.eclipse.persistence.internal.oxm.XMLMarshaller.marshal(XMLMarshaller.java:862)
        at org.eclipse.persistence.jaxb.JAXBMarshaller.marshal(JAXBMarshaller.java:455)
        ... 34 more

The only relevant information I've been able to find about my issue is in this related StackOverflow question/answer: Null pointer exception only on application startup org.eclipse.persistence.jaxb.JAXBMarshaller.marshal

This didn't start happening until I migrated my project to use Spring for Hibernate JPA EntityManager transaction management.

I'm at a complete loss. I could refactor my client to only issue synchronous calls, but even then, this issue will still occur when multiple users attempt to use the application simultaneously. Why is MOXy misbehaving in this way? It does seem like this happens less often after multiple refreshes of the Angular client, so the concept of "priming" the system does seem like it somewhat accurately explains what's going on. However, even then, this behavior is not consistent! There doesn't seem to be a way to reliably predict when this exception condition will occur.

Is there something additional that I need to do, now that Spring is managing transactions, to get MOXy to properly initialize when called from concurrent threads in rapid succession?

Summary:

  • Never happens when individual JAX-RS RESTful endpoints are accessed (regardless of server environment)
  • Never happens on Windows-based localhost
  • Sometimes happens on Linux-based test server, and only when multiple endpoints are being accessed concurrently
    • Sometimes doesn't happen at all, even under these condtitions
  • Only started happening after a migration from manual/custom application-managed Hibernate EntityManager transaction management to Spring-based transaction management
Community
  • 1
  • 1
Christopher Parker
  • 4,541
  • 2
  • 28
  • 33
  • It took a lot of Google-fu to craft the right set of search terms, but I've found another instance of this issue, which hasn't been fixed as of 2.5.1. If I want the fix, I'm going to have to use a SNAPSHOT version of MOXy. https://www.eclipse.org/forums/index.php/t/667901/ – Christopher Parker Dec 10 '14 at 03:53
  • SNAPSHOT version not necessary. Version 2.5.2 was released since I last checked for MOXy releases. Version 2.5.2 (the latest 2.5.x release) fixes the issue for me. I'm adding an answer and closing the question. – Christopher Parker Dec 10 '14 at 21:06

1 Answers1

1

According to the bug report at https://bugs.eclipse.org/bugs/show_bug.cgi?id=404951, a fix for this issue was checked in to the 2.5.x branch. I checked the stable MOXy releases, and sure enough, version 2.5.2 was released a few months ago.

I switched my project from 2.5.1 to 2.5.2 and I no longer experience this issue.

Note about the different behaviors between localhost and test server...

I was proxying endpoint requests through grunt-connect-proxy so that I could maintain relative pathing for endpoint URLs while using grunt-contrib-connect for livereload functionality.

When I removed this intermediate proxy, and the Angular client accessed the endpoints directly, I was able to duplicate the issue locally.

Christopher Parker
  • 4,541
  • 2
  • 28
  • 33