Spring context not found using groovy classloader - spring

I get a typical error, because the spring context could not be found:
Caused by: org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsingXML document from class path resource nested exception is java.io.FileNotFoundException: class path resource cannot be opened because it does not exist
The class creating the spring context is instantiated in a "strange" way. There's a java process, creating a groovy classloader and adding the required classpath entries (including the jar with the spring context). Using this classloader a groovy script will be executed, which in turn executes a java class creating a spring bean in the static init block. Unfortunately this fails with the above exception.
If the initial java process is called with -cp jarContainingContext it works. The jar containing the spring context, also contains the java class creating the spring context. Thus I'm sure that the jar is in the classpath.
Is it possible the the groovy classloader is different from the one of spring (if there's a seperate one)?
java MyClass -> Creates groovy classloader with all required classpath entries -> runscript -> groovy script -> running java class from a library also containing the spring context -> tries to create the bean within the static initializer -> failure
This whole chain sounds quite strange, it is but I can't really change it. I simply cannot understand where the problem is. Because the java class creating the spring context will be found by the groovy classloader but not the springContext within the same jar. It seems like there are 2 seperate classpaths.

The problem are really the classloaders. SpringBatch has a bug and might use the system classloader. Thus a classloader hell is created.
We issued a pull request to fix the issue.

Related

EnableLoadTimeWeaving annotation causes application context to fail to load

I am trying to enable AspectJ load-time weaving (not Spring AOP) in a Spring Boot application. My goal is to weave advice into annotated fields and java.lang.reflect.Field.set(Object, Object) at load-time.
Per the Spring docs, I tried:
#Configuration
#EnableLoadTimeWeaving
public class Config {}
Running the Spring Boot application with this configuration resulted in the application context failing to load with this message:
Caused by: java.lang.IllegalStateException:
ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader]
does NOT provide an 'addTransformer(ClassFileTransformer)' method.
Specify a custom LoadTimeWeaver or start your Java virtual machine
with Spring's agent: -javaagent:spring-instrument-{version}.jar
The latter suggestion in that message is not a good option as I am trying to avoid necessitating launch script modifications. The aspect I need to weave actually resides in a library, so all implementing Spring Boot projects will have to make whatever changes required to get LTW to work.
I also tried this configuration:
#Configuration
#EnableLoadTimeWeaving
public class Config implements LoadTimeWeavingConfigurer {
#Override
public LoadTimeWeaver getLoadTimeWeaver() {
return new ReflectiveLoadTimeWeaver();
}
}
Running the Spring Boot application with this configuration resulted in the application context failing to load with this message:
Caused by: java.lang.IllegalStateException:
ClassLoader [jdk.internal.loader.ClassLoaders$AppClassLoader]
does NOT provide an 'addTransformer(ClassFileTransformer)' method.
It seems I need to make the JVM use a class loader that has an addTransformer(ClassFileTransformer) method. I don't know how to do that, particularly for this situation. Any suggestions?
I am not an active Spring user, but I know that Spring supports annotation- or XML-configured agent hot-attachment and has some container-specific classes for that according to its documentation. It does not seem to work reliably in all situations, though, especially when running a Spring Boot application from an IDE or so.
Anyway, the AspectJ weaver 1.8.7 and more recent can be hot-attached. I explained how to do that in a Spring setup here. If you want a simpler solution with less boilerplate but one more dependency to a tiny helper library called byte-buddy-agent, you can use this solution as a shortcut. I have not tried it, but I know the helper library and am using it myself in other contexts when hot-attaching bytecode instrumentation agents, avoiding the fuss to cater to different JVM versions and configuration situations. But in order for that to work on JVM 9+, you might need to manually activate auto-attachment for the JVM, which would be another modification for your start-up script, and you would be back to square 1.

Bean scope is generating java.lang.UnsatisfiedLinkError

I have multi module maven project,which has one common module which is being used by other modules. In common module I have few beans(Beans are having singleton scope) that are used by other modules application context. Now the problem is having after using those beans in one module(m1) which was not previously using these beans. Importing the common.xml(Beans are defined here) in Application context of module(m1) generates lot of issue(Cannot find the beans). So I decided to directly use those beans in application context of module(m1). If I keep the scope of beans to singelton , I get java.lang.UnsatisfiedLinkError: no jzmq in java.library.path. This issue is solved by using prototype as scope.
Any idea about this issue.
1 Using native methods make your Java application code platform dependent.
2 The System.loadLibrary method is equivalent as executing the Runtime.getRuntime().loadLibrary method.
3 The System.loadLibrary method shall be used in a static initializer block, in order to be loaded only once, when the JVM loads the class for the first time.

How can I access Spring bean from Message-driven bean in JBoss AS 7

