Gradle integration test produces java.lang.NoClassDefFoundError - java

I am migrating multi-module Gradle Java project from Gradle 4.10 to Gradle 6.3.
Project structure looks like the following:
├── build.gradle
├── our-webapp
│   ├── build.gradle
│ └── src
│ ├── main
│ ├── integrationTest
│ └── test
└── cli-util
├── build.gradle
└── src
├── main
├── integrationTest
└── test
cli-util has a dependency on webapp to use it's classes.
build.gradle looks like:
plugins {
id 'java'
}
sourceSets {
integrationTest {
compileClasspath += sourceSets.main.output + sourceSets.test.output
runtimeClasspath += sourceSets.main.output + sourceSets.test.output
java.srcDir 'src/integrationTest/java'
resources.srcDir 'src/integrationTest/resources'
}
}
configurations {
integrationTestImplementation.extendsFrom testImplementation
integrationTestRuntime.extendsFrom testRuntime
}
dependencies {
implementation project(':our-webapp')
}
task integrationTest(type: Test) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
}
And now what is interesting is that tests under cli-util/src/intergrationTest are working fine in Intellij IDEA but they are failing from terminal whenever there is an import of a class defined in webapp project. The error is java.lang.NoClassDefFoundError: com/example/web/SomeClass.
I tried different approaches already, including the use of java-library plugin in cli-util project and importing webapp project like api project(':our-webapp') but it still fails.
Same issue in Gradle 5.6.x.
Is there some special change I have take into account to make it work?

Related

Multiple gradle versions

I have a java project in Visual Studio Code with some subprojects:
javaProject
├── README.md
├── build.gradle
├── chronos
│ ├── build.gradle
│ ├── settings.gradle
│ ├── src
├── crate-generator-strategy
│ ├── build.gradle
│ └── src
├── dafne
│ ├── build.gradle
│ ├── settings.gradle
│ └── src
├── gradle.properties
├── hermes
│ ├── build.gradle
│ ├── settings.gradle
│ ├── src
├── meti
│ ├── build.gradle
│ ├── settings.gradle
│ └── src
└── settings.gradle
Under the main dir javaProject there's a dir called .gradle and in that I have different versions of gradle (i.e. 6.4, 7.1.1, 7.4.1)
In my system I have only the 7.4.1 version installed.
------------------------------------------------------------
Gradle 7.4.1
------------------------------------------------------------
Build time: 2022-03-09 15:04:47 UTC
Revision: 36dc52588e09b4b72f2010bc07599e0ee0434e2e
Kotlin: 1.5.31
Groovy: 3.0.9
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 17.0.2 (Homebrew 17.0.2+0)
OS: Mac OS X 12.1 x86_64
If I delete the dir, it suddenly reappear with all the versions.
Why there are many versions and not the installed one?
How could I get rid of the old ones?
Thanks,
S.

Annotation proccessor configuration from a Gradle multi module build in IntelliJ 2019.3 seems not to work correctly

I have a Gradle multi module project that uses the Mapstruct annotation processor for data type mapping across Java modules. The Gradle build works fine but when I import the project into IntellJ IDEA 2019.3 I get an unexpected annotation processor configuration.
The project structure looks like this
.
├── build.gradle
├── module1
│   └── src
│   └── main
│   └── java
│   └── io
│   └── wangler
│   └── mapstruct
│   ├── ApplicationModule1.java
│   ├── Person.java
│   ├── PersonDTO.java
│   └── PersonMapper.java
├── module2
│   └── src
│   └── main
│   ├── generated
│   │   └── ch
│   │   └── silviowangler
│   │   └── mapstruct
│   │   └── CarMapperImpl.java
│   └── java
│   └── ch
│   └── silviowangler
│   └── mapstruct
│   ├── ApplicationModule2.java
│   ├── Car.java
│   ├── CarDTO.java
│   └── CarMapper.java
└── settings.gradle
and the build.gradle that registers the annotation processor for module1 and module2.
subprojects { p ->
apply plugin: 'java-library'
apply plugin: 'groovy'
repositories {
jcenter()
}
dependencies {
annotationProcessor 'org.mapstruct:mapstruct-processor:1.3.1.Final'
implementation 'org.mapstruct:mapstruct:1.3.1.Final'
testImplementation 'org.codehaus.groovy:groovy-all:2.5.8'
testImplementation 'org.spockframework:spock-core:1.3-groovy-2.5'
testImplementation 'junit:junit:4.12'
}
}
When I compile the project using ./gradlew compileJava all works out fine and I get no compilation errors.
But when I run Rebuild Project withing IntelliJ I get a compilation error in module1 since IntelliJ does not have an annotation processor registered for module1.
Error:(6, 35) java: cannot find symbol
symbol: class PersonMapperImpl
location: class io.wangler.mapstruct.ApplicationModule1
Am I doing something wrong here or is this a known IntelliJ issue? The source code for this example can be found at https://github.com/saw303/idea-annotation-processors
I faced the same issue in IDEA 2019.3. Looks like a bug.
It occurs only if two modules has the same set of annotation processors.
To solve the problem you need to add any library using annotationProcessor directive to one of modules. It does not have to be a real annotation processor. This one is working for me:
annotationProcessor "commons-io:commons-io:${commonsIoVersion}"
I have created a defect in JerBrains bugtracker: IDEA-230337

