spring aop #target and #within throw IllegalAccessError - spring-boot

when run the application, it throws IllegalAccessError,Application run failed
here is demo aop、service、annotation used,a simple annotation and #Before advice,also enable #EnableAspectJAutoProxy
#Target({ElementType.TYPE, ElementType.METHOD})
#Retention(RetentionPolicy.RUNTIME)
public #interface MethodInterceptAnnotation {
}
#Component
#Aspect
public class MethodInterceptAop {
#Before("#target(com.example.demo.aop.MethodInterceptAnnotation)")
public void beforeCheck() {
System.out.println("before check");
}
}
public interface UserService {
String getUserName(int a);
}
#Service
public class UserServiceImpl implements UserService {
#MethodInterceptAnnotation
public String getUserName(int age) {
System.out.println("age:" + age);
return age + "";
}
}
change#target to #within error again,
but change#target to #annotation everything is ok
here is partial stacktrace
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.IllegalAccessError-->class org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat$$EnhancerBySpringCGLIB$$e5c9e457 cannot access its superclass org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:538) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:363) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:582) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[na:1.8.0_201]
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:569) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:416) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:57) ~[spring-aop-5.2.4.RELEASE.jar:5.2.4.RELEASE]
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:205) ~[spring-aop-5.2.4.RELEASE.jar:5.2.4.RELEASE]
... 37 common frames omitted
Caused by: java.lang.IllegalAccessError: class org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat$$EnhancerBySpringCGLIB$$e5c9e457 cannot access its superclass org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat
at java.lang.ClassLoader.defineClass1(Native Method) ~[na:1.8.0_201]
at java.lang.ClassLoader.defineClass(ClassLoader.java:763) ~[na:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_201]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_201]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_201]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_201]
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:535) ~[spring-core-5.2.4.RELEASE.jar:5.2.4.RELEASE]
... 51 common frames omitted
anyone know what is wrong with this code, thanks in advance.

From the documentation : Supported Pointcut Designators
#target: Limits matching to join points (the execution of methods when
using Spring AOP) where the class of the executing object has an
annotation of the given type.
#within: Limits matching to join points within types that have the
given annotation (the execution of methods declared in types with the
given annotation when using Spring AOP).
Both #target and #within advice types are for the class/type .
The scope of the pointcut is global and when the application starts up it tries to identify all the classes/types with annotation and interferes with unwanted classes , here EmbeddedTomcat related.
For #target and #within advice types to work , try narrowing the scope by adding a scoping designator as follows
#Before("#target(com.example.demo.aop.MethodInterceptAnnotation) && within(com.example.demo..*)")
For me , narrowing the scope have always worked , but have come across SO questions where that too did not help. In that case , resolution for your issue is available in this answer from #kriegaex.
Please go through the answer and comments to understand the difference when #annotation is used. To summarize , advice types #target and #within when used , tends to create proxies for all classes irrespective if the annotation is present or not at class level.
Hope this helps.

Related

spring-aop On apple silicon (M1) : Illegal method name

