Create a FAT source-only jar using Gradle - groovy

I need to create a jar that includes dependencies (a FAT jar) using Gradle.
The catch: the jar needs to only include the straight .groovy files... no .class files.
I've seen the way to do it from the Gradle cookbook: http://docs.codehaus.org/display/GRADLE/Cookbook#Cookbook-Creatingafatjar
and the One-Jar plugin:
https://github.com/rholder/gradle-one-jar
but both ways involved using the compiled .class files instead of the actual source .groovy files. Also, I don't need this jar to be runnable. I just need to be able to reference my .groovy scripts and have the dependencies already be there for them.
Is this possible?

I'm not sure if you even need a .jar file, or a .zip would suffice as it would be confusing to distribute source in a .jar. But independently of what you need, the Zip task is what you want:
task('fatJar', type: Zip) {
extension = 'jar' // overriding default value: 'zip'
classifier = 'fat' // alternatively you can set basename or appending
from(sourceSets.main.allGroovy) // will fail if the groovy plugin isn't applied
from(configurations.runtime) // this includes all your jars needed on runtime
}
Now this is an extremely simple example which will create a file called [projectName]-[version]-fat.jar within build/distributions/ with all your jars in the root of the zip and the groovy source files next to them. You might want to take a look at the documentation of the Gradle Zip task for more options.

Related

How to customize destination path of each dependency

