Core J2EE Patterns - Session Facade

   

Context

Enterprise beans encapsulate business logic and business data and expose their interfaces, and thus the complexity of the distributed services, to the client tier.

Problem

In a multitiered Java 2 Platform, Enterprise Edition (J2EE) application environment, the following problems arise:

  • Tight coupling, which leads to direct dependence between clients and business objects;

  • Too many method invocations between client and server, leading to network performance problems;

  • Lack of a uniform client access strategy, exposing business objects to misuse.

A multitiered J2EE application has numerous server-side objects that are implemented as enterprise beans. In addition, some other arbitrary objects may provide services, data, or both. These objects are collectively referred to as business objects, since they encapsulate business data and business logic.

J2EE applications implement business objects that provide processing services as session beans. Coarse-grained business objects that represent an object view of persistent storage and are shared by multiple users are usually implemented as entity beans.

Application clients need access to business objects to fulfill their responsibilities and to meet user requirements. Clients can directly interact with these business objects because they expose their interfaces. When you expose business objects to the client, the client must understand and be responsible for the business data object relationships, and must be able to handle business process flow.

However, direct interaction between the client and the business objects leads to tight coupling between the two, and such tight coupling makes the client directly dependent on the implementation of the business objects. Direct dependence means that the client must represent and implement the complex interactions regarding business object lookups and creations, and must manage the relationships between the participating business objects as well as understand the responsibility of transaction demarcation.

As client requirements increase, the complexity of interaction between various business objects increases. The client grows larger and more complex to fulfill these requirements. The client becomes very susceptible to changes in the business object layer; in addition, the client is unnecessarily exposed to the underlying complexity of the system.

Tight coupling between objects also results when objects manage their relationship within themselves. Often, it is not clear where the relationship is managed. This leads to complex relationships between business objects and rigidity in the application. Such lack of flexibility makes the application less manageable when changes are required.

When accessing the enterprise beans, clients interact with remote objects. Network performance problems may result if the client directly interacts with all the participating business objects. When invoking enterprise beans, every client invocation is potentially a remote method call. Each access to the business object is relatively fine-grained. As the number of participants increases in a scenario, the number of such remote method calls increases. As the number of remote method calls increases, the chattiness between the client and the server-side business objects increases. This may result in network performance degradation for the application, because the high volume of remote method calls increases the amount of interaction across the network layer.

A problem also arises when a client interacts directly with the business objects. Since the business objects are directly exposed to the clients, there is no unified strategy for accessing the business objects. Without such a uniform client access strategy, the business objects are exposed to clients and may reduce consistent usage.

Forces

  • Provide a simpler interface to the clients by hiding all the complex interactions between business components.

  • Reduce the number of business objects that are exposed to the client across the service layer over the network.

  • Hide from the client the underlying interactions and interdependencies between business components. This provides better manageability, centralization of interactions (responsibility), greater flexibility, and greater ability to cope with changes.

  • Provide a uniform coarse-grained service layer to separate business object implementation from business service abstraction.

  • Avoid exposing the underlying business objects directly to the client to keep tight coupling between the two tiers to a minimum.

Solution

Use a session bean as a facade to encapsulate the complexity of interactions between the business objects participating in a workflow. The Session Facade manages the business objects, and provides a uniform coarse-grained service access layer to clients.

The Session Facade abstracts the underlying business object interactions and provides a service layer that exposes only the required interfaces. Thus, it hides from the client's view the complex interactions between the participants. The Session Facade manages the interactions between the business data and business service objects that participate in the workflow, and it encapsulates the business logic associated with the requirements. Thus, the session bean (representing the Session Facade) manages the relationships between business objects. The session bean also manages the life cycle of these participants by creating, locating (looking up), modifying, and deleting them as required by the workflow. In a complex application, the Session Facade may delegate this lifestyle management to a separate object. For example, to manage the lifestyle of participant session and entity beans, the Session Facade may delegate that work to a Service Locator object (see "Service Locator" on page 368).

