16.3. Introducing the Command pattern

The patterns and strategies introduced in the previous sections are perfect if you have to write a small to medium sized web application with Hibernate and Java Persistence. The OSIV pattern works in any two-tiered architecture, where the presentation, business, and persistence layers are colocated on the same virtual machine.

However, as soon as you introduce a third tier and move the presentation layer to a separate virtual machine, the current persistence context can't be held open anymore until the view has been rendered. This is typically the case in three-tiered EJB application, or in an architecture with a rich client in a separate process.

If the presentation layer runs in a different process, you need to minimize the requests between this process and the tier that runs the business and persistence layers of the application. This means that you can't use the previous lazy approach, where the view is allowed to pull data from the domain model objects as needed. Instead, the business tier must accept responsibility for fetching all data that is needed subsequently for rendering the view.

Although certain patterns that can minimize remote communication, such as the session facade and data transfer object (DTO) patterns, have been widely used in the Java developer community, we want to discuss a slightly different approach. The Command pattern (often also called EJB Command) is a sophisticated solution that combines the advantages of other strategies.

Let's write a three-tiered application that utilizes this pattern.

16.3.1. The basic interfaces

The Command pattern is based on the idea of a hierarchy of command classes, all of which implement a simple Command interface. Look at this hierarchy in figure 16.2.

A particular Command is an implementation of an action, an event, or anything that can fit a similar description. Client code creates command objects and prepares them for execution. The CommandHandler is an interface that can execute Command objects. The client passes a Command object to a handler on the server tier, and the handler executes it. The Command object is then returned to the client.

Figure 16-2. The interfaces of the Command pattern

The Command interface has an execute() method; any concrete command must implement this method. Any subinterface may add additional methods that are called before (setters) or after (getter) the Command is executed. A Command is therefore combining input, controller, and output for a particular event.

Executing Command objects—that is, calling their execute() method—is the job of a CommandHandler implementation. Execution of commands is dispatched polymorphically.

The implementation of these interfaces (and abstract classes) can look as follows:

public interface Command {
    public void execute() throws CommandException;
}

Commands also encapsulate exception handling, so that any exception thrown during execution is wrapped in a CommandException that can then be handled accordingly by the client.

The DataAccessCommand is an abstract class:

public abstract class DataAccessCommand implements Command {
    protected DAOFactory daoFactory;

    public void setDAOFactory(DAOFactory daoFactory) {
        this.daoFactory = daoFactory;
    }

}

Any Command that needs to access the database must use a data-access object, so a DAOFactory must be set before a DataAccessCommand can be executed. This is usually the job of the CommandHandler implementation, because the persistence layer is on the server tier.

The remote interface of the command handler is equally simple:

public interface CommandHandler {

    public Command executeCommand(Command c)
                    throws CommandException;

    public DataAccessCommand executeCommand(DataAccessCommand c)
                    throws CommandException;

    public Reportcommand executeCommand(ReportCommand c)
                    throws CommandException;
}

Let's write some concrete implementations and use commands.

16.3.2. Executing command objects

A client that wishes to execute a command needs to instantiate and prepare a Command object. For example, placing a bid for an auction requires a BidForAuctionCommand on the client:

BidForItemCommand bidForItem =
            new BidForItemCommand(userId, itemId, bidAmount);

try {
    CommandHandler handler = getCommandHandler();

    bidForItem = (BidForItemCommand)handler.execute(bidForItem);

    // Extract new bid for rendering
    newBid = bidForItem.getNewBid();

    // Forward to success page

} catch (CommandException ex) {
    // Forward to error page
    // ex.getCause();

}

A BidForItemCommand needs all input values for this action as constructor arguments. The client then looks up a command handler and passes the BidForItemCommand object for execution. The handler returns the instance after execution, and the client extracts any output values from the returned object. (If you work with JDK 5.0, use generics to avoid unsafe typecasts.)

How the command handler is looked up or instantiated depends on the implementation of the command handler and how remote communication occurs. You don't even have to call a remote command handler—it can be a local object.

Let's look at the implementation of the command and the command handler.

Implementing business commands

The BidForItemCommand extends the abstract class DataAccessCommand and implements the execute() method:

