Using a script to run a standalone jar

I want to demonstrate how to run Dom Parser application using a dos script (batch file). I maybe accessing some parameters in a round about way but that is just to demonstrate some features that one might find handly in a real situation.
I have modified some of the main class for the Dom parser example and the code for the POJO value object remains the same. The mapper.xml is also reused here.
Refer http://cuppajavamattiz.com/2009/03/19/using-jdom-to-map-an-xml-to-a-pojo-bean/ The Main class: ElementMapper.java

package com.mattiz.dom.reader;
 
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.XPath;
 
public class ElementMapper {
    Document doc;
    SAXBuilder builder;
 
    public ElementMapper(String xmlFile) throws Exception {
        try {
            builder = new SAXBuilder();
            // disabling xml validation
            builder.setValidation(false);
            builder.setIgnoringElementContentWhitespace(true);
            doc = builder.build(new File(xmlFile));
        } catch (JDOMException e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());
        } catch (IOException e) {
            e.printStackTrace();
            throw new Exception(e.getMessage());
        }
    }
 
    private ArrayList<ElementsVO> getXMLData() throws Exception {
        ArrayList<ElementsVO> elementsVOArrList = new ArrayList<ElementsVO>();
        try {
            List ElementSetList = ((List) XPath
                    .selectNodes(doc, "//ElementSet"));
            for (int i = 0; i < ElementSetList.size(); i++) {
                Element elementNode = (Element) ElementSetList.get(i);
                // get children of this parent
                List<Element> elementList = (elementNode)
                        .getChildren("Element");
                // iterate over list of list
                ElementsVO elementsVO = null;
                for (Element element : elementList) {
                    elementsVO = new ElementsVO();
                    elementsVO.setGroup(elementNode.getAttributeValue("group"));
                    // get ChemicalSymbol child
                    Element ChemicalSymbolSibling = element
                            .getChild("ChemicalSymbol");
                    elementsVO.setLatinName(ChemicalSymbolSibling.getAttribute(
                            "latin").getValue());
                    // get value of ChemicalSymbol element
                    String chemicalSymbol = ((Element) ChemicalSymbolSibling)
                            .getValue();
                    // get ChemicalName child
                    Element ChemicalNameSibling = element
                            .getChild("ChemicalName");
                    // get value of ChemicalName element
                    String chemicalName = ((Element) ChemicalNameSibling)
                            .getValue();
                    // setting to valueobject
                    elementsVO.setChemicalSymbol(chemicalSymbol);
                    elementsVO.setChemicalName(chemicalName);
                    // add to arraylist
                    elementsVOArrList.add(elementsVO);
                }// for
            }// for
        } catch (Exception ex) {
            throw new Exception();
        }
        return elementsVOArrList;
    }
 
    public static void main(String args[]) {
        String xmlLocation = null;
        String xmlFileName = null;
        try {
            File file = new File(
                    System.getProperty("mattiz.domReaderConfigLocation"));
            InputStream is = new FileInputStream(file);
            Properties sqlCache = new Properties();
            sqlCache.load(is);
            xmlLocation = sqlCache.getProperty("XMLlocation");
            if (args.length != 0) {
                xmlFileName = args[0];
            } else {
                System.out.println("Usage: domreader.bat {xml_file_name}");
                System.exit(-1);
            }
            ElementMapper elmapper = new ElementMapper(xmlLocation + "\\"
                    + xmlFileName);
            List<ElementsVO> elementsList = elmapper.getXMLData();
            for (ElementsVO vo : elementsList) {
                System.out.print("  GROUP IS " + vo.getGroup());
                System.out.print("  CHEMICAL NAME IS " + vo.getChemicalName());
                System.out.print("  CHEMICAL SYMBOL IS "
                        + vo.getChemicalSymbol());
                System.out.println(" LATIN NAME IS " + vo.getLatinName());
                System.out.println("************");
            }
            System.exit(0);
        } catch (Exception e) {
            e.printStackTrace();
            // handle exception
            System.exit(-1);
        }
    }
}

build.xml

<?xml version="1.0" encoding="UTF-8"?>
<project name="DomReader" default="clean" basedir=".">
    <property environment="env" />
    <property name="build.dir" location="./build" />
    <property name="build.classes.dir" location="${build.dir}/classes" />
    <property name="build.dist.dir" location="${build.dir}/dist" />
    <property name="lib.dir" location="./lib" />
    <path id="build.path">
        <pathelement location="${lib.dir}/jdom.jar" />
        <pathelement location="${lib.dir}/jaxen-core.jar" />
        <pathelement location="${lib.dir}/jaxen-jdom.jar" />
        <pathelement location="${lib.dir}/saxpath.jar" />
    </path>
    <target name="clean" depends="jar">
        <delete dir="${build.classes.dir}" />
    </target>
    <target name="init">
        <mkdir dir="${build.dir}" />
        <mkdir dir="${build.classes.dir}" />
        <mkdir dir="${build.dist.dir}" />
    </target>
    <target name="compile" depends="init">
        <javac srcdir="${basedir}" destdir="${build.classes.dir}" debug="on"
            deprecation="on" classpathref="build.path" optimize="off" />
    </target>
    <target name="jar" depends="compile">
        <jar destfile="${build.dist.dir}/DomReader.jar">
            <fileset dir="${build.classes.dir}" includes="**/*.class"
                excludes="**/*.java" />
        </jar>
    </target>
