You want to intercept and manipulate a request and a response before and after the request is processed.
You want centralized, common processing across requests, such as checking the data-encoding scheme of each request, logging information about each request, or compressing an outgoing response.
You want pre and postprocessing components loosely coupled with core request-handling services to facilitate unobtrusive addition and removal.
You want pre and postprocessing components independent of each other and self contained to facilitate reuse.
Use an Intercepting Filter as a pluggable filter to pre and postprocess requests and responses. A filter manager combines loosely coupled filters in a chain, delegating control to the appropriate filter. In this way, you can add, remove, and combine these filters in various ways without changing existing code.
As with other systems where there is a significant number of duplicated tasks, it's a good idea to take that duplicated processing, factor it out, and make it coarse grained enough to apply broadly. This is what pluggable filters accomplish.
In effect, you are able to decorate the main processing with a variety of common services, such as logging and debugging. Filters are independent of the main application code, and you can add or remove them declaratively.
Filters are controlled declaratively using a deployment descriptor, as described in the Servlet Specification. The Servlet Specification includes a standard mechanism for building filter chains and unobtrusively adding and removing filters from those chains. A deployment configuration file sets up a chain of filters and can include a mapping of specific URLs to this filter chain. When a client requests a resource that matches the configured URL mapping, the filters in the chain are invoked before (preprocessing) and/or after (postprocessing) the invocation of the requested target resource.
You want a centralized access point for presentation-tier request handling.
You want to avoid duplicate control logic.
You want to apply common logic to multiple requests.
You want to separate system processing logic from the view.
You want to centralize controlled access points into your system.
Use a Front Controller as the initial point of contact for handling all related requests. The Front Controller centralizes control logic that might otherwise be duplicated, and manages the key request handling activities.
The Front Controller provides a centralized entry point for handling requests. By centralizing control logic, the Front Controller also helps reduce the amount of programming logic embedded directly in the views. For a JSP view, for instance, this reduces the temptation to use large amounts of Java code, called scriptlet code, embedded within the JSP.
This pattern is similar to the Intercepting Filter, because they both factor out and consolidate common presentation-tier control logic. A key difference is that Intercepting Filter provides a loosely-coupled set of chained processors and powerful strategies for specifically performing pre and post processing. Centralizing control in a Front Controller and reducing business and processing logic in the view promotes code reuse across requests, reducing duplication. Unless the control logic is trivial, using a Front Controller is preferable to embedding code in multiple views, because the latter approach leads to a reuse-by-copy-and-paste environment, which is more error-prone.
A Front Controller typically uses an Application Controller, which is responsible for action and view management.
Action management refers to locating and routing to the specific actions that will service a request.
View management refers to finding and dispatching to the appropriate view. While this behavior can be folded into the Front Controller, partitioning it into separate classes as part of an Application Controller improves modularity, maintainability, and reusability.
You want to avoid using protocol-specific system information outside of its relevant context.
You have components and services that need access to system information.
You want to decouple application components and services from the protocol specifics of system information.
You want to expose only the relevant APIs within a context.
Use a Context Object to encapsulate state in a protocol-independent way to be shared throughout your application.
Encapsulating system data in a Context Object allows it to be shared with other parts of the application without coupling the application to a specific protocol.
For example, an HTTP request parameter exists for each field of an HTML form and a Context Object can store this data in a protocol-independent manner while facilitating its conversion and validation. Then other parts of the application simply access the information in the Context Object, without any knowledge of the HTTP protocol. Any changes in the protocol are handled by the Context Object, and no other parts of the application need to change.
This aspect of using a Context Object raises the question about its relationship to a Transfer Object. Transfer Objects carry state across remote tiers. While a Context Object acts as a Transfer Object when it is used for this purpose, a Context Object's main goal is to share system information in a protocol-independent way, improving the reusability and maintainability of an application.
A Context Object reduces the coupling between unrelated system and application components in this way. On the other hand, a Transfer Object main goal is to reduce remote network communication, improving performance. Additionally, Transfer Objects often have relationships with other Transfer Objects, mirroring the business data they represent, while Context Objects represent infrastructure state.
You want to centralize and modularize action and view management.
You want to reuse action and view-management code.
You want to improve request-handling extensibility, such as adding use case functionality to an application incrementally.
You want to improve code modularity and maintainability, making it easier to extend the application and easier to test discrete parts of your request-handling code independent of a web container.
Use an Application Controller to centralize retrieval and invocation of request-processing components, such as commands and views.
In the presentation tier, you map incoming request parameters to specific request-processing classes, and to view components that handle each request. Action management refers to locating and invoking actions to handle specific requests, while view management refers to navigating and dispatching to the appropriate view or view-generation mechanism. While a Front Controller acts as a centralized access point and controller for incoming requests, the mechanism for identifying and invoking commands and for identifying and dispatching to views can be broken out into its own set of components.
Separating this code from the Front Controller provides several benefits:
It separates this basic request management behavior from the protocol-specific code of the Front Controller. This improves the modularity of the system, while enhancing its reusability. Certain Application Controller components can be reused to handle requests from numerous channels, such as from a web application or a web service.
It makes it easier to test outside of a web container, simplifying testing.
You want to separate a view from its processing logic.
You want to use template-based views, such as JSP.
You want to avoid embedding program logic in the view.
You want to separate programming logic from the view to facilitate division of labor between software developers and web page designers.
Use Views to encapsulate formatting code and Helpers to encapsulate view-processing logic. A View delegates its processing responsibilities to its helper classes, implemented as POJOs, custom tags, or tag files. Helpers serve as adapters between the view and the model, and perform processing related to formatting logic, such as generating an HTML table.
Encapsulating processing logic in a helper instead of a view makes applications more modular and facilitates component reuse. A common approach for reusing logic that is embedded in a template-based view is to copy and paste it elsewhere. This sort of duplication makes a system harder to maintain, since the same bug potentially needs to be corrected in multiple places. Therefore, if scriptlet code dominates a JSP view, apply this pattern in order to localize disparate logic.
You want to build a view from modular, atomic component parts that are combined to create a composite whole, while managing the content and the layout independently.
You want common subviews, such as headers, footers and tables reused in multiple views, which may appear in different locations within each page layout.
You have content in subviews which might which frequently change or might be subject to certain access controls, such as limiting access to users in certain roles.
You want to avoid directly embedding and duplicating subviews in multiple views which makes layout changes difficult to manage and maintain.
Use Composite Views that are composed of multiple atomic subviews. Each subview of the overall template can be included dynamically in the whole, and the layout of the page can be managed independently of the content.
Composite Views are based on the inclusion and substitution of modular dynamic and static template fragments. Composite Views promote the reuse of atomic portions of the view by encouraging modular design. It is appropriate to use a Composite View to generate pages containing display components that can be combined in a variety of ways.
Service to Worker
You want to perform core request handling and invoke business logic before control is passed to the view.
You want specific business logic executed to service a request in order to retrieve content that will be used to generate a dynamic response.
You have view selections which may depend on responses from business service invocations.
You may have to use a framework or library in the application.
Use Service to Worker to centralize control and request handling to retrieve a presentation model before turning control over to the view. The view generates a dynamic response based on the presentation model.
Service to Worker is composed of several other patterns. Centralized control, request handling, and view creation are accomplished using Front Controller, Application Controller, and View Helper respectively.
Business processing logic is completed before control is passed to the view. Alternatively, Dispatcher View performs its business processing after control is passed to the view. As such, the two patterns suggest two ends of a continuum and both approaches are typically used within the same application to satisfy different use cases.
You want a view to handle a request and generate a response, while managing limited amounts of business processing.
You have static views.
You have views generated from an existing presentation model.
You have views which are independent of any business service response.
You have limited business processing.
Use Dispatcher View with views as the initial access point for a request. Business processing, if necessary in limited form, is managed by the views.
Use this approach when response generation requires little or no dynamic content, via a business service or data access call. Here are the two most common uses of Dispatcher View:
The response is entirely static
The response is dynamic, but is generated from an existing presentation model
You want to hide clients from the complexity of remote communication with business service components.
You want to access the business-tier components from your presentation-tier components and clients, such as devices, web services, and rich clients.
You want to minimize coupling between clients and the business services, thus hiding the underlying implementation details of the service, such as lookup and access.
You want to avoid unnecessary invocation of remote services.
You want to translate network exceptions into application or user exceptions.
You want to hide the details of service creation, reconfiguration, and invocation retries from the clients.
Use a Business Delegate to encapsulate access to a business service. The Business Delegate hides the implementation details of the business service, such as lookup and access mechanisms.
A Business Delegate acts as a client-side business abstraction: it abstracts and hides the implementation details of the business services. Using a Business Delegate reduces the coupling between the client and the system's business services. Depending on the implementation strategy, the Business Delegate might shield clients from possible volatility in the implementation of the business service API. Potentially, this reduces the number of changes that must be made to the client code when the business service API or its underlying implementation changes.
You want to transparently locate business components and services in a uniform manner.
You want to use the JNDI API to look up and use business components, such as enterprise beans and JMS components, and services such as data sources.
You want to centralize and reuse the implementation of lookup mechanisms for J2EE application clients.
You want to encapsulate vendor dependencies for registry implementations, and hide the dependency and complexity from the clients.
You want to avoid performance overhead related to initial context creation and service lookups.
You want to reestablish a connection to a previously accessed enterprise bean instance, using its Handle object.
Use a Service Locator to implement and encapsulate service and component lookup. A Service Locator hides the implementation details of the lookup mechanism and encapsulates related dependencies.
Application clients can reuse the Service Locator to reduce code complexity, provide a single point of control, and improve performance by providing a caching facility. You typically need a single Service Locator for the entire application. However, it is not uncommon to see two Service Locator implementations in an application, one for the presentation tier and one for business tier. A Service Locator reduces the client's dependency on the underlying lookup infrastructure, and optimizes resource-intensive lookup and creation operations.
You want to expose business components and services to remote clients.
Session Façade addresses two issues: controlling client access to business objects, and limiting network traffic between remote clients and fine-grained business components and services.
You want to avoid giving clients direct access to business-tier components, to prevent tight coupling with the clients.
You want to provide a remote access layer to your Business Objects and other business-tier components.
You want to aggregate and expose your Application Services and other services to remote clients.
You want to centralize and aggregate all business logic that needs to be exposed to remote clients.
You want to hide the complex interactions and interdependencies between business components and services to improve manageability, centralize logic, increase flexibility, and improve ability to cope with changes.
Use a Session Façade to encapsulate business-tier components and expose a coarse-grained service to remote clients. Clients access a Session Façade instead of accessing business components directly.
A Session Façade is implemented as a session bean and interacts with business components, such as Business Objects and Application Services. A Session Façade provides a remote service layer that exposes only the required interfaces used by the clients.
You want to centralize business logic across several business-tier components and services.
You want to minimize business logic in service facades (Session Façade or POJO Facade).
You have business logic acting on multiple Business Objects or services.
You want to provide a coarser-grained service API over existing business-tier components and services.
You want to encapsulate use case-specific logic outside of individual Business Objects.
Use an Application Service to centralize and aggregate behavior to provide a uniform service layer:
Application Service provides a central location to implement business logic that encapsulates Business Object and services. Implementing the business logic this way, extrinsically to the Business Object, is a one way to reduce coupling among Business Objects. With an Application Service, you encapsulate this higher-level business logic in a separate component that uses the underlying Business Objects and services.
Application Service is also used to provide a central business logic implementation layer even if you are not using Business Objects in your application. In this scenario, Application Services can include all the procedural business logic required to implement different services in your application and can use Data Access Objects when necessary to deal with persistent data.
You have a conceptual domain model with business logic and relationship.
You have a conceptual model containing structured, interrelated composite objects.
You have a conceptual model with sophisticated business logic, validation and business rules.
You want to separate the business state and related behavior from the rest of the application, improving cohesion and reusability.
You want to centralize business logic and state in an application.
You want to increase reusability of business logic and avoid duplication of code.
Use Business Objects to separate business data and logic using an object model.
Business Objects encapsulate and manage business data, behavior and persistence. Business Objects help separate persistence logic from business logic. Business Objects maintain the core business data, and implement the behavior that is common to the entire application or domain.
One of the core characteristics of a Business Object is that it represents persistent business information. Persistence can be achieved in different ways:
Using EJB 3.0 entities (JPA)
Using EJB 2.1 entity beans (CMP and BMP) persistence
Using custom Data Access Objects
Using Java Data Objects
Using a Domain Store
You want to use entity beans to implement your conceptual domain model
You want to avoid the drawbacks of remote entity beans, such as network overhead and remote inter-entity bean relationships.
You want to leverage bean-managed persistence (BMP) using custom or legacy persistence implementations.
You want to implement parent-child relationships efficiently when implementing Business Objects as entity beans.
You want to encapsulate and aggregate existing POJO Business Objects with entity beans.
You want to leverage EJB container transaction management and security features.
You want to encapsulate the physical database design from the clients.
Use a Composite Entity to implement persistent Business Objects using local entity beans and POJOs. Composite Entity aggregates a set of related Business Objects into coarse-grained entity bean implementations.
In a J2EE application, Business Objects are implemented as parent objects and dependent objects.
A parent object is reusable, independently deployable, manages its own life cycle, and manages its relationships to other objects. Each parent object might contain and manage the lifecycles of one or more objects called dependent objects.
A dependent object can be a simple self-contained object or might contain other dependent objects. The lifecycle of a dependent object is tightly coupled to the lifecycle of its parent object. Dependent objects are not directly exposed to clients and a client can access them only through their parent object. Dependent objects don't exist by themselves and rely on their parent for identity and management.
Regardless of whether you implement Composite Entity using local or remote entity beans, do not expose the entity beans to the application clients directly. Instead, encapsulate all entity beans behind a Session Façade and allow all clients to access the Session Façade, which can interact with the required Composite Entity behind the scenes.
You want to transfer multiple data elements over a tier.
You want clients to access components in other tiers to retrieve and update data.
You want to reduce remote requests across the network.
You want to avoid network performance degradation caused by chattier applications that have high network traffic.
Use a Transfer Object to carry multiple data elements across a tier.
A Transfer Object is designed to optimize data transfer across tiers. Instead of sending or receiving individual data elements, a Transfer Object contains all the data elements in a single structure required by the request or response.
NOTE: The Transfer Object is passed by value to the client. Therefore all calls to the Transfer Object are made on copies of the original Transfer Object.
Transfer Object Assembler
You want to obtain an application model that aggregates transfer objects from several business components.
You want to encapsulate business logic in a centralized manner and prevent implementing it in the client.
You want to minimize the network calls to remote objects when building a data representation of the business-tier object model.
You want to create a complex model to hand over to the client for presentation purposes.
You want the clients to be independent of the complexity of model implementation, and you want to reduce coupling between the client and the business components.
Use a Transfer Object Assembler to build an application model as a composite Transfer Object. The Transfer Object Assembler aggregates multiple Transfer Objects from various business components and services, and returns it to the client.
The Transfer Object Assembler retrieves Transfer Objects from the business components. The Transfer Objects are then processed by the Transfer Object Assembler, which creates and assembles a composite Transfer Object to represent the application model data. The clients use the Transfer Object Assembler to obtain this application model for read-only purposes to display or to perform other intermediate processing. Clients do not change the data in the composite Transfer Object.
Value List Handler
You have a remote client that wants to iterate over a large results list.
You want to avoid the overhead of using EJB finder methods for large searches.
You want to implement a read-only use-case that does not require a transaction.
You want to provide the clients with an efficient search and iterate mechanism over a large results set.
You want to maintain the search results on the server side.
Use a Value List Handler to search, cache the results, and allow the client to traverse and select items from the results.
The Value List Handler provides the search and iteration functionality. To perform a search, the Value List Handler uses a Data Access Object to execute the query and retrieve the matching results from the database. This bypasses using the EJB finders for your applications where Business Objects are implemented as entity beans.
Data Access Object
You want to encapsulate data access and manipulation in a separate layer.
You want to implement data access mechanisms to access and manipulate data in a persistent storage.
You want to decouple the persistent storage implementation from the rest of your application.
You want to provide a uniform data access API for a persistent mechanism to various types of data sources, such as RDBMS, LDAP, OODB, XML repositories, flat files, and so on.
You want to organize data access logic and encapsulate proprietary features to facilitate maintainability and portability.
Use a Data Access Object to abstract and encapsulate all access to the persistent store. The Data Access Object manages the connection with the data source to obtain and store data.
The Data Access Object (also known simply as DAO) implements the access mechanism required to work with the data source. Regardless of what type of data source is used, the DAO always provides a uniform API to its clients. The business component that needs data access uses the simpler interface exposed by the DAO for its clients. The DAO completely hides the data source implementation details from its clients. Because the interface exposed by the DAO to clients does not change when the underlying data source implementation changes, this allows you to change a DAO implementation without changing the DAO client's implementation. Essentially, the DAO acts as an adapter between the component and the data source.
The DAO is implemented as a stateless. It does not cache the results of any query execution, or any data that the client might need at a later point. This makes the DAOs lightweight objects and avoids potential threading and concurrency issues. The DAO encapsulates the details of the underlying persistence API.
You want to invoke services asynchronously.
You want to invoke business services, POJOs, or EJB components in an asynchronous manner.
You want to integrate publish/subscribe and point-to-point messaging to enable asynchronous processing services.
You want to perform a business task that is logically composed of several business tasks.
Use a Service Activator to receive asynchronous requests and invoke one or more business services.
The Service Activator is implemented as a JMS Listener and delegation service that can listen to and receive JMS messages. If your application uses EJB components and your EJB container implements EJB version 2.0 or later, you can use a message-driven bean (MDB) to receive asynchronous requests. If your application does not use EJB technology, or uses a pre-EJB 2.0 compliant container, then you must implement your own custom solution using Java Message Service (JMS).
Any client that needs to asynchronously invoke a business service, such as an EJB or a POJO service, creates and sends a message to the Service Activator. The Service Activator receives the message and parses it to interpret the client request. Once the client's request is unmarshalled, the Service Activator identifies and locates the correct business service component and invokes it to process the client's request asynchronously.
You want to separate persistence from your object model.
You want to avoid putting persistence details in your Business Objects.
You do not want to use entity beans.
Your application might be running in a web container.
Your object model uses inheritance and complex relationships.
Use a Domain Store to transparently persist an object model. Unlike J2EE's container-managed persistence and bean-managed persistence, which include persistence support code in the object model, Domain Store's persistence mechanism is separate from the object model.
Web Service Broker
You want to provide access to one or more services using XML and web protocols
You want to reuse and expose existing services to clients.
You want to monitor and potentially limit the usage of exposed services, based on your business requirements and system resource usage.
Your services must be exposed using open standards to enable integration of heterogeneous applications.
You want to bridge the gap between business requirements and existing service capabilities.
Use a Web Service Broker to expose and broker one or more services using XML and web protocols.
A Web Service Broker is a coarse-grained service exposed as a web service. It coordinates interactions among one or more services, aggregates responses and may demarcate and compensate transactions. A Web Service Broker is exposed either using an RPC (remote procedure call)-style interface such as WSDL, or a messaging interface. For RPC style interface, you can use a J2EE 1.4 session bean web service endpoint or a JAX-RPC implementation object as a web service endpoint. Both of these are exposed using WSDL.