Java jar file won't recognize external libraries added from gradle - java

Yo folks basically I'm using gradle in java project and can't export the libraries in jar file that I'm using.
Tried a few solutions but nothing worked.
Do you know what I'm missing in the gradle file or I need to specify some things when I'm exporting. I'm using Eclipse
Thanks, here is my gradle file
enter code here
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
}
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
mavenCentral()
}
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:27.0.1-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
implementation "redis.clients:jedis:3.0.1"
implementation 'org.pixsee.java-fcm:Java-fcm:1.0.0'
implementation 'com.google.firebase:firebase-admin:6.10.0'
compile "org.slf4j:slf4j-api:1.6.1"
implementation 'org.slf4j:slf4j-simple:1.7.25'
implementation "com.google.maps:google-maps-services:0.9.4"
implementation 'io.vertx:vertx-core:3.8.1'
}
sourceCompatibility = 1.8
version = '1.0'
jar {
manifest {
attributes 'Implementation-Title': 'GeofenceServer',
'Implementation-Version': version
}
}
apply plugin: "eclipse"

Finally solved it , the answer from Sterconium got me on the right track
answer but the problem was when I try to create the fatJar it says cannot find the main class ,the reason was because my files are in src/test/java instead of src/main/java and somehow when I tried to run fatJar it compiled It but could not find still the dependencies, so I change the implementation to compile in build.gradle file and now it works .So here is my final build.gradle file how it looks like .
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Java Library project to get you started.
* For more details take a look at the Java Libraries chapter in the Gradle
* User Manual available at https://docs.gradle.org/5.4/userguide/java_library_plugin.html
*/
plugins {
// Apply the java-library plugin to add support for Java Library
id 'java-library'
}
repositories {
// Use jcenter for resolving your dependencies.
// You can declare any Maven/Ivy/file repository here.
jcenter()
mavenCentral()
}
apply plugin: "java"
apply plugin: "eclipse"
version = '1.0'
//create a single Jar with all dependencies
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'Gradle Jar File Example',
'Implementation-Version': version,
'Main-Class': 'Server.Test'
}
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
dependencies {
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:27.0.1-jre'
// Use JUnit test framework
testImplementation 'junit:junit:4.12'
implementation "redis.clients:jedis:3.0.1"
implementation 'com.google.firebase:firebase-admin:6.10.0'
implementation 'org.slf4j:slf4j-simple:1.7.25'
implementation 'com.google.maps:google-maps-services:0.10.0'
compile 'io.vertx:vertx-core:3.8.1'
implementation 'com.google.code.gson:gson:2.8.5'
}

Related

How to export gradle project with google api dependencies in eclipse

this is my build.gradle
plugins {
// Apply the java-library plugin for API and implementation separation.
id 'java-library'
id 'java'
id 'application'
}
mainClassName = 'myproject.Main'
sourceCompatibility = 1.8
targetCompatibility = 1.8
version = '1.0'
repositories {
// Use Maven Central for resolving dependencies.
mavenCentral()
}
dependencies {
// Use JUnit Jupiter for testing.
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'
// This dependency is exported to consumers, that is to say found on their compile classpath.
api 'org.apache.commons:commons-math3:3.6.1'
// This dependency is used internally, and not exposed to consumers on their own compile classpath.
implementation 'com.google.guava:guava:31.1-jre'
implementation 'com.google.api-client:google-api-client:1.18.0'
implementation 'com.google.oauth-client:google-oauth-client-jetty:1.34.1'
implementation 'com.google.apis:google-api-services-sheets:v4-rev20220927-2.0.0'
}
jar {
exclude 'META-INF/*.SF', 'META-INF/*.DSA', 'META-INF/*.RSA', 'META-INF/*.MF', 'META-INF/LICENSE', 'META-INF/LICENSE.txt', 'META-INF/DEPENDENCIES', 'META-INF/NOTICE', 'META-INF/NOTICE.txt'
manifest {
attributes 'Main-Class':'myproject.Main'
}
from{
configurations.runtimeClasspath.collect{ it.isDirectory()? it : zipTree(it) }
}
}
after i export my project using eclipse, it got problem when i run it. It seems that it has problem with the dependencies.
i want to export it into runnable jar file that can get data from google spreadsheets

Gradle Builds an Empty Jar File