My working project uses kotlin + spring-boot.
I found this issue when I try to run a test case having space like should success WHEN setting key is api updatable on the MacBook apple-m1 machine.
Example
#Test
#Transactional
fun `should success when setting key is api updatable`()
Then JVM throw Exception that contains stack trace looks like this
Caused by: java.lang.ClassFormatError: Illegal method name "should success when setting key is api updatable" in class com/xxx/xxx/web/rest/CompanySettingResourceIntTest$$EnhancerBySpringCGLIB$$f0902682
This happens on my MacBook m1 machine but never happens on the intel machine.
I try to investigate this issue, then I found when using #Transactional on the method in bean, spring-aop will create a proxy class by using method java.lang.ClassLoader.defineClass.
I have a lot of methods that look like this and it's easy to read. Can I use a method name that contains space run in the m1 machine, How do I fix it?
Thank you.
Environment
JDK version 1.8 (AArch64)
Spring boot 1.5.16
JUnit 4
(I try to POC using spring-boot2+JUnit5 test-case name contains space is fine. But a method in beans throws the Illegal method name too.)
JUnit log (Run test)
Could not generate CGLIB subclass of class com.xxx.xxx.web.rest.CompanySettingResourceIntTest: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class com.xxx.xxx.web.rest.CompanySettingResourceIntTest: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:204)
at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:109)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:466)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:349)
at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:298)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:421)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1635)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:398)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:119)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.boot.test.autoconfigure.SpringBootDependencyInjectionTestExecutionListener.prepareTestInstance(SpringBootDependencyInjectionTestExecutionListener.java:44)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at org.junit.vintage.engine.execution.RunnerExecutor.execute(RunnerExecutor.java:40)
at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193)
at java.util.Iterator.forEachRemaining(Iterator.java:116)
at java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1801)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485)
at org.junit.vintage.engine.VintageTestEngine.executeAllChildren(VintageTestEngine.java:80)
at org.junit.vintage.engine.VintageTestEngine.execute(VintageTestEngine.java:71)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:92)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$100(JUnitPlatformTestClassProcessor.java:77)
at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:73)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
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:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.stop(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:131)
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:498)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:155)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:137)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:404)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345)
at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
at org.springframework.cglib.proxy.Enhancer.createClass(Enhancer.java:337)
at org.springframework.aop.framework.ObjenesisCglibAopProxy.createProxyClassAndInstance(ObjenesisCglibAopProxy.java:55)
at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:201)
... 73 more
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.GeneratedMethodAccessor82.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:459)
at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:336)
... 86 more
Caused by: java.lang.ClassFormatError: Illegal method name "should success when setting key is api updatable" in class com/xxx/xxx/web/rest/CompanySettingResourceIntTest$$EnhancerBySpringCGLIB$$f0902682
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(ClassLoader.java:756)
... 91 more
You might be hitting Spring issue #21674 which was fixed in Spring 5.1. You might want to upgrade, if that is an option. It seems there is a fix which ignores those kinds of methods. If that is OK for you or not, I do not know.
Some background information: Your target method is transactional, so Spring tries to create a CGLIB proxy for it. I quickly verified in a simple Spock (Groovy) test that CGLIB seems to be unable to handle methods containing spaces correctly -probably because it is simply unaware of languages like Groovy and Kotlin which allow such things. Here is a proof of concept. I used Groovy and Spock, because I am lazy and did not want to set up a Kotlin project. But I am expecting the result to be identical.
Java class under test:
package de.scrum_master.stackoverflow.q70654015;
public class SampleJava {
public String greet(String input) {
return "Hello " + input + "!";
}
}
Groovy class under test:
package de.scrum_master.stackoverflow.q70654015
class SampleGroovy {
String "say hello to"(String input) {
"Hello $input!"
}
}
Spock test creating CGLIB proxies:
package de.scrum_master.stackoverflow.q70654015
import net.sf.cglib.proxy.Enhancer
import net.sf.cglib.proxy.MethodInterceptor
import spock.lang.Specification
class CGLIBProxyTest extends Specification {
def "create CGLIB proxy for Java class"() {
given:
Enhancer enhancer = new Enhancer()
enhancer.superclass = SampleJava
enhancer.callback = { obj, method, args, proxy ->
method.getDeclaringClass() != Object.class && method.getReturnType() == String.class
? "Hello cglib!"
: proxy.invokeSuper(obj, args)
} as MethodInterceptor
when:
SampleJava proxy = enhancer.create()
then:
proxy.greet("world") == "Hello cglib!"
}
def "create CGLIB proxy for Groovy class with spaces in method name"() {
given:
Enhancer enhancer = new Enhancer()
enhancer.superclass = SampleGroovy
enhancer.callback = { obj, method, args, proxy ->
method.getDeclaringClass() != Object.class && method.getReturnType() == String.class
? "Hello cglib!"
: proxy.invokeSuper(obj, args)
} as MethodInterceptor
when:
SampleGroovy proxy = enhancer.create()
then:
proxy."say hello to"("world") == "Hello cglib!"
}
}
The first test passes, the second one fails with:
net.sf.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:345)
at net.sf.cglib.proxy.Enhancer.generate(Enhancer.java:492)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:93)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:91)
at net.sf.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at net.sf.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61)
at net.sf.cglib.core.internal.LoadingCache.get(LoadingCache.java:34)
at net.sf.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:116)
at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:291)
at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:480)
at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:305)
at de.scrum_master.stackoverflow.q70654015.CGLIBProxyTest.create CGLIB proxy for Groovy class with spaces in method name(CGLIBProxyTest.groovy:36)
Caused by: java.lang.reflect.InvocationTargetException
at net.sf.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:459)
at net.sf.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:336)
... 12 more
Caused by: java.lang.ClassFormatError: Illegal method name "say hello to" in class de/scrum_master/stackoverflow/q70654015/SampleGroovy$$EnhancerByCGLIB$$ef703cf1
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
... 14 more
This is the same error you experieced. As soon as you rename the Groovy method to something which is legal in a JVM, the test passes.
With regard to your claim that the behaviour is supposed to be dependent on the hardware or OS platform, I disagree. I think you probably have differences in your runtime environment. How are you building and running your project? Maven, Gradle, something else?
Update: I have good news for you: I had run my test on JDK 8 and 15 and cglib:cglib-nodep:3.2.6. When upgrading to CGLIB 3.3.0, the test started passing. So you might want to version-manage CGLIB in your Maven POM's <dependencyManagement> section (or whatever is Gradle's equivalent) to that version. Maybe it helps. Please note that some tools might also depend on cglib:cglib, so you want to version-manage that one too. I.e., make sure that you use these versions:
cglib:cglib-nodep:3.3.0
cglib:cglib:3.3.0 (if it is used in your application)
Update 2: I am not a regular Spring user, so I forgot that Spring Core (artifact org.springframework:spring-core) includes its own CGLIB version, relocated to base package name org.springframework.cglib. Please note the package name difference from your stack trace to the original net.sf.cglib for my stand-alone example.
I checked for you and found out that since version 5.2.0.RELEASE, Spring Core was upgraded to CGLIB 3.3.0. So if you can use a Spring version 5.2.0 or more recent, chances are that it works for you.