I'm trying to use Gradle to manage dependencies in non-Java projects. The idea is to have a single, generic plugin that along with a project's gradle.build file will bring into the project any dependencies the project needs, placing each dependency where the project expects the files to reside. Currently, it is working by placing them all in a /libs/ folder in the project, but that is not enough. What I'd like to be able to do is to specify in the gradle.build file where to put the dependency in the project.
Here is a simple example: I have a project that has been used for years as a component in other projects. It is a real pain to update all projects when that core component code has been updated... each project repository has to have the new files committed (using SVN, specifically). The files must reside in a particular directory so the ColdFusion framework (FW/1) correctly interacts with the code.
So what has been done is that core component is now in Artifactory and the gradle.build file pulls it down into the projects. That would be the end of the story if it was the only dependency, but there are others that need to be pulled down and the code expects those to be in a different directory than that one component. Each project will have different dependencies, and potentially different file structures (for example, our older apps are using the Fusebox framework). So the ability to control where a dependency ends up as specified in the gradle.build file is what I'm after.
This is what I was hoping to be able to do:
dependencies {
// exploded is a configuration that is added to this plugin
exploded('com.foo:bar:2.0-SNAPSHOT#zip') {
ext {
moveWhat = ['app']
moveWhere = 'assets'
}
}
exploded('com.foo2:bar2:1.0-SNAPSHOT#zip') {
ext {
moveWhat = ['*']
moveWhere = 'lib'
}
}
...
The hope was that I could pass directories/files into moveWhat that would then get placed into the directory specified by moveWhere, but I'm having trouble figuring out how to associate properties with each dependency. I'm having trouble figuring out if this is even possible.
Can anyone point me in the right direction?
I would suggest you use a separate task to extract what you need from the configuration. Something like this:
task copyFromExploded(type: Copy) {
into new File(project.buildDir, "assets")
from (configurations.exploded)
include "**/app"
}

How to make a GDSL file in a jar get picked up in another project in Intellij?

I have a project with a GDSL file that describes a DSL delegate like:
def ctx = context pathRegexp: ".*installer\\.groovy", scope: scriptScope()
contributor(ctx) {
delegatesTo(findClass("com.whatever.InstallerBase"))
}
I package this file up in the jar (just in the root of the jar) using maven.
In a separate project I have a maven dependency on my jar artifact containing the gdsl. However, my autocompletion doesn't work. It works fine with the sample scripts in the first project (with the GDSL).
Is there a step that I'm missing in order for the GDSL to be picked up? Do I need to place it in a special folder in the jar?
The problem was indeed what #PeterGromov indicated in the comment on the question:
ensure that the library jar is only attached as classes and not library source as well
both the source and library were configured and thus IDEA doesn't include it. I have opened a youtrack issue to fix this here:
https://youtrack.jetbrains.com/issue/IDEA-137411

How can symlink affect loading persistence.xml

In my project there're two different persistence.xml appearing in two different jar files after building. If I run application using command like this
/jre/v1.7.0_21/bin/java -cp patch:/path_to_app_jars/*:. org.somepath.MainClass
one of them is loaded but if I run it using symlink another one is peaked up
bin/ -> path_to_app_jars
/jre/v1.7.0_21/bin/java -cp patch:/bin/*:. org.somepath.MainClass
And this result is consistent regardless of what else I change.
How could that be?
My guess is that the expanded jars are returned in a different order when using the symlink, and it is loading the persistence.xml from the first jar listed.
As described in the java documentation, the order in which the jar files are returned when using a directory wildcard (*) is unpredictable. In order to always have the same jar loaded first, the solution is to list the jars explicitly in the classpath instead of using a directory wildcard:
The order in which the JAR files in a directory are enumerated in the
expanded class path is not specified and may vary from platform to
platform and even from moment to moment on the same machine. A
well-constructed application should not depend upon any particular
order. If a specific order is required then the JAR files can be
enumerated explicitly in the class path.

Using Bouncy Castle library causes massive increase in output .jar file size

I'm working on a Java ME/J2ME project which makes use of the Bouncy Castle J2ME library. When adding it to my project, however, I've noticed the resulting .jar file size increases 40 times (50kB vs. 2000kB). Other than setting ProGuard's obfuscator settings to level 9 (max), is there any other way I can minimize this increase in file size?
I'm only using a few of the libraries actual classes, namely:
import org.bouncycastle.util.encoders.Hex;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.crypto.digests.SHA256Digest;
Thanks in advance.
Now this is a very tricky one!
Before anything else please can you unzip your jar file and see if the Proguard has obfuscated the class files of BouncyCastle? Since you have included bouncycastle jar file as a library and there are class files in it so I am assuming the Proguard hasn't obfuscated these class files which are taking much of the space.
Anyways I have just downloaded the bouncy castle jar file and can see it is purely made up of class files, so there are no extra files which we might be able to delete and get rid of to reduce the resultant jar file.
Now If you really want to reduce then read on I am going to produce two solutions, both of them are risky:
Solution 1 (Not Recommended):
This is easy but I wouldn't recommend, It may cause runtime exceptions or errors:
Unzip the bouncycastle jar file. Then navigate to the directory src\org\bouncycastle
As you have mentioned you are only using these below packages
org.bouncycastle.util.*
org.bouncycastle.crypto.*
Now here I will be assuming that the source code inside these two packages is not dependant on the source code/class files inside other packages.
Now delete the other directories namely "asn1", "bcpg". At this stage I will not become a butcher and delete everything but will go by deleting a couple and then come back and delete others if it worked.
Now we will regenerate the jar file. After you have deleted the directories now go back to the root of the directory where you will see other directories like
META-INF
org
utils
This is an important step you need to this correctly otherwise jar file will not work. Select all the directories in the root directory and
then right click-> send to zip
Once the zip file is created then rename it to having *.jar instead of *.zip
The size of the jar file would have reduced and now include this jar file in your project. See if it compiles and executes. Then check
your functionality if it is working correctly at Runtime. If all goes fine, then you are done.
Now you can repeat from above steps to delete further directories to reduce the jar file size.
Solution 2:
Download the source code of the bouncycastle jar file that you are using.
You will have to remove the jar file from the project.
Include the source code into the project. Build the project and see if you dont get any compilation error. You have to be sure at this stage
that you are not using the original jar file, and only using the code.
Now start deleting the packages containing code that you dont need. Keep rebuilding the project that it doesn't come up compilation error,
and if it does then you dont want to delte that package and move on deleting others.
Once this butchring is done then Build the project and generate the jar file.
By this way the Proguard will obfuscate code of bouncy castle and because of deleting most of the code not needed you should get a substantial
decrease in the resultant jar file.

Groovy 2: Cant find JSonSlurper and XmlSlurper anymore

I upgraded to groovy 2 release and now my build is broken.
It fails when importing classes: groovy.json.JsonSlurper and XmlSlurper.
I have checked http://groovy.codehaus.org/gapi/ and cannot find these classes anymore. Do they still exist in groovy 2? Or have they moved somewhere?
The groovy.jar distributed with groovy 2 has been split out to contain just the bare minimum, with all the additional modules (XML, SQL, JSON, etc.) in separate jars. However, in the embeddable directory, you'll find a jar file groovy-all-2.0.0.jar which contains groovy and all the modules together, like previous versions. The easiest way to migrate is to use this jar file.
If you're using Maven Central, you can use an artifactId of groovy-all to get everything, or groovy (plus modules) to have finer grained control over your dependencies. Here's a list of the modules available on Maven Central: http://search.maven.org/#search|ga|1|g%3A%22org.codehaus.groovy%22
Never mind. Need to include groovy-xml and groovy-json jars.
These were split from groovy's jar. See: http://www.infoq.com/articles/new-groovy-20
When I import, groovy-json-2.4.3 and groovy-xml-2.4.3 , JsonSlurper is recognized.
Also refer for new code refactor after 1.8.0 version: Parsing array of JSON arrays in Groovy
I faced a similar issue in Gradle build of a Java project (Gradle uses Groovy).
Gradle stopped including the local Groovy libs in classpath automatically. So, I had to include the following lines (marked with +) in my build.gradle file:
buildscript {
ext {
springbootVersion = '2.x.x'
awsVersion = '1.x.x'
...
}
+ dependencies {
+ classpath localGroovy()
+ }
repositories ...
}
Instead of using "groovy.json.jsonSlurper", use "net.sf.json.groovy.JsonSlurper".
Your script must be running.

Resources