You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by "Lazar Kirchev (JIRA)" <ji...@apache.org> on 2017/06/16 07:11:00 UTC

[jira] [Comment Edited] (TOMEE-2058) Problem with persistence in application specifying a context path through sun-web.xml

    [ https://issues.apache.org/jira/browse/TOMEE-2058?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16051489#comment-16051489 ] 

Lazar Kirchev edited comment on TOMEE-2058 at 6/16/17 7:10 AM:
---------------------------------------------------------------

Hi,

I found that the problem is that the entities classes get loaded by two different classloaders.

More details:
If there is a sun-web.xml specifying a different context root the application gets deployed twice in Tomcat, hence the two classloaders. 

First it is deployed with the original context root, and a TomEEWebappClassLoader is created for it.
All configurations in the Assembler.createApplication() and ConfigurationFactory.configureApplication() take part here. As part of the deployment in the ConfigurationFactory deployers chain, the SunConversion deployer is called which detects that the application has a sun-web.xml and processes it. At this time it changes the contextRoot in the WebModule instance with the context root from the sun-web.xml. Also during the application creation phase the processing of the persistence units is performed. The EntityManager implementation is initialized with the descriptors of the entities. These descriptors are stored in a map, keyed by class objects of the entities' classes. And these class objects are loaded by the original TomEEWebappClassLoader. 

After that, in TomcatWebAppBuilder.deployWebApps() for each WebApp is checked if it is deployed. The check is performed in TomcatWebAppBuilder.isAlreadyDeployed() and is based on the context root. However, as the SunConversion deployer has changed the context root of the WebModule, the infos structure where the ContextInfo objects of the deployed applications are stored does not contain an entry for the new context root and that is why the application is deployed again in Tomcat, and a new TomEEWebappClassLoader gets created. None of the configuration steps from Assembler.createApplication() are performed upon this deployment. 

When the application is requested through the context root from sun-web.xml, the persistence fails because the entities classes are loaded with the second TomEEWebappClassLoader, while the classes in the EntityManager are loaded with the first one and that is why the EntityManager does not recognize these entities and throws the exception from the description of the issue.

What do you think should be the behavior here? Should the application be accessible both through the original context root, and the context root in the sun-web.xml, or only via the second? 


was (Author: lkirchev):
Hi,

I found that the problem is that the entities classes get loaded by two different classloaders.

More details:
If there is a sun-web.xml specifying a different context root the application gets deployed twice in Tomcat, hence the two classloaders. 

First it is deployed with the original context root, and a TomEEWebappClassLoader is created for it.
All configurations in the Assembler.createApplication() and ConfigurationFactory.configureApplication() take part here. As part of the deployment in the ConfigurationFactory deployers chain, the SunConversion deployer is called which detects that the application has a sun-web.xml and processes it. At this time it changes the contextRoot in the WebModule instance with the context root from the sun-web.xml. Also during the application creation phase the processing of the persistence units is performed. The EntityManager implementation is initialized with the descriptors of the entities. These descriptors are stored in a map, keyed by class objects of the entities' classes. And these class objects are loaded by the original TomEEWebappClassLoader. 

After that, in TomcatWebAppBuilder.deployWebApps() for each WebApp is checked if it is deployed. The check is performed in TomcatWebAppBuilder.isAlreadyDeployed() and is based on the context root. However, as the SunConversion deployer has changed the context root of the WebModule, the infos structure where the ContextInfo objects of the deployed applications are stored does not contain an entry for the new context root and that is why the application is deployed again in Tomcat, and a new TomEEWebappClassLoader gets created. None of the configuration steps from Assembler.createApplication() are performed upon this deployment. 

When the application is requested through the context root from sun-web.xml, the persistence fails because the entities classes are loaded with the second TomEEWebappClassLoader, while the classes in the EntityManager are loaded with the first one and that is why the EntityManager does not recognize these entities and throws the exception from the description of the issue.

What do you think should be the behavior here?

> Problem with persistence in application specifying a context path through sun-web.xml
> -------------------------------------------------------------------------------------
>
>                 Key: TOMEE-2058
>                 URL: https://issues.apache.org/jira/browse/TOMEE-2058
>             Project: TomEE
>          Issue Type: Bug
>          Components: TomEE Core Server
>    Affects Versions: 7.0.3
>            Reporter: Lazar Kirchev
>
> I am deploying a very simple application with JPA on TomEE Plume. 
> The application uses a sun-web.xml to specify an alternative context root. It defines one entity (Person) and in a servlet creates an instance of this entity and tries to persist it. 
> If the application is requested through the context root specified in sun-web.xml (http://localhost:8080/Test/TestServlet), the persisting fails with the following exception:
> {code}
> java.lang.IllegalArgumentException: Object: my.test.entity.Person@1 is not a known Entity type.
> 	at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.registerNewObjectForPersist(UnitOfWorkImpl.java:4226)
> 	at org.eclipse.persistence.internal.jpa.EntityManagerImpl.persist(EntityManagerImpl.java:507)
> 	at org.apache.openejb.persistence.JtaEntityManager.persist(JtaEntityManager.java:193)
> 	at my.test.TestServlet.doGet(TestServlet.java:28)
> 	at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
> 	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
> 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
> 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
> 	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
> 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
> 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
> 	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
> 	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
> 	at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
> 	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
> 	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
> 	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
> 	at org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
> 	at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:624)
> 	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
> 	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
> 	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
> 	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
> 	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798)
> 	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434)
> 	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
> 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
> 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
> 	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
> 	at java.lang.Thread.run(Thread.java:807)
> {code}
> On the other hand, if the application is requested through the context path, defined by the war name (http://localhost:8080/TestPersistence/TestServlet), the entity is successfully persisted.
> You can reproduce the problem with the [application|https://github.com/lkirchev/Misc]. For the Data Source resource definition you could use:
> {code}
> <Resource id="myDS" type="DataSource">
>     JdbcDriver org.hsqldb.jdbcDriver
>     JdbcUrl jdbc:hsqldb:file:hsqldb
>     UserName sa
>     Password
> </Resource>
> {code}



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)