In a previous post, I mentioned how to add a shutdown hook to your application. This is great for the case where you need to do some cleanup prior to exiting. The example below shows how to convert your class to work like a daemon on UNIX, or a service on Windows. I will not go into details on how to create a UNIX, or Windows service. I will provide a 
StartupItem example for Mac OS X, or a modern 
inetd plist for 
launchd.
In the example classes below, I create a value holder object, a 
Callable<ValueHolder>, a 
Future<ValueHolder>, an 
ExecutorService which uses a 
SingleThreadExecutor. The concurrency libraries are from java.util.concurrent which is based on the original work done by Doug Lea, et. al. These classes make doing 
Thread based programming much simpler.
Here are the relevant files for the application:
JavaDaemonExample.zip (NetBeans 7.0 project) 
JavaDaemonStartupItem.zip (This is for OS X 10.4 or less. It will work on 10.5+, but is not preferred)
com.bluelotussoftware.examples.Daemon (This is the 
inetd plist for 
launchd 10.5+ preferred)
Before we get to the code, the Mac OS X daemon controls must be modified to match your environment. 
The 
com.bluelotussoftware.examples.Daemon plist file needs to modified to point to the jar file to execute. This is for Leopard, and Snow Leopard.
- To install it, place it in the ~/Library/LaunchAgentsdirectory.
- From a command prompt, type:
 launchctl load -w /Users/jyeary/Library/LaunchAgents/JavaDaemonStartupItem/com.bluelotussoftware.examples.Daemon This loads it.
- To execute from launchctl:
 root:$ launctl
 launchd% start com.bluelotussoftware.examples.Daemon
 launchd% list
 launchd% quit
 root:$
 
Alternatively, you can use the 
JavaDaemonStartupItem.
- Modify the JavaDaemonStartupItemscript to match your environment.
- Place the files in the /Library/StartupItemsdirectory.
- Change permissions:
 sudo chown -R root:wheel JavaDaemonStartupItem 
- Execute the application using:
 sudo /sbin/SystemStarter start "Java Daemon Example" 
This is the main code Example:
 Daemon.java
package com.bluelotussoftware.examples;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
   
@author   <jyeary@bluelotussoftware.com>
@version
 
public class Daemon {
    private static final Logger logger = Logger.getLogger(Daemon.class.getName());
    
  
     
    public Daemon() {
    }
    
   
@param     
     
    public static void main(String[] args) {
        try {
            
            Handler handler = new FileHandler(Daemon.class.getName() + ".log");
            logger.addHandler(handler);
        } catch (IOException ex) {
            ex.printStackTrace(System.err);
        } catch (SecurityException ex) {
            ex.printStackTrace(System.err);
        }
        logger.log(Level.INFO, "Closing streams");
        closeDefaultStreams();
        logger.log(Level.INFO, "Fetching ExecutorService");
        final ExecutorService executorService = Executors.newSingleThreadExecutor();
        logger.log(Level.INFO, "Adding Shutdown Hook");
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                shutdown(executorService);
            }
        });
        logger.log(Level.INFO, "Submitting CallableDaemon");
        Future<ValueHolder> future = executorService.submit(new CallableDaemon());
        logger.log(Level.INFO, "Waiting for results...");
        try {
            StringBuilder sb = new StringBuilder();
            sb.append("Results: ");
            sb.append(Arrays.toString(future.get().getDates().toArray()));
            logger.log(Level.INFO, sb.toString());
        } catch (InterruptedException ex) {
            logger.log(Level.SEVERE, null, ex);
        } catch (ExecutionException ex) {
            logger.log(Level.SEVERE, null, ex);
        }
        logger.log(Level.INFO, "Shutting down ExecutorService normally.");
        
        executorService.shutdown();
    }
    
    
  @code @code @code 
        
     
    private static void closeDefaultStreams() {
        System.out.close();
        System.err.close();
        try {
            System.in.close();
        } catch (IOException ex) {
            logger.log(Level.WARNING, "Closing System.in() caused an Exception", ex);
        }
    }
    
   @code 
@param          
     
    private static void shutdown(ExecutorService executorService) {
        logger.log(Level.INFO, "Executing shutdown hook");
        List<Runnable> runnables = executorService.shutdownNow();
        logger.log(Level.INFO, "The following items were awaiting execution when the daemon shutdown",
                Arrays.toString(runnables.toArray(new Runnable[runnables.size()])));
    }
}
This is the 
Callable<ValueHolder>:
 CallableDaemon.java
package com.bluelotussoftware.examples;
import java.util.Date;
import java.util.concurrent.Callable;
  <code></code>    
     <code></code>   <code></code>
 <code></code>    <code></code>
@author   <jyeary@bluelotussoftware.com>
@version
 
public class CallableDaemon implements Callable<ValueHolder> {
    private int counter;
    private int iterations = 12;
    
  
     
    public CallableDaemon() {
    }
    
      
@param       
    
     
    public CallableDaemon(int iterations) {
        this.iterations = iterations;
    }
    
@inheritDoc 
     
    @Override
    public ValueHolder call() throws Exception {
        ValueHolder valueHolder = new ValueHolder();
        for (; counter < iterations; counter++) {
            valueHolder.getDates().add(new Date());
            synchronized (this) {
                this.wait(5000);
            }
        }
        return valueHolder;
    }
}
 ValueHolder
package com.bluelotussoftware.examples;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
   
@author   <jyeary@bluelotussoftware.com>
 
public class ValueHolder {
    private List<Date> dates;
    
  
     
    public ValueHolder() {
        dates = new ArrayList<Date>();
    }
    
 @code <Date>    <code></code>
              
<code></code>
@return@code <Date>    <code></code>
     
    public synchronized List<Date> getDates() {
        return dates;
    }
}