Run java application on Tomcat with Gradle

I have a project structure as follows:
└── src
├── main
│   ├── java
│   │   ├── MessageServlet.java
│   └── webapp
│       ├── META-INF
│       │   └── context.xml
│       ├── WEB-INF
│       │   └── web.xml
│       ├── index.html
│       └── style.css
└── test
└── java
I also have a tomcat server which I run using the gradle below. The tomcat server starts and displays the index.html page. But, when I try to run the servlet i get following error message:
HTTP Status 500 - Error instantiating servlet class MessageServlet
build.gradle
buildscript {
repositories {
jcenter()
mavenCentral()
}
dependencies {
classpath 'com.bmuschko:gradle-tomcat-plugin:2.2.4'
}
}
apply plugin: 'com.bmuschko.tomcat'
apply plugin: 'war'
apply plugin: 'idea'
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'org.mongodb:mongo-java-driver:3.3.0'
compile 'com.google.code.gson:gson:2.2.4'
def tomcatVersion = '8.0.42'
tomcat "org.apache.tomcat.embed:tomcat-embed-core:${tomcatVersion}",
"org.apache.tomcat.embed:tomcat-embed-logging-juli:${tomcatVersion}",
"org.apache.tomcat.embed:tomcat-embed-jasper:${tomcatVersion}"
}
QUESTION
I want to run the project on my tomcat server via this gradle. How do I make the gradle execute MessageServlet.java together with tomcat?

where does jitpack download build artifacts to?

