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
Related
We've been using the Eclipse #NonNull and #Nullable annotations in our code for a while.
We are now adding some Spring projects defined with Gradle to our system. These projects will share quite a bit of code with our standalone projects as well.
We are seeing a problem due the Eclipse annotations (being compile time checking) don't work when a Spring/Gradle project refers to the shared code via Gradle generated .jar file. Eclipse needs to have the source of the shared jar in order for the annotations to work. Attaching the source in the Eclipse project only works until you need to do a Gradle Refresh, as that rebuilds the eclipse .project and .classpath files.
It's also a problem that you have to explicitly rebuild the shared .jar each time you make a change to the shared code. It's not done automatically.
I haven't found a way to have the Spring/Gradle projects just use a 2nd source directory for the shared code, and not need to have the shared code as a generated .jar file.
Is there any good way to have shared code between multiple Gradle projects in Eclipse - without using an intermediate .jar file? (Or some other way to get the Eclipse annotations to work.)
Not really sure how to give a full example, as most of this is gradle and eclipse configuration.
Here are the Gradle config files: settings.gradle
pluginManagement {
repositories {
maven { url 'https://repo.spring.io/milestone' }
gradlePluginPortal()
}
}
rootProject.name = 'App1-Account-Manager'
and build.gradle
plugins {
id 'org.springframework.boot' version '2.5.0-RC1'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.efi'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
maven { url 'https://repo.spring.io/milestone' }
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation group: 'io.jsonwebtoken', name: 'jjwt', version: '0.2'
implementation 'org.springframework.boot:spring-boot-starter-amqp'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.amqp:spring-rabbit-test'
implementation files('lib/eflow/eFlowClientApi.jar',
'lib/eflow/eFlowCryptography.jar',
'lib/eflow/json-simple-1.1.1.jar',
'lib/eflow/commons-codec-1.4.jar',
'lib/eflow/commons-io-2.6.jar',
'lib/eflow/commons-lang-2.6.jar',
'lib/eflow/commons-logging-1.2.jar',
'../App1-Commons/build/libs/App1-Commons-0.0.1-SNAPSHOT.jar'
)
implementation group: 'org.eclipse.jdt', name: 'org.eclipse.jdt.annotation', version: '2.1.100'
implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.7'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.security:spring-security-test'
}
test {
useJUnitPlatform()
}
App1-Commons is the project of shared code that multiple other projects depend on. That's where a bunch of the #NonNull annotations are.
I can set the App1-Account-Manager project to depend on the App1-Commons project in eclipse - but as soon as you run a Gradle Refresh, it looses that connection.
I'd prefer to just have the source from App1-Commons included in the App1-Account-Manager project - but I don't see how to configure Gradle to do that with Eclipse projects.
I think I found the solution. I need to add a SourceSets block to the build.gradle file like this:
sourceSets {
main {
java {
srcDir 'src/main/java'
srcDir '../App1-Commons/src/main/java'
}
}
}
And remove the reference to the App1-Commons 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.
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.
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'
}
I'm new to gradle and I'm trying to configure gradle with lwjgl3. Because I didn't found a repo where lwjgl3 is hosted i decided that everybody who use this project has to define the path to the lwjgl lib. I created a user.gradle file with contains the paths to the jar and to the natives.
My build.gradle looks like this at the moment.
apply plugin: 'java'
apply from: 'user.gradle'
apply plugin: 'application'
sourceCompatibility = 1.8
targetCompatibility = 1.8
mainClassName = "mp.Main"
println("LWJGL jar path is configured to: ${config.lwjgl3Jar}")
println("LWJGL natives path is configured to: ${config.lwjgl3Natives}")
repositories {
mavenCentral()
flatDir {
dir config.lwjgl3Jar
}
}
dependencies {
compile 'com.google.code.gson:gson:2.3.1'
compile 'net.java.dev.jna:jna:4.1.0'
testCompile 'junit:junit:4.+'
testCompile 'com.carrotsearch:junit-benchmarks:0.7.2'
compile name: 'lwjgl'
}
tasks.withType(Test) {
scanForTestClasses = false
include "**/*Test.class" // whatever Ant pattern matches your test class files
}
sourceSets{
main {
java {
srcDir 'src'
exclude 'mp/graphics/gl/scene/Mesh.java'
exclude 'test'
}
}
test{
java {
srcDir 'src/test'
exclude '**/UnsafeTest.java'
exclude '**/DispatchTests/*'
exclude '**/MemoryTest.java'
exclude '**/SuperFastListTest.java'
exclude '**/MatrixTest.java'
exclude '**/SimulationTest.java'
}
}
}
task wrapper(type: Wrapper) {
gradleVersion = '2.3'
}
How to set the natives? I tried it different ways. Google didn't helped me out this time. All results are related to older versions of this lib and all are using repositories. Maybe I'm missing the forest for the trees in between. Any ideas?
Best regards!
PS: Not sure if it is important: We are using different IDE's like intelliJ and Eclipse on Windows, Linux, and Mac.
I have run into the same problem and wrote a plugin for handling the natives associated with Java jar files.
http://cjstehno.github.io/gradle-natives/
It will unpack them from the jar files so that you can use them and deploy them in your project.
I solved the problem for me. The problem for was that I didn't knew how to configure gradle to use the natives. Normally I set the the classpath in the run config. However:
The very simple solution how to set the classpath with gradle:
Apply the java plugin and use the function:
run {
systemProperty 'java.library.path', 'path to ur natives')
}
The simply run your application via gradle and it should work.
There were so many solutions by searching for "lwjgl gradle natives" that I didn't found the right one :-)
Hope the solution helps somebody.