gradle specify classpath via command line arguments - java

I would really like to do something like ./gradlew build -cp /$HOME/my/custom/testerLibrary.jar but I cannot find a straight answer anywhere. I have a special case where I need to add a jar to the class path because the class that I use for manual testing requires it, but nothing else in my project needs it and I don't want to include it in my build.gradle.
Should I create 2 projects where project A is run manually to debug project B?

You can create two JARs from the same source code:
the production application
the manual-testing application
The manual-testing application (2 in the list above) could be created using a Gradle task that appends the required JAR to the classpath:
task createManualTestingApp(type: JavaExec) {
classpath += "/$HOME/my/custom/testerLibrary.jar"
// ...other configuration...
}
If you want the task that creates the production JAR and the manual-testing JAR to be identical, except that the manual testing JAR contains the augmented classpath, this can be done by creating two tasks that extend the same type: How to extend the behavior of a Gradle task for a new task type?
Opinion: From a testing perspective, it is not ideal to have a JAR that is included in the manual-testing application but not in the production application. This results in a test application that is different than the production application. For example, what if that JAR includes something or changes the behavior of the application that causes the manual tests to work but the production application fails because it is missing that JAR? Depending on the nature of the JAR, this may be benign, but it is important to consider when deciding that the test and production applications will be different.

Related

Run mvn package every time I make changes?

Working on a DropWizard project for the first time which uses the docker-config.yml file to run the server using the jar file.
The command I run on the terminal to run the server is something like this:
java -jar target/foo-0.0.1.jar server conf/docker-conf.yml
Do I have to run mvn package every single time I make a change? (for eg: even a small change like adding a System.out.println() statement to debug something)
mvn package is used to create a JAR - a deployable artifact of the application. So if you really want to create the JAR every time, yes you need to package everything.
However, usually if you’re talking about small changes like adding System.out.println I assume that you have some “work-in-progress”. In this case you can configure your IDE to run the class with main method (the Application class in in terms of dropwizard framework). It won’t create a fat jar but for debugging you also don’t really need it.
This is what I (and I believe many of our colleagues) do when working with applications powered by dropwizard, spring-boot (which is similar in this aspect), etc.

Exclude source/class file from deployment only

I'm working on a JavaFX project and there is a framework behind the scenes which handles CDI to inject a context. The problem is that the GUI is part of a bigger application and I want to be able to test it without the need to start the whole application every time. For this, I needed to update a file which is included in a dependency. I copied it to my workspace and added system properties that I can set in my launcher to fake some needed data. Until the dependency is updated to include this behavior, I need to keep the patched class in my project. The problem is, it should not be released.
So basically I want to exclude a java file from deployment but not from compilation so I can use it locally in my project.
I already tried these things:
maven-compiler-plugin: via exclusion I managed to get rid of the file but then it won't compile at all which means that I can't use its functionality in my project
copy the file to src/test/java instead - the file is not visible from the JavaFX form in the main project
maven-assembly-plugin: can't exactly get this to work the way I want it
Did I miss something or is there a way to achieve this with the assembly plugin without interrupting normal deployment?

How to find unnecessary jars in a project

