Executing a Java running application from a Jar or Batch file - java

I have a Java application and a build file which, among its tasks, has one task to create a jar file from the application and one to run the application
<!-- ===== Create An Executable Jar target ======-->
<target name="jar-task" depends="compile-task">
<mkdir dir="${jar.dir}"/>
<jar destfile="jar/Guix.jar" basedir="${gui_bin.dir}">
<fileset dir="${basedir}">
<include name="img/**/" />
</fileset>
<manifest>
<attribute name="Main-Class" value="sys.deep.cepu.Start"/>
</manifest>
<filelist dir="${basedir}" files="user.properties"/>
</jar>
</target>
<!--
============ Run target ===================
-->
<target name="run-task" depends="jar-task">
<java classpath="${basedir};jar/Guix.jar;CK-DASP-2.0.0.jar;library/*;user.properties;img/* " classname="sys.deep.cepu.Start" fork="true">
</java>
</target>
The build file runs perfectly, the jar is created and the application runs. I would like to allow the user to start the application by clicking on a single file (jar or batch file). I tried to click on the generated executable jar file but nothing happens. Is it normal? Can someone give me an help on how to execute the program from this jar or from a batch file? Thanks!

Yes, this is normal. You have to start it from command line or via batch script. Try using as a batch script (if you have a MANIFEST.MF) added to your jar.
java -ea -jar Application.jar <Parameters>
or otherwise:
java -cp jar-file packageOfMainClass.MainClass

When building you jar file you already specify the Main-Class. But you did not specify the required libraries in the manifest file, only in the ant file when running the application.
Write another manifest attribute into the ant-file. The name should be Class-Path, the value a space separated list of libraries. Look here (Wikipedia) for an example.
After that your application should start when entering
java -jar Guix.jar
Then follow the step described in this question to make it startable with a double click.

Alternate ways to run a jar file
java -jar jar-file
java -cp jar-file MainClassNameFullyQualified

Related

.POST_MODULE: Failed to process phase POST_MODULE of deployment

I'm trying to generate a war using an Ant script, but it seems that it won't run on jboss. Anyone knows the diference between this and create a war using Eclipse(File ->Export -> War)?
<war warfile="${docflow4-web-home}/deploy/${nome}.war" webxml="web/WEB-INF/web.xml">
<fileset dir="${docflow4-web-home}/web">
</fileset>
</war>
In Eclipse, optionally, there is a supply WAR export Options, such as whether or not to include Java™ source files in the WAR, and whether to overwrite any existing resources during the export process. Source files are not usually included in a WAR file, because they are not necessary for the server to run the web application. Otherwise, everything is similar to ant script.
In Ant script, your script seems alright, but it is aways nice using the tag , for example: <classes dir="${classes.dir}" /> because it defines a grouping to specify what goes into the WEB-INF\classes folder.
If you are using some third part jar, use the tag lib too, example:
<lib dir="thirdpartyjars">
<exclude name="portlet.jar"/>
</lib>

Setting Class-Path in Ant build script

