Friday, October 30, 2009

MAC/IP lookup

I was trying to figure out more about a MAC address and found an interesting lookup mechanism:
To be concise, all lookups on one page:

Thursday, October 29, 2009

Automatic Restart Script for a Java service

This blog tries to describe a pattern on how to write a pragmatic Unix start and stop script for an automatically restarting Java service.
In many cases, you might want to write a Java service that should be up and running 24x7. Now in theory the garbage collector should deal with everything, and if programmed correctly, the process should never crash. But in praxis, things do happen. For example a web service could encounter user requests where memory use is much bigger than you ever expected.
What is a good maximum heap size anyway ?
A pragmatic approach is just to face the fact that your JRE could run out of memory and deal with it. There are sophisticated monitoring solutions out there to automatically restart processes (e.g. nagios/ganglia), but a poor-man's solution is to automatically restart the JRE from the Unix start script.
Please note, you don't want to restart in every case. A bad command line option should just stop the process and not run into the restar loop. Also, there must be a clean way to manually stop it.
Under these constraints, the best solution I could find is to create a temporary file from the Java code at exactly the point 'of no return'. If the JRE stops before this point, no restart happens. If the JRE stops after this point, automatic restart will kick in.
... parse command line options ...
 
     // register shutdown hook      Runtime.getRuntime().addShutdownHook(new ShutdownHook(...));
     // register uncaught exception handler
    Thread.currentThread().setDefaultUncaughtExceptionHandler( new UncaughtExceptionHandler() {
      public void uncaughtException(Thread t, Throwable e)
      {
        e.printStackTrace();
        if( e.getClass()==java.lang.OutOfMemoryError.class ) {
      
          System.err.println("FATAL: shutting down because of java.lang.OutOfMemoryError ...");
          System.exit(7);
        }
      }} );

    File restart = new File("webservice.restart"); // tell the shell to restart me
    restart.createNewFile();

... start your service ...
The Unix start script below will restart the JRE if, and only if, the temporary file (webservice.restart) exists. This could go like this:
#!/bin/sh

#try to start service once
${JAVA_HOME}/bin/java -DREPLAYWEB ${JOPT} com.codestreet.replay.jms.shell.web.ReplayWeb $*

# restart again (until webservice.restart file was removed)
while [ -f webservice.restart ]; do
echo "### RESTART ###"
/bin/rm -f webservice.restart # let Java decide if we really want to restart
${JAVA_HOME}/bin/java -DREPLAYWEB ${JOPT} com.codestreet.replay.jms.shell.web.ReplayWeb $*
done

