I'll first describe the problem, files referenced here can be found below.
I am trying to use an external library in the form of a jar file. This library contains code that I use in my Spring @Configuration
file. As such I have included it as an implementation dependency in my build.gradle
(see code below).
All of the library files are contained in the package com.rusticisoftware.tincan
. My own code resides under de.my.example
.
Leaving the @SpringBootApplication
at its default (which is the same as de.my.example
as this is where the Application.java
class resides works when assembling the project with the Gradle assemble
task. I can then start the project from my IDE and everything works as expected.
However, both when running the Gradle test
task and when executing the bootJar created by spring boot's bootJar
task the following error is thrown:
java.lang.IllegalStateException at DefaultCacheAwareContextLoaderDelegate.java:132
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException at ConstructorResolver.java:798
Caused by: org.springframework.beans.factory.BeanCreationException at ConstructorResolver.java:656
Caused by: org.springframework.beans.BeanInstantiationException at SimpleInstantiationStrategy.java:185
Caused by: java.lang.NoClassDefFoundError at Config.java:29
Caused by: java.lang.ClassNotFoundException at BuiltinClassLoader.java:581
Where Caused by: java.lang.NoClassDefFoundError at Config.java:29
is referencing this line in the code: RemoteLRS lrs = new RemoteLRS();
RemoteLRS
is the class from the jar-library contained in com.rusticisoftware.tincan
.
I was able to rid myself of this error by specifiying the scanBasePackages
in the @SpringBootApplication
annotation like so: @SpringBootApplication(scanBasePackages = {"com.rusticisoftware.tincan"})
. Doing this will however then no longer scan and find MyResource.java
leading the REST service to not load.
To fix this issue, I tried manually adding my own package to @SpringBootApplication
together with the package from the jar, leading to this: @SpringBootApplication(scanBasePackages = {"com.rusticisoftware.tincan", "de.my.example"})
.
This once again loads the REST service, but runs into the same problem as before when running the test
task or executing the jar generated by the bootJar
task. I have also manually inspected the generated bootJar and can confirm that the library jar is included within.
Project structure
Project
|
+-- build.gradle
|
+-- src
| |
| +-- main/java/
| | |
| | +-- de/my/example
| | |
| | +-- Application.java
| | |
| | +-- Config.java
| | |
| | +-- controller
| | |
| | +-- MyResource.java
| +-- test/java/
| |
| +-- de/my/example
| |
| +-- ApplicationTests.java
+-- libs
|
+-- tincan-1.1.0.jar
build.gradle
plugins {
id "java"
id "idea"
id 'org.springframework.boot' version '2.3.0.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}
// project settings
group 'de.my.example'
version '1.0'
sourceCompatibility = 11
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
// spring
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
// tin-can xAPI
implementation files('libs/tincan-1.1.0.jar')
}
test {
useJUnitPlatform()
}
Application.java
@SpringBootApplication(scanBasePackages = {"com.rusticisoftware.tincan", "de.my.example"})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
ApplicationTests.java
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
}
}
TestResource.java
public class TestResource {
private final LearningRecordStore learningRecordStore;
public TestResource(LearningRecordStore learningRecordStore) {
this.learningRecordStore = learningRecordStore;
}
@GetMapping(value = "/ping", produces = MediaType.TEXT_PLAIN_VALUE)
public String ping() {
return "pong";
}
}
Config.java
@Configuration
public class Config {
@Bean
public LearningRecordStore learningData() {
RemoteLRS lrs = new RemoteLRS();
return new LearningRecordStore(lrs);
}
}
The simplest way to check is to explore build file after Gradle build to ensure it's present in build package. This way, you will make sure, it is getting included and should not throw class-not-found exception. Also, you might need to include both the packages in the scanBasePackage.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.