jakartaee / messaging

Jakarta Messaging
https://eclipse.org/ee4j/messaging
Other
39 stars 33 forks source link

Bind JMS to CDI events and/or business interfaces #88

Open glassfishrobot opened 12 years ago

glassfishrobot commented 12 years ago

The simplified API is a huge leap forward in terms of simplicity to create and consume messages. But when writing a real service (probably an MDB) that consumes multiple messages coming in from a queue or topic, then unpacking them and dispatching calls to the right method is still rather tedious, error prone, and difficult to test.

Take this example of a service that handles two different xml messages, one to create a customer and one to delete a customer. Using text messages that contain xml is a good option, if you want to exchange complex objects and need tools to look into messages in transit. I don't show the Create/DeleteCustomer data objects here.

@MessageDriven(activationConfig = { @ActivationConfigProperty(propertyName = "destination", propertyValue = "CustomerService") })
public class ReceiverMdb implements MessageListener {
    @Override
    public void onMessage(Message message) {
        try {
            String xml = ((TextMessage) message).getText().trim();
            StringReader reader = new StringReader(xml);
            if (xml.endsWith("</createCustomer>")) {
CreateCustomer create = JAXB.unmarshal(reader, CreateCustomer.class);
createCustomer(create.getFirstName(), create.getLastName());
            } else if (xml.endsWith("</deleteCustomer>")) {
DeleteCustomer delete = JAXB.unmarshal(reader, DeleteCustomer.class);
deleteCustomer(delete.getId());
            } else {
throw new RuntimeException("unknown message type: " + xml);
            }
        } catch (JMSException e) {
            throw new RuntimeException(e);
        }
    }

    private void createCustomer(String firstName, String lastName) {
        System.out.println("create customer " + firstName + " " + lastName);
    }

    private void deleteCustomer(String id) {
        System.out.println("delete customer " + id);
    }
}

I can see two alternatives to reduce the unpacking and dispatching to the bare minimum:

1) Binding to CDI events

The same example would look like this:

@Stateless
public class CustomerService {
    public void createCustomer(@Observes CreateCustomer create) {
        System.out.println(create);
    }

    public void deleteCustomer(@Observes DeleteCustomer delete) {
        System.out.println(delete);
    }
}

Note that the Create/DeleteCustomer classes would have to be annotated as @MessageEvent, so the container can create an appropriate binding from JMS.

2) Binding to a business interface

For the same example, the Create/DeleteCustomer classes would not be necessary. Instead there would be a business interface and the service implements it:

@MessageApi
public interface CustomerService {
    public void createCustomer(String firstName, String lastName);
    public void deleteCustomer(String id);
}

public class CustomerServiceBean implements CustomerService {
    @Override
    public void createCustomer(String firstName, String lastName) {
        System.out.println("create: " + firstName + " " + lastName);
    }

    @Override
    public void deleteCustomer(String id) {
        System.out.println("delete: " + id);
    }
}

Both binding methods would help with sending messages as well, but the difference is bigger when receiving them.

A lot of questions still need to be answered: How do you define message properties, destination name, delivery mode, time-to-live, delay, etc.? All would have useful defaults, but sometimes they need to be specified, and sometimes they even need to be dynamic. How do you bind to other message types, like mapped messages?

I've started to collect some possible answers to most of these questions here as part of an experimental implementation for both binding types here. I'm aware of the CDI binding implementation in the Seam JMS module here.

glassfishrobot commented 6 years ago
glassfishrobot commented 12 years ago

@glassfishrobot Commented Reported by rdohna

glassfishrobot commented 7 years ago

@glassfishrobot Commented This issue was imported from java.net JIRA JMS_SPEC-88