jakartaee / jakartaee/messaging
Proposal: resource declarations without JCA
- Dominant language
- Java
- Stars
- 49
- Forks
- 34
- PR merge metrics
- No merged PRs in 30d
Description
(this partially solves #251, but still requires some way of configuration injection. If necessary, I can pare this down to the bare minimum that is needed for CF definition)
One of the things in JMS 2.1 (or rather Java EE 6) that are incredibly useful in theory, but terrible in practice are resource definitions. `@JMSConnectionFactoryDefinition` looks a lot like JDBC `@DataSourceDefinition`, but is much more cumbersome to use:
- it requires JCA adapters for each message broker, which must be deployed into the application server, are often poorly documented, and even functionally incomplete
- `@MessageDriven` beans, the place where you would expect to get away with just JNDI names of the factory and the destination plus the destination name, do not work with such JMS resources without vendor-specific ActivationConfigProperties
Better `@JMSConnectionFactoryDefinition` and `@JMSDestinationDefinition` should possess the following traits:
- create JMS resources that are indistinguishable from those created by the application server
- not require any additional wrappers around existing libraries that implement JMS interfaces
- use the same configuration properties as existing JMS libraries
This will allow Jakarta EE developers to create applications that work equally well with existing application servers running Java EE 6 or 7 (by not declaring JMS resources in their code) as well as with cloud native lightweight application servers that support the next version of JMS and that can be packaged as uberjars or hollow jars + skinny jars, all this without vendor-specific code.
The changes to the annotations, interfaces and the expected behavior that, in my opinion, will achieve that are outlined below.
**JMSConnectionFactoryDefinition**
- when `resourceAdapter()` is not set, `className()` is used to select a class from the classpath, not from the default resource adapter; `interfaceName()` is used to disambiguate in cases when the class implements several JMS connection factory interfaces
- `XAConnectionFactory` and its subinterfaces are added to the list of allowed connection factory interfaces, the application server must provide their non-XA counterparts as JNDI resources and manage transactions transparently
- it's a runtime error when `interfaceName()` is `XAConnectionFactory` or its subinterface and `transactional()` is false
- `user()` and `password()` are used to call `ConnectionFactory.createConnection()` and `ConnectionFactory.createContext()`
- when `resourceAdapter()` is not set, `properties()` must set the properties of the instantiated connection factory class, which must be a JavaBean
**JMSDestinationDefinition**
- when `resourceAdapter()` is not set, `className()` is used to select a class from the classpath, not from the default resource adapter; `interfaceName()` is used to disambiguate in cases when the class implements several JMS connection factory interfaces
- `destinationName()` must be used to create destinations in a JMS-standard way
- String `connectionFactoryLookup()` must be added to the interface. It can be used instead of `className()` or `resourceAdapter()` to create a destination
**ConnectionFactory**
- Queue createQueue(String name) and Topic createTopic(String name) must be added to the interface. Right now the docs say similar methods on Session should not generally be used and JNDI lookup should be preferred, but this simply obscures the facts that application servers and JMS providers still need some API that lets them configure destinations. Putting the methods on the factory provides that common API.
**Concerns**
- Most `Queue` and `Topic` implementations provide a constructor that accepts the destination name as its only String parameter, so changes to `ConnectionFactory` are theoretically unnecessary, but constructors are not a part of the interface, so I'd prefer two trivial factory methods instead. If some vendors don't provide a compliant implementation, writing a wrapper will still be trivial.
- Low demand for the change. MicroProfile Reactive Messaging is the new hip API, and vendors that provide cloud native Jakarta EE application servers might not be interested in changes that let customers migrate away from their software with ease.
An example of how this might look in practice:
```java
@JMSConnectionFactoryDefinition(
name = "java:app/jms/Artemis",
className = "org.apache.activemq.artemis.jms.client.ActiveMQXAConnectionFactory"
interfaceName = "javax.jms.XAConnectionFactory",
user = "foo",
password = "bar",
properties = {
"brokerURL=tcp://example.com:61616"
}
)
@JMSDestinationDefinition(
name = "java:app/jms/SourceQueue",
interfaceName = "javax.jms.Queue",
destinationName = "FOO.BAR.ADAPTER",
connectionFactoryLookup = "java:app/jms/Artemis"
)
```
These declarations do not require a JCA resource adapter to work, but work with `artemis-jms-client` directly, which must be packaged with either the application or the application server.
Contributor guide
Research direction
Start by reviewing the JMSConnectionFactoryDefinition, JMSDestinationDefinition, and ConnectionFactory interfaces named in the proposal, along with the current JMS resource-definition behavior. Trace how resource adapters, className, interfaceName, properties, and connectionFactoryLookup are currently handled. Done would require an agreed API and behavior for declarations without JCA, including the proposed factory methods and compatibility expectations.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100