Spring Boot 2.0.0.M4 throws ConverterNotFoundException on Spring Data REST call

I tried to bump my project up to the most recent Spring Boot 2.0.0 milestone (M4 at the moment of this writing) and I keep getting an exception for a missing Converter (ZonedDateTime to java.util.Date) although it's clearly configured - to me at least. Here's the code and stacktrace:
import org.springframework.core.convert.converter.Converter;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import java.time.ZonedDateTime;
import java.util.Date;
#Component
public class ZonedDateTimePersistenceConverter implements Converter<ZonedDateTime, Date> {
#Nullable
#Override
public Date convert(ZonedDateTime source) {
return Date.from(java.time.ZonedDateTime.now().toInstant());
}
}
When calling the respective Spring Data REST endpoint I get:
2017-09-17 21:07:53.634 ERROR 1894 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.time.ZonedDateTime] to type [java.util.Date]] with root cause
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.time.ZonedDateTime] to type [java.util.Date]
at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:321) ~[spring-core-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:194) ~[spring-core-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:174) ~[spring-core-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.data.rest.webmvc.HttpHeadersPreparer.lambda$getLastModifiedInMilliseconds$5(HttpHeadersPreparer.java:123) ~[spring-data-rest-webmvc-3.0.0.RC3.jar:na]
at java.util.Optional.map(Optional.java:215) ~[na:1.8.0_131]
at org.springframework.data.rest.webmvc.HttpHeadersPreparer.getLastModifiedInMilliseconds(HttpHeadersPreparer.java:123) ~[spring-data-rest-webmvc-3.0.0.RC3.jar:na]
at org.springframework.data.rest.webmvc.HttpHeadersPreparer.prepareHeaders(HttpHeadersPreparer.java:83) ~[spring-data-rest-webmvc-3.0.0.RC3.jar:na]
at org.springframework.data.rest.webmvc.ResourceStatus.getStatusAndHeaders(ResourceStatus.java:71) ~[spring-data-rest-webmvc-3.0.0.RC3.jar:na]
at org.springframework.data.rest.webmvc.RepositoryEntityController.lambda$getItemResource$3(RepositoryEntityController.java:337) ~[spring-data-rest-webmvc-3.0.0.RC3.jar:na]
at java.util.Optional.map(Optional.java:215) ~[na:1.8.0_131]
at org.springframework.data.rest.webmvc.RepositoryEntityController.getItemResource(RepositoryEntityController.java:333) ~[spring-data-rest-webmvc-3.0.0.RC3.jar:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_131]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_131]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_131]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_131]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:209) ~[spring-web-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136) ~[spring-web-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:102) ~[spring-webmvc-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:869) ~[spring-webmvc-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:775) ~[spring-webmvc-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:981) ~[spring-webmvc-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:915) ~[spring-webmvc-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:978) ~[spring-webmvc-5.0.0.RC4.jar:5.0.0.RC4]
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:870) ~[spring-webmvc-5.0.0.RC4.jar:5.0.0.RC4]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:855) ~[spring-webmvc-5.0.0.RC4.jar:5.0.0.RC4]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
...
I've already done some research like debugging and inspecting the GenericConversionService, DefaultConversionService, manually adding it to the converter registry via WebMvcConfigurerAdapter... to no avail.
Any idea where I should look further or what's going here?
Thanks a lot in advance! :)
Edit 1: Additional information to what I've tried and where it's happening. Adding the converter manually didn't help, like so:
#Component
public class AdditionalConverterConfig extends WebMvcConfigurerAdapter {
#Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new ZonedDateTimePersistenceConverter());
}
}
Funnily, the error occurs when I try to access the URI to one of the entities exposed via a Spring Data REST repository (entity is called "Posting", btw), like so:
#RepositoryRestResource(collectionResourceRel = "postings", path = "postings")
public interface PostingRepository extends PagingAndSortingRepository<Posting, Long> {
}
A GET for /api/postings works just fine, listing the first collection page as expected. GET /api/postings/1 however does not. The only critical ZonedDateTime properties in the entity are from its mapped superclass:
#CreatedDate
protected ZonedDateTime createdAt;
#LastModifiedDate
protected ZonedDateTime modifiedAt;
In the listing they appear just fine - in the detail view... not so much ;)