It is important to examine the relationship between business objects. Some relationships between business objects are transient, which means that the relationship is applicable to only that interaction or scenario. Other relationships may be more permanent. Transient relationships are best modeled as workflow in a facade, where the facade manages the relationships between the business objects. Permanent relationships between two business objects should be studied to determine which business object (if not both objects) maintains the relationship.

Use Cases and Session Facades

So, how do you identify the Session Facades through studying use cases? Mapping every use case to a Session Facade will result in too many Session Facades. This defeats the intention of having fewer coarse-grained session beans. Instead, as you derive the Session Facades during your modeling, look to consolidate them into fewer numbers of session beans based on some logical partitioning.

For example, for a banking application, you may group the interactions related to managing an account into a single facade. The use cases Create New Account, Change Account Information, View Account information, and so on all deal with the coarse-grained entity object Account. Creating a session bean facade for each use case is not recommended. Thus, the functions required to support these related use cases could be grouped into a single Session Facade called AccountSessionFacade.

In this case, the Session Facade will become a highly coarse-grained controller with high-level methods that can facilitate each interaction (that is, createNewAccount, changeAccount, getAccount). Therefore, we recommend that you design Session Facades to aggregate a group of the related interactions into a single Session Facade. This results in fewer Session Facades for the application, and leverages the benefits of the Session Facade pattern.

Structure

Figure 8.15 shows the class diagram representing the Session Facade pattern.

Figure 8.15
Figure 8.15 Session Facade class diagram

Participants and Collaborations

Figure 8.16 contains the sequence diagram that shows the interactions of a Session Facade with two entity beans, one session bean, and a DAO, all acting as participants in fulfilling the request from the client.

Figure 8.16
Figure 8.16 Session Facade sequence diagram

Client

This represents the client of the Session Facade, which needs access to the business service. This client can be another session bean (Session Facade) in the same business tier or a business delegate (see "Business Delegate" on page 248) in another tier.

SessionFacade

The SessionFacade is implemented as a session bean. The SessionFacade manages the relationships between numerous BusinessObjects and provides a higher level abstraction to the client. The SessionFacade offers coarse-grained access to the participating BusinessObject represented by the Invoke invocation to the session bean.

BusinessObject

The BusinessObject is a role object that facilitates applying different strategies, such as session beans entity beans and a DAO (see the next section, "Strategies"). A BusinessObject provides data and/or some service in the class diagram. The SessionFacade interacts with multiple BusinessObject instances to provide the service.

Strategies

The Session Facade is a business-tier controller object that controls the interactions between the client and the participant business data and business service objects. In a complex application, there may be numerous Session Facades that can intermediate between the client and these objects. You can identify where a Session Facade might be useful by studying the client requirements and interactions typically documented in use cases and scenarios. This analysis enables you to identify a controller layer-composed of Session Facades-that can act as facades for these scenarios.

This section explains different strategies for implementing a Session Facade.

Session Facade Strategies

Stateless Session Facade Strategy

When implementing the Session Facade, you must first decide whether the facade session bean is a stateful or a stateless session bean. Base this decision on the business process that the Session Facade is modeling.

A business process that needs only one method call to complete the service is a nonconversational business process. Such processes are suitably implemented using a stateless session bean.

A careful study of the use cases and scenarios enables you to determine the Session Facade definitions. If the use case is nonconversational, then the client initiates the use case, using a single method in the Session Facade. When the method completes, the use case completes too. There is no need to save the conversational state between one method invocation and the next. In this scenario, the Session Facade can be implemented as a stateless session bean.

Stateful Session Facade Strategy

A business process that needs multiple method calls to complete the service is a conversational business process. The conversational state must be saved between each client method invocation. In this scenario, a stateful session bean may be a more suitable approach for implementing the Session Facade.

In both the Stateless Session Facade and the Stateful Session Facade strategies, the business object's role can be fulfilled in different ways, as explained next.