public class BidForItemCommand extends DataAccessCommand
                               implements Serializable {

    // Input
    private Long userId;
    private Long itemId;
    private BigDecimal bidAmount;

    // Output
    private Bid newBid;

    public BidForItemCommand(Long userId,

                             Long itemId,
                             BigDecimal bidAmount) {
        this.userId = userId;
        this.itemId = itemId;
        this.bidAmount = bidAmount;
    }

    public Bid getNewBid() {
        return newBid;
    }

    public void execute() throws CommandException {

        ItemDAO itemDAO = daoFactory.getItemDAO();
        UserDAO userDAO = daoFactory.getUserDAO();

        try {

            Bid currentMaxBid = itemDAO.getMaxBid(itemId);
            Bid currentMinBid = itemDAO.getMinBid(itemId);

            Item item = itemDAO.findById(itemId, false);
            newBid = item.placeBid(userDAO.findById(userId, false),
                                   bidAmount,
                                   currentMaxBid,
                                   currentMinBid);

        } catch (BusinessException ex) {
            throw new CommandException(ex);

        }

    }

}

This is basically the same code you wrote in the last stage of the web application refinement earlier in this chapter. However, with this approach, you have a clear contract for required input and returned output of an action.

Because Command instances are sent across the wire, you need to implement Serializable (this marker should be in the concrete class, not the superclasses or interfaces).

Let's implement the command handler.

Implementing a command handler

The command handler can be implemented in any way you like; its responsibilities are simple. Many systems need only a single command handler, such as the following:

@Stateless
public class CommandHandlerBean implements CommandHandler {

    // The persistence layer we want to call

    DAOFactory daoFactory =
        DAOFactory.instance(DAOFactory.HIBERNATE);

    @TransactionAttribute(TransactionAttributeType.NEVER)
    public Command executeCommand(Command c)
            throws CommandException {
        c.execute();
        return c;
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public Command executeCommand(DataAccessCommand c)
            throws CommandException {
        c.setDAOFactory(daoFactory);
        c.execute();
        return c;
    }

}

This is a command handler implemented as a stateless EJB 3.0 session bean. You use an EJB lookup on the client to get a reference to this (local or remote) bean and then pass Command objects to it for execution. The handler knows how to prepare a particular type of command—for example, by setting a reference to the persistence layer before execution.

Thanks to container-managed and declarative transactions, this command handler contains no Hibernate code. Of course, you can also implement this command handler as a POJO without EJB 3.0 annotations and manage transaction boundaries programmatically. One the other hand, because EJBs support remote communication out of the box, they're the best choice for command handlers in three-tier architectures.

There are many more variations of this basic Command pattern.

16.3.3. Variations of the Command pattern

First, not everything is perfect with the Command pattern. Probably the most important issue with this pattern is the requirement for nonpresentation interfaces on the client classpath. Because the BidForItemCommand needs the DAOs, you have to include the persistence layer interface on the client's classpath (even if the command is executed only on the middle tier). There is no real solution, so the severity of this problem depends on your deployment scenario and how easily you can package your application accordingly. Note that the client needs the DAO interfaces only to instantiate a DataAccessCommand, so you may be able to stabilize the interfaces before you work on the implementation of your persistence layer.

Also, because you have just one command, the Command pattern seems like more work then the traditional session facade pattern. However, as the system grows, addition of new commands is made simpler because crosscutting concerns like exception handling and authorization checking may be implemented in the command handler. Commands are easy to implement and extremely reusable. You shouldn't feel restricted by our proposed command interface hierarchy; feel free to design more complex and sophisticated command interfaces and abstract commands. You can also group commands together using delegation—for example, a DataAccessCommand can instantiate and call a ReportCommand.

A command is a great assembler for data that is required for rendering of a particular view. Instead of having the view pull the information from lazy loaded business objects (which requires colocation of the presentation and persistence layer, so you can stay inside the same persistence context), a client can prepare and execute the commands that are needed to render a particular screen—each command transports data to the presentation layer in its output properties. In a way, a command is a kind of data-transfer object with a built-in assembling routine.

Furthermore, the Command pattern enables you to implement any Undo functionality easily. Each command can have an undo() method that can negate any permanent changes that have been made by the execute() method. Or, you can queue several command objects on the client and send them to the command handler only when a particular conversation completes.

The Command pattern is also great if you have to implement a desktop application. You can, for example, implement a command that fires events when data is changed. All dialogs that need to be refreshed listen to this event, by registering a listener on the command handler.

You can wrap the commands with EJB 3.0 interceptors. For example, you can write an interceptor for your command handler session bean that can transparently inject a particular service on command objects of a particular type. You can combine and stack these interceptors on your command handler. You can even implement a client-local command handler which, thanks to EJB interceptors, can transparently decide whether a command needs to be routed to the server (to another command handler) or if the command can be executed disconnected on the client.

The stateless session bean need not be the only command handler. It's easy to implement a JMS-based command handler that executes commands asynchronously. You can even store a command in the database for scheduled execution. Commands may be used outside of the server environment—in a batch process or unit test case, for example.

In practice, an architecture that relies on the Command pattern works nicely.

In the next section, we discuss how EJB 3.0 components can further simplify a layered application architecture.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.13.76