I have some jars in my project. I want to know how these jars are used or what the effects will be if I remove them?
You can achieve it using loosejar.
It is a simple Java Agent that can be used to discover unnecessary
jars lying on application classpath. It performs per classloader JVM
heap analysis and displays its results. loosejar can be safely used
during development, QA, UAT or even in production as it doesn't modify
the state of the JVM at all and adds no overhead.
How to use:
Start your application or application server with
-javaagent:loosejar.jar flag (loosejar.jar should obviously point to the correct path of the actual jar)
Exercise your application to make sure that the classes get loaded
into the JVM.
Get loosejar analysis results via JMX console (open jconsole and run
com.googlecode.loosejar.LooseJarMBean#summary() in MBeans folder) or
on application shutdown (via regular console log).
You are using Maven, so you can use Maven's features to have a look what jars you need. Run the following in the root of your project:
mvn dependency:analyze
And you'll see the line [WARNING] Unused declared dependencies found: with a list of dependencies that you don't actually need.
Try using UCDetector. See here UCDetector

How to load a resource from compound JAR?

I have the following problem:
I am writing an application that uses some of the JARs from the Netbeans Platform. To be exact, I am only using the Netbeans Visual Library for creating some graphs. This can be done without using the Netbeans Platform by extracting 3 JARs from the platform. This is all working well, except for 1 problem.
Some Background
I am using the Java Simple Plugin Framework (JSPF) to handle my plugin management. So I have an application that basically consists of a skeleton framework, and then depending on which plugin JARs it finds, it can do various things, one of which is drawing graphs. The JAR plugin for this functionality has all it's dependant libraries inside. This is done by exporting the JAR as an artifact in IntelliJ, which will unJAR all the dependant libraries and reJAR them inside yours (so everything you need is there).
The Problem
What seems to be happening though, is that when it tries to start use the classes from the embedded libraries, it works fine, but when it needs resources (.png specifically in my case), it complains that it cannot find it.
My Thoughts
The only thing I can think of why it is not working, is that it could be since the plugin JAR is not in a classpath. Could this be it?
Is there anyway to specify a classpath directory in the MANIFEST maybe? Otherwise must I create my own ClassLoader and manually load all the JARs in the plugins directory?
Thank you!
UPDATE:
I have subsequently pinpointed that it is indeed a problem with the classpath. If I place my compound library on the classpath, everything works perfectly. The problem I experience now though is:
If I copy the library to /Library/Java/Home/lib/ext/ it works fine. If I execute the application with java -cp "/path/to/plugins/myLib.jar" -jar Application.jar it does not work.
How can I load all the jars in the plugins directory into my application so the resources inside them can be used?
Thanks again!
So I have finally figured out what was happening. When creating a executable jar, the MANIFEST.MF file overrides any classpath you specify in the command-line, which basically renders it useless if you want to specify external jars. This seems to be a general problem that has been logged since Java 1.3 already.
My simple solution is to simply not create a executable jar, and then launch the application with a script:
java -cp App.jar:plugins/* my.package.structure.App
which works perfectly.
The default classloader's do not load classes in nested jars. You'll need to write your own classloader to get the classes in the nested jars.
You can check out this jspf article...
"I forgot: Adding dependencies as JARs inside JARs is not possible, because it would not work in all scenarios (e.g., applets); IIRC also tools like Eclipse would have problems if you used classes with unresolved (read: runtime-resolved-dependencies). To my knowledge there is no established way yet to gracefully handle nested JARs in all circumstances."
http://code.google.com/p/jspf/wiki/UsageGuide

Whats best way to package a Java Application with lots of dependencies?

I'm writing a java app using eclipse which references a few external jars and requires some config files to be user accessable.
What is the best way to package it up for deployment?
My understanding is that you cant put Jars inside another jar file, is this correct?
Can I keep my config files out of the jars and still reference them in the code? Or should the path to the config file be a command line argument?
Are there any third party plugins for eclipse to help make this easier? I'm using an ant build file at the moment but I'm not sure I know what I'm doing.
Is there an equivelent of the deployment projects in Visual studio, that will figure out everything you need and just make an installer? I've used install4j before, and it was powerful if no where near as automated as .Net deployment projects.
Cheers.
There is no one 'best way'. It depends on whether you are deploying a swing application, webstart, applet, library or web application. Each is different.
On point 2, you are correct. Jar files cannot contain other jar files. (Well, technically they can, its just that the inner jar file won't be on your classpath, effectively meaning that jar files do not contain jar files).
On point 3, you certainly can reference config files outside the jar file. You can typically reference a config file as a file or a resource. If you use the resource approach, it typically comes from the classpath (can be in a jar). If you use a file, then you specify the filename (not in a jar).
In general, most Java developers would use Apache Ant to achieve deployment. Its well documented, so take a look.
(1) An alternative to ant that you may wish to consider is maven.
A brief intro to maven can be found here.
For building a JAR, maven has the jar plugin, which can automate the process of ensuring all dependent jars are listed in your jar's manifest.
If you're using eclipse, then download the maven integration as well.
(2) Another alternative is to use OneJar (disclaimer: haven't tried this myself).
The answers vary depending on what kind of thing you're building.
If you're building a library, it's best to distribute your work as a jar file. It's possible to refer to your jar dependencies via the Class-path attribute in your jar manifest, although I generally think that's uncool. That attribute was designed for applets and it's used infrequently enough in libs that when this technique pulls stuff into the classpath (particularly common stuff the user might already be using), you can get unexpected version conflicts. And it's hard to track down why you're seeing them.
Publishing a jar to a Maven repo with pom info to track dependencies is an excellent choice for libraries as well. If you do that, please publish your Maven coordinates in your docs!
If you're building an app, the two popular choices are to distribute a zip/tar/whatever of a deployment structure OR to use an installer program. If the program is a server-ish kind of thing, the former is far more common. The latter is more common for clients. Generally, the installer program is just going to lay out the deployment structure and maybe do some extra tasks like installing in OS-specific locations.
To build your deployment structure (aka "kit") you'll want to create a repeatable process in whatever build system you're using. Ant has copious examples of this and Maven has the assembly plugins that can help. Generally you'll want to include a jar of your code, any dependencies, scripts to start the program, maybe a JRE, and any other resources you might need.
If you want to create an installer, there are many options both free and commercial. Some folks I know have recently had good experiences with the free IzPack but check out your options.
You should try FatJar. It's an Eclipse plugin that with just a right click at the Project can build a JAR file with all you need to run the application, including the necesary third party JAR.
We use it everyday, in conjuction with JSmooth to create the executables, to deploy our software packages to our customers, and works like a charm.
Well, if you are speaking of deployment of a standalone desktop application:
Before we switched to web start we have been creating three deployment archives, one for windows, one for mac and one for other platforms.
On windows we have successfully used the Nullsoft Scriptable Install System (known for it's usage by the older winamp versions) and its ant task, although some drawbacks are:
It is only usable on windows AFAIR
You have to do some work by hand, i.e. customizing the wizard-created script AFAIR
It can create a windows installation with start menu entries on the other hand. There also exists an eclipse plugin for integrated NSIS shell script editing.
On Mac OS X there is an ant task to create an .app file from your java files so that you can start it like a native os x application. But beware of not writing any setting to your home dir and using the the application dir instead.
For others you have to expect they are in a un*x env and deploy your app with a shell script to start the application.
In any case you may have to deploy your custom policy file to get access rights for your application.
If you want to get rid of all the packaging and stuff you should seriously consider using web start. We have saved much time since switching to it, i.e. simplified our deployment process, takes care of updates etc.
Update 2014
Use maven assembly plugin, see section "Creating an executable jar"
Ant. It's not the best thing in the world, but it's standard, it's apache, and it works.
There's some good examples on the web how to make a simple build.xml for any, and it's got some features like the 'war' task that knows how to put all the basic stuff (classes, web.xml etc) in the jar file for you.
You can also tell it to pick up other config files and jars and it will happily do it.
It's also really smart about what to compile. You give it a directory, and it finds all the java files and builds them only if their classfile is out of date, so you get some of the traditional make functionality for free without much effort.
You could look at other java projects (e.g. JMeter, SquirrelSQL, JEdit, Cernunnos, etc.). Each package their applications slightly differently, so consider your goals when you review these.

Categories

Resources