Business Objects Strategies

You can implement a business object as a session bean, entity bean, DAO, or regular Java object. The following strategies discuss each of these choices.

Session Bean Strategy

The business object can be implemented as a session bean. The session bean typically provides a business service and, in some cases, it may also provide business data. When such a session bean needs access to data, it may use a DAO to manipulate the data. The Session Facade can wrap one or more such service-oriented or data-oriented session beans acting as business objects.

Entity Bean Strategy

Representing the business object by an entity bean is the most common use of the Session Facade. When multiple entity beans participate in the use case, it is not necessary to expose all the entity beans to the clients. Instead, the Session Facade can wrap these entity beans and provide a coarse-grained method to perform the required business function, thus hiding the complexity of entity bean interactions.

Data Access Object Strategy

The Session Facade can directly use one or more DAOs to represent the business data. This is done when the application is so simple that it requires no entity beans, or when the application's architecture is based only on session beans and does not use entity beans. Using DAOs inside session beans partially simulates the persistent nature of entity beans.

The application might need the services provided by an arbitrary Java object (that is, an object that is not an enterprise bean or a DAO, though a DAO can be viewed as a type of arbitrary Java object). In such cases, the Session Facade accesses this arbitrary Java object to provide the necessary functionality.

Consequences

  • Introduces Business-Tier Controller Layer
    Session Facades can represent a control layer between clients and the business tier, as identified through analysis modeling. A Session Facade encompasses the interactions between the client and the business components. In a sophisticated application, you can identify numerous Session Facades that can intermediate between the client and the participating business-tier objects. For simpler applications, one might feel that a Session Facade is not adding much value, as it may act to mostly proxy the client requests to a single business component. However, as applications grow more complex over time, using a Session Facade up front will yield benefit at a later stage.

  • Exposes Uniform Interface
    The underlying interactions between the business components can be very complex. A Session Facade pattern abstracts this complexity and presents the client a simpler interface that is easy to understand and to use. By applying a Session Facade, you can design a service layer that exposes simpler interfaces to the system as a whole. Thus a facade provides a uniform coarse-grained access layer to all types of clients and can protect and hide the underlying participant business components.

  • Reduces Coupling, Increases Manageability
    Using a Session Facade decouples the business objects from the clients, thus reducing tight coupling and the client's dependency on the business objects. It is best to use a Session Facade to manage workflow among business objects, rather than making the business objects aware of each other. A business object should only be responsible for its own (data and logic) management. Inter-business object interactions can be abstracted into a workflow in a facade. This provides better manageability, centralization of interactions (responsibility and workflow), greater flexibility, and greater ability to cope with changes.

    Separating workflow into a Session Facade eliminates the direct dependency of the client on the participant objects and promotes design flexibility. Although changes to participants may require changes in the Session Facade, centralizing the workflow in the facade makes such changes more manageable. You change only the Session Facade rather than having to change all the clients. Client code is also simpler because it now delegates the workflow responsibility to the Session Facade. The client no longer manages the complex workflow interactions between business objects, nor is the client aware of interdependencies between business objects.

  • Improves Performance, Reduces Fine-Grained Methods
    The Session Facade also impacts performance. The Session Facade reduces network overhead between the client and the server because its use eliminates the direct interaction between the client and the business data and business service objects. Instead, all interactions are routed via the Session Facade in a coarse-grained manner. The Session Facade and its participants are closer to each other, making it more efficient for the facade to manage interactions between the participant objects. All data transfer and method invocations from the facade to the participants are presumably on a relatively high-speed network. The network performance can be further tuned to provide maximum throughput by applying the Transfer Object pattern for the participant objects where applicable.

  • Provides Coarse-Grained Access
    A Session Facade is meant to be a highly coarse-grained abstraction of the workflow. Thus, it is not desirable to have one Session Facade per entity bean interaction, which would represent a fine-grained abstraction rather than a coarse-grained one. Analyze the interaction between the client and the application services, using use cases and scenarios to determine the coarseness of the facade. Determine the optimal granularity of the Session Facade for the application by partitioning the application into logical subsystems and providing a Session Facade for each subsystem. However, providing a single facade for the entire system can result in a very large Session Facade whose numerous methods make it inefficient. A single facade may be sufficient for very simple applications that do not warrant subsystems.

  • Centralizes Security Management
    Security policies for the application can be managed at the Session Facade level, since this is the tier presented to the clients. Because of the Session Facade's coarse-grained access, it is easier and more manageable to define security policies at this level rather than at the participating business component level. Business components offer fine-grained control points. It is easier to manage security for Session Facades that provide coarse-grained access, because there are relatively fewer coarse-grained methods to be securely managed.

  • Centralizes Transaction Control
    Because the Session Facade represents the workflow for the use cases, it is more logical to apply transaction management at the Session Facade level. Centralized transaction control has advantages similar to centralized security. The facade offers a central place for managing and defining transaction control in a coarse-grained fashion. It is much more work to do transaction management individually on participant business components, especially since they are more fine-grained than the facade. Also, not using a Session Facade, but rather having the client access the enterprise beans directly, puts the transaction demarcation burden on the client and can produce unwanted results.

  • Exposes Fewer Remote Interfaces to Clients
    Clients that interact directly with the business data and business service objects cause an increase in chattiness between the client and the server. Increased chattiness may degrade network performance. All access to the business object must be via the higher level of abstraction represented by a facade. Since the facade presents a coarse-grained access mechanism to the business components, this reduces the number of business components that are exposed to the client. Thereby, the scope for application performance degradation is reduced due to the limited number of interactions between the clients and the Session Facade when compared to direct interaction by the client to the individual business components.

