Fork me on GitHub

Monday, April 20, 2009

Submitting form to new window

Today one of my co-workers was in an effort to submit a form that would bring up a new popup window. After some Googling, they found a solution.
<form name="datacollector" method="POST" action="new-url.do" target="_blank">
<!--
     ...
     other form elements
     ...
-->
</form>
Though this was getting them a new window, on Firefox it was appearing as a new tab. They soon found a setting in FF, that would bring it to a new window itself. However, they wanted a popup without any toolbars, menus etc.

They approached me. Thanks to one of my student days HTML/JavaScript tutorial. I was able to recollect it and give them a solution.
<script type="text/javascript">
   function submitToNewWindow(frm) {
       window.open('','popupWin','scrollbars=no,menubar=no,height=600,width=800,resizable=yes,toolbar=no,status=no');
       frm.action= "new-url.do";
       frm.target = "popupWin";
       frm.submit();
   }
</script>
...
...
<form name="datacollector" method="POST">
<!--
     ...
     other form elements
     ...
-->
      <input type="button" value"Generate" onclick="javascript:submitToNewWindow(this.form)"/>
</form>
The idea is simple. Open a window with a name (here popupWin) using JavaScript that will have no scrollbar, menu, etc. Now in the form's target, supply this window name. This would bring up the form submission's result on the specified popup window. As far as the "_blank" is concerned, it is a HTML's default name for a new blank window.

This is a basic feature of HTML, that in the target, it accepts the name of a window. Note that if a window with that name does not exist, probably a new one will be created.

This solution was tested to be working in FF as well as IE.

Though this is a simple solution, I thought to put up here on my blog, as my co-workers were not able to get anything like this on Googling.

Thursday, April 16, 2009

Cross Platform Java Daemon

Running a Java application (non graphical) would normally need a command line for it. This seems OK if we are developing small applications, but today we see enterprise applications that often needs to go and work as a server, that need to start up and go down with the OS. For such applications, the requirement of avoiding a command line gains importance. Such applications are often referred to as Daemons in the *nix space, and services in the Windows space.

Solutions?

Wondering that you have seen so many Java applications that can work without command line? Its not that Java applications without a command line is not possible. Though Java is popular for being platform independent, doing this "daemonising" task has not been of that nature. Many of the Java based server products have been doing that in various different ways, and in most cases using native code. And if your look around for Java Daemon, or Java as Windows Service, you will find separate and widely different solutions.

And there are solutions specific to platforms, for instance - the nohup and screen command in linux can get you an application without terminal. For the nohup, though your solution to stop the application, is probably to kill it.

Recently I had a similar need, I looked around and could find a bunch of solutions:
  1. Commons Daemon (C, Java)
  2. Java Service Wrapper (C and Java)
  3. Yet Another Java Service Wrapper (pure Java)
  4. Akuma


Do it yourself!

Going through even the surface of these will give you an idea of how widely the implementations vary. These are solutions that help you lift your existing application, if you yourself do not want to provide any implementation of getting daemonised. But if you are happy to learn on this concept, or want to get your code provide the "daemon" power natively with simplicity and lightweight effort, read on...

(Note: I would recommend a reading of the Commons Daemon. Also note that the code below is just ideas and concepts, you may need to evolve it further to make it production ready.)

The concepts

Any Java application needs an entry point for it to start working. This is the public static void main(String[]) method. And the common way to do this invocation is to instruct the JVM and show it the class that contains this method block, with the java command. This command will start the JVM which starts the Java program starting with the main method. The command line is blocked until the Java program completes. This is a valid scenario for small and interactive applications, but for multi-threaded server programs, we do not want the command line.

The daemon solutions have varied way to enter a Java program (other than the main method as well). But here, we will use what we already know: enter a Java program with main method and still remain detached from the command line.

There we need to understand two concepts:
1. Starting a program. Using Java, it is possible to start "any program" using Runtime.exec() and ProcessBuilder.exec(). Wondering? Yes, any program that you can run in a command line can also be launched within Java programs as well. Another notable aspect of this is that the launched program does not have a command line associated with it, and it is optional for the launching Java program to keep track of this process. Well, we will use this concept to launch a Java process inside a Java program!
2. Stopping the program For a Java program, there is no way to get the control of a process running in the system. So if we launched a process from a Java program, and lost control over it, how can we tame it to bring it down? Establish protocol! We will make the launched program to open a port and start listening to it, and when it receives a valid shutdown command, start its shutdown procedures.

