Closed CodeNinjai closed 7 years ago
hi @CodeNinjai, Which version of Tomcat you use? I suggest you use from 7.0.26 onwards. There is a bug in previous versions of Tomcat on WebClassloader.
please give me a feedback if you resolve this issue, so I can write it in the wiki
Hi @avurro
thanks for the quick reply. We use Tomcat 8.5.5
"Starting Servlet Engine: Apache Tomcat/8.5.5"
So this might not be the cause of the problem?
Thanks, Jan
Probably due to a management with more ClassLoader. Can you attach a project that recreates the error?
We also assume that the problem is related to the classloader being used. When JMapper is instantiated for the first time, MapperBuilder.exist( ) returns false as expected. But on further instantiations it is still false, causing javassist to dynamically create a (duplicate) class definition.
Give me a moment to create a project for you...
Try to configure the web application class loader as described here, adding the <Loader delegate="true"/>
Can you try to build this https://github.com/CodeNinjai/JMapperClassloaderIssue ? Just run the app and go to http://localhost:8080 The first time, it will run successfully, the second call will fail.
@avurro Ok, we are going to try this <Loader delegate="true"/>
thing....
switching on jetty the issue there isn't, so now i have to decide if to load all ClassLoaders and check the class existence or delegate to a Tomcat configuration.
we checked delegation and it is enabled. Also tried to override the ThreadContextClassLoader:
@Override
protected TomcatEmbeddedServletContainer getTomcatEmbeddedServletContainer( Tomcat tomcat) {
tomcat.enableNaming();
TomcatEmbeddedServletContainer container = msuper.getTomcatEmbeddedServletContainer(tomcat);
for (Container child: container.getTomcat().getHost().findChildren()) {
System.out.println("------->"+child.getClass().getName());
if (child instanceof Context) {
ClassLoader contextClassLoader = ((Context)child).getLoader().getClassLoader();
System.out.println("------->"+contextClassLoader.getClass().getName());
ClassUtils.overrideThreadContextClassLoader(contextClassLoader);
//Thread.currentThread().setContextClassLoader(contextClassLoader);
break;
}
}
return container;
}
But didn't help either. What do you suggest?
Thanks, Jan
I will solve the problem tonight and will release a SNAPSHOT with this fix.
Awesome! Thank you very much for the quick help!
Fixed!
<dependency>
<groupId>com.googlecode.jmapper-framework</groupId>
<artifactId>jmapper-core</artifactId>
<version>1.6.1.CR2-SNAPSHOT</version>
</dependency>
You need to add the Snapshot repository! go to wiki page for this.
good work! 👍
Alessandro,
just tried out the snapshot version. Now I'm getting an ClassCastException at the mapper.getDestination() call:
//JMapper<CampaignMappingDTO, CampaignMapping> mapper = mapperProvider.getMapper(CampaignMappingDTO.class, CampaignMapping.class);
JMapper<CampaignMappingDTO, CampaignMapping> mapper = new JMapper<>(CampaignMappingDTO.class, CampaignMapping.class);
CampaignGroup campaignGroup = this.campaignGroupService.getById(id);
List<CampaignMappingDTO> dtos = new ArrayList<>();
campaignGroup.getCampaigns().forEach(c -> {
// following throws exception with 1.6.1.CR2-SNAPSHOT
CampaignMappingDTO campaignMappingDTO = mapper.getDestination(c);
campaignMappingDTO.setCampaignGroupId(id);
dtos.add(campaignMappingDTO);
});
return dtos;
Exception:
com.googlecode.jmapper.exceptions.JMapperException: java.lang.ClassCastException: de.mycompany.campaigngroup.entity.CampaignMapping cannot be cast to de.mycompany.campaigngroup.entity.CampaignMapping
at com.googlecode.jmapper.config.JmapperLog.ERROR(JmapperLog.java:46)
at com.googlecode.jmapper.JMapper.getDestination(JMapper.java:100)
at de.mycompany.campaigngroup.controller.CampaignGroupController.lambda$getCampaignGroupCampaigns$5(CampaignGroupController.java:151)
at de.mycompany.campaigngroup.controller.CampaignGroupController$$Lambda$7/1147850257.accept(Unknown Source)
at java.lang.Iterable.forEach(Iterable.java:75)
at de.mycompany.campaigngroup.controller.CampaignGroupController.getCampaignGroupCampaigns(CampaignGroupController.java:150)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
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.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
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:108)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
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:784)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.ClassCastException: de.mycompany.campaigngroup.entity.CampaignMapping cannot be cast to de.mycompany.campaigngroup.entity.CampaignMapping
at demycompanycampaigngroupdtoCampaignMappingDTOdemycompanycampaigngroupentityCampaignMapping.nullVSouAllAll(demycompanycampaigngroupdtoCampaignMappingDTOdemycompanycampaigngroupentityCampaignMapping.java)
at com.googlecode.jmapper.JMapper.getDestination(JMapper.java:98)
... 64 more
Curious, the application that you sent to me work perfectly. There are differences between the demo application and the one you use? Destination Class is loaded two times... i'm sorry for the time that I'm doing lose to you, i will solve as soon as possible
We found the difference! spring-boot-devtools causes the issue..
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
So, we'll exclude this for the moment. We might investigate the class cast issue in this context further, but you may too, if you have spare time for that ;-)
Thanks, Jan
ok Jan, the important thing is that you are not locked. In the meantime i will find a solution for that too :+1:
Thank you very much for you efforts!
I'm trying with dependency you said but the error does not recur. There's probably something else. If you can recreate the error on your project, I will take it back
Hi avurro, I'm a collegue of CodeNinjai. We both work on the same project. With the 'new' demo Project we can reproduce the error (using 1.6.1.CR2-SNAPSHOT and spring-boot-devtools). Without devtools all is working fine, without not. (We also use hibernate-handling now, to reproduce our main project realistically)
Thanks!
First step: Insert one row in hsqldb "http://localhost:8080/insert". Second step : Fetch the inserted row by "http://localhost:8080/1". (It's craching with devtools included)
thanks @abweg! I work on it as soon as possible.
Guys i have fixed the issue, i have deployed the snapshot with the same name. Let me know if it works (be sure to load the right one).
Hi @avurro. I have just tried out your new version. The method exists() (in jmapper.class (Line 449)) seems to work, but mapper. get... returns null. Let's wait until monday, so my colleagues can have a look about that too. Calling "final JMapper<XDTO, X> mapper = new JMapper<>(XDTO.class, X.class);" twice, is now throwing a Nullpointerexception...
Many thanks for your efforts! And have a nice weekend!
Try again now, i don't understand why i haven't your errors, however i have modified the get method, in this way the same classLoader will be used. I hope this is the right time :sunglasses:
Alessandro, we just had success with your latest snapshot.. On my machine everything worked just fine even with spring-devtools enabled.
We keep you updated.
good news! JMapper is more robust thanks to you! close the issue when you are confident :+1:
Hello,
we are using JMapper 1.6.1.CR1 in a Spring Boot Environment. We have a controller with a method like this:
Calling getByClientId() the first time works fine, and also the mapping does what we expect it should. But calling the method twice raises following exception:
com.googlecode.jmapper.exceptions.JMapperException: javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedWebappClassLoader): attempted duplicate class definition for name: "demycompanycampaigngroupdtoCampaignGroupDTOdemycompanycampaigngroupentityCampaignGroup" at com.googlecode.jmapper.config.JmapperLog.ERROR(JmapperLog.java:46) at com.googlecode.jmapper.JMapper.(JMapper.java:437)
at com.googlecode.jmapper.JMapper.(JMapper.java:373)
at com.googlecode.jmapper.JMapper.(JMapper.java:360)
at de.mycompany.campaigngroup.controller.CampaignGroupController.getByClientId(CampaignGroupController.java:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
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.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:89)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
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:108)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
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:784)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:802)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1410)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Caused by: javassist.CannotCompileException: by java.lang.LinkageError: loader (instance of org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedWebappClassLoader): attempted duplicate class definition for name: "demycompanycampaigngroupdtoCampaignGroupDTOdemycompanycampaigngroupentityCampaignGroup"
at javassist.ClassPool.toClass(ClassPool.java:1170)
at javassist.ClassPool.toClass(ClassPool.java:1113)
at javassist.ClassPool.toClass(ClassPool.java:1071)
at javassist.CtClass.toClass(CtClass.java:1264)
at com.googlecode.jmapper.generation.JavassistGenerator.generate(JavassistGenerator.java:90)
at com.googlecode.jmapper.generation.MapperGenerator.generateMapperClass(MapperGenerator.java:74)
at com.googlecode.jmapper.generation.MapperBuilder.generate(MapperBuilder.java:88)
at com.googlecode.jmapper.JMapper.createMapper(JMapper.java:450)
at com.googlecode.jmapper.JMapper.(JMapper.java:432)
... 63 more
Caused by: java.lang.LinkageError: loader (instance of org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedWebappClassLoader): attempted duplicate class definition for name: "demycompanycampaigngroupdtoCampaignGroupDTOdemycompanycampaigngroupentityCampaignGroup"
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
at java.lang.ClassLoader.defineClass(ClassLoader.java:642)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at javassist.ClassPool.toClass2(ClassPool.java:1183)
at javassist.ClassPool.toClass(ClassPool.java:1164)
Any help would be appreciated :-)
Jan