</project>

The structure of the project resources on the Eclipse IDE I am using can be deduced from the property attribute values in the build.xml, so I am not describing that.
Runing the build.xml will produce DomReader.jar under DomReader/build/dist
I have created the following folder structure to place the resources to run the jar from a script.

<dom-xml>
      domreader.bat
      DomReader.jar
      <lib>
           jdom.jar
           jaxen-core.jar
           jaxen-jdom.jar
           saxpath.jar
      <config>
           domreader.properties
      <xml>
           mapper.xml

The jar files will be found in the JDOM installation as mentioned in the previous post.
Here is the content of domreader.properties:

XMLlocation=.\\xml

Finally domreader.bat has the following contents:

REM Environment variables
set JAVA_HOME=”C:\Program Files\Java\jre1.6.0_02″
set CONFIGURATION_LOCATION=.\config\domreader.properties
set REQUIRED_JARS=.\DomReader.jar;.\lib\jdom.jar;.\lib\jaxen-core.jar;.\lib\jaxen-jdom.jar;.\lib\saxpath.jar;%classpath%
echo off
%JAVA_HOME%\bin\java -cp %REQUIRED_JARS%; -Dmattiz.domReaderConfigLocation=%CONFIGURATION_LOCATION% com.mattiz.dom.reader.ElementMapper %1
echo Exit Code : %ERRORLEVEL%

In the java code you can get path of domreader.properties by doing
System.getProperty(“mattiz.domReaderConfigLocation”);
where mattiz.domReaderConfigLocation property has been defined in the script and contains the path to the directory that hold the xml file. (directory could be absolute or relative path, it doesn’t matter)
The params to the script(in this case name of the xml file) is being passed on as is to the java program… See %1 at the end of the script.
So in the main method of the java program args[0] will give you the name of the xml file in this case mapper.xml
In this example, I have put the DomReader jar in the current directory (where script is being executed) and the remaining jars in a subfolder called lib; and properties file in a subfolder called config while the xml file is in a subfolder called xml.

Run the script using
domreader.bat mapper.xml
standing at dom-xml folder.

The output should be something like this:

D:\work\projects\JAVA6SANDBOX\dom-xml>domreader.bat mapper.xml
D:\work\projects\JAVA6SANDBOX\dom-xml>REM Environment variables
D:\work\projects\JAVA6SANDBOX\dom-xml>set JAVA_HOME="C:\Program Files\Java\jre1.6.0_02"
D:\work\projects\JAVA6SANDBOX\dom-xml>set CONFIGURATION_LOCATION=.\config\domreader.properties
D:\work\projects\JAVA6SANDBOX\dom-xml>set REQUIRED_JARS=.\DomReader.jar;.\lib\jdom.jar;.\lib\jaxen-core.jar;.\lib\jaxen-jdom.jar;.\lib\saxpath.jar;.;
D:\work\projects\JAVA6SANDBOX\dom-xml>echo off
GROUP IS Reactive Elements CHEMICAL NAME IS Sodium CHEMICAL SYMBOL IS Na LATIN NAME IS Natrium
************
GROUP IS Reactive Elements CHEMICAL NAME IS Potassium CHEMICAL SYMBOL IS K LATIN NAME IS Kalium
************
GROUP IS Metals CHEMICAL NAME IS Antimony CHEMICAL SYMBOL IS Sb LATIN NAME IS Stibium
************
GROUP IS Metals CHEMICAL NAME IS Copper CHEMICAL SYMBOL IS Cu LATIN NAME IS Cuprum
************
GROUP IS Metals CHEMICAL NAME IS Tin CHEMICAL SYMBOL IS Sn LATIN NAME IS Stannum
************
Exit Code : 0

We could use the following shell script to run the jar on a Linux machine. The shell script should be placed in the same directory structure where the batch file stood.

#!/bin/bash
## Environment variables
export JAVA_HOME=/space/java/jdk1.5.0_07
export JAR_CLASSPATH=./DomReader.jar:./lib/jdom.jar:./lib/jaxen-core.jar:./lib/jaxen-jdom.jar:./lib/saxpath.jar
export CONFIGURATION_LOCATION=./config/domreader.properties
# If we got less than 1 arg, print usage and exit
if [ $# -lt 1 ]; then
echo 'Usage: domreader.sh {mapping xml file}'
exit -1
fi
$JAVA_HOME/bin/java -cp $JAR_CLASSPATH -Dmattiz.domReaderConfigLocation=$CONFIGURATION_LOCATION com.mattiz.dom.reader.ElementMapper $*
exit $exitValue

Tips
* The params to the shell script is being passed as is to the java program… See $* at the end of the shell script.
* Remember to specify the below as the first line of the sh script. You want to be sure the script is executed in bash and not some other shell, csh, ksh etc.
#!/bin/bash

* If you want to return the exitValue to the calling program, assuming some other shell script is invoking your shell script, and wants to know the status you can do it by
exit $exitValue
* Don’t forget to make the shell script executable.
chmod ugo+x *.sh

Call the script thus: domreader.sh mapper.xml

About cuppajavamattiz
Matty Jacob - Avid technical blogger with interests in J2EE, Web Application Servers, Web frameworks, Open source libraries, Relational Databases, Web Services, Source control repositories, ETL, IDE Tools and related technologies.

Comments are closed.

%d bloggers like this: