views:

743

answers:

5

I am interested in creating a Spring standalone application that will run and wait to receive messages from an ActiveMQ queue using Spring JMS. I have searched a lot of places and cannot find a consistent way of implementing the main method for such a standalone application. There appears to be few examples of Spring standalone applications. I have looked at Tomcat, JBoss, ActiveMQ and other examples from the around the web but I have not come to a conclusion so ...

What is the best practice for implementing a main method for a Java application (specifically Spring with JMS) ?

Update: Here's an example from: http://forum.springsource.org/showthread.php?t=48197 Is this the best way of doing this?

public static void main(String args[]) {
        try {
           ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
            . . . . .
            Object lock = new Object();
            synchronized (lock) {
                lock.wait();  
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
}
A: 

Attempt a read in a loop. If a message is found, process it, then sleep and iterate again. Also put some sort of terminator logic in there (interrupt the thread). You could terminate after X attempts, read from a file, kill the JVM, read a terminator msg from the queue, etc., etc.

public static void main(String[] args) {
    while(true) {
        // look for some terminator
        // attempt to read off queue
        // process message
        try {
            TimeUnit.SECONDS.sleep(5);
        } catch (Exception e) {
            break;
        }
    }
}
Droo
I may be wrong but I think this causes performance issues in two spots: 1. The constantly processing while loop would consume processor. 2. The sleep would cause a delay in processing messages (not as much a concern because the framework handles this). I think the answer will involve the locking the main method but I'm not sure.
Brandon
he was asking for a spring-based solution...
Hans Westerbeek
Didn't know `What is the best practice for implementing a main method for a Java application` had anything to do with Spring. If his question was `How do I obtain a bean from a Spring config` then your answer would be splendid.
Droo
@Brandon, process the message in another thread, i.e. inside a `Runnable`.
Droo
A: 

In your main() do something like this:

// gather config files
String[] configs = { "classpath:applicationContext-myutil.xml" };

// create the app context
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(configs);

// obtain reference to your utility bean
MyUtilityBean utility = (MyUtilityBean) ctx.getBean("utility");

// invoke methods on your utility bean
utility.doSomething()

You would inject your Utiltity bean with Spring's JMS template to do the gruntwork for your usecase.

Hans Westerbeek
I think I am think of something along these lines: http://forum.springsource.org/showthread.php?t=48197 because the bean method is note executing anything is is only waiting to receive messages.
Brandon
What does this have to do with main methods in Java applications.
Droo
I've provided an update. I think the question was to implicit.
Brandon
I think you should configure a Message Driven Pojo, as described here: http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jms.html#jms-asynchronousMessageReceptionIt would eliminate the programming you have to do to poll for a message. Spring will do it for you so you can't mistakes :)
Hans Westerbeek
+1  A: 

This is what we have, inside app-context.xml we use spring JMS classes like (org.springframework.jms.listener.DefaultMessageListenerContainer to manage number of consumers and provide custom listener using org.springframework.jms.listener.adapter.MessageListenerAdapter)

app-context.xml contains all spring beans listeners and other stuff, the code below is bootstrapping Spring provided listeners on queues. So idea is to use Spring classes to manage multiple consumers. Let me know if this is what you need and need more information on configuring MessageListenerAdapter.

public static void main(String[] args)
{

    try
    {
        new ClassPathXmlApplicationContext("app-context.xml");

    }
    catch (Throwable e)
    {
        e.printStackTrace();
        System.exit(-1);
    }

}
soody
A: 

The main idea is to make main thread wait until app will be finished. while(!finished) is correct way to wait until main thread will be wake up.

finishEventHandler - is a method that handles finish/quit event.

I consider that JMS initialization is done in Spring conf. and in ". . . . ." section.

public static void main(String args[]) {

try {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        lock = new Object();

        while(!finished) {
           synchronized (lock) {
               lock.wait();  
           }
        }

    } catch (Exception e) {
        e.printStackTrace();
    }

}

 public void finishEventHandler() {
     finished = true;
     lock.notify();
}
Vladimir
+3  A: 

When using Spring JMS you already use components/beans in your configuration that get auto-started and will stay alive (subscribe and read from queue/topic) until you stop the application.

To start and keep the application running, loading the applicationcontext should therefore be enough. Good practice though is to also call the registerShutdownHook, so on a application halt (i.e via ctrl+c in the console), al your beans are gracefully shutdown and disposed :)

public static void main(String args[]) {
    AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
    context.registerShutdownHook();
}
momania