I want to make a call to a Spring bean (a #Component) from my message-driven bean (MDB) but have problems getting a reference to it. I've tried with a class implementing org.springframework.context.ApplicationContextAware which stores the Spring ApplicationContext in a static field in a class MyAppContext. The static field in MyAppContext is then accessed from the MDB. But MyAppContext is loaded from different classloaders. The Spring application context is correctly set in the web module classloader context, but in the MDB's classloader context, it's null.
Can I somehow instruct JBoss to use the same classloader for the web app and the MDB?
Or is there a better way than storing the Spring application context in a static field?
Thanks for any advice!
A static holder for the context is not really a good idea. To make your beans available to other applications in a Java EE environment, you should consider making use of JNDI.
Unfortunately, there is no plain JNDI exporter available out of the box, but it's fairly easy to write one yourself, as shown in this blog post: http://maestro-lab.blogspot.ro/2009/01/how-to-export-spring-managed-bean-to.html
There is however a JndiRmiServiceExporter that you may want to look at.
Once your beans are bound to names in JNDI, they can be referenced using standard CDI in your message bean without worrying about class loading issues.
Why not use "ClassPathXmlApplicationContext" to load and look up for the Spring bean you require in your MBean?

conflicts with existing, non-compatible bean definition of same name and class after proguard obfuscation

after Proguard obfuscation i get the following error :
Unexpected exception parsing XML document from ServletContext resource
[/WEB-INF/applicationContext.xml]; nested exception is
java.lang.IllegalStateException: Annotation-specified bean name 'a'
for bean class [com.company.project.b.a.a.a] conflicts with existing,
non-compatible bean definition of same name and class
[com.company.project.a.a]
i'm using annotation based spring configuration , how can i avoid having two classes with the same name using Proguard because Spring doesn't allow two beans to have the same name.
I'm not sure if this is what you want, but you can specify bean name in #Component (and stereotypes #Repository, #Service and #Controller) value:
#Component("myBeanName")
public class MyBean {
}
I had the same problem and nothing else was helping out. Sometimes the problem occurs if you have moved your classes around and it refers to old classes, even if they don't exist.
In this case, just do this :
mvn eclipse:clean
mvn eclipse:eclipse
This worked well for me.
Another cause; you may have different versions of Spring in your classpath, for example, spring 2.x with spring 3.x. In such condition, beans seem to be loaded twice. If you use maven, check if a module does not import an old version of Spring (mvn dependency:tree) and remove it by excluding the involved spring artifact (exclusions).

Getting Spring Error "Bean named 'x' must be of type [y], but was actually of type [$Proxy]" in Jenkins

I have been debugging this for awhile now, and I'm hoping someone could shed some light here.
I have a Maven project that is added into Jenkins, using JDK 1.6. I'm using AOP in this project to handle the database transaction.
When I run the build in Jenkins, my testcase fails with the following exceptions:-
Caused by: org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'dataHandlerClassificationImpl':
Injection of resource dependencies failed; nested exception is
org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'writerDataLocationImpl' must be of type [xxx.script.WriterData],
but was actually of type [$Proxy17]
...
...
Caused by: org.springframework.beans.factory.BeanNotOfRequiredTypeException:
Bean named 'writerDataLocationImpl' must be of type [xxx.script.WriterData],
but was actually of type [$Proxy17]
...
...
The DataHandlerClassificationImpl class looks something like this:-
#Service
public class DataHandlerClassificationImpl extends DataHandler {
#Resource(name="writerDataLocationImpl")
private WriterData writerData;
...
}
WriterData is an interface with multiple implementations.
I am able to execute the code without problem from the IDE. To determine whether it is a Maven problem or Jenkins problem, I navigated to the Jenkins' project job folder using command line and I'm able to run mvn test without any errors.
I know the proxy error has something to do with AOP, and that I can only autowire to an interface instead of a concrete class... but that's not the case here since I'm able to run my code fine outside Jenkins.
Any ideas? Thanks.
Excerpt from question comments above:
Are you running Cobertura, Sonar or other code-instrumenting tool on Jenkins? Note that mvn site might also be configured to include Cobertura report in generated site.
The problem with Cobertura is that it performs pretty heavy byte-code instrumentation including the addition of some custom interfaces. When Spring starts up it generates proxies for beans. If bean has at least one interface, it uses standard Java proxy. Otherwise it tries to create class-based proxy.
I guess in your case the CGLIB class proxy was used but after Cobertura instrumentation Spring fall back to java proxies. This caused startup error because dependency injection expected class (or CGLIB subclass).
To cut long story short, force CGLIB class proxies and you'll be fine:
<aop:config proxy-target-class="true"/>
Got the same problem using AspectJ.
There was a bean w
#Configuration public class MyConfig{
#Value("classpath:some.properties")
private Resource theResource;
#Bean
public SomeResource getSomeResource()
{
return SomeResource.getOne(theResource);
}
/******/
#Component
public class SomeResource{
public SomeResource(Resource r) {...}
public static getOne(Resource r} { return new SomeResource(r); }
This works fine until AOP/AspectJ is enabled. The injection validates that the SomeResource bean is from class SomeResource, but since it is a Proxy it crashes.
SOlution: use GLIBC proxy for that Bean instead of AspectJ proxies.
#EnableAspectJAutoProxy(proxyTargetClass=false)
public class SomeResource{...}
Makes no sense, but now got a clearer message
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.springframework.cglib.core.ReflectUtils
(file:/path/spring-core/5.2.10.RELEASE/spring-core-5.2.10.RELEASE.jar) to method
java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain)
WARNING: Please consider reporting this to the maintainers of org.springframework.cglib.core.ReflectUtils
Meaning Java prevent reflection on this method.Either Spring or Java needs to fix that.

Resources