Sample Code

Implementing the Session Facade

Consider a Professional Services Application (PSA), where the workflow related to entity beans (such as Project, Resource) is encapsulated in ProjectResourceManagerSession, implemented using the Session Facade pattern. Example 8.15 shows the interaction with Resource and Project entity beans, as well as other business components, like Value List Handlers (see "Value List Handler" on page 354) and Transfer Object Assemblers (see "Transfer Object Assembler" on page 340).

Example 8.15 Implementing Session Facade - Session Bean

package corepatterns.apps.psa.ejb;

import java.util.*;
import java.rmi.RemoteException;
import javax.ejb.*;
import javax.naming.*;
import corepatterns.apps.psa.core.*;
import corepatterns.util.ServiceLocator;
import corepatterns.util.ServiceLocatorException;

// Note: all try/catch details not shown for brevity.

public class ProjectResourceManagerSession
  implements SessionBean {

  private SessionContext context;

  // Remote references for the
  // entity Beans encapsulated by this facade
  private Resource resourceEntity = null;
  private Project projectEntity = null;
  ...

  // default create
  public void ejbCreate() 
  throws CreateException {
  }

  // create method to create this facade and to
  // establish connections to the required entity
  // beans
  // using primary key values
  public void ejbCreate(
    String resourceId, String projectId, ...)
  throws CreateException, ResourceException {

    try {
      // locate and connect to entity beans
      connectToEntities(resourceId, projectId, ...);
    } catch(...) {
      // Handle exceptions
    }
  }

  // method to connect the session facade to its 
  // entity beans using the primary key values
  private void connectToEntities (
    String resourceId, String projectId)
  throws ResourceException {
    resourceEntity = getResourceEntity(resourceId);
    projectEntity = getProjectEntity(projectId);
    ...
  }

  // method to reconnect the session facade to a
  // different set of entity beans using primary key
  // values
  public resetEntities(String resourceId,
    String projectId, ...)
  throws PSAException {

    connectToEntities(resourceId, projectId, ...);
  }

  // private method to get Home for Resource
  private ResourceHome getResourceHome()
  throws ServiceLocatorException {
    return ServiceLocator.      getInstance().getHome(
        "ResourceEntity", ResourceHome.class);
  }

  // private method to get Home for Project
  private ProjectHome getProjectHome()
  throws ServiceLocatorException {
    return ServiceLocator.      getInstance().getHome(
        "ProjectEntity", ProjectHome.class);  
  }

  // private method to get Resource entity
  private Resource getResourceEntity(
    String resourceId)   throws ResourceException {
    try {
      ResourceHome home = getResourceHome();
      return (Resource) 
        home.findByPrimaryKey(resourceId);
    } catch(...) {
      // Handle exceptions
    }
  }

  // private method to get Project entity
  private Project getProjectEntity(String projectId)
  throws ProjectException {
    // similar to getResourceEntity
    ...
  }

  // Method to encapsulate workflow related
  // to assigning a resource to a project.
  // It deals with Project and Resource Entity beans
  public void assignResourceToProject(int numHours)
  throws PSAException {

    try {
      if ((projectEntity == null) ||
          (resourceEntity == null)) {

        // SessionFacade not connected to entities
        throw new PSAException(...);
      }

      // Get Resource data
      ResourceTO resourceTO =
          resourceEntity.getResourceData();

      // Get Project data
      ProjectTO projectTO =
        projectEntity.getProjectData();
      // first add Resource to Project
      projectEntity.addResource(resourceTO);
      // Create a new Commitment for the Project
      CommitmentTO commitment = new
        CommitmentTO(  ...);

      // add the commitment to the Resource
      projectEntity.addCommitment(commitment);

    } catch(...) {
      // Handle exceptions
    }
  }

  // Similarly implement other business methods to
  // facilitate various use cases/interactions
  public void unassignResourceFromProject()
  throws PSAException {
    ...
  }

  // Methods working with ResourceEntity
  public ResourceTO getResourceData()
  throws ResourceException {
    ...
  }

  // Update Resource Entity Bean
  public void setResourceData(ResourceTO resource) 
  throws ResourceException {
    ...
  }

  // Create new Resource Entity bean
  public ResourceTO createNewResource(ResourceTO 
    resource)   throws ResourceException {
    ...
  }

  // Methods for managing resource's blockout time
  public void addBlockoutTime(Collection blockoutTime) 
  throws RemoteException,BlockoutTimeException {
    ...
  }
  
  public void updateBlockoutTime(
    Collection blockoutTime)   
  throws RemoteException, BlockoutTimeException {
    ...
  }
  
  public Collection getResourceCommitments() 
  throws RemoteException, ResourceException {
    ...
  }

  // Methods working with ProjectEntity
  public ProjectTO getProjectData()
  throws ProjectException {
    ...
  }

  // Update Project Entity Bean
  public void setProjectData(ProjectTO project) 
  throws ProjectException {
    ...
  }

  // Create new Project Entity bean
  public ProjectTO createNewProject(ProjectTO project)
  throws ProjectException {
    ...
  }

  ...

  // Other session facade method examples

  // This proxies a call to a Transfer Object Assembler
  // to obtain a composite Transfer Object.
  // See Transfer Object Assembler pattern
  public ProjectCTO getProjectDetailsData()
  throws PSAException {
    try {
      ProjectTOAHome projectTOAHome = (ProjectTOAHome)
        ServiceLocator.getInstance().getHome(
          "ProjectTOA", ProjectTOAHome.class);
      // Transfer Object Assembler session bean
      ProjectTOA projectTOA = 
          projectTOAHome.create(...);
      return projectTOA.getData(...);
    } catch (...) {
        // Handle / throw exceptions
    }
  }

  // These method proxies a call to a ValueListHandler
  // to get a list of projects. See Value List Handler 
  // pattern.
  public Collection getProjectsList(Date start, 
  Date end) throws PSAException {
    try {
      ProjectListHandlerHome projectVLHHome = 
        (ProjectVLHHome)
          ServiceLocator.getInstance().getHome(
            "ProjectListHandler",
            ProjectVLHHome.class);
      // Value List Handler session bean
      ProjectListHandler projectListHandler = 
        projectVLHHome.create();
      return projectListHandler.getProjects(
                    start, end);
    } catch (...) {
        // Handle / throw exceptions
    }
  }

  ...

  public void ejbActivate() {
    ...
  }

  public void ejbPassivate() {
    context = null;
  }

  public void setSessionContext(SessionContext ctx) {
       this.context = ctx;
  }

  public void ejbRemove() {
    ...
  }
}