I converted a project to gradle using gradle init from maven after updating the dependencies. gradle test works as expected. However, when I run gradle build, the jar file that's generated is entirely empty.
I've attempted to tweak the source set to make something happen, but that doesn't seem to solve the problem. The directory structure matches what gradle expects from what I can tell everything is nested in src/main/groovy
The project's full code is available on Github.
In general what causes no files to be added to a build? Is there additional configuration I need to add besides whatever gradle init creates?
Gradle build file:
plugins {
id 'java'
id 'maven-publish'
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
}
dependencies {
implementation 'org.codehaus.groovy:groovy-all:3.0.5'
implementation 'com.github.javafaker:javafaker:1.0.2'
testImplementation 'org.spockframework:spock-core:2.0-M3-groovy-3.0'
testCompileOnly 'org.projectlombok:lombok:1.18.12'
testAnnotationProcessor 'org.projectlombok:lombok:1.18.12'
}
group = 'nl.topicus.overheid'
version = '0.2.0'
description = 'java-factory-bot'
sourceCompatibility = '1.8'
publishing {
publications {
maven(MavenPublication) {
from(components.java)
}
}
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
What going on now is the project is try to build as Java project and get src from src/main/java as it is default from Java project. So, you need id 'groovy' not id 'java' in plugins section to make it look into src/main/groovy and build both .java and .groovy files in there.

Clojure (clara rule) file not generated when gradle build

I have a Spring application that integrates a clara rule engine (clojure) file that is triggered from a java class. When building the app with gradle, the clojure file is not generated as part of the JAR.
So, when running ther jar, it throws the following exception:
Caused by: java.io.FileNotFoundException: Could not locate au/com/acme/mti/mec/runtime/rules/mec__init.class or au/com/acme/mti/mec/runtime/rules/mec.clj on classpath.
What is the best way (or at least a way) to make gradle generates the clj file when building/generating the jar?
I have already include a task in the build.gradle file to copy the clj file from src path to the build path. It copies the file under the build path, but it does not in the jar.
build.gradle:
plugins {
id 'org.springframework.boot' version '2.3.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
id 'jacoco'
}
group = 'au.com.acme.mti.mec'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
mavenLocal()
maven {
url "http://clojars.org/repo"
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.clojure:clojure:1.9.0'
implementation 'com.cerner:clara-rules:0.20.0'
implementation 'org.projectlombok:lombok'
}
}
task copyRules(type: Copy){
from 'src/main/resources/au.com.acme.mti.mec.runtime.rules/'
into 'build/classes/java/main/au/com/acme/mti/mec/runtime/rules/'
}
test {
test.dependsOn copyRules
useJUnitPlatform()
finalizedBy jacocoTestReport
}
jacocoTestReport {
reports {
xml.enabled false
csv.enabled false
html.destination file("${buildDir}/jacocoHtml")
}
}
Putting the Clojure files (the Clara rules) in a place, where they end up in the correct place inside the JAR, would make the copy task obsolute (which is not used for building the JAR -- at least from the part of the build.gradle we can see in the question.
Move the files from src/main/resources/au.com.acme.mti.mec.runtime.rules to src/main/resources/au/com/acme/mti/mec/runtime/rules
Get rid of the copyRules task (and it's dependsOn)
edit:
Added a repository that shows a minimal working example, that puts the clj files just into resources https://github.com/christoph-frick/try-java-clara

Gradle multi-module. Check context of first module with EventListener from another module

I have two modules, first runs Spring boot Application and second it is EventListener which loads files from resources when context starts. All this modules works well separately but I wanna to include event listener module to my first module (Spring boot module) to get all files from resource of my first module when it runs context.
My main module with setting.gradle:
allprojects {
buildDir = file("${rootDir}/build")
group = 'com.example'
version = "0.1.1"
}
subprojects {
apply plugin: 'java'
apply plugin: 'maven'
}
setting.gradle
rootProject.name = 'test-application'
include 'bootApplication'
include 'eventListener'
project(":eventListener").projectDir = file("C:/examples/eventListener")
My bootApplication.gradle:
plugins {
id 'org.springframework.boot' version '2.2.1.RELEASE'
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group 'com.example.bootApplication'
version = "0.1.1"
sourceCompatibility = '11'
targetCompatibility = '11'
repositories {
jcenter()
mavenLocal()
mavenCentral()
}
bootJar {
baseName("bootApplication")
}
jar {
enabled = true
}
dependencies {
compile project(":eventListnere")
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.springfox:springfox-swagger2:+'
implementation 'io.springfox:springfox-swagger-ui:+'
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
And my eventListener:
plugins {
id 'org.springframework.boot' version '2.2.1.RELEASE'`enter code here`
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
group 'com.example.eventlistener'
version '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
targetCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
ext {
spring_boot_version = '2.2.1.RELEASE'
}
implementation "org.springframework.boot:spring-boot-starter:$spring_boot_version"
compileOnly 'org.projectlombok:lombok:1.18.8'
annotationProcessor 'org.projectlombok:lombok:1.18.8'
testImplementation "org.springframework.boot:spring-boot-starter-test:$spring_boot_version"
testCompile group: 'junit', name: 'junit', version: '4.12'
}
jar.enabled = true
When I run my bootApplication main class it creates a eventlistener-.jar file in root build directory. But eventlistener module doesn't check the resource folder, I guess it doesn't see a bootApplication context. Maybe it should be collect to one jar file? It looks like I missed something in gradle build files.
I will just prefix this by saying I don't know if the stuff below is the actual cause of your problems. But you should probably change a few things related to the jar configuration no matter what.
The Spring Boot Gradle plugin is used to create a fat jar out of the project. By default it disables the normal jar task.
You are re-enabling the normal jar task through jar.enabled = true, which is fine. But you also need to give it another name as one will otherwise override the other. For instance, for your eventListener project, you could do this:
// eventListener/build.gradle
bootJar {
classifier = 'boot'
}
However, if the eventListener is not actually a stand-alone executable, there is no need to create a boot jar from it. So unless you are using the plugin for other things, I would remove it from the eventListener completely:
// eventListener/build.gradle
plugins {
// id 'org.springframework.boot' version '2.2.1.RELEASE'`enter code here` <-- Remove this
id 'io.spring.dependency-management' version '1.0.8.RELEASE'
id 'java'
}
You can still use the Spring Boot starters in the project, you just don't need the plugin for repackaging the jar.
The same thing applies to your bootApplication project: you are both trying to create a fat executable jar at the same time as a normal jar. One will override the other. In this case, you probably don't need the normal jar, so you should disable the jar task again:
// eventListener/build.gradle
// jar.enabled = true <-- Remove this
Lastly, replace compile project(":eventListnere") with implementation project(":eventListener") and testCompile with testImplementation to avoid some deprecation warnings. The maven plugin is deprecated as well in favor of maven-publish. You can probably also get rid of mavenLocal() unless you are integrating with local Maven projects that you build yourself with mvn install.
The eventListener, if packaged correctly as a normal jar inside the fat jar of the bootApplication, should be able to access resources in both its own resource folder as well as the one from bootApplication when you run the latter.

How do I correctly output META-INF when libraries use SPIs using gradle?

I am attempting to make a test application using Gradle and Java that uses several libraries that use the Java Service Provider interface. I think this means that I need to modify META-INF but I am not really sure how to do this.
The error that I get is An SPI class of type org.apache.lucene.codecs.codec with nameLucene50does not exist. You need to add the corresponding JAR file supporting this SPI to your classpath. The current classpath supports the following names [ SimpleText]
I think that I need to get the SPI information into META-INF but I am not sure how to do this with Gradle.
Specifically, I am trying to use Lucene and Hadoop jars in the following build file:
apply plugin: 'java'
sourceCompatibility = 1.8
version = '1.0'
repositories {
mavenCentral()
}
dependencies {
compile group:'org.apache.lucene', name:'lucene-core', version:'5.0.0'
compile group:'org.apache.lucene', name:'lucene-queryparser', version:'5.0.0'
compile group:'org.apache.lucene', name:'lucene-analyzers-common', version:'5.0.0'
compile group:'org.apache.lucene', name:'lucene-facet', version:'5.0.0'
compile group:'org.apache.lucene', name:'lucene-codecs', version:'5.0.0'
compile group:'org.apache.hadoop', name:'hadoop-hdfs', version:'2.6.0'
compile group:'org.apache.hadoop', name:'hadoop-core', version:'1.2.1'
compile group:'org.apache.hadoop', name:'hadoop-common', version:'2.6.0'
}
jar
{
from {configurations.compile.collect {it.isDirectory() ?it:zipTree(it) }}
manifest
{
attributes 'Main-Class': 'LuceneTest'
}
}
Both the lucene-core and lucene-codecs libraries provide org.apache.lucene.codecs.Codec implementations, so they both have a META-INF/services/org.apache.lucene.codecs.Codec service file. When you merge all your dependencies, both files are added to the jar file, but Lucene only sees the lucene-codecs one. You could merge the service files manually in the jar task, as in this post, which basically finds all the service files and combines them. The easier solution is probably to use something like the Gradle Shadow plugin.
If you add this to build.gradle, using the shadowJar task instead of the jar task should do what you want.
buildscript {
repositories { jcenter() }
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:1.2.1'
}
}
apply plugin: 'com.github.johnrengelman.shadow'
shadowJar {
mergeServiceFiles()
}

Categories