I have .jar that runs with spring boot loader:
apply plugin: 'spring-boot'
jar {
into('lib') {
from configurations.runtime
}
manifest {
attributes("Implementation-Vendor": "tttt",
"Implementation-Title": project.name,
"Implementation-Version": version,
"Implementation-Vendor-Id": "tttt",
"Built-By": "Administrator",
"Build-Jdk": "1.7.0_101",
"Start-Class": "org.cp.Application",
"Spring-Boot-Version": "1.3.3.RELEASE",
"Main-Class": "org.springframework.boot.loader.JarLauncher")
}
}
I run my build:
:ttt:compileJava
:ttt:processResources
:ttt:classes
:ttt:findMainClass
:ttt:jar
:ttt:bootRepackage
:ttt:assemble
:ttt:check
:ttt:build
java -jar tttt.jar:
java.lang.IllegalStateException: Unable to open nested entry 'lib/spring-boot-starter-1.3.3.RELEASE.jar'. It has been compressed and nested jar files must be stored without compression. Please check the mechanism used to create your executable jar file
at org.springframework.boot.loader.jar.JarFile.createJarFileFromFileEntry(JarFile.java:382)
at org.springframework.boot.loader.jar.JarFile.createJarFileFromEntry(JarFile.java:357)
at org.springframework.boot.loader.jar.JarFile.getNestedJarFile(JarFile.java:343)
at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchive(JarFileArchive.java:112)
at org.springframework.boot.loader.archive.JarFileArchive.getNestedArchives(JarFileArchive.java:96)
at org.springframework.boot.loader.ExecutableArchiveLauncher.getClassPathArchives(ExecutableArchiveLauncher.java:75)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:60)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:52)
I exploded spring.boot.loader manually into src/main/resources if that means something. What am I doing wrong here ?
You cannot execute Jar inside a JAR. if you need to do that, then you have to add the dependent JAR to environment variable & make use of it.
Related
Currently my gradle task looks like:
apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
...
}
task sourcesJar(type: Jar) {
getArchiveClassifier().set('sources')
from android.sourceSets.main.java.sourceFiles
}
artifacts {
archives sourcesJar
}
But in result jar artifact has *.java and *.kt files, but how to generate jar artifact with *.class files?
From command line, you just type:
jar uf0 path_to_your_jar_file\yourJarFile.jar path_to_your_classes\*.class
and of course, you can use the class name instead of a wildcard (*) if you don't want to add all classes from that directory.
jar --help
will give you more options.
Based on your screenshot, you are opening xxx-sources.jar file. Of course it contains only Java source file inside. This is the correct result as you configure as below:
task sourcesJar(type: Jar) {
getArchiveClassifier().set('sources')
from android.sourceSets.main.java.sourceFiles
}
You classes file normally are separated in another jar file. You didn't specify what are the tasks you executed. So let's assume you run the default Android build task, it will generate the aar file, it should contain your module classes file. You can unzip sapi-1.6.aar to check.
You can refer to this doc as well.
Updated:
You didn't specify why you need the Jar file instead of AAR file, let's assume you want to use Jar file in other project, then you need to use other gradle plugin to build (can't use android gradle plugin), it could be java or base gradle plugin. Some answer saying, you can find the jar file inside aar file, you can check this.
I have a question regarding to the difference between Gradle depedencies mechanism vs Maven dependency mechanism:
My project structure is following and app is dependent on common:
project
common
conf
src
java
test
app
conf
src
java
test
and build.gradle in app is:
dependencies {
compile project(':common')
....
}
sourceSets {
main {
java {
srcDir 'src/java'
}
resources {
srcDir 'conf'
}
}
test {
java {
srcDir 'src/test'
}
}
}
When I use ant dist. The class paths contain /common/conf folder, which contains lots of configuration files.
When I use Gradle build. The class paths contain build/common.jar instead of /common/conf.
Is there a way I could make Gradle do the same thing as Maven does (make class paths contain /common/conf instead of build/common.jar)?
Because app will read xml configuration files under common/conf folder when I run test cases under app but app is not able to read xml from a jar file. Because right now my code is not able to handle the inputStream from Jar.
Is it using:
res.getFile()
where res is the reference to xml configuration files.
I am a newbie to both Maven and Gradle. Could someone please help? Really appreciate!
If what you're trying to achieve is have those xml files available at runtime from within the Jar, then just add your XML files to /src/main/resources.
Anything in that directory automatically gets added to the Jar file and available as classpath resources. Both Maven and Gradle use convention over configuration, where it's a convention to put classpath resources into /src/main/resources as it is to put application Java code in /src/main/java and unit test classpath resources in /src/test/resources and unit test Java code in /src/test/java.
Following Mavan/Gradle conventions will make your configuration simpler too. Unlike Ant where everything needed to be configured.
If your xml files are in common.jar (by putting the xml in common/src/main/resources, and common is on the class path for for app then you should be able to read those files by getting via class loader. E.g SomeClassFromCommon.class.getClassLoader().getResourceAsStream("somefile.xml")
I'm maintaining a Java applet launched via Java Web Start but I know little about this technology (we are in the process of moving away from applets but we need some maintenance on it). This applet depends on some external JAR files (batik, etc.).
We use gradle as the build system. We build a normal JAR and a fat JAR (with the com.github.johnrengelman.shadow plugin) as follows:
sourceSets {
main {
java {
}
}
}
repositories {
flatDir {
dirs 'lib'
}
}
dependencies {
compile 'commons-lang:commons-lang:2.0',
'jargs:jargs:1.0',
'org.apache.xmlgraphics:batik-svggen:1.7',
'org.apache.xmlgraphics:batik-dom:1.7',
'org.apache.xmlgraphics:batik-awt-util:1.7',
'org.apache.xmlgraphics:batik-util:1.7',
'org.apache.xmlgraphics:batik-xml:1.7',
'xerces:xercesImpl:2.8.0'
}
jar {
manifest {
attributes 'Application-Name': project.name,
'Permissions': 'all-permissions',
'Implementation-Title': project.name,
'Implementation-Version': version,
'Main-Class': 'Foo',
'Class-Path': configurations.compile.files.collect{ "lib/${it.name}" }.join(' ')
}
baseName project.name
// include dependencies into lib dir in produced jar
into('lib') {
from configurations.runtime
}
from "README.md"
}
shadowJar {
baseName project.name
}
gradle includes the JAR files in lib/ folder inside the main JAR and they are added to the Class-Path in MANIFEST.MF.
The applet works on client computers with the normal JAR but I don't fully understand why.
Somehow, the JAR files are loaded when Java Web Start launches the applet. They are not mentioned in the JNLP file (no <resource>) and there is no class loader (we don't use JarRsrcLoader or similar) so I guess it's because they are in Class-Path but I am not sure and I haven't been able to produce a MWE. In fact all the information that I have found states the opposite (at least for applications as opposed to applets).
Does anybody know if it's the case or a simple explanation/tutorial ?
Well, I was wrong. In fact the JAR files are not loaded: when one tries to access the functionality that needs batik, it fails. This confirms my readings and #eckes and #zakki comments.
I also discovered that I can simplify our build.gradle file.
I was told to include this in my build.gradle file in exercism.io in order to run my test suite in Java.
jar {
manifest {
attributes 'Main-Class': 'net.petrikainulainen.gradle.HelloWorld'
}
}
What is jar? What is the attributes 'Main-Class' doing? Is it specifying where my main class exists in the build folder?
In essence, gradle seems to be doing a few things for me:
1. creating a build folder where my Javascript compiled code exists
2. running my test suite
3. fetching any dependencies that I specify in the build.gradle file.
Is this typically what a dependency manager does?
In order to run tests you don't need to add a Main-Class attribute. What you've done there is specify that when building a jar file, include the Main-Class attribute in the jars manifest, which is the class to use as the entry when running a jar file via java -jar.
In answer to your second question, Gradle isn't a dependency manager, it's a build automation tool and yes, that's typically what they do for you.
I've successfully configured my gradle build script to create a zip distribution of my application with an extra 'config' folder at the root. This folder contains (at least right now) only one properties file in use by the application, and is on the classpath for the application.
What I'm looking for now, however, is a way to do the same with the 'run' task in the application plugin. When I try to run my application this way, (for testing), my program fails to run because of a class trying to access this properties file on the root of the classpath.
A bonus would be if I could get IntelliJ or Eclipse to also add this folder to its classpath just like the other folders (src/main/java, src/main/resources, ...) so I can run and debug my code from within the IDE without invoking a gradle task. I want to try to avoid as much as possible tying this code to any one IDE, so that when anybody needs to work on the project, they just need to import the build.gradle file and have the IDE make the appropriate config files it needs.
Here is my build.gradle file:
apply plugin: 'application'
mainClassName = "MainClass"
startScripts {
// Add config folder to classpath. Using workaround at
// https://discuss.gradle.org/t/classpath-in-application-plugin-is-building-always-relative-to-app-home-lib-directory/2012
classpath += files('src/dist/config')
doLast {
def windowsScriptFile = file getWindowsScript()
def unixScriptFile = file getUnixScript()
windowsScriptFile.text = windowsScriptFile.text.replace('%APP_HOME%\\lib\\config', '%APP_HOME%\\config')
unixScriptFile.text = unixScriptFile.text.replace('$APP_HOME/lib/config', '$APP_HOME/config')
}
}
repositories {
...
}
dependencies {
...
}
Likely what needs to happen is that I need to have the /src/dist/config folder to be copied into the build directory and added to the classpath, or have its contents be copied into a folder that is already on the classpath.
I ended up taking Opal's suggestion as a hint, and came up with the following solution. I added the following to my build.gradle file:
task processConfig(type: Copy) {
from('src/main/config') {
include '**/*'
}
into 'build/config/main'
}
classes {
classes.dependsOn processConfig
}
run {
classpath += files('build/config/main')
}
Alternatively, a simpler approach would be to add a runtime dependency to my project as such:
dependencies {
...
runtime files('src/main/config')
}
I didn't end up doing it this way, however, because my distribution package ended up having .properties files in the lib folder... and I'm just picky that way.
As you can see in the docs run is a task of type JavaExec. So classpath for it can be modified. Try to add config folder to the classpath. See here.