This hello world project runs fine, but where is the hello_api-latest.jar file? (Regardless that the client doesn't actually "need" the JAR, it should still download.)
The JAR is on the classpath:
thufir#mordor:~/NetBeansProjects/hello_client$
thufir#mordor:~/NetBeansProjects/hello_client$ gradle clean build;java -jar build/libs/hello_client.jar
:clean
:compileJava
:processResources UP-TO-DATE
:classes
:jar
:startScripts
:distTar
:distZip
:assemble
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:test UP-TO-DATE
:check UP-TO-DATE
:build
BUILD SUCCESSFUL
Total time: 1.229 secs
hello world
thufir#mordor:~/NetBeansProjects/hello_client$
thufir#mordor:~/NetBeansProjects/hello_client$ jar -xf build/libs/hello_client.jar
thufir#mordor:~/NetBeansProjects/hello_client$
thufir#mordor:~/NetBeansProjects/hello_client$ cat META-INF/MANIFEST.MF
Manifest-Version: 1.0
Main-Class: net.bounceme.mordor.Main
Class-Path: hello_api-latest.jar
thufir#mordor:~/NetBeansProjects/hello_client$
thufir#mordor:~/NetBeansProjects/hello_client$ tree build
build
├── classes
│   └── main
│   └── net
│   └── bounceme
│   └── mordor
│   └── Main.class
├── dependency-cache
├── distributions
│   ├── hello_client.tar
│   └── hello_client.zip
├── libs
│   └── hello_client.jar
├── scripts
│   ├── hello_client
│   └── hello_client.bat
└── tmp
├── compileJava
│   └── emptySourcePathRef
└── jar
└── MANIFEST.MF
13 directories, 7 files
thufir#mordor:~/NetBeansProjects/hello_client$
build file:
apply plugin: 'java'
apply plugin: 'application'
sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
if (!hasProperty('mainClass')) {
ext.mainClass = 'Main'
}
mainClassName = 'net.bounceme.mordor.Main'
repositories {
mavenCentral()
maven { url "https://jitpack.io" }
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.10'
compile 'com.github.THUFIR:hello_api:latest'
}
jar {
manifest {
attributes ('Main-Class': 'net.bounceme.mordor.Main',
"Class-Path": configurations.compile.collect { it.getName() }.join(' '))
}
}
Notably, the jitpack dependency doesn't show in Netbeans:
The build artifact at the end of the log would seem to indicate that the JAR, hello_api-latest.jar, was found:
latest
commit 244c611ae48dc95daee544fbfb5767ae1f961e10
Author: thufir
Date: Fri Feb 5 05:39:47 2016 -0800
increment
submodule status:
Run gradle build
Gradle build script
WARNING: Gradle wrapper not found. Please add. Using default gradle to build.
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
------------------------------------------------------------
Gradle 2.7
------------------------------------------------------------
Build time: 2015-09-14 07:26:16 UTC
Build number: none
Revision: c41505168da69fb0650f4e31c9e01b50ffc97893
Groovy: 2.3.10
Ant: Apache Ant(TM) version 1.9.3 compiled on December 23 2013
JVM: 1.8.0_60 (Oracle Corporation 25.60-b23)
OS: Linux 3.14.32-xxxx-grs-ipv6-64 amd64
0m0.684s
Getting a list of gradle tasks
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
Found javadoc task
WARNING:
Gradle 'install' task not found. Please add the 'maven' or 'android-maven' plugin.
See the documentation and examples: https://jitpack.io/docs/
Looking for android-library
Looking for com.android.application
Adding maven plugin
Running: gradle clean -Pgroup=com.github.THUFIR -Pversion=latest -xtest install
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
:clean UP-TO-DATE
:compileJava
Download https://repo1.maven.org/maven2/org/codehaus/groovy/groovy-all/2.4.1/groovy-all-2.4.1.pom
Download https://repo1.maven.org/maven2/org/codehaus/groovy/groovy-all/2.4.1/groovy-all-2.4.1.jar
:processResources UP-TO-DATE
:classes
:jar
:install
BUILD SUCCESSFUL
Total time: 1.883 secs
Gradle exit code 0
Looking for artifacts...
Picked up JAVA_TOOL_OPTIONS: -Dfile.encoding=UTF-8
Found artifact: com.github.THUFIR:hello_api:latest
EXIT_CODE=0
2016-03-10T09:47:34.133966887Z
Exit code: 0
Build artifacts:
com.github.THUFIR:hello_api:latest
Files:
com/github/THUFIR/hello_api/latest
com/github/THUFIR/hello_api/latest/build.log
com/github/THUFIR/hello_api/latest/hello_api-latest.jar
com/github/THUFIR/hello_api/latest/hello_api-latest.pom
com/github/THUFIR/hello_api/latest/hello_api-latest.pom.md5
com/github/THUFIR/hello_api/latest/hello_api-latest.pom.sha1
but where was it downloaded to?
see also:
https://stackoverflow.com/a/22724504/262852
https://stackoverflow.com/a/30094915/262852
https://stackoverflow.com/a/34329145/262852
UPDATE
here it is:
thufir#mordor:~$
thufir#mordor:~$ tree .gradle/ | grep latest
│   │   │   └── latest
│   │   │   │   └── hello_api-latest.pom
│   │   │   └── hello_api-latest.jar
│   │   │   │   └── latest
│   │   │   │   └── latest
thufir#mordor:~$
As with any external dependency, it is downloaded to the gradle cache. The default location is ~/.gradle

import JPA Model from gradle sub-project in Spring

In an android project, I want to use a shared model library with the REST Server(JPA)
Project structure:
├── android
│ └ ...
│
├── model
│   ├── build.gradle
│   └── src
│   └── com
│   └── model // error at runtime
│   └── Customer.java
├── server
│   ├── build.gradle
│   └── src
│   └── com
│   └── server
│   ├── Application.java
│   ├── CustomerController.java
│   ├── CustomerRepository.java
│   └── model // works fine
│   └── Customer.java
├── build.gradle
I am using gradle sub-projects to manage the dependency which works fine at compile time.
But when I run the Application, Spring can't resolve the JPA annotations.
When I move the model class to the server project, it works fine.
Exception in thread "main" org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'requestMappingHandlerMapping' defined in class path resource [...] Instantiation of bean failed;
[...]
Not an managed type: class com.model.Customer
root build.gradle
buildscript { ... }
allprojects {
repositories {
mavenCentral()
}
}
project(":android") { ... }
project(":model") {
apply plugin: "java"
}
project(":server") {
apply plugin: "java"
dependencies {
compile project(":model")
}
}
Is there a solution to include JPA models from a gradle sub-project ?
The reason is mostly to prevent duplicate code between the android and server appication
You Customer entity will not be found by default because it is not in a sub-pacakge of your Application class. Try using the #EntityScan annotation (see http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-separate-entity-definitions-from-spring-configuration).

Categories