If you have read some of my previous articles, you should know that I’m using the SOA Suite on my project as a BPM, based on the coordination of JMS messages.
I naturally went for the solution proposed by Oracle : the JMS adapter. But it took me some time to figure out how to make it work :) The official documentation is complete, but when you need to really implement the concept, it’s often too light.
Then I got it working, as demonstrated in a previous blogpost but it was quite disappointing. In fact, I found it quite strenuous and complex. To me, the need for JCA (and deployment plan) is not mandatory : I just wanted to KISS (keep it simple & stupid)
Then I started looking for some content on that and I found some interesting stuff on Edwin’s blog & Guido’s blog. But once again, I could not go with a complete implementation. Then I tried several things, tested and finally, I came up with an implementation that was satisfying (and which is used every single day in production).
To keep you from going the same loong path I went, here is my code :
package fr.mbutton.blog.mdb; import java.io.StringWriter; import javax.ejb.ActivationConfigProperty; import javax.ejb.MessageDriven; import javax.jms.Message; import javax.jms.MessageListener; import javax.jms.Queue; import javax.jms.QueueConnectionFactory; import javax.jms.TextMessage; import javax.naming.InitialContext; import javax.sql.DataSource; import javax.transaction.UserTransaction; import javax.xml.namespace.QName; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import oracle.fabric.blocks.event.BusinessEventConnection; import oracle.fabric.blocks.event.BusinessEventConnectionFactory; import oracle.fabric.common.BusinessEvent; import oracle.integration.platform.blocks.event.BusinessEventBuilder; import oracle.integration.platform.blocks.event.jms.JmsRemoteBusinessEventConnectionFactory; import oracle.integration.platform.blocks.event.saq.SAQRemoteBusinessEventConnectionFactory; import oracle.soa.common.util.XMLUtil; import org.w3c.dom.Document; @MessageDriven(mappedName = "your.topic.jndi.name", activationConfig = { @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"), @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"), @ActivationConfigProperty(propertyName = "topicMessagesDistributionMode", propertyValue = "One-Copy-Per-Application") }) public class JMSBridgeToEDN implements MessageListener { // EDN JMS environment private final String connFactName = "jms/fabric/EDNConnectionFactory"; private final String xaConnFactName = "jms/fabric/xaEDNConnectionFactory"; private final String queueName = "jms/fabric/EDNQueue"; public void onMessage(Message message) { if (message instanceof TextMessage) { TextMessage txt = (TextMessage) message; BusinessEventConnection connection = null; try { // You can choose between two methods : Oracle AQ or JMS // Default is Oracle AQ connection = getOracleAQConnection (); // But you can choose the other one : // connection = getWebLogicJMSConnection(); // Publish to EDN BusinessEvent event = updateAndConvertBody(txt.getText()); // System.out.println("Element : " + displayXMLDoc(event.getAsDoc())); connection.publishEvent(event, 3); // The number represents message priority (3 = default) } catch (Exception e) { e.printStackTrace(); } finally { connection.close(); } } } private BusinessEventConnection getWebLogicJMSConnection () throws Exception { InitialContext context = new InitialContext(); UserTransaction userTransaction = (UserTransaction) context.lookup("javax.transaction.UserTransaction"); QueueConnectionFactory queueConnectionFactory = ((QueueConnectionFactory)context.lookup(connFactName)); QueueConnectionFactory xaQueueConnectionFactory = ((QueueConnectionFactory)context.lookup(xaConnFactName)); Queue jmsQueue = ((Queue)context.lookup(queueName)); BusinessEventConnectionFactory factory = new JmsRemoteBusinessEventConnectionFactory(queueConnectionFactory, xaQueueConnectionFactory, jmsQueue, userTransaction); return factory.createBusinessEventConnection(); } private BusinessEventConnection getOracleAQConnection () throws Exception { InitialContext context = new InitialContext(); UserTransaction userTransaction = (UserTransaction) context.lookup("javax.transaction.UserTransaction"); // Working with both EDN datasources (as seen in class SAQRemoteBusinessEventConnectionFactory) DataSource ds = (DataSource) context.lookup("jdbc/EDNDataSource"); DataSource localTxDs = (DataSource) context.lookup("jdbc/EDNLocalTxDataSource"); BusinessEventConnectionFactory factory = new SAQRemoteBusinessEventConnectionFactory(ds, localTxDs, userTransaction); return factory.createBusinessEventConnection(); } private BusinessEvent updateAndConvertBody (String body) throws Exception { // [...] // Creation of the message to be sent over the EDN String TCEvenement = "TCEvenement"; // A common mistake is to use the namespace of your message : IT'S NOT THE ONE YOU SHOULD USE ! // You have to provide the namespace of your message as defined IN THE EDL FILE ! String NameSpace = "http://fr.edf.doaat.coctos/events/edl/EventDefinition"; BusinessEventBuilder builder = BusinessEventBuilder.newInstance(); builder.setEventName(new QName(NameSpace, TCEvenement)); builder.setBody(XMLUtil.parseDocumentFromXMLString(updatedBody).getDocumentElement()); return builder.createEvent(); } private String displayXMLDoc (Document doc) throws Exception { TransformerFactory transFactory = TransformerFactory.newInstance(); Transformer transformer = transFactory.newTransformer(); StringWriter buffer = new StringWriter(); transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); transformer.transform(new DOMSource(doc), new StreamResult(buffer)); return buffer.toString(); } }
The method displayXMLDoc is completely optionnal : I used it to help me debug my code but that’s all.
Feel free to improve those codelines, as long as they help you, I’m glad.
Useful links:
http://docs.oracle.com/cd/E21764_01/integration.1111/e10231/adptr_jms.htm
http://docs.oracle.com/cd/E21764_01/integration.1111/e10224/obe_intro.htm#BABHBGAG
http://guidoschmutz.wordpress.com/2010/01/12/using-the-event-api-to-publish-an-event-to-the-event-delivery-network-edn-the-spring-way/
http://biemond.blogspot.fr/2011/06/configure-en-test-jms-based-edn-in-soa.html
No comments:
Post a Comment