EMBEDDED MESSAGING USING ACTIVEMQ

Similar documents
Introduction to JMS & Apache ActiveMQ

Distributed Systems. Messaging and JMS Distributed Systems 1. Master of Information System Management

java message service marek konieczny

Java TM. Message-Driven Beans. Jaroslav Porubän 2007

Enterprise Messaging With ActiveMQ and Spring JMS

Purplefinder Enterprise Platform Messagng with ActiveMQ. Peter Potts 13 th October 2010

Web Design and Applications

Using Message Driven Beans.

Communication Technologies MoM JMS.NET. Part VI. Message-Oriented Middleware

Java Enterprise Edition

Asynchrone Kommunikation mit Message Driven Beans

NetBeans IDE Field Guide

The Java EE 6 Tutorial

ESIR SR. Unit 10a: JGroups. François Taïani

Example simple-mdb can be browsed at

Asynchronous Messaging. Benoît Garbinato

Introduction to Messaging using JMS

This document licensed exclusively to: Mark Richards No Fluff Just Stuff TM. Redistribution strictly prohibited.

(9A05803) WEB SERVICES (ELECTIVE - III)

SUMMARY LAYERED ARCHITECTURE

Java Message System. Petr Adámek. April 11 th 2016

JBoss AMQ 7 Technical Deep Dive

Writing Portable Applications for J2EE. Pete Heist Compoze Software, Inc.

Oracle Exam 1z0-895 Java EE 6 Enterprise JavaBeans Developer Certified Expert Exam Version: 14.0 [ Total Questions: 90 ]

Vision of J2EE. Why J2EE? Need for. J2EE Suite. J2EE Based Distributed Application Architecture Overview. Umair Javed 1

DESIGN PATTERN - INTERVIEW QUESTIONS

BEAWebLogic Server and WebLogic Express. Programming WebLogic JNDI

Socket attaches to a Ratchet. 2) Bridge Decouple an abstraction from its implementation so that the two can vary independently.

User Guide. The mom4j development team

Bruce Snyder Dejan Bosanac Rob Davies

Introduction Abstract. 1.2 Overview. This specification describes the objectives and functionality of the Java TM Message Service (JMS).

presentation DAD Distributed Applications Development Cristian Toma

Data Management in Application Servers. Dean Jacobs BEA Systems

IBM. Enterprise Application Development with IBM Web Sphere Studio, V5.0

Borland Application Server Certification. Study Guide. Version 1.0 Copyright 2001 Borland Software Corporation. All Rights Reserved.

Module 10 Developing Java EE Applications using Messaging

Using Properties for runtime ICAN 5.0.x JCD Configuration

Java EE 7: Back-End Server Application Development

3C05 - Advanced Software Engineering Thursday, April 29, 2004

A domain model-centric approach to J2EE development. Keiron McCammon CTO Versant Corporation

SUN Sun Certified Enterprise Architect for J2EE 5. Download Full Version :

CO Java EE 7: Back-End Server Application Development

Distributed Architectures & Microservices. CS 475, Spring 2018 Concurrent & Distributed Systems

CAS 703 Software Design

Ellipse Web Services Overview

Indirect Communication

Classloader J2EE rakendusserveris (Bea Weblogic Server, IBM WebSphere)

Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions

Example Purchase request JMS & MDB. Example Purchase request. Agenda. Purpose. Solution. Enterprise Application Development using J2EE

Enterprise JavaBeans, Version 3 (EJB3) Programming

Introduction to WebSphere Platform Messaging (WPM)

MTAT Enterprise System Integration. Lecture 2: Middleware & Web Services

Process Choreographer: High-level architecture

SOA-14: Continuous Integration in SOA Projects Andreas Gies

Chapter 6 Enterprise Java Beans

Java Lounge. Integration Solutions madeeasy ComparisonofJava Integration Frameworks. Mario Goller

Oracle FLEXCUBE Universal Banking 12.0 Interface Getting started. Release 1.0

Building loosely coupled and scalable systems using Event-Driven Architecture. Jonas Bonér Patrik Nordwall Andreas Källberg

J2EE Development with Apache Geronimo. Aaron Mulder Chariot Solutions

Getting Started with Web Services

Using JNDI from J2EE components

~ Ian Hunneybell: CBSD Revision Notes (07/06/2006) ~

Enterprise Java and Rational Rose -- Part I

2.0 Technical Description of the new features

Asynchronous Web Services: From JAX-RPC to BPEL

