Deciding when to Use Asynchronous Calling with JMS

        So far we've considered only synchronous functionality, and only remote communication using RMI/IIOP. J2EE also allows us to implement asynchronous functionality, and to use messaging as an alternative form of communication with other applications

        We may need to use messaging to meet some business requirements, or we may choose to use messaging if we believe that an asynchronous model is the best implementation option. In this section we'll consider some of the architectural and implementation choices relating to messaging

Message-Oriented Middleware (MOM) and JMS 

        MOM is infrastructure that supports messaging: loosely-coupled, standards-based and usually asynchronous communication between components or applications. Messaging involves a message broker that sits between message producers (equivalent to method callers in a synchronous model) and message consumers (objects that listen for and process messages). There may be multiple message consumers. A message producer can normally continue with its work after publishing a message: unlike a synchronous method invocation, publishing a message does not block. This is sometimes called fire-and-forget.

        Until recently, MOM has not been widely used in J2EE. However, its value has been proven in many other systems.

        Different messaging systems traditionally have proprietary APIs. The Java Message Service (JMS) is a standard J2EE API for messaging, which sits on a Service Provider Interface (SPI) that can be implemented for different messaging systems. Like JDBC, JMS abstracts the details of low-level access using proprietary conventions. Application code that uses JMS doesn't need to concern itself with the underlying messaging system, or the message transport it uses. JMS supports both Publish and subscribe (Pub/Sub), and Point-to-Point (PTP) messaging

        The JMS API is available to EJBs, servlets and application clients. J2EE 1.3 integrates the JMS into the EJB model, enabling the EJB container to handle some low-level JMS API issues. Message-driven beans provide special support for JMS message consumers.

        We can make full use of JMS in any component managed by a J2EE server. However, EJBs are especially well-equipped both to produce and consume messages.

Producing Messages 

        Any object running within a J2EE server can produce JMS messages.

        EJBs benefit from no special JMS-related services for JMS message publication. Like other objects running within a J2EE server, they must use JNDI and the JMS API to obtain a JMS connection and session before publishing messages

        However, message production - like resource management - can benefit from CMT in the EJB Container-managed transactions can provide transparent transaction management for transacted | JMS sessions

        JMS supports the notion of transactions. However, it's important to distinguish between JMS transactions and JTS (that is, ordinary J2EE) transactions. A transacted JMS session enables us to batch messages. When creating a JMS session (which we need to do before sending messages in a message producer), we must specify whether or not a session should be transacted. If a session is transacted, either the session's commit () or rollback () method should be called to let JMS know what to do with an buffered messages. In the event of a commit they will be delivered as a single unit (all delivered atomically); in the event of a rollback, they will all be discarded.

        It’s possible to work with different JMS session objects if some messages must be transacted while others not be. Enterprise resources such as databases are not enlisted in JMS transactions. Resource enlistment is the business of ordinary JTS transactions. JMS transactions are local transactions with a special meaning. It is possible for JTS transactions to enlist JMS resources, so it's usually preferable for message producers to work with JTS transactions (which can, of course, be managed by the container in the EJB tier) than with JMS transactions directly.

        If message production is not transactional (for example, if only one message is published per operation, or if each message has to be processed individually), there's no compelling reason to use EJBs as message producers.

Consuming Messages 

        It is in consuming messages that EJBs really shine

Consuming Messages without Using EJB 

        Any component running within an environment managed by the J2EE server can consume JMS messages. However, implementing a message consumer involves using JNDI to look up a JMS destination and registering a listener with it; the JNDI and JMS code involved is fairly complex. While we can use generic infrastructure code to remove these responsibilities from application code, it's better to use standard infrastructure offered by the EJB container, if possible

Consuming Messages with Message-Driven Beans (MDB)

        Consuming messages with MDBs is much easier, as we can specify the message destination and filter declaratively in the ejb-jar.xml deployment descriptor, and concentrate on handling messages, not writing low-level JMS or JNDI code. Let's consider some of the capabilities of MDBs, and some important implementation considerations.

MOB Concepts

        A MDB is an asynchronous message consumer with access to EJB container services. An MDB is not visible to a client. Unlike session or entity beans, MDBs don't have home or component interfaces; instead, MDB instances are invoked at runtime by an EJB container on receipt of a JMS message. The EJB container knows which MDB to invoke on receipt of a message, based on a declarative mapping in EJB deployment descriptors.

        MDBs can consume messages from either topics (in Pub/Sub messaging) or queues (in FTP messaging). The EJB container, not the bean developer, handles JMS message acknowledgment for MDBs; the developer must not use the JMS API to acknowledge messages.

When to Use Asynchronous Calling 

        Now that we are familiar with the major issues concerning JMS and MDBs, we can consider when to use messaging. 

