I would like to make a runnable jar for my test project with gradle. (with java -jar jajson.jar).
Here is my file tree :
-src
--JaJon.java
--Student.java
build.gradle
gson-2.8.8.jar
Here is my JaJson.java :
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class JaJson {
public static void main(String args[]) {
System.out.println("Hello");
String jsonString = "{\"name\":\"Mahesh\", \"age\":21}";
GsonBuilder builder = new GsonBuilder();
builder.setPrettyPrinting();
Gson gson = builder.create();
Student student = gson.fromJson(jsonString, Student.class);
System.out.println(student);
jsonString = gson.toJson(student);
System.out.println(jsonString);
}
public JaJson(){
System.out.println("what time is it ?");
}
public void getTime(){
System.out.println("Hammer time!");
}
}
Here is my Student.java :
public class Student {
private String name;
private int age;
public Student(){}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student [ name: " name ", age: " age " ]";
}
}
Actually it works when i do a :
javac -cp gson-2.8.8.jar;*.jar;src; src/JaJson.java
then a :
java -cp gson-2.8.8.jar;*.jar;src; JaJson
it show me as expected :
Student [ name: Mahesh, age: 21 ]
{
"name": "Mahesh",
"age": 21
}
So here is my messy attempt to make a runnable fat jar with gradle with gson included and Student class also included :
build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'
//apply plugin: 'java-library'
apply plugin: 'application'
apply plugin: 'idea'
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath 'gradle.plugin.com.github.jengelman.gradle.plugins:shadow:7.0.0'
}
}
apply plugin: 'com.github.johnrengelman.shadow'
mainClassName = "JaJson"
// tag::repositories[]
repositories {
mavenCentral()
}
// end::repositories[]
configurations {
// configuration that holds jars to include in the jar
extraLibs
}
sourceSets {
single{
java {
srcDir 'src'
}
}
}
task compile(type: JavaCompile) {
source = sourceSets.single.java
sourceSets.main.java.srcDirs = ['src']
classpath = sourceSets.main.compileClasspath
destinationDirectory = sourceSets.main.output.classesDirs[0]
}
compileJava {
options.release = 7
}
// tag::dependencies[]
dependencies {
implementation 'com.google.code.gson:gson:2.8.8'
implementation "joda-time:joda-time:2.2"
testImplementation "junit:junit:4.12"
shadow 'com.google.code.gson:gson:2.8.8'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
}
}
jar {
manifest {
attributes(
'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
'Main-Class': 'JaJson'
)
}
}
task fatJar(type: Jar) {
manifest.from jar.manifest
classifier = 'all'
from {
configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
} {
exclude "META-INF/*.SF"
exclude "META-INF/*.DSA"
exclude "META-INF/*.RSA"
}
with jar
}
shadowJar {
archiveBaseName.set('shadow')
archiveClassifier.set('')
archiveVersion.set('')
manifest {
inheritFrom project.tasks.fatJar.manifest
}
}
version = '1.2.1'
Any idea on how to do a runnable fatjar with student and gson ?
regards
CodePudding user response:
With gradle 7.2, I was able to create the executable fat jar using gradle build
(or ./gradlew build
if you use a gradle wrapper) command just by removing one line from the build.gradle
in the question. I removed 'Class-Path': configurations.compile.collect { it.getName() }.join(' '),
line, from within the attributes
method of jar
task.
Running the generated fat jar using command java -jar build/libs/shadow.jar
returns below response:
Hello
Student [ name: Mahesh, age: 21 ]
{
"name": "Mahesh",
"age": 21
}
CodePudding user response:
Add two dependencies
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.25'
compile group: 'org.slf4j', name: 'slf4j-simple', version: '1.7.25'
}
Using the Jar Task From the Java Plugin
We need two things to make it work:
- a Main-Class attribute in the manifest file
- Include dependencies jars
Let's add few modifications to the Gradle task:
jar {
manifest {
attributes "Main-Class": "com.baeldung.fatjar.Application"
}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
Creating a Separate Task
If we want to leave the original jar task as it is, we can create a separate one that will do the same job.
The following code will add a new task called customFatJar:
task customFatJar(type: Jar) {
manifest {
attributes 'Main-Class': 'com.baeldung.fatjar.Application'
}
baseName = 'all-in-one-jar'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
Using Dedicated Plugins
We can also use existing Gradle plugins in order to build a fat jar.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.1'
}
}
apply plugin: 'java'
apply plugin: 'com.github.johnrengelman.shadow'
Once we apply the Shadow plugin
, the shadowJar
task will be ready to use.
for more detail check this link