WebSphere MQ V7 STEW. JMS Setup Lab. October 2008 V2.3

Fast Track to EJB 3.0 and the JPA Using JBoss

Java EE Patterns 176

EJB Development Using Borland JBuilder 6 and Borland Enterprise Server 5

Installing and Configuring the Runtime Processes 2

: ESB Implementation Profile

RFC 003 Event Service October Computer Science Department October 2001 Request for Comments: 0003 Obsoletes: none.

Exam Questions 1Z0-895

EJB ENTERPRISE JAVA BEANS INTRODUCTION TO ENTERPRISE JAVA BEANS, JAVA'S SERVER SIDE COMPONENT TECHNOLOGY. EJB Enterprise Java

Erik Dörnenburg JAOO 2003

Solace JMS Integration with JBoss Application Server EAP 6.2

Oracle Banking APIs. Part No. E Third Party Simulation Guide Release April 2018

Distributed Transactions and PegaRULES Process Commander. PegaRULES Process Commander Versions 5.1 and 5.2

WHAT IS EJB. Security. life cycle management.

Enterprise Java in 2012 and Beyond From Java EE 6 To Cloud Computing

Appendix A - Glossary(of OO software term s)

Component-Based Software Engineering. ECE493-Topic 5 Winter Lecture 26 Java Enterprise (Part D)

Java EE Architecture, Part Two. Java EE architecture, part two 1

WebLogic JMS Clustering. Jayesh Patel

Oracle EXAM - 1Z Java EE 6 Enterprise JavaBeans Developer Certified Expert Exam. Buy Full Product.

Commercial Component Creation (EJB 2.0)

1Z Oracle. Java Enterprise Edition 5 Enterprise Architect Certified Master

Easy Scalability with Akka. Distribute your domain

CS506 Web Design & Development Final Term Solved MCQs with Reference

Time and Space. Indirect communication. Time and space uncoupling. indirect communication

Arquillian & ShrinkWrap

OCP JavaEE 6 EJB Developer Study Notes

Introduction to WebSphere Platform Messaging (WPM)

In the most general sense, a server is a program that provides information

Adapting JDT to the Cloud. Alex Boyko Pivotal Jay Arthanareeswaran - IBM John Arthorne - IBM

IEC : Implementation Profile

PASS4TEST. IT Certification Guaranteed, The Easy Way! We offer free update service for one year

Getting Started with Web Services

App Servers NG: Characteristics of The Next Generation Application Servers. Guy Nirpaz, VP R&D and Chief Architect GigaSpaces Technologies

The application must track specific user actions / events and communicate them to Responsys through a SOAP service.

Transcription:

Mark Richards EMBEDDED MESSAGING USING ACTIVEMQ Embedded messaging is useful when you need localized messaging within your application and don t need (or want) an external message broker. It s a good technique for decoupling components within your application, resolving application bottlenecks, increasing the overall scalability of your application, or adding an embedded entry point for remote access to your application. Introduction Have you ever wanted to leverage JMS messaging in your application, but couldn t because your company doesn t have a messaging infrastructure in place? Have you ever had a simple JMS messaging need in your application, but didn t want to go through the hassles of setting up an entire messaging infrastructure for one small use case? Have you ever wanted to scale out portions of your monolithic application to resolve bottlenecks, but didn t want to deal with the complexity of threads and concurrency? If so, you might want to consider using embedded messaging. Embedded messaging is a technique that lets you create an internal message broker within your application and leverage all of the features of JMS messaging internally without the need for an external message broker. In this article I will start with the basics of embedded messaging using ActiveMQ, and then show you a real world example of how to use embedded messaging to resolve application bottlenecks within your application. If you want more information about embedded messaging (as well as a plethora of other really cool messaging topics), you can view two new enterprise messaging videos I recently recorded from O Reilly. The references to these videos can be found at the end of this article. No Fluff Just Stuff, the Magazine 12

