最近在升级项目的版本,由jdk8.x升到jdk 11.x, 发现一个奇怪的EclipseLink异常:java.lang.AbstractMethodError does not define or inherit an implementation of the resolved method abstract _persistence_shallow_clone()
完整异常栈:
java.lang.AbstractMethodError: Receiver class com.apobates.forum.core.entity.BoardActionCollection does not define or inherit an implementation of the resolved method abstract _persistence_shallow_clone()Ljava/lang/Object; of interface org.eclipse.persistence.internal.descriptors.PersistenceObject.
at org.eclipse.persistence.descriptors.copying.PersistenceEntityCopyPolicy.buildClone(PersistenceEntityCopyPolicy.java:37)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildBackupClone(ObjectBuilder.java:602)
at org.eclipse.persistence.descriptors.changetracking.DeferredChangeDetectionPolicy.buildBackupClone(DeferredChangeDetectionPolicy.java:233)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildWorkingCopyCloneFromRow(ObjectBuilder.java:2270)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObjectInUnitOfWork(ObjectBuilder.java:858)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:745)
at org.eclipse.persistence.internal.descriptors.ObjectBuilder.buildObject(ObjectBuilder.java:699)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.buildObject(ObjectLevelReadQuery.java:861)
at org.eclipse.persistence.queries.ReadAllQuery.registerResultInUnitOfWork(ReadAllQuery.java:987)
at org.eclipse.persistence.queries.ReadAllQuery.executeObjectLevelReadQuery(ReadAllQuery.java:598)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeDatabaseQuery(ObjectLevelReadQuery.java:1232)
at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:911)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1191)
at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:485)
at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1279)
at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2983)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1898)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1880)
at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1845)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:262)
at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:482)
at javax.persistence.TypedQuery.getResultStream(TypedQuery.java:87)
at jdk.internal.reflect.GeneratedMethodAccessor147.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.orm.jpa.SharedEntityManagerCreator$DeferredQueryInvocationHandler.invoke(SharedEntityManagerCreator.java:409)
at com.sun.proxy.$Proxy87.getResultStream(Unknown Source)
at com.apobates.forum.core.impl.dao.BoardActionCollectionDaoImpl.findAllMemberFavoriteBoard(BoardActionCollectionDaoImpl.java:241)
at com.apobates.forum.core.impl.dao.BoardActionCollectionDaoImpl$$FastClassBySpringCGLIB$$85b044de.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:687)
at com.apobates.forum.core.impl.dao.BoardActionCollectionDaoImpl$$EnhancerBySpringCGLIB$$6124c825.findAllMemberFavoriteBoard(<generated>)
at com.apobates.forum.core.impl.service.BoardServiceImpl.getMemberFavorites(BoardServiceImpl.java:227)
at com.apobates.forum.core.impl.service.BoardServiceImpl$$FastClassBySpringCGLIB$$c71260d2.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:95)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691)
at com.apobates.forum.core.impl.service.BoardServiceImpl$$EnhancerBySpringCGLIB$$2256bf96.getMemberFavorites(<generated>)
at com.apobates.forum.thrones.controller.MemberHomeController.getMemberStarBoard(MemberHomeController.java:558)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.sitemesh.webapp.contentfilter.ContentBufferingFilter.bufferAndPostProcess(ContentBufferingFilter.java:169)
at org.sitemesh.webapp.contentfilter.ContentBufferingFilter.doFilter(ContentBufferingFilter.java:126)
at org.sitemesh.webapp.SiteMeshFilter.doFilter(SiteMeshFilter.java:120)
at org.sitemesh.config.ConfigurableSiteMeshFilter.doFilter(ConfigurableSiteMeshFilter.java:163)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at com.apobates.forum.thrones.controller.helper.RequestTokenParameterFilter.doFilter(RequestTokenParameterFilter.java:87)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:358)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:271)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:690)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.base/java.lang.Thread.run(Thread.java:834)
BoardActionCollection 类是一个子类, 实现单表继承. 完全参考官方的示例: EclipseLink/Examples/JPA/Inheritance
具体代码如下:
/**
* 抽像的操作集合
*
* @author xiaofanku
* @since 20200514
*/
@Entity
@Table(name = "apo_action_event_set")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "TYPE", discriminatorType = DiscriminatorType.STRING, length = 20)
@DiscriminatorValue("P")
public class ActionEventDescriptor implements Serializable {
//ETC
}
/**
* 版块的操作集合
*
* @author xiaofanku
* @since 20200514
*/
@Entity
@DiscriminatorValue("B")
public class BoardActionCollection extends ActionEventDescriptor{
//ETC
}
/**
* 话题的操作集合
*
* @author xiaofanku
* @since 20200514
*/
@Entity
@DiscriminatorValue("T")
public class TopicActionCollection extends ActionEventDescriptor{}
子类TopicActionCollection 织入成功, 只有BoardActionCollection子类的业务方法调用失败, 抛出上面的异常. 原来的织入设置,persistence.xml
<property name="eclipselink.weaving" value="true"/>
<property name="eclipselink.weaving.lazy" value="true"/>
<property name="eclipselink.weaving.internal" value="true"/>
用spring3 + EclipseLink 2.5.2 + jdk8 运行没问题, 后来升级到jdk8 + spring 5.0.7 + EclipseLink2.7.1 运行没问题. 当前异常的环境为: spring 5.2.6 + EclipseLink2.7.6 + jdk 11.0.2 + tomcat 9.x
原来一直以为是环境没配置对, 必竟是第一次写jdk 11的项目. 去EclipseLink官方文档一顿找,发现下面的文章:
AbstractMethodError: _persistence_shallow_clone()
Configuring Static Weaving
eclipselink-static-weave-plugin
按此路子可以解决. 在编译时进行静态织入, 也省的项目启动时进行动态织入,项目的启动时间也缩短了. 注意改用静态织入需要在persistence.xml中进行如下变动:
<property name="eclipselink.weaving" value="false"/>
<property name="eclipselink.weaving.lazy" value="false"/>
<property name="eclipselink.weaving.internal" value="true"/>
项目pom.xml的build部分如下:
<build>
<finalName>ROOTfinalName>
<resources>
<resource>
<directory>src/main/resourcesdirectory>
<filtering>truefiltering>
resource>
resources>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>3.8.1version>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-war-pluginartifactId>
<version>2.3version>
<configuration>
<failOnMissingWebXml>falsefailOnMissingWebXml>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-dependency-pluginartifactId>
<version>3.0.1version>
<executions>
<execution>
<id>copyid>
<phase>packagephase>
<goals>
<goal>copygoal>
goals>
<configuration>
<outputDirectory>${endorsed.dir}outputDirectory>
<silent>truesilent>
<artifactItems>
<artifactItem>
<groupId>javaxgroupId>
<artifactId>javaee-endorsed-apiartifactId>
<version>7.0version>
<type>jartype>
artifactItem>
artifactItems>
configuration>
execution>
executions>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-surefire-pluginartifactId>
<version>2.20version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefiregroupId>
<artifactId>surefire-junit4artifactId>
<version>2.20version>
dependency>
dependencies>
<configuration>
<argLine>-Dfile.encoding=${project.build.sourceEncoding}argLine>
<argLine>-javaagent:${settings.localRepository}/org/springframework/spring-instrument/${spring-framework.version}/spring-instrument-${spring-framework.version}.jarargLine>
configuration>
plugin>
<plugin>
<groupId>de.empulse.eclipselinkgroupId>
<artifactId>staticweave-maven-pluginartifactId>
<version>1.0.0version>
<executions>
<execution>
<phase>process-classesphase>
<goals>
<goal>weavegoal>
goals>
<configuration>
<persistenceXMLLocation>META-INF/persistence.xmlpersistenceXMLLocation>
<logLevel>FINElogLevel>
configuration>
execution>
executions>
<dependencies>
<dependency>
<groupId>org.eclipse.persistencegroupId>
<artifactId>org.eclipse.persistence.jpaartifactId>
<version>${eclipselink.version}version>
dependency>
dependencies>
plugin>
plugins>
build>