I'm trying to build my console application and I'm using Ant to build it. I can run my application in Eclipse, but when I try to run it from jar that I get - the ClassNotFoundException: is thrown. is in one of jars, that I use for my application. Here is a part of build.xml where I create manifest:
<manifest>
<attribute name="Main-Class" value="com.package.Reporter" />
<attribute name="Class-Path" value="lib/commons-httpclient-3.1.jar
lib/commons-logging-api.jar
...lot of jars...
lib/stax-api-1.0.1.jar" />
</manifest>
The required class is in commons-httpclient-3.1.jar
And here is how I set up classpath for compiling, that is fine:
<path id="libs.dir">
<fileset dir="lib" includes="**/*.jar"/>
</path>
UPD: Should I put jars with libs to my jar? Now I'm putting them to "lib" directory of my jar. So myjar.jar contains package with my classes, META-INF directory and lib directory.
Max, you can't insert jar libs into jar, assuming normal usage. Either you don't have to specify them manually at runtime as Romski suggested. When invoking java -jar myjar.jar it should locate all your jars provided that they are located in the lib directory. lib directory must be in the same directory that jar resides in. Doesn't matter if you call java executable directly or through ant java task.
Note that the current directory doesn't matter only the relation between the jar and the lib.
Now being overly explicit. Perform sanity test as follows: create a new tmp directory and copy files to it:
tmp/myjar.jar
tmp/lib/commons-httpclient-3.1.jar
Run java -jar tmp/myjar.jar
Edit: now I see I just wrote the same what is in Oracle jar tutorial. But I also made tests myself with a relative directory. I also see dozens of stackoverflow questions searching for jar in jar so please first search SO, then ask.
try to change the path like this.
<path id="libs.dir">
<fileset dir="./lib" includes="**/*.jar"/>
</path>
You need the manifestclasspath task.
Example:
Ant - how to get all files' name in a specific folder

How do I load optional task sshexec into Ant in a no-configuration manner?

I am using sshexec, which depends on jsch-0.1.48.jar. I can't just put that into the ant/lib directory because other users wishing to use the same build script will have to make a configuration on their machine before they can do so.
What I want to do is to be able to reference jsch-0.1.48.jar as part of the project. Currently, I have it sitting in project/libs directory and I am trying something like:
<property name="lib" location="lib"/>
<taskdef name="sshexec" classname="org.apache.tools.ant.taskdefs.optional.ssh.SSHExec">
<classpath>
<pathelement location="${lib}/jsch-0.1.48.jar"/>
</classpath>
</taskdef>
<target name="sshcmd" description="ssh command">
<sshexec host="X.X.X.X" username="USER" password="PASS" command="cmd" trust="true"/>
</target>
But that's not working:
C:\dev\trunk\project:>ant sshcmd
Buildfile: C:\dev\trunk\project\build.xml
BUILD FAILED
C:\dev\trunk\project\build.xml:275: taskdef A class needed by class org.apache.tools.ant.taskdefs.optional.ssh.SSHExec cannot be found: com/jcraft/jsch/Logger
using the classloader AntClassLoader[C:\dev\trunk\project\lib\jsch-0.1.48.jar]
Total time: 0 seconds
The sshexec task is built into ANT, you do not need to invoke a taskdef operation to use it. All that's missing is the jsch jar.
This can installed using a bootstrap target as follows (from Maven Central):
<target name="bootstrap" description="Install missing jars">
<mkdir dir="${user.home}/.ant/lib"/>
<get src="http://search.maven.org/remotecontent?filepath=com/jcraft/jsch/0.1.48/jsch-0.1.48.jar" dest="${user.home}/.ant/lib/jsch.jar"/>
</target>
This target only needs to be run once, after which the ANT sshexec task will work as expected on the developer's PC.
Update
If you don't want to download jars another mechanism to pass the location of ANT libraries from the command line as follows:
ant -lib /path/to/project/lib/dir ...
For more details on ANT library management, I refer you to the ANT manual
The jsch jar is packaged with my project. So instead of downloading it, I am copying it into the ant library. The build will fail the first time it is run, which is fine for my purposes. It will succeed the second time because the jar will be in the library and would be loaded at start.
<target name="jschset" description="Set the jar">
<copy file="${lib}/jsch-0.1.48.jar" tofile="${ant.home}/lib/jsch-0.1.48.jar"/>
</target>

Trying to get a properties file from a jar file in another jar file