EhCache No serializer found

I am initializing my cache in the following way:
CacheManager cacheManager;
cacheManager = CacheManagerBuilder.newCacheManagerBuilder().build();
cacheManager.init();
Cache<String, SmsMessageDto> myCache = cacheManager.createCache("myCache", CacheConfigurationBuilder.newCacheConfigurationBuilder(String.class, SmsMessageDto.class)
.withExpiry(Expirations.timeToLiveExpiration(new Duration(cacheDuration, TimeUnit.MINUTES)))
.build());
Which gives me the following warning:
org.ehcache.core.EhcacheManager - Could not create serializers for myCache
org.ehcache.spi.serialization.UnsupportedTypeException: No serializer found for type 'com.example.dto.SmsMessageDto'
at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider$AbstractProvider.getClassFor(DefaultSerializationProvider.java:271) ~[ehcache-3.0.0.rc1.jar:3.0.0.rc1]
at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider$TransientProvider.createSerializer(DefaultSerializationProvider.java:149) ~[ehcache-3.0.0.rc1.jar:3.0.0.rc1]
at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider$AbstractProvider.createValueSerializer(DefaultSerializationProvider.java:239) ~[ehcache-3.0.0.rc1.jar:3.0.0.rc1]
at org.ehcache.impl.internal.spi.serialization.DefaultSerializationProvider.createValueSerializer(DefaultSerializationProvider.java:96) ~[ehcache-3.0.0.rc1.jar:3.0.0.rc1]
at org.ehcache.core.EhcacheManager.getStore(EhcacheManager.java:455) [ehcache-3.0.0.rc1.jar:3.0.0.rc1]
at org.ehcache.core.EhcacheManager.createNewEhcache(EhcacheManager.java:308) [ehcache-3.0.0.rc1.jar:3.0.0.rc1]
at org.ehcache.core.EhcacheManager.createCache(EhcacheManager.java:261) [ehcache-3.0.0.rc1.jar:3.0.0.rc1]
at org.ehcache.core.EhcacheManager.createCache(EhcacheManager.java:240) [ehcache-3.0.0.rc1.jar:3.0.0.rc1]
at at.xcard.helper.SmsFailedCache.init(SmsFailedCache.java:45) [classes/:na]
at at.xcard.SmsWorker.<init>(SmsWorker.java:49) [classes/:na]
at at.xcard.Main.main(Main.java:36) [classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147) [idea_rt.jar:na]
How can I convince EhCache to use my toString method of the com.example.dto.SmsMessageDto object?
In short it is not possible. You have to implement Serializable interface in your class SmsMessageDto. It will create a serializer for your Serializable class and the Exception will not display again. This answer was based in the following link http://www.ehcache.org/documentation/3.1/serializers-copiers.html section Bundled implementations.
From the documentation:
By default, cache managers are pre-configured with specially optimized
Serializer that can handle the following types, in the following
order:
java.io.Serializable
java.lang.Long
java.lang.Integer
java.lang.Float
java.lang.Double
java.lang.Character
java.lang.String
byte[]
Given that you are not using the offheap or disk tier, there is no requirement for a serializer.
Now I see you are using version 3.0.0.rc1. I would strongly recommend not using an RC at this point and instead use the latest (at this time) 3.1.2.
I believe what you are experiencing is a bug that has most likely been fixed since then.

Could not load TestContextBootstrapper - spring-boot integration testing error for non-web application