Taming the terms...

Below, I will show how to do this. But before, I will introduce some terms, so that further discussions are easy.
  1. TargetApp - the Java application (possibly a server program) that we want to get detached from the command line and go "daemonised".
  2. Daemon - The class that actually goes into daemon mode and listens to shutdown commands. If you are coding the daemon inside your application, this functionality will be inside one of your classes in the TargetApp.
  3. Launcher - This program will kick off the Daemon as a process detached from the command line. Also provides interfacing to provide shutdown command to the Daemon.


Reaching out with Code

1. TargetApp

Since this can be any Java application that usually works in a loop, I will create a simple application that will keep printing a funny text to a file created in your current working directory.
package org.otw.daemon;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Date;

public class FunnyTargetApp {

   private boolean shouldRun = false;
   /**
    * @param args
    */
   public static void main(String[] args) {
       FunnyTargetApp app = new FunnyTargetApp();
       app.start();
   }

   /**
    * Starts the application.
    */
   public void start() {
       shouldRun = true;
       Thread workerThread = createWorkerThread();
       Thread commandTracker = createCommandTrackerThread();
       commandTracker.start();
       workerThread.start();
       try {
           workerThread.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }

   /**
    * Stops the application, in a clean way.
    */
   public void stop() {
       System.out.println("Stopping...");
       shouldRun = false;
   }

   /**
    * Creates a thread that mimics a continuous job as that of a server.
    * @return
    */
   private Thread createWorkerThread() {
       return new Thread(
               new Runnable () {
                   public void run() {
                       File file = null;
                       FileWriter wri = null;
                       try {
                           file = new File("test.out");
                           System.out.println("Started with file at ["
                                   + file.getAbsolutePath() + "].");
                           file.createNewFile();
                           wri = new FileWriter(file);
                           while(shouldRun) {
                               wri.write("Funny Text >> "+ new Date());
                               wri.write("\n");
                               wri.flush();
                               Thread.sleep(1000);
                           }
                       } catch(Exception e) {
                           e.printStackTrace();
                       } finally {
                           if (file !=null && wri!=null) {
                               try {
                                   wri.flush();
                                   wri.close();
                               } catch (Exception e) {
                                   e.printStackTrace();
                               }
                           }
                       }
                   }
                  
               }, "Worker Thread"
       );
   }

   /**
    * Creates a thread that will keep track of the commands issued on the command line.
    * @return
    */
   private Thread createCommandTrackerThread() {
       return new Thread(
               new Runnable () {
                       public void run() {
                           System.out.println("Listening to commands from terminal.");
                           while(true) {
                               InputStreamReader isr = new InputStreamReader(System.in);
                               BufferedReader reader =  new BufferedReader(isr);
                               String command = null;
                               try {
                                   command = reader.readLine();
                               } catch (IOException e) {
                                   e.printStackTrace();
                                   break;
                               }
                               if (command.equalsIgnoreCase("stop")) {
                                   stop();
                                   break;
                               } else {
                                   System.out.println("invalid command.");
                               }
                           }
                       }
               }, "Command Tracker"
       );
   }
}


2. Daemon

This is the class that actually gets detached from the terminal and becomes a daemon, while keeping a reference of the TargetApp. So basically it has to deal with 3 functionality:
a. Launch the TargetApp and keep its reference.
The TargetApp can be launched as a thread or as a process. The preferred way should be as a thread. For launching as a process, the TargetApp should have a either a start method or a regular main method. For launching TargetApp as a thread, invoke methods needed to start the TargetApp, if no such specific method is there, just invoke the main method.
//Starting as a Thread (reflecting on the main method)
Class payload = getPayloadStartClass(); // determine the payload class via configurations
Object payloadInstance = payload.newInstance();
Class[] paramTypes = new Class[1];
paramTypes[0] = arguments.getClass();
Object[] param = new Object[1];
param[0] = getPayloadArguments();
Method method = payload.getMethod("main", paramTypes);
method.invoke(payloadInstance, param);


Note: This snippet uses reflection. You may use an interface to make things better, using a startup method.
// Starting as a Process
Class payload = getPayloadStartClass(); // determine the payload class via configurations
String javaOptions = //get it via configurations
String payloadArg = //get it via configurations
String command = "java " + javaOptions + " "
 + payload.getCanonicalName() + " "
 + payloadArg;
log.debug("Starting command line: " + command);
Runtime.getRuntime().exec(command, null);


b. Starts up a shutdown port and waits for a shutdown command to be issued.
ServerSocket serverSocket = ServerSocket(getShutdownPort());
Socket socket = serverSocket.accept();
boolean isLocalConnect = false;
InputStream stream = null;
PrintWriter out = null;
try {
   isLocalConnect = socket.getInetAddress().isLoopbackAddress();
   socket.setSoTimeout(getNetworkTimeout());
   stream = socket.getInputStream();
   out = new PrintWriter(socket.getOutputStream(), true);
} catch (AccessControlException ace) {
   log.warn("StandardServer.accept security exception: "
                      + ace.getMessage(), ace);
   return;
} catch (IOException e) {
   log.error("StandardServer.await: accept: ", e);
   return;
}


c. Stop the TargetApp and then itself for a clean shutdown on receiving valid shutdown command on the shutdown port.
String command = readStream(stream); // reads command from the input stream
boolean match = command.toString().equals(shutdown);
if (match) {
   log.debug("Shutdown command recieved via Telnet.");
   shutdown(); // calling the shutdown procedures
   return;
} else {
   log.warn("Invalid command.");
}


You can telnet to the port and provide shutdown command. The Launcher's stop routine also does the same thing (the code will follow soon).

Remember to register shutdown hooks on the application startup, and remove it explicitly, if the shutdown was not initiated by the shutdown hook. Shutdown hook is a Thread that is not started, and registered with the JVM. When the JVM goes down, this thread will be started. So we can write some cleanup code in this thread. Remember to return from the run of the shutdown hook quickly.

3. Launcher

This class will provide us hooks to start up the Daemon, and stop it based on arguments (from the command line). To launch the Daemon as a Java process and detach it from the command line, we will use the Runtime.exec(). This will be similar to the process mode launching of TargetApp.
String strCmd = "java " + "-classpath " + classpath + javaOptions
   + " org.ops4j.laboratory.users.open4thomas.jdaemon.Carrier";
log.debug("Starting command line: " + strCmd);

Process proc = Runtime.getRuntime().exec(strCmd, builder.getArguments());
Thread hook =  createShutdownHook(proc);// create shutdown hook thread
Runtime.getRuntime().addShutdownHook(hook);


To stop the running Daemon cleanly, the class will set up a socket connection to the Daemon's shutdown port, and supply a shutdown command. This will trigger a shutdown procedure in Daemon, which in turn can trigger shutdown on the TargetApp.
Socket socket = null;
PrintWriter out = null;
try {
   socket = new Socket("localhost", getShutdownPort());
   out = new PrintWriter(socket.getOutputStream(), true);
} catch (UnknownHostException e) {
   log.error("Unknown address: localhost.");
  return;
} catch (IOException e) {
   log.error("Couldn't connect to: localhost.");
   return;
}

out.write("shutdown\n");
out.flush();


Getting around with security holes.

There is one important security hole in this approach. When the Daemon is listening on the shutdown port for shutdown command, it is possible for a hacker to compromise on this feature.
This can be eliminated with few approaches:

1. Provide password protection

The application could ask for a password that could be stored in encrypted format, and before accepting shutdown command, the user will be needed to provide a password.

2. Preventing DoS attack

A malicious user can connect to the shutdown port, and provide junk command continuously effectively doing a DoS attack. This can be dealt by accepting limited amount of failed password, or wrong command attempts. Limit the length of command/password.

More improvements

In the Launcher's stop, after issuing shutdown command to the Daemon, we could check for the existence of a PID file to know if the application is still running. The PID file can be created by the Daemon with "deleteOnExit" flag.

Another improvement area is to provide an interface that the TargetApp should implement, so that it will be easy to call startup and shutdown routines on the TargetApp.

There could be more, but not right now in my mind.

Want more code?

Sure, the code snippet I provided here is just to explain the core concept. There are other things required to get it working. I worked out quickly on this, and the code is available in my lab at OPS4J here. Please note that I may change the code over time. I am writing this article as of revision #14752.

This is a regular SVN repository. So you can get the source code with
svn co https://scm.ops4j.org/repos/ops4j/laboratory/users/open4thomas/jdaemon/jdaemon-main

Wednesday, April 8, 2009

Exciting future for the web

The future of web applications seem to be exiting for every web user. With the drafting and evolution of HTML 5 , and browsers like Firefox coming up with plans on Prism and Weave , its plugins, and evolving nature of supporting applications such as Google Sync (mobile and browser ) and Google Gears , the experience of a web user seems to be in a good light. Some of the fantastic experiences would be:
  • Inherent support for offline browsing and using web applications by browsers.
  • Inherent support for rich web UI.
  • Enhanced experiences with audio and video on web browsers.
  • Seamless and centralized browser profiles. Browser will seamlessly synchronize your profile including bookmarks, browsing history, saved passwords and tabs across multiple browsers, so that your desktop, laptop, and mobile phone can all work together.
Many of them are already available for a beta preview. These seem to not only enhance the experience of a web user, but also developers like me will find an interesting turn in developing web applications.

Monday, April 6, 2009

Beating the Recession with Free Software

Few weeks back, one of my friends working with a big enterprise asked for my help in getting his personal PC to the right health. He would use computers only for browsing, spreadsheets, preparing presentations, and for word processing. His PC had Windows installed all infested with viruses, that was making his daily working trouble. He told that he had installed a free Antivirus , but still was having such problems. Even in the past that he had to get his PC with a fresh installation of Windows, and now it was barely a month after that.

I was more than happy to introduce him to Linux. But he was not readily accepting the call since he had only used Windows, and had not even had a glance of Linux. But because I told him that Linux won't catch a virus, he was ready to go for a dual boot. Just then I took out my Laptop and showed him my Ubuntu installation, and asked him to use it for a while. After sometime he was comfortable to use all of its features that he wanted - the Firefox and the Open-Office met all his needs. To make him further convinced, showed him my installation of Sun's Virtual-Box, in which I had a Windows XP image running. He was so happy at this that he asked me to teach him on how to get on to Linux from the boot.

The next question he asked me was - "Why are we using Windows XP in office? We have to spend a good amount for its licensing every year. Added to that, we also have to spend on purchasing Antivirus and its licensing, while we can actually do it all with Linux."

Spending on the Stack?

The question is not only on spending on one or two paid and closed software, but rather the stack of such software that is often built up. Let us not think about geeks who are able to modify the FOSS software such as the Linux to their use, but even from the perspective of end users like my friend, who use computers only to get their daily tasks done. For them, getting a functionality on their system means searching on the net for a software, finding the cheapest of all (many a times a shareware, and if they are not lucky - a malware), and installing them with a questionable security of your personal data. By just considering the Operating System, Antivirus software and Internet Security solutions now seem as an inevitable part of paid and closed software stack. Does anyone know, what is inside a closed software?

Compare this with a Free OS such as Linux. First, you are legally free to copy and redistribute the software. And the software comes for free "as in free beer" most of the time. Even if you spend, compare this to the cost you spend on the closed source OS.

This is true not just for simple end users, but also advanced users of computers. Those software companies who are providing solutions with FOSS stack, can provide their customers with reasonably cheaper solutions (stability - I am avoiding here, because it depends on the solution provider).

Leveraging business with FOSS

Even if considering this on an enterprise scale, I am sure there should be enough testimonials to say how much one should have saved when using a Free Software stack. In either case you need a support staff to manage all the software and its maintenance, so then why not spend on a software that are know to contain comparatively lesser security holes, and fewer headaches on licensing, and of course saving on the expenses.

One thing however, is that it becomes necessary to choose a stack wisely that can reduce your overall costs. You have to weigh a lot of factors, but definitely, in your considerations, give a good space to the FOSS stack. I am sure every business can workout a good solution to beat such recessions with an optimal strategy with FOSS stack.

Some questions can come up in your mind when reading through this. I have left those for you to think. I can't cover every aspect of this discussion in a blog post like this. But feel free to post your comment on here.