The remote interface for the Session Facade is listed in Example 8.16.

Example 8.16 Implementing Session Facade - Remote Interface

package corepatterns.apps.psa.ejb;

import java.rmi.RemoteException;
import javax.ejb.*;
import corepatterns.apps.psa.core.*;

// Note: all try/catch details not shown for brevity.

public interface ProjectResourceManager
  extends EJBObject {

  public resetEntities(String resourceId,
  String projectId, ...)
  throws RemoteException, ResourceException ;

  public void assignResourceToProject(int numHours)
  throws RemoteException, ResourceException ;

  public void unassignResourceFromProject()
  throws RemoteException, ResourceException ;

  ...

  public ResourceTO getResourceData()
  throws RemoteException, ResourceException ;

  public void setResourceData(ResourceTO resource) 
  throws RemoteException, ResourceException ;

  public ResourceTO createNewResource(ResourceTO resource)
  throws ResourceException ;

  public void addBlockoutTime(Collection blockoutTime) 
  throws RemoteException,BlockoutTimeException ;
  
  public void updateBlockoutTime(Collection blockoutTime) 
  throws RemoteException,BlockoutTimeException ;
  
  public Collection getResourceCommitments()
  throws RemoteException, ResourceException;

  public ProjectTO getProjectData()
  throws RemoteException, ProjectException ;
  
  public void setProjectData(ProjectTO project) 
  throws RemoteException, ProjectException ;

  public ProjectTO createNewProject(ProjectTO project)
  throws RemoteException, ProjectException ;

  ...

  public ProjectCTO getProjectDetailsData()
  throws RemoteException, PSAException ;

  public Collection getProjectsList(Date start, 
  Date end) throws RemoteException, PSAException ;

  ...
}

