We are prototyping some possible extensions to MDBs to see if we can make things a little easier for development. The idea is to give a message consumer (an MDB) a typed interface that message producers can send messages through. Both the publisher and subscriber would be typed interfaces.
It might be best to look at a full example.
For each producer interface the Consumer implements, there will be a proxy that implements that Producer interface registered in JNDI under the FQN of that Producer interface.
Let's do a simple example. First define the consumer. Take a look at ExampleConsumerBean.java. This is our bean class and defines the methods than can receive JMS messages. The bean class implements three interfaces which are configured as Producers in jboss.xml. These interfaces will be used by clients (JMS publishers) to send messages to the Consumer via JMS.Note that ExampleProducerXA.java is tagged with connection-factory to indicate the jndi name of the XA transaction factory.
Let's now take a look at the client (really the producer of the actual messages) Client.java
When the Consumer is deployed by the EJB3 container, it looks for all of its Producer interfaces and registers each one of them in JNDI under their FQN class name. The client code above looks up the ExampleProducerRemote.java interface in JNDI and accesses the local interfaces ( ExampleProducerLocal.java, ExampleProducerXA.java) through the Stateless Session bean TesterBean.java. Each producer implements the ProducerObject. The client typecasts the ExampleProducerRemote to the ProducerObject. It then gets a ProducerManager that manages the JMS connection for this proxy. To start being able to send messages to the Queue, the client calls connect() on the manager. It then can successfully call methods on the remote Producer. When it calls method1() this method call is converted into a JMS message and published to the Queue of the Consumer. The consumer will receive the message and invoke its method1 method.
The proxy registered in JNDI will know how to contact the JMS Queue/Topic to publish messages. You can specify explicitly through the connnection-factory tag what the JMS ConnectionFactory JNDI name is, or you can rely on defaults.
The default value is "ConnectionFactory" for the ConnectionFactory JNDI name.
If you additionally tag the producer as local-producer instead of producer, then "java:/ConnectionFactory" will be used.
If you tag a producer as local-producer, the proxy will lookup the connection factory via the default InitialContext when connect() is called. Otherwise, the ConnectFactory reference will be embedded directly within the proxy.
The methods defined in a Producer are turned into JMS messages. The default message properties are a Time To Live of 0, a Priority of 4, and a delivery mode of PERSISTENT. You can override these default values using the message-properties tag. This tag can be specified per method or wildcarded for all methods in the Producer interface.
So, in the above example, method1() uses the default message properties, and method2() overrides the defaults via the message-properties tag.
Sometimes you may need to access the real JMS message. Maybe you need to obtain the replyTo destination or set an acknowledgement or something. You can obtain it by using the current-message tag.
This tag will inject the current JMS message into your Consumer bean before your target method is invoked.
Please provide feedback to this proposed feature on our forum. We would really like feedback on this feature.
Unix: $ export JBOSS_HOME=<where your jboss 4.0 distribution is> Windows: $ set JBOSS_HOME=<where your jboss 4.0 distribution is> $ ant $ ant run
Look in the console window to determine that the message was sent.
12:25:59,734 INFO [Ejb3Module] found EJB3 consumer bean: org.jboss.tutorial.consumer.bean.ExampleConsumerBean 12:25:59,734 INFO [Ejb3Module] found EJB3 stateless session bean: org.jboss.tutorial.consumer.bean.TesterBean 12:25:59,796 INFO [ConsumerContainer] Producer: org.jboss.tutorial.consumer.bean.ExampleProducerRemote 12:25:59,796 INFO [ConsumerContainer] Producer: org.jboss.tutorial.consumer.bean.ExampleProducerLocal 12:25:59,796 INFO [ConsumerContainer] Producer: org.jboss.tutorial.consumer.bean.ExampleProducerXA 12:25:59,812 INFO [ProxyDeployer] no declared remote bindings 12:25:59,812 INFO [ProxyDeployer] there is remote interfaces 12:25:59,812 INFO [ProxyDeployer] default remote binding has jndiName of org.jboss.tutorial.consumer.bean.Tester 12:25:59,828 INFO [EJB3Deployer] Deployed: file[the deployment] 12:26:09,000 INFO [STDOUT] method1(Remote method1 called, 1) 12:26:09,015 INFO [STDOUT] method2: Remote method2 called 12:26:09,015 INFO [STDOUT] method2 key/val: great:ejb3 12:26:09,015 INFO [STDOUT] method2 key/val: hello:world 12:26:09,109 INFO [STDOUT] method1(testLocal, 1) 12:26:09,125 INFO [STDOUT] method2: testLocal2 12:26:09,125 INFO [STDOUT] method2 key/val: great:ejb3 12:26:09,125 INFO [STDOUT] method2 key/val: hello:world 12:26:09,125 INFO [STDOUT] end TESTXA ** 12:26:09,140 INFO [STDOUT] method2: testXA2 12:26:09,140 INFO [STDOUT] method2 key/val: great:ejb3 12:26:09,140 INFO [STDOUT] method2 key/val: hello:world 12:26:09,140 INFO [STDOUT] method1(testXA, 1)