The EJB Advocate: Implementing loosely coupled SOA applications using Java EE

The EJB Advocate explores various forms of loose coupling in service-oriented architecture, with a focus on when it is best to take advantage of the asynchronous processing power provided by message-driven beans.

Share:

Geoff Hambrick (ghambric@us.ibm.com), Distinguished Engineer, IBM

Geoff HambrickGeoff Hambrick is a lead consultant with the IBM Software Services for WebSphere Enablement Team and lives in Round Rock, Texas (near to Austin). The Enablement Team generally helps support the pre-sales process through deep technical briefings and short term Proof of Concept engagements. Geoff was appointed an IBM Distinguished Engineer in March of 2004 for his work in creating and disseminating best practices for developing J2EE applications hosted on IBM WebSphere Application Server.



07 December 2005

Also available in Russian

From the IBM WebSphere Developer Technical Journal.

In each column, The EJB Advocate presents the gist of a typical back-and-forth dialogue exchange with actual customers and developers in the course of recommending a solution to an interesting design issue. Any identifying details have been obscured, and no "innovative" or proprietary architectures are presented. For more information, see Introducing the EJB Advocate.

Is your definition of loose coupling too tight?

Since this is the last article of 2005, this exchange about Java™ Platform, Enterprise Edition (Java EE) components other than session and entity beans seemed like a good way to summarize the year-long discussion conducted through this column and put the all of the components together into a complete service oriented architecture.


The problem: too much focus on sessions and entities in SOA

Dear EJB Advocate,