The Basics Many of the popular open source message brokers available today support embedded messaging, including ActiveMQ, OpenMQ, and HornetQ. Embedded messaging is a technique that allows you to create an internal message broker instance within the context (JVM) of your application. Aside from possibly clustering, there is little or no difference between the broker you create within your application and an external broker started in a separate JVM. There are a few things to consider before jumping right into using embedded messaging. When using embedded messaging to decouple components within an application, you cannot perform the intended operation in the same transactional unit of work. For example, suppose class A is invoking an operation on class B within the context of a transaction. If you decouple these components using embedded messaging, the operation invoked in class B (now a message listener) will run under a different transaction context than class A. Another thing to be aware of when using embedded messaging is that you need to design your application in such a way as to ensure that the embedded broker is always started and available before starting any message listeners. While this may seem really obvious, it does get a bit tricky at times, particularly for complex applications. There are two possible topologies to consider as well when designing your application to use embedded messaging. The most basic (and typical) embedded messaging topology is one where the scope of the embedded broker is limited to only the application (and JVM) the broker is started in. In other words, other applications in separate JVMs are completely unaware that the embedded message broker exists. The second topology is one where the internal broker exposes a port and IP address so that other applications can talk to it as well. Due to the limitations of this second type of topology (specifically embedded broker availability when the application is down), it is really only useful in the context of providing an embedded remote endpoint. For example, suppose application A has a service that can be remotely accessed from application B. In this case application A can start up an embedded broker with a queue to act as an end point for the service. Application B can now connect to the embedded broker in application A and communicate with that remote service. Creating a Broker There are numerous ways of creating an embedded broker within your application. For ActiveMQ (which I will be using for this article), you can directly instantiate the ActiveMQ BrokerService class, or create the BrokerService through an ActiveMQ BrokerFactory class. 13 NoFluffJustStuff.com

You will need to add a couple of JAR files from the ActiveMQ distribution (specifically from the ACTIVEMQ_HOME/lib directory) to create and run an embedded broker. In most cases you will only need to add the activemq-all-5.9.1.jar file (or whatever version you may be using) located in the ACTIVEMQ_HOME root distribution directory. Depending on what broker features you are using, you may need to add one or more of the following JAR files, also found in the ACTIVEMQ_HOME/lib directory: commons-logging.jar log4j-1.2.17.jar spring-beans-3.2.5.release.jar spring-context-3.2.5.release.jar spring-core-3.2.5.release.jar spring-expression-3.2.5.release.jar xbean-spring-3.15.jar commons-logging.jar There are times when the activemq-all-5.9.1.jar may cause some conflicts (particularly with some application servers), so if you experience this you can use the activemq-broker-5.9.1.jar and the activemq-client-5.9.1.jar in place of the activemq-all-5.9.1.jar. To create a broker using the ActiveMQ BrokerService, you first instantiate a BrokerService object, then set the necessary configuration through Java as follows: BrokerService broker = new BrokerService(); broker.addconnector("tcp://localhost:61888"); broker.setbrokername("broker1"); broker.setpersistent(false); //other broker properties can be set here... broker.start(); Once you instantiate the BrokerService you will need to set some broker configuration parameters. There are literally hundreds of parameters you can set, but the ones I am showing here are the three most basic ones. The addconnector() operation is only needed if you intend on exposing your embedded broker to outside applications. For internal application use only, you should not set this property. If you don t like setting configuration parameters in Java, you can use another technique in ActiveMQ that uses an XML properties file along with a BrokerFactory class. This technique encapsulates all of the configuration parameters in a single XML configuration file located in your classpath. While you can use any name you like, I prefer using the standard activemq.xml No Fluff Just Stuff, the Magazine 14