Indications for Using Messaging 

        Asynchronous calling can only be used when the caller doesn't need an immediate response. Thus, a method that has a return value isn't a candidate for asynchronous calling. Nor is a method that may throw an application exception. Checked exceptions provide alternative return values for Java methods, and force clients to take action. This isn't possible with asynchronous calling 

        Assuming that these essential conditions hold, the following indications suggest the use of JMS. The more of these indications that apply, the more appropriate the use of messaging is likely to be:

o To improve the client's perception of application response If a client can be given an immediate response with "fire-and-forget", the system will seem faster than one which blocks on the same action.

o When business logic calls for the result to be delivered to the client other than by a direct method response Sending an e-mail is a perfect example of this, and is often a good use of JMS.

o To perform slow operations A slow operation that doesn't result in a java return value and won't throw an exception is a perfect candidate for JMS. Consider, for example, a reporting operation that involves both Java-based calculations and database queries. It might be more appropriate to return such a report in an e-mail, allowing immediate return to the client while the report is generated in the background.

o When the order of processing tasks doesn't matter While we can guarantee the ordering of synchronous RMI calls, we can't guarantee the ordering of message processing. It may not be the same as that of message publication. This rules out messaging in some cases.

o To achieve the smoothest possible load balancing Stateless session beans offer excellent load balancing, but MDBs are still better. While the EJB container decides which stateless session bean instance should handle a client request, EJB containers that know they have enough spare capacity actually ask for messages to process. Message queuing also allows load balancing over time.

o To achieve loose coupling between components Note that JMS isn't the only way to achieve loose coupling in J2EE applications: often we can simply use Java interfaces to decouple objects.

o To integrate distinct applications that expose message-based interfaces In some cases JMS may be the best way to integrate with legacy systems or achieve interoperability with non-J2EE applications.

o As an alternative to creating threads when this is not an option Remember that it is illegal to create threads in the EJB tier. JMS and MDBs provide an alternative. If a problem could otherwise be solved by creating a background thread and waiting for it to do something, messaging will be a good fit, as an immediate return value is not required.

o If it's possible to parallelize independent parts of a slow operation This is a special case of the last indication.

o To escape the EJB sandbox Occasionally we might want to configure a JMS message consumer other than an MDB, to enable an application to perform operations that are illegal within the EJB container, such as call native code. However, messaging isn't the only way to achieve this - we could also use an RMI object, running in a separate process

Disadvantages of Using Messaging 

        Using JMS is likely to bring the following disadvantages

o Although messaging may give the client the perception of faster response, using messaging actually increases the total amount of work the application server will do (although it allows greater freedom in scheduling the work). With durable subscriptions, the amount of work will increase markedly.

o Messaging makes it impossible to take the client's security identity into account when performing work on behalf of the client.

o It's harder to understand and debug an asynchronous system than a synchronous system. 

        Thus, don't take the decision to adopt JMS lightly (even if the situation suggests that it's appropriate to use messaging)

JMS and Performance 

        Messaging is often advocated for performance reasons. However, if messaging is to achieve the same degree of reliability as RMI (which at least guarantees that the client knows if something goes wrong on the server), it's unlikely to achieve any performance benefit

        The overhead of JMS varies greatly depending on how it is used: acknowledgment modes, subscription durability etc. Guaranteed delivery (necessary for some operations) is likely to be slow. Imagine a system that queues requests to create user accounts, performing the actual database inserts synchronously. To be sufficiently reliable, this would have to use guaranteed delivery, meaning that the application server would need to store the messages in a database or other persistent store to ensure that the messages were delivered. Thus the EJB container would probably end up doing a database insert when the message was published anyway, meaning that there would be no performance benefit even in the short term, and increased cost overall.

        Only if we can use messaging without guaranteed delivery or if the asynchronous operation is extremely slow is messaging likely to deliver performance gains.

        Do not use messaging without good reason. Using messaging inappropriately will make a system more complex and error-prone, add no value, and probably reduce performance.

Alternatives to JMS Messaging 

        In some situations there may be simpler, lighter-weight alternatives to JMS, using thread creation (allowed outside the EJB container) or the Observer design pattern without JMS (that is, notifying listeners - who may perform actions in the calling thread or in a new thread - using an ordinary Java implementation, and not JMS). The Observer design pattern implemented this way will create much less overhead than JMS. However, whether it works in a clustered environment depends on what listeners must do. The server provides cluster-wide support for JMS; clearly we don't want to build our own cluster-capable Observer implementation, when JMS already delivers this. Situations in which simple implementations of the Observer design pattern are a viable alternative to JMS include

o When the application does not run in a cluster and is never likely to.

o When it doesn't matter if all event processing occurs on the server on which the event was generated. For example, if the event should lead to the sending of an e-mail in the background this condition applies. We only want one e-mail to be sent. On the other hand, if a data cache needs to be invalidated in response to an event, this will normally need to happen on every machine that runs the cache: single-server event processing is insufficient.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值