So far your columns have been all about session and entity EJBs for services, which is great for directly connected Java applications, like HttpServlets for Web based clients, or Swing applications for rich (we don't like to say "fat") clients. But we have heard that service-oriented architecture is all about loose coupling. Doesn't that imply using SOAP to provide language neutrality and asynchronous protocols that enable the client and server applications to run independently as much as possible? In other words, why haven't you talked much about JMS and message-driven beans?

Signed,
Feeling Disconnected


There are many aspects to loose coupling to consider

Dear Disconnected,

The EJB Advocate has focused on the services layers of the application and not much at all on the client side because I am a big believer in the old adage form follows function.

The reason is that many projects embarking on SOA fail because they get caught up in the implementation details before they have a good model for defining services in the first place.

This tendency is somewhat natural because most of the people I deal with on the subject of SOA are architects and programmers who know that the devil is always in the details and want to get down to them as quickly as possible. So, as soon as we agree that the attributes of a good service are that they are coarse grained, stateless, mediatable and adaptable (see Is it ever best to use EJB components without facades in service oriented architectures?), it seems obvious that session beans with data transfer objects will play a role in the implementation.

But that previous column leads one to question whether a session bean is necessary at all, introducing the possibility of using entity beans and their Home methods instead of session beans. Figure 1 shows both approaches being used simultaneously.

Figure 1. A service implemented with session and entity EJBs waiting to be used
Figure 1. A service implemented with session and entity EJBs waiting to be used

Figure 1 shows how the pure entity approach, enabled since EJB 2, has fewer components and a shorter path length when using session beans that pass through. A green box is used to represent the client, blue ones to represent various interface and facade classes. The orange box is the commonly accessed entity bean. The boxes are connected with double headed arrows labeled with the protocol used to communicate between the components; the blue ones representing Java calls in the same JVM, and the red ones representing connections that are remote (using RMI/IIOP in this case). The flow arrows are numbered to show the end-to-end flow, with A1-A10 showing the flow from the Java client through the session bean to the entity and back, and B1-B4 showing the flow from the client directly to the entity bean and back.

The programming model to retrieve the service interface used by the client is simpler too, although this is not shown in the diagram. Retrieving a session bean interface requires looking up the session Home in a JNDI context and using it to create a session; an entity Home merely needs a lookup, its methods can be directly invoked without creating a reference to an EJB Object. The following two code samples show the difference.

Listing 1. Locating and invoking a remote session EJB method
Context initCtx = new InitialContext();
Object obj = initCtx.lookup("java:comp/env/ejb/OrderEntry");       
OrderEntryHome home = (OrderEntryHome)PortableObjectRemote(
	obj, OrderEntryHome.class
);       
OrderEntry ref = home.create();

// Method must be invoked on a session reference
CustomerData data = ref.getOpenOrderForCustomer(cID);
Listing 2. Locating and invoking the equivalent remote entity EJB Home method
Context initCtx = new InitialContext();
Object obj = initCtx.lookup("java:comp/env/Customer");
CustomerHome ref = (CustomerHome)PortableObjectRemote(
	obj, CustomerHome.class
);

// Note how the method is invoked directly   
CustomerData data = ref.getOpenOrder(cID);

Figure 1 and the associated code samples show a real benefit of the Java EE programming model, whether or not you choose to use the entity Home method approach. The programming model changes incrementally and provides backwards compatability. In short, your best practices can evolve without forcing you to change existing applications. Also, the JNDI context provides a related aspect of loose coupling that should not be overlooked: implementation independence.

Remote interfaces to session or entity EJB components provide location independence. Using a remote interface makes it possible to deploy the client application and service components in the same JVM where it makes sense for the response time, throughput, and maintainability goals of the system, such as with a Web application using HttpServlets. Figure 2 shows just such a configuration, where an enterprise-quality application server, like IBM® WebSphere® Application Server, "short circuits" a remote interface to use Java and pass by reference when the client and service components are co-deployed (whether the service is implemented as an entity Home method or session bean). Flows A1-A6 show the use of an HttpServlet co-deployed with a service component. Flows B1-B4 show how it is reused by a remote rich client Java EE application.

Figure 2. Service deployed locally to a Web application and remotely to a rich
Figure 2. Service deployed locally to a Web application and remotely to a rich

But it sounds like you have decided that the most important aspects of loose coupling are language neutrality and asynchronous operations. And you are right that needing asynchronous operations will lead you towards using message-driven beans (MDBs) and JMS on the server side.

The approach that many programmers use when implementing a MDB is to invoke the EJB component representing the service through its remote interface to maximize location independence as described above. Then, whether the service implementation is deployed remotely or locally, the purpose of the MDB is to serve as a simple adaptor, connecting an MQ layer into the EJB container where the service is hosted. JMS may be used by the asynchronous client application (if it is Java) or by the MDB (usually for the reply queue). Figure 3 shows this configuration as yet another input channel for our service implementation.

Figure 3. The service deployed with MDBs providing an asynchronous client channel
Figure 3. The service deployed with MDBs providing an asynchronous client channel

The flow C1-C2 is shown separately from D1-D6 to illustrate the independence of the client and server processes. C2 and D6 simply show an "acknowledgement" to the writer that the message was written and does not imply waiting. Listing 3 shows a typical structure of an MDB that should help clarify the processing that it must do:

Listing 3. A typical message-driven bean implementation
public class OrderSubmitMsgHandler implements MessageDrivenBean {
    private transient MessageDrivenContext context = null;

    // Interface supported by either the session Bean or entity Home
    private transient OrderEntry ref;

    public void ejbCreate() {
        // Cache the home according to either snippet one or two
    }
    public void ejbRemove() {}
    public void setMessageDrivenContext(MessageDrivenContext mdc) {    
        context = mdc; 
    }
    // Message acknowledge and database update participate
    public void onMessage(Message inMessage) {
        // Parse the customer from the message
	try {
	    ref.submit(customer); 
	} 
        catch (CustomerDoesNotExist e) {
            // Send JMS message to reply queue from exception
        }
        catch (OrderNotOpen e) {
            // Send JMS message to reply queue from exception
        }
        catch (OrderHasNoItemsException e) {
            // Send JMS message to reply queue from exception
        }
    }
}

The EJB Advocate would now like to get back to the issue of language neutrality that you brought up. It seems that you have tightly coupled the requirement of language neutrality with that for asynchronous processing. There is no reason that you cannot separate these concerns; the ability to parse a SOAP message and use it to invoke a session bean should be independent of whether the processing of that message is asynchronous (through MQ or another protocol over which JMS equivalent messages flow), or synchronous (such as through HTTP or even IIOP). In fact, some of the early "inventions" of Web services on Java EE applications used an HttpServlet to parse an XML message passed over HTTP. This approach eventually evolved to be SOAP/HTTP. Figure 4 shows yet another path that can be provided on top of the services implemented by an EJB component.

Figure 4. Separating the concerns of language neutrality from asynchronicity
Figure 4. Separating the concerns of language neutrality from asynchronicity

The Web Service Servlet and the Message Driven Bean could share the code that parses the data transfer objects from a stream extracted from the message string or HttpServletRequest. Similarly, the response or reply could share the code that generates a stream from the data transfer object (which could be an instance of Exception).

Hope this helps you understand the positioning of the Java EE components, all of which provide some form of loose coupling essential to a service-oriented architecture.

OK then,
Your EJB Advocate


Still too many options to choose from

Dear EJB Advocate,

Thanks.

I hadn't considered before now that services like JNDI and remote interfaces provide aspects of loose coupling. I can also see how we (as you put it) "tightly coupled" the idea of SOAP and MQ, and should try to separate them where possible. So it makes a lot of sense to treat the parsing and generating of SOAP messages like a service itself that is reused by the Web services servlet and the MDB.

But no thanks.

Before this discussion, SOA seemed pretty simple: every service exposed a SOAP/MQ interface. Now it seems that I have too many choices to think about, and since I am treating the SOAP message parsing and generation like services, why wouldn't I want to make a separate session bean to encapsulate them for reuse like you show in your figures?

I'm afraid that I am:
Still Disconnected


Not everything is a service: use the business model to decide

Dear Disconnected,

This discussion is a great example of what happens when you get down to the implementation details too soon. The EJB Advocate column, Which type of EJB component should assemble the data returned by a service? was important because it describes a top-down approach to defining services that tied them directly to the business process model. To summarize the essential details of that approach here:

  1. Develop a model of the business process, showing the major milestones in the lifecycle of an important domain object:

    1. We used a state-transition diagrams for this model, where the states represent the milestones, and the transitions represent events that cause changes in that state. The transitions can be considered the services offered by the application (see Figure 5 for an example).

    2. We extend the state-transition diagram with UML "Actor" notation to show the owner of the object when it is in that state. The owner of the state is responsible for initiating the transitions, so drives the security model of the application (also see Figure 5).

    3. For each state in the business process, we also model the attributes of each domain object and the relationships between them needed to support the actions of the transitions. The notation we typically use is a UML class diagram (see Figure 6 for an example). Having separate diagrams for each state let us model the changing "shape" of the object over time. These diagrams drive the persistent data.

  2. Develop a model of the user interface flow, showing how a given actor from the business process will interact with the system during a typical "session".

    1. Like the business process model, we used a state-transition diagram, where the states indicate the screens and dialogs and the transitions represents the actual UI events, like menu items being selected and buttons being pressed. The actions associated with the transitions are specified in terms of business process transitions.

    2. Also like the business process model, we build a class diagram to show the data that must be visible in each state to support the various choices. The implication is that this data must be derivable from user inputs and drives the read operations on the services in a top down fashion.

    3. Unlike the business process model, we need not extend the state diagram with Actor notation, since the diagram itself can be thought of as a "day in the life" of a single user role.

Figure 5. An example state-transition diagram showing the lifecycle of an order
Figure 5. An example state-transition diagram showing the lifecycle of an order
Figure 6. An example class diagram showing the "shape" of an open order
Figure 6. An example class diagram showing the

This comprehensive approach insures that:

  • The right operations are grouped together into a service (all the transitions and read methods associated with a state in the business process lifecycle).

  • The purpose of each service is well understood (the actions are specified in terms of the related business objects).

  • The pre-conditions needed to invoke a service and the post conditions that can result are communicated (the current state and optional guards, as well as the next state are specified by the transition).

  • The user role responsible for invoking the service is identified (an actor is associated with each state).

None of this information is provided by a method signature regardless of where they are implemented, but this information is crucial to a good SOA. Otherwise, programmers will fall back on another tendency: when in doubt, build it over again. Since development costs are higher for SOA (to provide all the different mediators and adaptors needed for the completely loose coupling shown in Figure 4), this tendency against reuse can minimize the benefits.

To answer the issue in your reply about simplicity, none of this information forces you to expose the interfaces in a certain way, and the EJB Advocate has learned that simplicity is in the eye of the beholder. If you want to eliminate choices for the service developer, you can simply provide all of the "blue" components shown Figure 5 for each service:

  • A remote service interface to provide location independent synchronous Java EE client access to the service operations.

  • A MDB associated with each operation that provides asynchronous non-Java client access over a JMS compliant MQ implementation. Optionally, this or a different MDB can be coded to expect Java messages for JMS clients (to avoid the HTTP Parsing overhead).

  • A Web services servlet associated with each operation that provides synchronous SOAP over HTTP client access.

For those worried about the number of unused components that this approach would generate, another approach to simplicity is to apply what the EJB Advocate likes to call client-oriented architecture (COA); give the client exactly what they need to use the service in a way most natural to them.

This COA approach requires looking at the details of the business process and UI models to pick the most likely candidates for each approach. For example:

  • Transitions between states in the business process lifecycle are likely candidates for asynchronous services, since there will be a change of "owner" for the associated domain object. For example, the submit method can simply change the state of the order to "submitted" in the open order application (we called this OrderEntry in the example above), and send a JMS message to copy it into the submitted order application (we called this one OrderFulfillment).

  • Transitions within states should normally be synchronous, since there is no change of owner. As an example of why these operations should not be asynchronous, imagine if you went to a book seller's Web application and had to poll or wait for a pub-sub event for the catalog to be displayed or an item to be added to the shopping cart! And for those that want to use a pseudo-synchronous style over an asynchronous channel, please, please, please, see Bobby Woolf's book on Designing Messaging Systems.

  • Only provide SOAP over HTTP or MQ for integration scenarios where you have non-Java clients or services involved.

The COA approach results in the components being developed "just-in-time", which is why the EJB Advocate likes to recommend it.

And a final point to address your question (why not treat everything like a service, even the transformations associated with mediators and adapters): the simple answer goes beyond the fact that there can be too much of a good thing. When developing SOA or COA Java EE applications, it is best to consider services as operations on the business process model. Services have to do with the functional requirements of the application. Mediations and the associated transformations are associated with the non-functional requirements like reliability, usability, efficiency, maintainability, and portability. If you treat the mediations or the associated transformations as a first class service, you eventually obscure the real purpose of the application.

I know this is a lot to take in, so do not hesitate to contact me on the details as you apply these approaches.

OK then,
Your EJB Advocate.


Conclusion

The dialog in these exchanges show how Java EE provides a complete implementation framework for applications employing service-oriented architecture, with each component or API playing an important role in some aspect of "loose coupling":

  • Operating system independence is provided by Java itself because Java provides a write-once run anywhere language for components that decouples your code from the underlying operating system.

  • Implementation independence is provided by the Java Naming and Directory Interface (JNDI), with the ability to bind a logical name to an implementation at runtime.

  • Location independence is provided by remote interfaces using RMI over IIOP to stateless session beans or entity home methods that encapsulate the services. RMI/IIOP is a stateful connection that is relatively fast, but does not scale all that well.

  • Web server independence is provided by HttpServlets that can respond to the synchronous HTTP protocol. Unlike RMI/IIOP, HTTP is (normally) a stateless protocol that scales well, but does not perform as well due to the size of the messages and the need to create and break down the connection between client and server each time.

  • Application independence is provided by the asynchronous Java Messaging Service (or MQ for non-Java clients) and message-driven beans (for the queue handler).

  • Language independence is provided by using a standard message format like SOAP, whether it flows on RMI/IIOP, HTTP, or MQ. Thus, SOAP may be used by every component, but it is important to only use it when necessary.

We are willing to bet you can find others. The challenge is managing the tradeoffs associated with each. That should keep you busy until next year.

Resources

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Java technology
ArticleID=100072
ArticleTitle=The EJB Advocate: Implementing loosely coupled SOA applications using Java EE
publish-date=12072005