javajakarta-eeejbjmsmessage-driven-bean

Pipes and filters pattern with MDB in Java EE


I'm trying to implement the pipes and filters pattern with Message-Driven Beans in Java EE, but I want to do it in a way that the queues are configurable and the beans are created on run time. This way changing the order in which the filters execute would be easy.

I'm really new to Java EE and when I used MDB in the past I always did it like this:

@MessageDriven(mappedName = "jms/myQueue", activationConfig = {
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue")
})
public class ReceiveMessageBean implements MessageListener {

This won't work for what I want.

I was thinking of doing a bean that each one of the filters could inherit from, that way I can put the read and write from queue method in one place only, something like this:

public class StepBean {
    public void createBean(String queueRead, String queueWrite) {
        //make the bean listen from queueRead
        //make the bean write to queueWrite
    }
    public void onMessage(Message message){
        //get the message  from queueRead and transform it to my own class
        processMessage(myMessage);
    }

    public void processMessage(MyMessage message){
        //each filter should implement this method 
        sendMessage(myMessage);
    }

    public void sendMessage(MyMessage message){
        //send message to queueWrite
    }
}

And then have some kind of factory in my ejb that creates the step beans with the desired values for the queues.

But I'm pretty much lost on how to do any of this. I have been looking at this, but since my beans both read and write from queues they are not strictly MDB.

I'm using GlassFish 4.1.2 and Netbeans 8.2.

Any guidance on how to do this or about whether it is even possible is welcome.


Solution

  • You can't create MDB programatically as they have to be managed by the server. If you want to create dynamic listeners, use the MessageConsumer and setMessageListener. Depending on your setup, you need to get access to Connection from some connection factory, then create session, consumer and finally message listener. A consumer can be created with message selector = your filter. A short example:

    ConnectionFactory conFactory = (ConnectionFactory) ic.lookup("java:/ConnectionFactory");//customize the jndi to match your server
    Connection connection = conFactory.createConnection();
    Queue myqueue = ic.lookup("java:/jms/queue/MyQueue");
    Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
    String messageSelector = "MY_MSG_PROPERTY = 'MY_FILTER_VALUE'";
    Consumer consumer = session.createConsumer(myqueue, messageSelector);
    
    consumer.setMessageListener(new MessageListener() {
        @Override
        public void onMessage(Message message) {
            //handle you message here
        }
    });
    

    With this approach, you can create multiple consumers with different filters and different message listeners. But keep in mind, that those listeners are not container managed, and you need to take care of resource cleanup/close if you no longer need those listeners(close the session, etc).