Go to content Go to sidebar

Building an executable jar with Ant

An executable jar file has a defined default class, allowing the default class to be invoked without explicitly identifying it via the command line. On a supporting OS (such as Mac OS/X or Microsoft Windows), this allows the class to be invoked by double-clicking the file.

I know that making a jar file executable requires an entry in the manifest file. I can usually remember that the attribute in question is Main-Class (although I'm usually fuzzy about the proper capitalization). The problem is remembering the correct command line options to insert my own MANIFEST.MF file into a jar file.

All in all, it is much simpler to just use ant to handle it for me. Let's start with the example from my Ant Hello World Revisited. The new ant build file follows, with the new lines shown in bold. Note that I've also designated the "jar" task as the default task.


$ cat hello.xml
<project default="jar">
  <target name="compile">
    <javac srcdir="." />
  </target>
  <target name="jar" depends="compile">
    <jar destfile="hello.jar"
         basedir="."
         includes="**/*.class">
      <manifest>
        <attribute name="Main-Class" value="hello" />
      </manifest>
    </jar>
  </target>
</project>
$ cat hello.java public class hello { public static void main( String[] args ) { System.out.println( "Hello World" ); } }

Now we simply build our jar file:


$ rm *.jar
$ ant -f hello.xml
Buildfile: hello.xml

compile:

jar: [jar] Building jar: /Tutorial/Ant/Jar/hello.jar

BUILD SUCCESSFUL Total time: 2 seconds

And execute the default class by using the -jar command line option to java:


$ java -jar hello.jar
Hello World

Disclaimer: I don't claim to be an expert on ant. Please send comments and corrections.


Java Web Service Messages Client Redux

What's the simplest thing that …

I'm sure that my colleagues are tired of me asking "What's the simplest thing …". But simple things are focused on just one thing. And when the simple thing fails, then there is just one thing to check. In furtherance of the "simplest thing", here is an updated Java Web Services Message Client pointed at a publicly available web service. Thanks to Sean Collins of XML Me for allowing us to use their web service.

This client reads an input document from standard input, invokes a web service, and then prints the web service response. It has been updated to support the SOAPActionURI required by the Shakespeare web service and to force a newline between XML elements (changes are shown in bold). The results shown here use Java 1.4.2_11 and Axis 1.3.


import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import org.apache.axis.constants.Style;
import org.apache.axis.Message;
import org.apache.axis.message.SOAPEnvelope;


public class Invoke {

    public static void main ( String[] args )
        throws Exception
    {
        String endpoint   = "http://www.xmlme.com/WSShakespeare.asmx";
        String action     = "http://xmlme.com/WebServices/GetSpeech";
        /*
         * Two optional command line arguments:
         *   the web service uri
         *   the web action uri
         */
        switch(args.length) {
        case 0:
            break;
        case 1:
            endpoint = args[0];
            action   = null;
            break;
        case 2:
            endpoint = args[0];
            action   = args[1];
            break;
        default:
            System.out.println( "Usage java -cp $AXISCLASSPATH Invoke [WebServiceUri] [WebActionUri] < data.xml" );
            System.exit(2);
        }
        /*
         * Read input
         */
        String document = streamToString( System.in );
        System.out.println( document );
        System.out.println( "Invoking " + endpoint + "\n" );
        /*
         * Pass to web service
         */
        Service service = new Service();
        Call call       = (Call) service.createCall();
        call.setTargetEndpointAddress( new java.net.URL(endpoint) );
        call.setOperationStyle( org.apache.axis.constants.Style.MESSAGE );
        if ( action != null ) {
            call.setProperty(Call.SOAPACTION_USE_PROPERTY,Boolean.TRUE);
            call.setProperty(Call.SOAPACTION_URI_PROPERTY,action);
        }
        SOAPEnvelope envelope = call.invoke( new Message(document) );
        /*
         * Print the Web Service return
         */
        System.out.println( envelope.getBody().toString().replaceAll("><",">\n<") );
    }

    /**
     * Utility to read textual data from in InputStream to a String
     */
    public static String streamToString( java.io.InputStream is )
        throws java.io.IOException
    {
        java.io.InputStreamReader ir = new java.io.InputStreamReader(is);
        java.io.BufferedReader    in = new java.io.BufferedReader(ir);

        StringBuffer buffer = new StringBuffer();
        {
            String line = null;
            while( (line=in.readLine()) != null ) {
                buffer.append( line );
                buffer.append( '\n' );
            }
        }
        return buffer.toString();
    }
}

And here is the client in action. For brevity, I've requested a Shakespeare speech containing those famous words "Hello, World". You may want to request something more along the lines of: "dogs of war" or "unto the breach".

12 $ javac -classpath $AXISCLASSPATH Invoke.java
13 $ java -classpath $AXISCLASSPATH Invoke < data/speech.xml
<?xml version="1.0" standalone="yes" ?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:ns="http://xmlme.com/WebServices">
  <soap:Body>
    <ns:GetSpeech>
      <ns:Request>Hello, World</ns:Request>
    </ns:GetSpeech>
  </soap:Body>
</soap:Envelope>

Invoking http://www.xmlme.com/WSShakespeare.asmx

<soapenv:Body xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<GetSpeechResponse xmlns="http://xmlme.com/WebServices">
<GetSpeechResult>&lt;MESSAGE&gt;Speech not found.&lt;/MESSAGE&gt;</GetSpeechResult>
</GetSpeechResponse>
</soapenv:Body>
14 $

Feb 9 08: Examing your Java app with a debugging proxy.


Two weeks with Vista

The IT powers that be are ordering our new computers with Vista. And lacking a compelling argument against it, I’m now using a shiny new laptop running Windows Vista Business.

With two weeks of usage under by belt, I have to say “eh”. I haven’t found anything compelling for Vista over XP. While Vista starts up much faster, it shuts down much slower to make up for it. [And yes, I have looked at advanced settings on the Control Panel Performance for advice].

While I wouldn’t advise running away from Vista, I wouldn’t advise rushing to embrace it either. My advice would be to stall and hope that XP wins another reprieve.


Housekeeping

I’ve completed some general housekeeping here at Take the First Step. If I’ve done it correctly, then there will be fewer 404 – Not Found errors around here.

The first step for the budding webmaster is to register your site at Google Webmaster Tools. That will you a window into how Google sees your site. I like to check once a week to make sure that the Googlebot can find everything that it is looking for.

The next step is to learn how to interpret your web server log files. Your mileage may vary, but here’s how I look for 404 errors:

$ zgrep -w 404 access_log.20080512.gz | cut -d ' ' -f7,11 | uniq -c
   1 /blog/2004/09/27.html "-"
   2 /blog/topic/software/2003/08/18.html "-"
   1 /id/1319/jms-providers/ "-"
   1 /id/1318/leopard-part-4/ "-"
   1 /id/1317/brief-history/ "-"
   1 /id/1316/march-drabness/ "-"
   1 /id/1315/march-madness-08/ "-"
where:
"zgrep -w 404" retrieves lines with the word 404 from my compressed access logs
"cut -d ' ' -f7,11" defines a space as field delimiter and retrieves the 7th and 11th fields from those lines
"uniq -c" shows the unique lines preceded by the instance count

Here we see some failing radio userland links and a mis-behaving client that is adding a trailing '/' to my page links. A little htaccess magic and the 404's are cured.


Open Source JMS Providers

I’d like to take a look at JMS and the leading contenders for an open source JMS provider seem to be:

Circumstances are pushing me to JORAM by a process of elimination:

  • ActiveMQ seems to be happiest with Java 1.5
  • The last release of OpenJMS seems to have been back in June 2006
  • JBoss Messaging appears to only run inside of JBoss

I’ll let you know how things work out.


Leopard Configuration IV

  1. Map the Caps Lock key to a second Control key via System Preferences.
  2. To be Continued …

The full configuration list can be viewed at my MacBook Configuration Log.


Brief History of Blogging

  • Gold Blogging is discovered
  • Gold Blog rush begins
  • Early prospectors bloggers stake claims
  • Some get rich, most get blisters, merchants make a bundle selling
  • Disillusioned miners bloggers abandon claims blogs
  • Disputes begin over ownership role in history

I was going to comment on: Writers Blog Till They Drop, but Marc Andreessen got there first: New York Times covers blogging. And I somehow ended up with this. Go figure.


« Previous