Spring boot testing : NoClassDefFound exception - spring-boot

I'm using the latest version of Spring boot and an old test fails.
I'm having
Caused by: java.lang.IllegalStateException: Failed to introspect annotated methods on class
Caused by: java.lang.NoClassDefFoundError: MyClass
My config is
spring boot 2.7.2
gradle 7.5
a structure using idiomatic gradle (multiproject and composite build)
The subproject failing is the spring-boot-application. The class not found exists inside the src/main/java
The test failing is under src/test/java, annotated with
#SpringJUnitConfig(classes = ApplicationServiceAspectTestConfigSuccessListener.class) because it is using #Inject fields.
I understand it is not perfect (unit testing depending on injection ; prefer integration test)
When I debug this test, the classloader tries to use a JarLoader and searches inside the spring-boot-application-default.jar. The jar structure is BOOT-INF / META-INF / org... The class not found is inside the BOOT-INF/classes/org/xxxx. The jar loader failed :/
My question is : why searching inside the jar and not the build/classes/org/xxx ? and why is the JarLoader not finding the class ?
Update 1
I think I have a lead. I created a gradle precompiles quality plugins which uses java-text-fixtures. When enable the java-text-fixtures produces two jars and the problem comes from here.
I don't really understand why for the moment (why 2 jars and not only the text-fixtures one).
Update 2
Ok seems I ran across https://github.com/gradle/gradle/issues/11696

Related

How to include a standalone jar that uses spring and beans as a dependency in maven project for jenkins plugin?

I want to include a standalone jar file (which uses spring), inside my java code to develop a jenkins plugin. When I add this as a dependency and I run the plugin ,I get errors like: Caused: org.springframework.beans.factory.BeanDefinitionStoreException: IOException parsing XML document from class path resource [com/XXX/YYY/jmsclient3/XXXclient-jms-config.xml]
It says cant find the class path resource [com/XXX/YYY/jmsclient3/XXXclient-jms-config.xml], because it doesnt exist.
But this file is clearly there in the jar. Its a bean file(I dont know much about it).

my application.properties from dependency is not available in spring boot application

I have spring boot application.
In this spring boot (fat-jar) application I have classpath:config/application.properties and classpath:application-env.properties.
I am starting this application using command:
java -Dspring.profiles.active=env -jar application.jar --some-parameter=some-value
Question: Why application.properties file is not available during initialization this application from classes (beans) localized in my dependency?
This file (application.properties) is localized in classpath:application.properties of my dependency.
I am expecting some properties with some specific prefix - using annotation:
#ConfigurationProperties(prefix = "someprefix")
and again the same in other words:
Application A have classpath:config/application.properties
+ Application A have/is using dependency to some artifact D
dependency (jar) D.jar have classpath:application.properties
this application.properies is not available during initialization of bean B with annotatin #ConfigurationProperties(prefix = "someprefix")
according to 24.3 Application property files "The classpath root" should be fine - but it is not.
This is fat-jar application - in one big jar we have everything - including folder 'lib' with all dependencies.
OK, :(
solution of my issue was trivial. My application was loading different classpath:/application.properites than I thought.
I had another dependency jar introduced to my project not-directly (it was dependency for my dependency) which contains different classpath:/application.properites.
In other words everything works fine but only one 'classpath:/application.properties' is loaded even you have two in two different dependencies.
I used /actuator/env to find out which classpath:/application.dependency was loaded.

Why isn't this jar packaging valid for Spring Boot?

I am trying to understand the packaging of Spring Boot into "fat" jars. From what I know "fat" jars have their own special classes that load up the main class when the jar is running and also sets the classpath accordingly.
What I cannot understand is why when I use Eclipse to extract all my dependencies into a folder structure in the jar, the jar no longer runs as a correct Spring Boot application.
To repeat what I have done here just take a simple Spring Boot app and from Eclipse select the following-:
Export --> Runnable Jar --> Select Main Class --> Extract required libraries into jar.
Just run the jar from the command line as you would any jar. Spring Boot initially starts up but fails with the following message-:
2017-05-02 22:06:40.484 WARN 3468 --- [ main]
ationConfigEmbeddedWebA pplicationContext : Exception encountered
during context initialization - cancel ling refresh attempt:
org.springframework.beans.factory.BeanDefinitionStoreExcep tion:
Failed to process import candidates for configuration class
[com.main.Test Main]; nested exception is
java.lang.IllegalArgumentException: No auto configuration classes
found in META-INF/spring.factories. If you are using a custom packa
ging, make sure that file is correct.
Can I somehow edit the spring.factories file to include my classses ?
I just trying to understand how Spring actually packages the files through its Maven plugin.
I think that because it's a Spring Boot application, you need to use their plugin for building. It is because, spring Boot has its own jar loading mechanism for that (the BOOT-INF introduction in Spring Boot 1.4).
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
From documentation:
The Spring Boot Maven Plugin provides Spring Boot support in Maven, allowing you to package executable jar or war archives and run an application “in-place”.
Link to documetantion (Appendix E)
Something about spring.factories and locating auto-configuration candidates - Auto-configuration

Spring Boot 1.4.3 Embedded Tomcat NoSuchMethodError StringManager.getManager

I have update my project to use Spring BOOT 1.4.3. The code compiles and runs without issues from Eclipse Neon 1.
But when I run from command line
mvn clean install -DskipTests
java -jar myweb\target\my-web-1.0-SNAPSHOT.jar
I get runtime error and tomcat is not starting
Caused by: java.lang.NoSuchMethodError: org.apache.tomcat.util.res.StringManager.getManager(Ljava/lang/Class;)Lorg/apache/tomcat/util/res/StringManager;
at org.apache.catalina.util.LifecycleBase.<clinit>(LifecycleBase.java:43) ~[tomcat-embed-core-8.5.6.jar!/:8.5.6]
Please can you tell why? How to find which tomcat is used at runtime, as my understand is that 8.5.6 is having compile scope(?)
Please help. If the suggestion is to use tomcat.version in properties of POM file or add tomcat-juli dependency, then please help me understand why it is required?
Impatient stackoverflow'ers dont just flog new comers only because you can do. You can easily ask if you want my POM, but I used just spring-boot-starter-web thats it.
For this kind of problem, it's often due to multiple jar having the same class inside your classpath, so :
Find where this class / method could come from, by opening the type popup (CTRL + SHIFT + T in Eclipse). It will display you every jar in your classpath that contains the class.
Open the class in each jar to see which one contains your method and which one don't.
Display the dependency hierarchy of your project with mvn dependency:tree
If the 2 jars are in your classpath, you might exclude the one that don't contain the method.

Eclipselink Static Weaving and Spring Boot is not Working

In a Spring Boot project we use Eclipselink as ORM. We configured the build to weave statically and to package as jar. The interesting thing is that starting the program with mvn spring-boot:run works without problem, but starting with java -jar archive.jar works only if all entities are listed in the persistence.xml. Without having the class in the persistence.xml I get the error:
java.lang.IllegalArgumentException: No [ManagedType] was found for the key class [eltest.Customer] in the Metamodel - please verify that the [Managed] class was referenced in persistence.xml using a specific <class>eltest.Customer</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element
Also in the case, when we package the program as war, it starts without issues.
My questions are: Does the mvn spring-boot:runinvoke the static weaving at all, or does it weave at load-time? The same with the war deployment: does the war-build really invoke the static weaving, or is the weaving implicitly triggered, when the Tomcat starts the app? Is there a way to avoid listing the classes in the persistence.xml, and still go for statical weaving in a jar-packaging?
Here is an example:
https://github.com/gfinger/eltest
Build it with mvn clean package. If you start it with mvn spring-boot:run it uses Spring Data Rest to expose a Customer entity as REST resource. If you start it with java -jar target/static-eclipselink-0.0.1-SNAPSHOT.jar you get an error.

Resources