I have an executable jar file (A.jar), built with Eclipse, that relies on other jar files (B.jar) that are included in the jar file, and accessed via the jarinjarloader. While this works to access the java code inside those jar files, when that code calls
InputStream inStream = <Class>.getClassLoader().getResourceAsStream(propFile);
it fails to find the properties file contained in B.jar. The code works when run in Eclipse, so I know the correct properties files are there.
I tried extracting A.jar, then extracting B.jar, and then zipping up the combined files, but this does not work. Looking at the Manifest file, the Main-Class is org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader
Is there some change I can make to the Manifest file (say, adding something to Rsrc-Class-Path) that will get this to work? Rsrc-Class-Path includes "./" already, but that clearly isn't letting the properties loader see my properties files.
TIA,
Greg
I'd also recommend working around nested jars. I usually just do this in my build.xml to build one jar with all the libraries unpacked into it:
<target name="fatjar" depends="compile">
<jar destfile="${isamjar}" filesetmanifest="mergewithoutmain">
<manifest>
<attribute name="Main-Class" value="com.xyz.Main"/>
<attribute name="Class-Path" value="."/>
</manifest>
<fileset dir="./bin"/>
<fileset dir="." includes="src/**"/>
<zipfileset excludes="META-INF/*.SF" src="${l}/derby.jar"/>
<zipfileset excludes="META-INF/*.SF" src="${l}/jconn3.jar"/>
<zipfileset excludes="META-INF/*.SF" src="${l}/log4j-1.2.9.jar"/>
<zipfileset excludes="META-INF/*.SF" src="${l}/${jar4j}"/>
</jar>
Turns out Eclipse has a setting I missed. When Exporting a "Runnable JAR File" you can select "Extract required libraries into generated JAR". while this may give some license issues (depending upon the JARs you're merging in), in my case it worked like a charm, giving me a single (smaller, since there were a lot of duplicates among the various jar files I'd been including) jar that actually worked.

Java: How to compile a runnable jar from packages?

My Java application has got a package structure similar to this:
src/com/name/app
src/com/name/app/do
src/com/name/utils/db
How would I go about compiling Java files in these directories in to a runnable jar? I need to package required libraries into the generated JAR (jdbc).
I've always done these things in Eclipse but now I need to supply a couple of people with a way to compile the repository without the use of eclipse and I was thinking of making a makefile or a script that invokes the necessary javac pattern.
Take a look at Ant. It's a relatively simple build tool to understand, and provides everything that meets your requirements. Here's a quick skeleton build.xml to get you started:
<project name="my_app_name" default="jar">
<target name="compile">
<javac srcdir="src" destdir="bin">
<classpath>
<fileset dir="lib">
<include name="**/*.jar" />
</fileset>
</classpath>
</javac>
</target>
<target name="jar">
<jar manifest="manifest_file" destfile="dist/my_app_name.jar">
<fileset dir="bin" />
<fileset dir="lib" />
</jar>
</target>
You need to create a manifest file that will tell the java process which class holds the "main" method. Here is a good place to start learning about manifests.
As an alternate that produces really cluttered Ant build files, you can right click on your Eclipse project and choose "Export...", then choose "General > Ant Buildfiles".
Anyway, that should get you started. You can ask more specific questions as you run into them.
First of all, consider using Ant for such a task.
But since you asked for a manual process, you need to first create a manifest file, like so:
Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
Class-Path: lib/jdbc.jar lib/otherlib.jar
Main-Class: com.name.app.MainClass
Replace the contents of Class-Path with your libs, and Main-Class with the fully qualified name of your main class.
Then, you need to generate the actual .jar, using the following command:
jar cfm app.jar MANIFEST.MF src/com/name/app/*.class src/com/name/app/do/*.class
Where MANIFEST.MF is the previously mentioned manifest file, and the rest is the folders where your .java classes lie in.
Finally, to run your app, you simply execute: java -jar app.jar.
Consider using Ant to do this. http://ant.apache.org/
I recommend that you use Apache Ant to implement your build scripts.
If implemented correctly, Ant is easy to use and the build scripts can be run on any platform that you can install a JDK on. Indeed, with a little bit of work, you can even set up your project so that users don't even need to download / install Ant. (Hint: add the Ant JAR files and a wrapper script to your project distro)

Categories