I am using spring-boot schedular based out of a gradle project. The scheduler runs fine when I run through the main class under src/main/java (either using debugger or by executing the spring-boot jar). The For integration testing - i created a new integrationTest directory parallel to java.
For integration test, the class that i created is as follows.
---------------
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootApplication
#ContextHierarchy({
#ContextConfiguration(name = "testContext", classes = ConfigCommons.class, loader = SpringApplicationContextLoader.class),
})
#TestPropertySource("classpath:integrationtest.properties")
//#IntegrationTest
public class IntegrationUseCase {
BeanA beana;
BeanB beanb;
#Before
public void setup() {
beana = new BeanA();
beanb = new BeanB();
}
#Test
public void testUseCase() {
// logic that uses beanA and beanB
}
}
---------------
Have following questions:
1. I have not leveraged autowired. Is there a way I can do that?
2. While buiding the project - Getting an error that TestContextBootstrapper cannot be loaded. I am using the following spring-boot packages-
"org.springframework.boot:spring-boot-starter-test:1.4.0.RELEASE". However, when I commented out this test class, the project buolds and runs fine. Does anyone know what is happening here?
The log is:
java.lang.IllegalStateException: Could not load TestContextBootstrapper [null]. Specify #BootstrapWith's 'value' attribute or make the default bootstrapper class available.
at org.springframework.test.context.BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.java:143)
at org.springframework.test.context.TestContextManager.<init>(TestContextManager.java:105)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTestContextManager(SpringJUnit4ClassRunner.java:152)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.<init>(SpringJUnit4ClassRunner.java:143)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at org.junit.internal.builders.AnnotatedBuilder.buildRunner(AnnotatedBuilder.java:104)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:86)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:26)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:59)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:33)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:88)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:56)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:64)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:50)
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:497)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:106)
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:497)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)
at org.gradle.messaging.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.messaging.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:360)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)
at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NoSuchMethodError: org.springframework.core.annotation.AnnotatedElementUtils.findAllMergedAnnotations(Ljava/lang/reflect/AnnotatedElement;Ljava/lang/Class;)Ljava/util/Set;
at org.springframework.test.context.BootstrapUtils.resolveExplicitTestContextBootstrapper(BootstrapUtils.java:150)
at org.springframework.test.context.BootstrapUtils.resolveTestContextBootstrapper(BootstrapUtils.java:126)
... 39 more
I had a similar problem. There are problems with the dependencies in the pom.xml file. There could be many reasons for that: a conflict in versions, or conflict declaring the same dependency twice: in the current pom.xml and also in the parent pom.xml, like using different versions.

Junit hibernate-validation error

I'm using Hibernate-validator annotations in my Entities and this causes an exception in my Junit tests.
If I disable the hibernate validation with the property:
<prop key="javax.persistence.validation.mode">none</prop>
Then the Junit test works very well otherwise I receive the following error:
Caused by: java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/el/ExpressionFactory
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClassCond(ClassLoader.java:637)
at java.lang.ClassLoader.defineClass(ClassLoader.java:621)
at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<init>(ResourceBundleMessageInterpolator.java:169)
at org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator.<init>(ResourceBundleMessageInterpolator.java:118)
at org.hibernate.validator.internal.engine.ConfigurationImpl.<init>(ConfigurationImpl.java:110)
at org.hibernate.validator.internal.engine.ConfigurationImpl.<init>(ConfigurationImpl.java:86)
at org.hibernate.validator.HibernateValidator.createGenericConfiguration(HibernateValidator.java:41)
at javax.validation.Validation$GenericBootstrapImpl.configure(Validation.java:276)
at javax.validation.Validation.buildDefaultValidatorFactory(Validation.java:110)
at org.hibernate.cfg.beanvalidation.TypeSafeActivator.getValidatorFactory(TypeSafeActivator.java:445)
at org.hibernate.cfg.beanvalidation.TypeSafeActivator.activate(TypeSafeActivator.java:96)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.hibernate.cfg.beanvalidation.BeanValidationIntegrator.integrate(BeanValidationIntegrator.java:148)
... 61 more
The JUnit test:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:spring-config-test.xml")
#Transactional
public class BaseTest {
#Test
public void init () {
Assert.assertEquals(15,15);
}
}
Any suggestion?
Caused by: java.lang.ClassFormatError: Absent Code attribute ...
indicates that you use an jar that contains only the class and method signatures but not the method implementation.
Often is cause is that one use javaee-api.jar from http://download.java.net/maven/2/.
Remove this jar! (and when needed, replace it with the right jars that contains the code)
#See http://www.mkyong.com/hibernate/java-lang-classformaterror-absent-code-attribute-in-method-that-is-not-native-or-abstract-in-class-file/

Resources