file name. When you create a broker from the BrokerFactory, you pass in the name of the XML configuration file as follows: BrokerService broker = BrokerFactory.createBroker( new URI("xbean:activemq.xml"); broker.start(); Your XML configuration file should be located somewhere in the application classpath (I typically use src/main/resources). Although there are hundreds of properties you can set, the bare minimum configuration file would look like this: <broker xmlns="http://activemq.apache.org/schema/core" brokername="broker1" persistent="false"> <!-- other properties can be set here... --> <transportconnectors> <transportconnector name="openwire" uri="tcp://0.0.0.0:61888/> </transportconnectors> </broker> Accessing an Embedded Broker Normally, when establishing a connection to an external ActiveMQ message broker you would create a Connection object through an ActiveMQ connection factory and pass it the IP address and port it is listening on as follows: Connection connection = new ActiveMQConnectionFactory( "tcp://localhost:61616").createconnection(); While you can use this technique for accessing an embedded broker, there is a much better way. ActiveMQ has a special protocol for accessing an embedded broker called the vm protocol. When using the vm protocol, you use the broker name rather than an IP address and port when making a connection to the embedded broker: Connection connection = new ActiveMQConnectionFactory( "vm://broker1?create=false").createconnection(); 15 NoFluffJustStuff.com

Notice I added the?create=false parameter to the broker address. I usually do this because if the embedded broker doesn t exist when making a connection the broker, ActiveMQ will dynamically create the broker for you. While this is a neat feature, I prefer to create the broker explicitly so I can control the default configuration settings. Using an Embedded Broker Now that you know the basics of setting up and accessing an embedded broker, its time to see how to use one within an application. Rather than make up a fictitious example, I will show you a real-world example I recently coded and deployed at the company I am currently working at. In the application I am currently working on, application reference data is loaded from the database into an internal cache on application startup with the ability to reload the internal data cache on demand whenever there is a change to the reference data. Specifically, there are nine reference tables that are loaded, some of them rather large. The basic code skeleton looks like this (all of the details are removed for brevity): public class ReferenceManager { //key is the table name private Map<String, ReferenceCache> cache; public void loadrefdata() { loadtable1(); loadtable2();... private void loadtable1() { //perform database query //format data and add to cache... Due to the size of the reference tables and the formatting of the data prior to adding it to the cache, this process was taking around 90 seconds to complete. Since the application startup and reload is part of a larger transaction, this process was sometimes causing transaction timeouts, particularly under heavy load. By adding embedded messaging, the table loads from No Fluff Just Stuff, the Magazine 16

the database were able to be run asynchronously and in parallel without the need for complex threading or external message broker configuration and setup. This reduced the endto-end cache load elapsed time to just under 12 seconds. Let s run through the changes needed to add embedded messaging to run each individual table load in parallel. The first change to the original synchronous ReferenceManager class is to add an embedded broker to the startup method to the ReferenceManager. Depending on the implementation of your class, this can be done through the constructor, in the post construct method of the bean, or a separate public method called after instantiation: public ReferenceManager() { BrokerService broker = new BrokerService(); broker.setbrokername("refbroker"); broker.setpersistent(false); broker.start(); Since the embedded broker is not exposed to other applications outside of the JVM, you do not need to use the useconnector() property (only the setbrokername()). Generally you will not need message persistence, which is why you should consider setting the persistence property to false. Once the embedded broker is defined, the next step is to move the logic to load each table into a separate message listener class (one listener for each of the nine tables or a single listener with conditional logic based on the queue name or message property). These listener classes can be a simple POJO-based JMS message listener (as is shown here), or it can be a Spring message-driven POJO or EJB message-driven bean. Usually you will find that a simple POJObased message listener class is most practical because you will need control of when the listener starts (remember, the embedded broker must be started before the listeners can start!). 17 NoFluffJustStuff.com

public class RefTable1Loader implements MessageListener { Session session = null; public RefTable1Loader(String queuename) { Connection conn = new ActiveMQConnectionFactory( "vm://refbroker?create=false").createconnection(); conn.start(); session = conn.createsession( false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createqueue(queuename); MessageConsumer consumer = session.createconsumer(queue); consumer.setmessagelistener(this); public void onmessage(message message) { //perform database query //format data as formatteddata ObjectMessage msg = session.createobjectmessage(formatteddata); MessageProducer sender = session.createproducer(message.getjmsreplyto()); sender.setdeliverymode(deliverymode.non_persistent); sender.send(msg); Notice that the message listener above establishes a connection to the broker named refbroker through the vm protocol using the string vm://refbroker?create=false. As long as the listeners are in the same JVM, you can (and should) use the vm protocol. In the reference manager class you then need to start each of the listeners. This can be done in the startup method after you start the embedded broker instance. Notice that you do not need to hold a references to these listeners in the ReferenceManager; they can be created anonymously because the only thing we care about is that the listener thread starts in each of the classes: No Fluff Just Stuff, the Magazine 18

private void startlisteners() { new RefTable1Listener("TABLE1_REQ.Q"); new RefTable2Listener("TABLE2_REQ.Q");... Once the listeners are started, the next thing to do is to modify the original loadrefdata() method to send a message to each of the listeners, then wait for the response for each of them. Once the response is received, the data from each response message containing the formatted cache data is added to the reference cache: public void loadrefdata() { Connection conn = new ActiveMQConnectionFactory( "vm://refbroker?create=false").createconnection(); conn.start(); //send the messages to the listeners startload(conn, "TABLE1_REQ.Q, "TABLE1_RESP.Q"); startload(conn, "TABLE2_REQ.Q, "TABLE2_RESP.Q");... //now get the results from the response queues cache.put("table1", getloadresults(conn, "TABLE1_RESP.Q"); cache.put("table2", getloadresults(conn, "TABLE2_RESP.Q");... conn.close(); The startload() method creates a Message object, sets the JMSReplyTo, and sends the message to the request queue as a non-persistent message. Notice that this method only creates a Message object (rather than a TextMessage or one of the other message types). This is because you only need to send an event to the listener to start the load process. Alternatively, you can set application properties on the message or use a TextMessage to send additional information to the listeners if needed. 19 NoFluffJustStuff.com

private void startload(connection conn, String requestq, String responseq) { Session session = conn.createsession(false, Session.AUTO_ACKNOWLEDGE); Queue queuereq = session.createqueue(requestq); Queue queueresp = session.createqueue(responseq); Message msg = session.createmessage(); msg.setjmsreplyto(queueresp); MessageProducer sender = session.createproducer(queuereq); sender.setdeliverymode(deliverymode.non_persistent); sender.send(msg); session.close(); The final step is to then use request/reply processing to wait for the data to be returned via the response queue. You don t need to use a correlation id and filtering here because there is only one response message in each of the dedicated response queues. private ReferenceData getloadresults( Connection conn, String queuename) { Session session = conn.createsession(false, Session.AUTO_ACKNOWLEDGE); Queue queue = session.createqueue(queuename); MessageConsumer receiver = session.createconsumer(queue); ObjectMessage msg = (ObjectMessage)receiver.receive(30000); if (msg == null) { throw new RuntimeException( "No response from " + queuename + ": Unable to load data."); session.close(); return (ReferenceData)msg.getObject(); Notice here I added some error handling that is necessary when receiving a reply from the listeners. In this case, if the consumer doesn t receive a response from the response queue within 30 seconds it assumes something went wrong. You will then need to take corrective No Fluff Just Stuff, the Magazine 20

action (or in this case throws an exception). In the actual ReferenceManager class I wrote, on an error such as this I revert back to sequential processing in the spirit of reactive architecture so that the request can still be completed (albeit slower). In this real-world example I skipped all of the ceremony involved with error handling, cache synchronization, method delegation, constants, and many other improvements you can make to streamline this code. While the actual code is rather complicated, the embedded messaging portions are not. Hence, I only highlight those elements in the code to demonstrate the technique of using embedded messaging in your applications. Alternatives While embedded messaging is an easy and reliable technique for introducing asynchronous behavior into your applications, there are some alternatives you might want to consider. Within the EJB space you can use asynchronous beans (coupled with Future objects if you need a return value). For a more general approach, you can use Actors such as those supplied by the Akka framework (which is available in Java and Scala). In cases where you cannot use asynchronous beans (such as application server startup), threads, or third-party asynchronous libraries, embedded messaging provides a very fast, reliable, and easy way to perform parallel processing and increase both performance and scalability. References and Further Reading Enterprise Messaging: JMS 1.1 and JMS 2.0 Fundamentals Video (Mark Richards, O Reilly, 2014) (O Reilly Shop, Safari Books Online) Enterprise Messaging: Advanced Topics and Spring JMS Video (Mark Richards, O Reilly, 2014) (O Reilly Shop, Safari Books Online) Java Message Service, 2nd Edition (Mark Richards, O Reilly, 2009) (O Reilly Shop, Safari Books Online) ActiveMQ Embedded Broker Messaging OpenMQ Embedded Broker Messaging HornetQ Embedded Broker Messaging 21 NoFluffJustStuff.com

About the Author Mark Richards is a hands-on software architect involved in the architecture, design, and implementation of Microservices Architectures, Service Oriented Architectures, and distributed systems in J2EE and other technologies. He has been involved in the software industry since 1983, and has significant experience and expertise in application, integration, and enterprise architecture. Mark served as the President of the New England Java Users Group from 1999 thru 2003. He is the author of several technical books and videos, including "Software Architecture Fundamentals" (O Reilly video), "Enterprise Messaging" (O Reilly video), and "Java Message Service 2nd Edition" (O Reilly). Mark carries a masters degree in computer science, and has numerous architect and developer certifications from IBM, Sun, The Open Group, and BEA. He is a regular conference speaker at the No Fluff Just Stuff (NFJS) Symposium Series, and has spoken at over 100 conferences and user groups around the world on a variety of enterprise-related technical topics. No Fluff Just Stuff, the Magazine 22