Overview

As with most applications and development tools, the best place to start is usually with a simple Hello World! example. The usual Java Hello World application starts up, prints out Hello World and then exits. That is not very interesting to show off a tool for running and monitoring services. In the case of the Java Service Wrapper, an example that can be installed and then stay running as a Windows Service or UNIX daemon is required.

This page will describe our Hello World Server example application and help you through the process of building it. The How can I run my Java application as a Windows Service? page will make use of this example to walk you through the process of quickly configuring and installing this example to run as a Windows Service with the Java Service Wrapper.

This example Hello World application launches a daemon thread, which listens on port 9000 for simple text based clients, who connect through telnet. It will then simply echo any input until it finds the input exit, at which point that particular connection will be closed.

While this is a little more complicated than the typical Hello World example, it allows you to run an easy server application, being able to interact with a client program, following the fundamental server client design model.

Example Source Code

To keep our example clean and let it work cleanly with our examples, please start with an empty directory at the location of your choice that we will call %HELLO_HOME%. Please create lib\classes and src\java directories within %HELLO_HOME%. You should end up with the following:

Directory Structure
%HELLO_HOME%\
  lib\
    classes\
  src\
    java\

Next create a single file in the src\java directory called HelloWorldServer.java and open it in an editor. Copy the following source into the file and save it.

HelloWorldServer.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class HelloWorldServer
    implements Runnable
{
    private final Socket m_socket;
    private final int m_num;

    HelloWorldServer( Socket socket, int num )
    {
        m_socket = socket;
        m_num = num;
        
        Thread handler = new Thread( this, "handler-" + m_num );
        handler.start();
    }
    
    public void run()
    {
        try
        {
            try
            {
                System.out.println( m_num + " Connected." );
                BufferedReader in = new BufferedReader( new InputStreamReader( m_socket.getInputStream() ) );
                OutputStreamWriter out = new OutputStreamWriter( m_socket.getOutputStream() );
                out.write( "Welcome connection #" + m_num + "\n\r" );
                out.flush();
                
                while ( true )
                {
                    String line = in.readLine();
                    if ( line == null )
                    {
                        System.out.println( m_num + " Closed." );
                        return;
                    }
                    else
                    {
                        System.out.println( m_num + " Read: " + line );
                        if ( line.equals( "exit" ) )
                        {
                            System.out.println( m_num + " Closing Connection." );
                            return;
                        }
                        //else if ( line.equals( "crash" ) )
                        //{
                        //    System.out.println( m_num + " Simulating a crash of the Server..." );
                        //    Runtime.getRuntime().halt(0);
                        //}
                        else
                        {
                            System.out.println( m_num + " Write: echo " + line );
                            out.write( "echo " + line + "\n\r" );
                            out.flush();
                        }
                    }
                }
            }
            finally
            {
                m_socket.close();
            }
        }
        catch ( IOException e )
        {
            System.out.println( m_num + " Error: " + e.toString() );
        }
    }
    
    public static void main( String[] args )
        throws Exception
    {
        int port = 9000;
        if ( args.length > 0 )
        {
            port = Integer.parseInt( args[0] );
        }
        System.out.println( "Accepting connections on port: " + port );
        int nextNum = 1;
        ServerSocket serverSocket = new ServerSocket( port );
        while ( true )
        {
            Socket socket = serverSocket.accept();
            HelloWorldServer hw = new HelloWorldServer( socket, nextNum++ );
        }
    }
}

The application starts up and begins listening on port 9000 for remote connections from any source. As each new connection is accepted, a dedicated handler thread is created to handle all communication with that connection until it is closed.

The handler thread will read and then echo any line of text back to the client. If a line of text containing only the word exit is received, then the client connection will be closed.

Building the Example

Building the example is a simple task. Start by opening up a Command Prompt or Shell on UNIX and go into the %HELLO_HOME% directory, which we created above, using the cd command.

The example can now be compiled using the following command:

Compiling the Example:
javac -d lib\classes src\java\HelloWorldServer.java

If you get an error that the javac command could not be found, please make sure that you have installed a Java SDK on your system. If everything went well, then you should get the prompt back without any additional output after the compiling is done.

Please check to make sure that the class file was created by running:

Check for Class File:
dir lib\classes

Congratulations, you have successfully built the HelloWorldServer example.

Running the Example

Running the example can be done executing the following command from within the %HELLO_HOME% directory.

Run the example:
java -classpath lib\classes HelloWorldServer

If everything is working, you should see the following:

Example Output:
Accepting connections on port: 9000

Connecting as a Client

Let's now try connecting a client to our server and see what happens. Start by opening up a second Command Prompt and connecting using telnet:

Connecting with Telnet:
telnet localhost 9000

Once connected, you should receive a response showing your connection number. Then any text you type followed by the enter key will be echoed back to you.

Example telnet session:
Welcome connection #1
Test
echo Test
Hello there world!
echo Hello there world!

When you are done having a conversation with the server, you can close your connection by typing exit alone on its own line.

Our example server is also capable of accepting telnet connections from any computer that is able to see the server. If you have any problems connecting however, please first make sure that there are not any firewalls in the way.

Crashing the Server

The above example is great as a simple standalone Java server. But we would like to show off how the Java Service Wrapper is able to help make our little example server much more stable so your organization can begin to rely on it for mission critical systems.

To start, we want to add a new crash command so we can make it possible for a connected client to crash the JVM. While it is possible to cause an actual crash using various known bugs in the JVM, many of them only work on certain platforms or with specific versions of Java. For this example we will simulate a crash by calling Runtime.getRuntime().halt(0) to instantly exit the JVM without shutting down cleanly.

Please open the HelloWorldServer.java source file back into an editor and update the code as follows:

HelloWorldServer.java (Change)
    ...
    System.out.println( m_num + " Read: " + line );
    if ( line.equals( "exit" ) )
    {
        System.out.println( m_num + " Closing Connection." );
        return;
    }
    else if ( line.equals( "crash" ) )
    {
        System.out.println( m_num + " Simulating a crash of the Server..." );
        Runtime.getRuntime().halt(0);
    }
    else
    {
        System.out.println( m_num + " Write: echo " + line );
        out.write( "echo " + line + "\n\r" );
        out.flush();
    }
    ...

The example can now be recompiled and run using the same commands as above.

Now try connecting to the server and sending the command: crash. Our simple little example server will of course die and we will no longer be able to connect and make use of the server from telnet. Obviously if this was a mission critical server, the system administrator would be getting a phone call as soon as one of the users was inconvenienced.

To resolve this problem, please see the How can I run my Java application as a Windows Service? page for instructions on how to turn this simple example server into a Windows Service or UNIX daemon that will be able to recover automatically from our example crash, as well as a number of other problems.