Problem with JSON-P and JPA lazy fetch
dbschofield Jan 15, 2014 6:23 PMI have a simple jax-rs service which returns JSON.
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Stateless
@Path("roles")
public class RoleResource {
@EJB private ENC enc;
@GET
@Produces("text/json")
public List<Role> roles(){
return enc.getRoles();
}
}
The JSON data to return is a JPA entity.
@Entity
public class Role implements Serializable {
@Id
private String name;
@ManyToMany(fetch=FetchType.EAGER)
@JoinTable(
name="role_profile_map",
joinColumns={@JoinColumn(name="role", referencedColumnName="name")},
inverseJoinColumns={@JoinColumn(name="profile", referencedColumnName="name")})
private Set<Profile> profiles;
@ManyToMany
@JoinTable(
name="role_environment_map",
joinColumns={@JoinColumn(name="role", referencedColumnName="name")},
inverseJoinColumns={@JoinColumn(name="environment", referencedColumnName="name")})
private Set<Environment> environments;
...
}
If I want the ManyToMany relationships to be lazily fetched I get the following exception.
17:45:11,007 ERROR [io.undertow.request] (default task-11) UT005023: Exception handling request to /paas/rest/roles: org.jboss.resteasy.spi.UnhandledException: org.codehaus.jackson.map.JsonMappingException: failed to lazily initialize a collection of role: com.xyz.paas.entity.Role.environments, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.xyz.paas.entity.Role["environments"])
at org.jboss.resteasy.core.ExceptionHandler.handleException(ExceptionHandler.java:247) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.writeException(SynchronousDispatcher.java:149) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:432) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:376) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:179) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher.service(ServletContainerDispatcher.java:220) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:56) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher.service(HttpServletDispatcher.java:51) [resteasy-jaxrs-3.0.6.Final.jar:]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar:1.0.0.Final]
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:87) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:70)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.security.handlers.AuthenticationCallHandler.handleRequest(AuthenticationCallHandler.java:52) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.security.handlers.AuthenticationConstraintHandler.handleRequest(AuthenticationConstraintHandler.java:51) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.security.ServletSecurityConstraintHandler.handleRequest(ServletSecurityConstraintHandler.java:56) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:67) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:70) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:164) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:654) [undertow-core-1.0.0.Beta30.jar:1.0.0.Beta30]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_40]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_40]
at java.lang.Thread.run(Thread.java:724) [rt.jar:1.7.0_40]
Caused by: org.codehaus.jackson.map.JsonMappingException: failed to lazily initialize a collection of role: com.xyz.paas.entity.Role.environments, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.xyz.paas.entity.Role["environments"])
at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:218) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.JsonMappingException.wrapWithPath(JsonMappingException.java:183) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.std.SerializerBase.wrapAndThrow(SerializerBase.java:140) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:158) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:112) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:72) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:23) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:86) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:659) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:271) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ObjectWriter.writeValue(ObjectWriter.java:325) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.jaxrs.JacksonJsonProvider.writeTo(JacksonJsonProvider.java:557)
at org.jboss.resteasy.core.interception.AbstractWriterInterceptorContext.writeTo(AbstractWriterInterceptorContext.java:129) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.core.interception.ServerWriterInterceptorContext.writeTo(ServerWriterInterceptorContext.java:62) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.core.interception.AbstractWriterInterceptorContext.proceed(AbstractWriterInterceptorContext.java:118) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.security.doseta.DigitalSigningInterceptor.aroundWriteTo(DigitalSigningInterceptor.java:143) [resteasy-crypto-3.0.6.Final.jar:]
at org.jboss.resteasy.core.interception.AbstractWriterInterceptorContext.proceed(AbstractWriterInterceptorContext.java:122) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.plugins.interceptors.encoding.GZIPEncodingInterceptor.aroundWriteTo(GZIPEncodingInterceptor.java:100) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.core.interception.AbstractWriterInterceptorContext.proceed(AbstractWriterInterceptorContext.java:122) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.core.ServerResponseWriter.writeNomapResponse(ServerResponseWriter.java:99) [resteasy-jaxrs-3.0.6.Final.jar:]
at org.jboss.resteasy.core.SynchronousDispatcher.writeResponse(SynchronousDispatcher.java:427) [resteasy-jaxrs-3.0.6.Final.jar:]
... 33 more
Caused by: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.xyz.paas.entity.Role.environments, could not initialize proxy - no Session
at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:572) [hibernate-core-4.3.0.Final.jar:4.3.0.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:212) [hibernate-core-4.3.0.Final.jar:4.3.0.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:551) [hibernate-core-4.3.0.Final.jar:4.3.0.Final]
at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:140) [hibernate-core-4.3.0.Final.jar:4.3.0.Final]
at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180) [hibernate-core-4.3.0.Final.jar:4.3.0.Final]
at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:45) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.std.CollectionSerializer.serializeContents(CollectionSerializer.java:23) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.std.AsArraySerializerBase.serialize(AsArraySerializerBase.java:86) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:446) [jackson-mapper-asl-1.9.12.jar:1.9.12]
at org.codehaus.jackson.map.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:150) [jackson-mapper-asl-1.9.12.jar:1.9.12]
... 50 more
My understanding is this exception is thrown because the container managed transaction for the hibernate session has already ended by the time hibernate attempts to lazily fetch the environments set needed for the JSON conversion. I'm wondering if WildFly should (or some way can) make the conversion of the JPA entity to JSON part of the container managed transaction. Or is their a compelling reason not to do this?