Gradle project dependency does not reference SNAPSHOT jar - jar

I am trying to create a fat jar file in a multi-project Gradle build, something like the following:
root
+-- project1
+-- project2
project1 provides the basic functionality, which is then used by project2 to create an executable jar. The executable JAR needs to contain all of the code from the dependencies so that it can be run standalone.
For external dependencies this works fine. In project2 I create a new configuration:
apply plugin: 'maven'
apply plugin: 'java'
configurations {
// configuration for JARs that need to be included in the final packaging
includeInJar
}
and then add the dependencies:
dependencies {
includeInJar 'com.fasterxml.jackson.core:jackson-databind:2.2.3'
...
configurations.compile.extendsFrom(configurations.includeInJar)
}
The packaging then looks like this:
jar {
manifest {
attributes "Main-Class": "com.acme.project1.MyTest"
}
// import all dependencies into the Jar so that it can be run easily
from {
configurations.includeInJar.collect {
it.isDirectory() ? it : zipTree(it)
}
}
}
The jar is correctly built with all of the files from the external dependencies. The problem comes with the project dependency to project1:
includeInJar project(':project1')
When this is present, I get an error when it tries to assemble the JAR that it can't find the jar (e.g. project1-0.4.0.jar) in the project1 build/libs directory as it does not exist. The message is correct, as project1 builds a SNAPSHOT jar (e.g. project1-0.4.0-SNAPSHOT.jar).
The question is, why does the configuration refer to the non-SNAPSHOT jar when the project is building SNAPSHOT jars? What can I change so that it finds the correct jar?

As a comment :
In my opinion, fatjar is not a great pattern. Maybe Gradle application plugin would fit your need ?

I found the answer to my own question.
The problem was that we have some additional scripting at the project level which is apparantly making a change to the version at the end of the configuration phase.
When the fat jar configuration is assembled, the 'plain' version is used. This is then changed to the -SNAPSHOT version before the jars are built.
Moving the from { ... } code into the build phase by wrapping it in doFirst { ... } is enough to fix the problem, although the real fix is obviously to avoid changing the version in the middle of the in the first place.

Related

Specify jar structure in sbt assembly

When sbt-assembly builds a fat jar, it places all the dependencies in the main folder. I need to construct a jar that looks like this
--domain
domain classes
-- lib
dependency classes
is it possible to do this with sbt assembly, or any other plugin?
If you want to seperate your app jar file and your dependecy jar files, here is the most practical method i found with sbt;
Create project/plugins.sbt file if not exists and add following line:
addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.8.0")
After adding this line refresh your project.
Note: Plugin version might change in time.
When sbt refresh finishes update your build.sbt file like this:
lazy val MyApp = project.in(file("."))
.settings(artifactName := {(
sv: ScalaVersion,
module: ModuleID,
artifact: Artifact) => "MyApp.jar"
})
.settings(packSettings)
Then run:
sbt pack
Or if you're doing this for child project, run this:
sbt "project childproject" clean pack
This will nicely seperate your main jar file and your dependency jars.
Your app jar will be in target scala folder.
Your dependencies will be in target/pack/lib.
In this way you can deploy your dependencies once.
And whenever you change your app, you can just deploy your app jar file.
So in every change you don't have to deploy an uber jar file.
Also in production, you can run your app like:
java -cp "MyApp.jar:dependency_jars_folder/*" com.myapp.App

How to use Gradle to download JAR dependencies on production site?

In the hope of finding the solution on Google as it seems a very general task, I've been trying to do this past few weeks but strangely I couldn't find anything!
What I'm doing:
I am writing an small application, It will be at most a 20KB JAR file in the end. However it has many dependencies, Hibernate and SLF4J to name a few. Directly including these dependencies with the jar file will make it 9Mb.
What is used:
Gradle is used as the build tool. the custom task fatJar creates the jar including all required dependency jar files from (the original) maven repository.
The problem
with my slow internet connection I'd rather not to directly include dependencies, but download these them on the server and not my local production site. What would be the Gradle task like to:
Read the dependencies from jar file
Download them (I know how to do it during Gradle build task).
Add them to class path
Add classpath defined in MANIFEST.mf too
run the jar, by main class defined in MANIFEST.mf
I've read gradle documentation over and over, but no help.

How to unpack dependency jars into the classpath in target?

I am using sbt-osgi to repackage some library dependencies into OSGi packages, and that works well, until I started using scalajs as well. The library dependencies are defined as normal projects something like this:
lazy val bonecp = OsgiProject("com.jolbox.bonecp", buddyPolicy = Some("global")) settings
(libraryDependencies += "com.jolbox" % "bonecp" % "0.8.0-rc1")
The OsgiProject function has default OSGi settings plus some implicits for determining what path the project has. When the bundle task is run on these projects, a new jar with OSGi stuff is created based on the OSGiProject settings. This project just rebundles the bonecp library as an OSGi jar and has no sources. The problem here is that since there's no source, theres no files in target/scala-2.11. This causes sbt-osgi to spit out a ton of ignorable errors, but scalajs is not as forgiving and refuses to do anything with these projects. Is there any good way to unpack the downloaded libraryDependency jars into target/scala-<scalaVersion>?

How to find out which files have changed using Sbt

Sbt can re-run tasks when some of watched files have changed (~task). How to find out which files have changed?
You can add this to your build.sbt to see what files are watched:
watchSources ~= { files =>
println(files.mkString("\n")+"\n\n\n")
files//here you can add files or filter out
}
It might help you to test specific Test classes: ins sbt (interactice mode):
~test-only full.path.test.ClassName
To track file changes in general you can use Java 7 WatchService or Apache VFS for Java 6.
Source: WatchService for Java 6

Add external jars to Eclipse plugin classpath

In the manifest file for an eclipse plugin its possible to add jar files and
folders to the classpath (on the Runtime tab).
In the root of my plugin I have a folder lib containing a-1.0.1.jar, b-1.0.0-SNAPSHOT.jar. But only when I select each jar separately:
Bundle-ClassPath: .,
lib/a-1.0.1.jar,
lib/b-1.0.0-SNAPSHOT.jar
...can they be used inside my project. Why is it not possible to add them to the classpath by adding the common root folder only:
Bundle-ClassPath: .,
lib/
?
No, you can't. Eclipse is based on OSGi, which is the platform providing MANIFEST.MF support to build plugins.
When you set values under Bundle-ClassPath, OSGi search into each one to find class files. So you can put folders containing Java packages and class files. When you put a jar file, it is uncompressed in memory and viewed by OSGi as a regular folder, still searching for class files.
Unfortunately, there is no way to load all jar from a folder. No wildcard mechanism or something like that is allowed here.

Resources