Friday, November 30, 2012

How to start a thread on JBoss startup

I recently had to initiate a thread to read mails on server start-up. This had to run after the application was deployed since the thread class depended on a few classes of the application. Note that we are running on JBoss 4.2.3 currently, so i am not sure how this works with latest versions of JBoss.

You need to create a folder called deploy.last within your deployment directory (e.g : default configuration). Then we first create a normal interface/implementation as follows;


public interface EmailRetrieverInvokerServiceMBean {

 void start() throws Exception;

 void stop();
}



public class EmailRetrieverInvokerService implements
  EmailRetrieverInvokerServiceMBean {

 public void start() throws Exception {

  
  MailRetriever mailRetriever= new MailRetriever();
  mailRetriever.start();
 }

 public void stop() {
  
            MailRetriever.START_STOP_FLAG = true;

 }
}


Just a normal interface and implementation. Note that the start() method will be called when we deploy the application. The MailRetriever class has an implementation as follows;


public class MailRetriever extends Thread {

   public static boolean START_STOP_FLAG = false;

    @Override
    public void run() {
        
        log.info("MailRetriever started....");

        //Until the flag is not set to true, this thread will keep running
        while (!START_STOP_FLAG) {
            try {
                
                
             
             //Do mail reading

             //Then sleep for a specified time until the next iteration
                Thread.sleep(1000 * 60 * mailPollingDelay);
            } catch (Exception ex) {
                log.error("MailRetriever.run()" + ex.getMessage(), ex);
                //Exception handling and thread respawning should be handled
            }
        }
    }
}


This is the thread that will be started when the start() method of our MBean implementation class is invoked. The thread will continue to run until the boolean flag is set to true. Then to wire it up, you need to specify a jboss-service.xml which should go in the META-INF directory when building your distribution. Let us have a look at what that looks like;


<?xml version="1.0" encoding="UTF-8"?>

<server>
   <mbean code="com.service.EmailRetrieverInvokerService"
   name="com.service:service=EmailRetrieverInvokerService">    
  </mbean>
</server>


Within this xml we define the fully qualified path to our interface class that we defined and give a name where we can access our implementation as a normal MBean definition. If you are using a maven build then all you need to do is create this XML file and put it under src/main/resources/META-INF. This will put it under the META-INF during the distribution creation stage.

As a last step what you need to do is bundle everything up as a service archieve (SAR). You can achieve this using maven as follows;


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.example</groupId>
 <artifactId>mailreader</artifactId>
 <packaging>sar</packaging>
 <version>1.0</version>
 <name>Mail Reader</name>

 <build>
 <finalName>MailReader</finalName>
  <plugins>

   <plugin>
    <groupId>net.sf.maven-sar</groupId>
    <artifactId>maven-sar-plugin</artifactId>
    <version>1.0</version>
    <extensions>true</extensions>
   </plugin>
  </plugins>

 </build>


 <properties>
  <project.build.sourceEncoding>UTF-8
  </project.build.sourceEncoding>
 </properties>


</project>


A service archive will be created for you. Then it is just a matter of copying the SAR file onto your deploy.last which you created within the jboss deployment directory. This will guarantee that the thread will run after all other components are deployed within jboss.

That's it. If you have any queries, comments, suggestions, please leave them which is much apprecaited as always.

Thank you for reading and have a great day!!