DZone

Monday, January 24, 2011

Bash Script to launch Java Application

If you develop or just use any Java standalone application, you may know it is not comfortable at all to launch it from a linux console. You have to invoke it with the java command this way.

user@host:~$ java -cp myapp.jar:any-thirdparty-lib.jar com.myapp.MainClass some parameters

You can simplify it a lot packaging your application as an executable jar. The file structure should be something like this.

app_home
  lib
    any-thirdparty-lib.jar
  myapp.jar

myapp.jar must contain the special file META-INF/MANIFEST.MF with the following content.

Manifest-Version: 1.0
Class-Path: . lib/any-thirdparty-lib.jar
Main-Class: com.myapp.MainClass

There are a lot of tools to auto-generate it, such as Eclipse export Wizard, Ant task and Maven jar plugin just to mention some.

Last step has reduced a lot the verbosity of the java command. You can invoke an executable jar this way

user@host:~$ java -jar myapp.jar some parameters

It is much better. Isn't it? but still has some problems. Firstly, it is path-dependent, you must be placed at app_home folder for it to work since in the manifest file the dependencies are listed in a relative to the main jar form. Secondly it is not that natural for linux command-line users, it should be much better to just invoke it this way

user@host:~$ myapp some parameters

So, in order to achieve it we will create a really simple yet useful bash script to launch our java app ala linux. I googled it for a while to find an example but without any luck, so I did it myself.
You will need to create a file called myapp in app_home folder with execute permission and with the following content

#!/bin/sh
SCRIPT_PATH=$(readlink -fn $0)
APP_HOME=$(dirname $SCRIPT_PATH)
java -jar $APP_HOME/myapp.jar $@

The first thing to do is to know the real path for the app_home, this way we will be able to invoke it even if we are not placed in the app_home folder. It is the preferred way for invoking a command which works with files, we go to the folder were the files are and it will be more comfortable for passing the file names as parameters.

So, thanks to the especial bash argument $0 we know the path which the script was invoked with. But it is not enough to use it directly, since another nice thing to do with scripts is to create a symbolic link in any folder included in the PATH environment variable, such as ~/bin or /usr/bin so we can just type the script name without including any folder. This way, if we create such link for our app, $0 will be /usr/bin/myapp and we cannot use it for getting the app_home real path. But we solve it with readlink, this way we resolve the link and we get the physical path the link points to.

Once we have the real script path, we use dirname to get the folder it is placed in. Finally, we use the APP_HOME variable to construct the absolute path to our app jar, it will let java to resolve all relative paths in the manifest Class-Path header.

Done. It is just a 3 lines bash script but it let invoke our java applications in a linux-like  manner. I don't know if it is the best solution, but it works, and it can be improved for sure.

Hope it helps you.
Gaston.

No comments:

Post a Comment