I have a spring project with Gradle. I created a task in the build.gradle:
task dockerFile(type: Dockerfile) {
destFile.set(project.file('Dockerfile'))
from "alpine:$alpineVersion"
runCommand 'apk add --no-cache openjdk11'
copyFile "build/libs/${jar.archiveFileName.get()}", '/app/'
workingDir '/app/'
entryPoint 'java'
defaultCommand '-jar', "/app/${jar.archiveFileName.get()}"
}
Everything works fine. Dockerfile is generated. But when I try to run the image it gives me the error: no main manifest attribute, in /app/demo-0.0.1-SNAPSHOT-plain.jar
Also here is my entire build.gradle:
import com.bmuschko.gradle.docker.tasks.image.Dockerfile
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.6'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
id 'com.bmuschko.docker-remote-api' version '6.6.1' apply false
}
group = 'ms10gradle2'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation "org.springframework.boot:spring-boot-starter-data-jpa:$jpaVersion"
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
tasks.named('test') {
useJUnitPlatform()
}
task printJpaVer{
print "JPA VERSION: ${jpaVersion}"
}
task printfiles {
doLast {
def files = "cmd.exe /c dir".execute().text.trim()
println(files)
project.getAllprojects().forEach(System.out::print)
}
}
task printTasks{
project.getTasks().forEach{
println("task name: "+ it)
}
}
task printTasksInsideSubModulesTrueOrFalse{
project.getAllTasks(false).entrySet().forEach(System.out::println)
}
task printTaskVersion{
project.getAllprojects()
.forEach(p -> println p.name +"- "+p.getVersion())
print "================================================================"
project.getAllprojects().forEach(p -> println p.getVersion())
}
task dockerFile(type: Dockerfile) {
destFile.set(project.file('Dockerfile'))
from "alpine:$alpineVersion"
runCommand 'apk add --no-cache openjdk11'
copyFile "build/libs/${jar.archiveFileName.get()}", '/app/'
workingDir '/app/'
entryPoint 'java'
defaultCommand '-jar', "/app/${jar.archiveFileName.get()}"
}
and Dockerfile:
FROM alpine:3.11.2
RUN apk add --no-cache openjdk11
COPY build/libs/demo-0.0.1-SNAPSHOT-plain.jar /app/
WORKDIR /app/
ENTRYPOINT ["java"]
CMD ["-jar", "/app/demo-0.0.1-SNAPSHOT-plain.jar"]
Looks like you tried to run jar is not executable.
Let's say you have main class in your code with name fully.qualified.MainClass
There are 2 ways:
It it necessary to add manifest with main-class(preferable):
for maven:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
...
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>fully.qualified.MainClass</mainClass>
</manifest>
</archive>
</configuration>
...
</plugin>
maven documentation for more info.
for gradle
it is necessary to add jar task with Main-Class:
jar {
manifest {
attributes 'Main-Class': 'fully.qualified.MainClass'
}
}
Jar task documentation
and also there was question about gradle executable jar: Creating runnable JAR with Gradle
run jar with your main class as param:
java -cp MyJar.jar fully.qualified.MainClass
How to run a class from Jar which is not the Main-Class in its Manifest file
Related
Same thing works in my other project, but here I get an error :
no main manifest attribute, in jar
here's my Gradle :
group 'com.vladdrummer.txtadventureserver'
version '1.0-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile "com.sparkjava:spark-core:2.7.2"
}
Here's where manifest is :
So, it seems to be in a right place.
The manifest itself :
Manifest-Version: 1.0
Main-Class: TextAdventureServer
and the Artifact:
So, it seems to me that everything is in place, but when I build Artifact and try java -jar txtadventureserver_main.jar - it shows me error:
no main manifest attribute, in txtadventureserver_main.jar
Where did I make a mistake?
My build.gradle file is as following
apply plugin: 'java' sourceCompatibility = 1.8
repositories {
mavenCentral() }
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.12'
compile 'io.javalin:javalin:1.3.0'
compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.9.4'
compile 'org.slf4j:slf4j-simple:1.7.25' }
jar {
manifest {
attributes(
'Class-Path': configurations.runtime.files.collect {"$it.name"}.join(' '),
'Main-Class': 'products.ProductAPI'
)
} }
task stage {
dependsOn 'build'
dependsOn 'clean'
build.mustRunAfter clean }
Trying to build a java application with gradle and deploy it to a heroku server. I have some issues on java -jar build/libs/MyApp-0.0.1.jar as it returns the following:
Exception in thread "main" java.lang.NoClassDefFoundError:
io/javalin/Javalin at products.ProductAPI.main(ProductAPI.java:7)
Caused by: java.lang.ClassNotFoundException: io.javalin.Javalin at
java.net.URLClassLoader.findClass(URLClassLoader.java:381) at
java.lang.ClassLoader.loadClass(ClassLoader.java:424) at
sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:338) at
java.lang.ClassLoader.loadClass(ClassLoader.java:357)
To run your app without any NoClassDefFoundError, you should have your dependencies in the runtime class path. Creating a fat jar is the simplest solution. Change your jar section like below;
jar {
manifest {
attributes(
'Class-Path': configurations.compile.files.collect {"$it.name"}.join(' '),
'Main-Class': 'products.ProductAPI')}
from {
configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
}
run gradle build command and jar with dependencies will be created.
Other way is to add jars to runtime class path are; with java -cp flag. (Also If your application has already a classpath folder configured, copying dependencies in this folder will add them to the classpath)
I am getting the following error while spring boot jar in CI environment
java -jar application.jar
no main manifest attribute, in application.jar
The weird thing is, it does not give the issue in my local or jenkins slave. It starts all right.
It faces issue when I upload the jar to Nexus artifactory and download it on my CI environment.
Building jar using
gradle clean build -x test
My gradle.build file
buildscript {
repositories {
maven {
url "https://plugins.gradle.org/m2/"
}
jcenter()
mavenLocal()
mavenCentral()
}
dependencies {
classpath 'org.akhikhl.gretty:gretty:1.2.4'
classpath 'org.ajoberstar:gradle-jacoco:0.1.0'
classpath 'org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:1.2'
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.6.RELEASE")
}
}
repositories {
mavenCentral()
mavenLocal()
maven {
credentials {
username "hello"
password "world"
}
url "Nexus URL"
}
}
apply plugin: 'maven-publish'
apply plugin: 'java'
apply plugin: 'maven'
apply plugin: 'spring-boot'
apply plugin: "org.sonarqube"
apply plugin: 'jacoco'
group = 'com.company.pod'
/* Determining version from jenkins pipeline, otherwise is set to 1.0.0-SNAPSHOT */
version = new ProjectVersion(1, 0, System.env.SOURCE_BUILD_NUMBER, System.env.RELEASE_TYPE)
println(version)
class ProjectVersion {
Integer major
Integer minor
String build
String releaseType
ProjectVersion(Integer major, Integer minor, String build, String releaseType) {
this.major = major
this.minor = minor
this.build = build
this.releaseType = releaseType
}
#Override
String toString() {
String fullVersion = "$major.$minor"
if(build) {
fullVersion += ".$build"
}
else{
fullVersion += ".0"
}
if(releaseType) {
fullVersion += "-RELEASE"
}
else{
fullVersion += "-SNAPSHOT"
}
fullVersion
}
}
/*Sonarqube linting of your repository.*/
sonarqube {
properties {
property "sonar.language", "java"
}
}
/* Please don't comment out the part below
To run the same on your laptops/prod boxes/CUAT boxes, just edit the gradle.properties file.
(It will be present in the home directory of the user you are using to run gradle with.`sudo` means root user and likewise)
Enter the following lines(and yes, it will run without values, thank you gradle!)
nexusUrl=
nexusRelease=
nexusSnapshot=
nexusUsername=
nexusPassword=
*/
uploadArchives {
repositories {
mavenDeployer {
repository(url: nexusUrl+"/"+nexusRelease+"/") {
authentication(userName: nexusUsername, password: nexusPassword)
}
snapshotRepository(url: nexusUrl+"/"+nexusSnapshot+"/"){
authentication(userName: nexusUsername, password: nexusPassword)
uniqueVersion = false
}
}
}
}
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
}
}
}
publishing {
publications {
maven(MavenPublication) {
groupId 'com.company.something'/*This is different from group variable before*/
artifactId 'something'
version '2.0.0'
from components.java
}
}
}
/*
publishing {
repositories {
maven {
url "~/.m2/repository/"
}
}
}
*/
task wrapper(type: Wrapper) {
gradleVersion = '2.9'
distributionUrl = "https://services.gradle.org/distributions/gradle-$GradleVersion-all.zip"
}
dependencies {
compile('org.projectlombok:lombok:1.16.6')
compile("com.company.commons:company-app:0.0.1-RELEASE")
compile group: 'com.google.guava', name: 'guava', version: '19.0'
compile("com.squareup.retrofit2:retrofit:2.0.1")
compile("com.squareup.retrofit2:converter-jackson:2.0.1")
compile("org.springframework.boot:spring-boot-starter-data-jpa")
compile group: 'ch.qos.logback', name: 'logback-classic', version: '1.1.7'
compile("com.getsentry.raven:raven-logback:7.2.2")
compile("org.springframework.boot:spring-boot-starter-actuator")
testCompile("org.springframework.boot:spring-boot-starter-test")
testCompile("com.h2database:h2")
testCompile("junit:junit")
// testCompile("org.springframework.boot:spring-boot-starter-test")
// testCompile group: 'org.hibernate', name: 'hibernate-validator', version: '4.2.0.Final'
}
Articles consulted with no vain
1. Gradle- no main manifest attribute
2. http://www.vogella.com/tutorials/Gradle/article.html#specifying-the-java-version-in-your-build-file
3. Can't execute jar- file: "no main manifest attribute"
The default packaged jar file does not contain MANIFEST file.
I don't know how to configure in Gradle, but in Maven when I added plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>vn.dung.Application</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<appendAssemblyId>false</appendAssemblyId>
</configuration>
</plugin>
And it works for me.
You could change that Maven plugin config to Gradle.
i had to run gradle bootRepackage after building the jar and git a jar that I could execute!
It worked with
gradle upload -x jar
In build.gradle, I noticed boot repackaging was disabled so I enabled it :
bootRepackage {
enabled = true
}
Hi I had exactly same problem, and I found the answer in:
Spring Boot Upload BootRepackage Executable Jar
I used the solution 2
publish {
dependsOn assemble
}
why does the Class-Path include Groovy, and why is it packaged as if it's a run-time dependency? What is pulling Groovy in?
thufir#mordor:~/NetBeansProjects/hello_client$
thufir#mordor:~/NetBeansProjects/hello_client$ gradle clean assemble
:clean
:compileJava
:processResources UP-TO-DATE
:classes
:jar
hello_api-dev.jar groovy-all-2.4.1.jar
:startScripts
:distTar
:distZip
:assemble
BUILD SUCCESSFUL
Total time: 2.401 secs
thufir#mordor:~/NetBeansProjects/hello_client$
The Groovy JAR's are included in the distribution as well:
thufir#mordor:~/NetBeansProjects/hello_client$
thufir#mordor:~/NetBeansProjects/hello_client$ unzip build/distributions/hello_client-dev.zip
Archive: build/distributions/hello_client-dev.zip
creating: hello_client-dev/
creating: hello_client-dev/lib/
inflating: hello_client-dev/lib/hello_client-dev.jar
inflating: hello_client-dev/lib/hello_api-dev.jar
inflating: hello_client-dev/lib/groovy-all-2.4.1.jar
creating: hello_client-dev/bin/
inflating: hello_client-dev/bin/hello_client.bat
inflating: hello_client-dev/bin/hello_client
thufir#mordor:~/NetBeansProjects/hello_client$
thufir#mordor:~/NetBeansProjects/hello_client$ java -jar hello_client-dev/lib/hello_client-dev.jar
hello [fred]
thufir#mordor:~/NetBeansProjects/hello_client$
The build.groovy file:
apply plugin: 'java'
apply plugin: 'application'
apply plugin: 'maven'
mainClassName = 'net.bounceme.mordor.hello.client.HelloClient'
version = 'dev'
group = 'com.some.project'
description = 'hello world KISS'
sourceCompatibility = '1.8'
[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'
if (!hasProperty(mainClassName)) {
ext.mainClass = mainClassName
}
repositories {
mavenCentral()
maven { url "https://jitpack.io" }
}
dependencies {
testCompile group: 'junit', name: 'junit', version: '4.10'
compile 'com.github.THUFIR:hello_api:dev'
}
jar.doFirst
{
def manifestClasspath = configurations.runtime.collect { it.name }
manifestClasspath = manifestClasspath.unique().join(" ")
println (manifestClasspath)
manifest.attributes.put("Main-Class", mainClassName)
manifest.attributes.put("Class-Path", manifestClasspath)
}
I think that the solution lies in dealing with configurations.runtime.collect in that Groovy should be removed from that collection. It just seems odd that it's included implicitly. Is this typical, to include Groovy?
The notion of a providedCompile looks interesting, but I'm not sure that it applies. Am I using Gradle in an odd way somehow?
The library and client repos are on github. Code posted might not be 100% as the latest commits, to make the questions as clear as possible.
OSGI-INF/serviceComponent.xml can be generated using maven scr felix plugin by adding dependency like
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.15.0</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
but for gradle I am not able to generate.. I have tried to add the
buildscript {
dependencies {
classpath group:'be.jlr-home.gradle' , name:'scrPlugin', version:'0.1.0'
}}
apply plugin: 'java'
`apply plugin: 'eclipse'
apply plugin: 'maven'
apply plugin: 'osgi'
apply plugin: 'scr'
It's giving error that be.jlr-home.gradle not found.
I am doing something wrong???
basically I need the dependency to add in gradle to generate the servicecomponent.xml
Your maven pom snippet configures the maven plugin for scr from felix. You need a gradle plugin for scr annotation processing. I don't know that felix has one. The bnd project has added gradle support (2.4.0.M1 includes a gradle plugin for bnd) and bnd can process annotations for DS (but maybe not the one's from Felix).
I have resolved the issue
add the below lines to your gradle file and it will work.
ant.properties.src = 'src/main/java'
ant.properties.classes = 'build/classes/main'
task genscr(dependsOn: compileJava) << {
println ant.properties.classes
ant.taskdef(resource: 'scrtask.properties', classpath: configurations.compile.asPath)
ant.scr(srcdir: ant.properties.src, destdir: ant.properties.classes, classpath: configurations.compile.asPath)
}
jar.dependsOn(genscr)
jar {
manifest {
// version = '1.0'
name = 'xxxxxxxxx'
instruction 'Service-Component', 'OSGI-INF/<PKGNAME>.<CLASSNAME>.xml'
}
dependencies {
......//All other dependencies........
compile 'org.apache.felix:org.apache.felix.scr.annotations:1.9.8'
compile 'org.apache.felix:org.apache.felix.scr.ds-annotations:1.2.4'
compile group: 'org.apache.felix', name: 'org.apache.felix.scr.ant', version: '1.110.'
}
sourceSets.main.compileClasspath += configurations.compile
#saviour23's solution did not work for me
It turns out we need to change the buildscript, and that gradle 1.6 does not work; after I upgraded to gradle 2.1, it works fine.
java code:
import org.apache.felix.scr.annotations.*;
#Component
public class Bndtest {
public static void main(String[] args) {
System.out.println("Hello World");
}
}
build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'be.jlr-home.gradle:scrPlugin:0.1.3'
}
}
apply plugin: 'java'
apply plugin: 'osgi'
apply plugin: 'scr'
apply plugin: 'groovy'
apply plugin: 'maven'
sourceCompatibility = 1.6
targetCompatibility = 1.6
version = '0.0.1-SNAPSHOT'
group = 'be.jlrhome.gradle.scr'
description = 'Gradle scr example'
dependencies {
compile 'org.apache.felix:org.apache.felix.scr.annotations:1.9.8'
}
gradle will wrap a jar with correct MANIFEST and OSGI XML