So Java decides if the service should be restarted and the shell actually performs the restart.
An alternative would have been to simply use return codes from System.exit() ?
But then the question would be: what's the return code with a not yet known exception ?
If someone else uses kill-9 on the jre, a shutdown hook wouldn't be invoked. And to manually stop the restarting you would have to kill the start script as well as the JRE.
With this file-based approach, the stop script is pretty simple: remove the temporary file and kill the JRE. Please note that finding the proper Java process is not as simple as it seems since the classpath is usually very long and 'ps -f' potentially won't show the classname anymore because the line gets too long. On Linux you can use the --col option to see a longer output, but that doesn't work on Solaris :-(
So a little trick around this is to use a dummy JRE property, -DREPLAYWEB in this case. This mock up property has no meaning except that it will show up in ps before the classpath and you can make it unique enough to identify only this instance of JRE.
The stop script would then perform these steps:
  1. get the 'ps line' that contains the dummy JRE property (REPLAYWEB)
  2. get the task id of that process (awk is good enough)
  3. remove the temporary restart file so the start script won't restart automatically
  4. kill the process
#!/bin/sh -f

psline=`/bin/ps -aef | /bin/grep "REPLAYWEB" | /bin/grep -v grep`
echo $psline
pid=`echo $psline | /bin/awk '{ print $2}'`
if [ $pid ]
then
 /bin/rm -f webservice.restart
 echo "stop_webservice: killing Web Service with pid=$pid"
 kill $pid
else
 echo "stop_webservice: Web Service was not running"
fi

Thursday, October 15, 2009

JAX-WS inside Jetty

Jetty is a nice and easy to use Web Server (see previous post), but it can it handle an open standards, heavy weight JAX-WS Web Service ?
With a bit of luck and glue code, it can.
So first we need a Service Provider Implementation (SPI) from Jetty: J2se6HttpServerSPI
This will make the JAX-WS endpoint use the Jetty server instead its default Sun HttpServer.
To plugin different SPI's you would define this new service in a META-INF/services file, but you can also set a system property, as described here. You can even do this in code which reduces the number of files you need to worry about when refactoring.
So here's an example of a Jetty Server handling a JAX-WS endpoint in combination with a File system directory.
      Server jettyServer = new Server(port);
     HandlerCollection handlerCollection = new HandlerCollection();
     jettyServer.setHandler(handlerCollection);
    
     /** 1) Publish WebService (JettyHttpServerProvider) */ 
     String context = "/web/ws";
             
     // 1.1) register THIS Jetty server with the JettyHttpServerProvider
     new JettyHttpServerProvider().setServer(jettyServer);
      
     // 1.2) make sure JAX-WS endpoint.publish will use our new service provider: JettyHttpServerProvider
     System.setProperty("com.sun.net.httpserver.HttpServerProvider",
           "org.mortbay.jetty.j2se6.JettyHttpServerProvider");
      
     // 1.3) add an empty HandlerCollection to by setup by this provider
     handlerCollection.addHandler( new HandlerCollection() );
      
     // 1.4) use JAX-WS API to publish the endpoint (will use a JettyHttpServerProvider)
     Endpoint endpoint = Endpoint.create(replayServiceImpl);
     endpoint.publish("http://localhost:" + port + "/web/ws", replayServiceImpl);
    
     /** 2) Publish WebGUI (Jetty) */       
     String context = "/gui";

     // 2.1) configure File Resource Handler
     ResourceHandler fileResourceHandler=new ResourceHandler();
     fileResourceHandler.setWelcomeFiles(new String[]{"index.html"});
     fileResourceHandler.setResourceBase(guiPath); // start here
       
     // 2.2) configure 'gui' Context
     ContextHandler guiHandler = new ContextHandler();
     guiHandler.setContextPath(context);
     guiHandler.setResourceBase(".");
     guiHandler.setClassLoader(Thread.currentThread().getContextClassLoader());
     guiHandler.setHandler(fileResourceHandler);
      
     // 2.3) add this context handler
     handlerCollection.addHandler(guiHandler);
 
     /** 3) start JETTY server */
     jettyServer.start();
     jettyServer.join();

Embedding an HTTP daemon in Java

Apache Tomcat, the well-known WebServer is about 84MB after installation. Other contenders are even bigger. Does it have to be so complicated ? The following blog is about the search for a 'right size' HTTP daemon embedable in Java.
Now, what's a Web Server anyway ?
To my mind, its just a piece of software that opens a socket (port 8080) where you send requests to (as defined by the HTTP protocol) and it returns data, in most cases something from the file system (HTML pages and such). This doesn't sound too complicated. In fact, there are examples on the net of HTTP daemons that only take 10 lines of source code (compare the C++ obfuscation contest).
But besides this little niche, there is also NanoHTTPD which already handles some of the ugliness of HTTP. So in order to serve up a system directory, which could contain fairly complicated AJAX/Javascript/JSP files, you don't need more than this single file of Java source code.
If serving a file directory is all you need, go back to the previous chapter.
Unfortunately, things are not that easy ... sometimes you also need to publish a WebService or a Servlet or an already packaged Web application (a war file). Then you need something slightly bigger. The best thing I could find in this category is Jetty. It gives up a nice stand-alone WebServer with all kinds of configuration choices and extension points, but most importantly, it is very easy to embed. By using three jar files (less then 1 MB in total) and writing very little code you again have a complete HTTP daemon. Oh, and also, Jetty is already used inside Eclipse and GWT.

Publishing a JAX-WS Endpoint not just to localhost

Interestingly enough, publishing the JAX-WS Endpoint with endpoint.publish(url) as described in a previous post, publishes the WSDL to http://localhost:8080 but this socket is not accessible from any other host ! Strange default, but there you go ...
So in order to really make a JAX-WS Endpoint public to the world, you can revert to the slightly more cumbersome API of com.sun.net.httpserver.HttpServer (at least on Sun's JDK):

HttpServer server = HttpServer.create(new InetSocketAddress(port), 3 ); // backlog
server.start();
  
endpoint.setExecutor( Executors.newFixedThreadPool(10) );
  
// publish WebService
HttpContext wsContext = server.createContext( "/" + service );
  
//wsContext.setAuthenticator(new TestBasicAuthenticator("test"));
endpoint.publish( wsContext );

Sunday, October 4, 2009

Quarkbase

Ever wondered who are the key people behind a website ?
Check out http://www.quarkbase.com/ and enter the URL to check.
Not always perfect, though ... ;-)