jakartaee / jakartaee/messaging
Annotation-Based API for Consuming Messages
- Dominant language
- Java
- Stars
- 49
- Forks
- 34
- PR merge metrics
- No merged PRs in 30d
Description
The only means to declare message consumers via configuration or annotation is currently via JMS Message-Driven Beans. A new expressive annotation-based approach modeled after JAX-RS is desired to bring JMS into the future.
A follow-up to an older issue: https://github.com/jakartaee/messaging/issues/134.
Current MDB API Example:
```
import javax.ejb.ActivationConfigProperty;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageListener;
import javax.jms.ObjectMessage;
@MessageDriven(activationConfig = {
@ActivationConfigProperty(propertyName = "maxSessions", propertyValue = "3"),
@ActivationConfigProperty(propertyName = "maxMessagesPerSessions", propertyValue = "1"),
@ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
@ActivationConfigProperty(propertyName = "destination", propertyValue = "TASK.QUEUE")
})
public class BuildTasksMessageListener implements MessageListener {
@Override
public void onMessage(Message message) {
try {
if (!(message instanceof ObjectMessage)) {
throw new JMSException("Expected ObjectMessage, received " + message.getJMSType());
}
final ObjectMessage objectMessage = (ObjectMessage) message;
final BuildTask buildTask = (BuildTask) objectMessage.getObject();
doSomethingUseful(buildTask);
} catch (JMSException e) {
// Why can't I throw a JMS Exception
throw new RuntimeException(e);
}
}
// This is the only "useful" code in the class
private void doSomethingUseful(BuildTask buildTask) {
System.out.println(buildTask);
}
}
```
Issues with this API involve:
- User manual required to know what names can be used in `@ActivationConfigProperty`.
- Loosely typed. All values are string, but have an implied type which is not compile-time checked.
- Poor targeting. The metadata for the `onMessage` method is on the class, not the method, making additional methods impossible.
- Too Course-grained. The `MessageListener.onMessage(Message msg)` method is similar to the `HttpServlet.service(ServletRequest req, ServletResponse res)` in being too course-grained and requires boilerplate; casting, message property checking, string parsing.
- EJB-specific. The above API is only available to EJB Message-Driven beans.
Some form of annotation-based approach styled after JAX-RS could solve all of the above issues. For example:
```
import io.breezmq.MaxMessagesPerSession;
import io.breezmq.MaxSessions;
import javax.ejb.MessageDriven;
import javax.jms.JMSException;
import javax.jms.JMSMessageDrivenBean;
import javax.jms.ObjectMessage;
import javax.jms.QueueListener;
import javax.jms.TopicListener;
@MessageDriven
@MaxSessions(3)
@MaxMessagesPerSession(1)
public class BuildTasksMessageListener implements JMSMessageDrivenBean {
@QueueListener("TASK.QUEUE")
public void processBuildTask(final ObjectMessage objectMessage) throws JMSException {
final BuildTask buildTask = (BuildTask) objectMessage.getObject();
doSomethingUseful(buildTask);
}
@TopicListener("BUILD.TOPIC")
public void processBuildNotification(final ObjectMessage objectMessage) throws JMSException {
final BuildNotification notification = (BuildNotification) objectMessage.getObject();
System.out.println("Something happened " + notification);
}
// This is the only "useful" code in the class
private void doSomethingUseful(BuildTask buildTask) {
System.out.println(buildTask);
}
}
```
Benefits:
- Multiple user-defined message consuming methods allowed.
- Method signature implies message type, avoiding casting.
- Message Properties can be passed as annotated method arguments. (not shown above)
- Strongly-typed annotations replace string properties so names and values are compile-time checked.
- Opens the door for use outside EJB
The above API should be considered a straw-man just to get conversations started.
## Proposals
Actual proposals from the community are welcome, but should achieve or not-conflict with the same 5 benefits. Partial proposals are welcome, such as #241 which focuses on one aspect required to make an annotation-based API work.
- `@MessageConsumer` for discovery #241
File your proposals and mention in the comments below and we'll add it to the list, regardless of state.
TODO: find JMS 2.1 proposal and link it
## Related
Contributor guide
Research direction
No target files or tests are identified. Start by reading the older issue #134 and the discovery proposal #241, then compare possible designs against the five stated benefits and the JMS and EJB constraints. Done would be an agreed, concrete annotation-based API proposal rather than the current straw-man discussion.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, backend-api-design
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 20/100