The Home interface for the Session Facade is shown in Example 8.17.

Example 8.17 Implementing Session Facade - Home Interface

package corepatterns.apps.psa.ejb;

import javax.ejb.EJBHome;
import java.rmi.RemoteException;
import corepatterns.apps.psa.core.ResourceException;
import javax.ejb.*;

public interface ProjectResourceManagerHome 
extends EJBHome {
    
    public ProjectResourceManager create() 
            throws RemoteException,CreateException;
    public ProjectResourceManager create(String
        resourceId, String projectId, ...) 
            throws RemoteException,CreateException;
}

Related Patterns

  • Facade [GoF]
    The Session Facade is based on the Facade Design pattern.

  • Data Access Object
    One of the strategies for the business component in the Session Facade pattern is to use the DAO. This can be the case in simpler applications designed using session beans and DAOs instead of entity beans.

  • Service Locator
    The Session Facade is a coarse-grained object that allows encapsulation of the workflow by managing business data and business service objects interactions. Business data objects can be entity beans or DAOs, and the business service objects can be session beans and other objects that provide service. The Session Facade can use the Service Locator pattern to reduce the code complexity and to exploit the benefits offered by the Service Locator.

  • Business Delegate
    The Session Facade is used by the Business Delegate when the client requests access to business services. The Business Delegate proxies or adapts the client request to a Session Facade that provides the requested service.

  • Broker [POSA1]
    The Session Facade performs the role of a broker to decouple the entity beans from their clients.

 

Contact Us © 2001-2002 Sun Microsystems, Inc. All Rights Reserved.
Left Curve
Java SDKs and Tools
Right Curve
Left Curve
Java Resources
Right Curve
JavaOne Banner
Java 8 banner (182)