Value Object Assembler J2EE

In a J2EE application, the server-side business components are implemented using session beans, entity beans, DAOs, and so forth. Application clients frequently need to access data that is composed from multiple objects.

Problem
Application clients typically require the data for the model or parts of the model to present to the user or to use for an intermediate processing step before providing some service. The application model is an abstraction of the business data and business logic implemented on the server side as business components. A model may be expressed as a collection of objects put together in a structured manner (tree or graph). In a J2EE application, the model is a distributed collection of objects such as session beans, entity beans, or DAOs and other objects. For a client to obtain the data for the model, such as to display to the user or to perform some processing, it must access individually each distributed object that defines the model. This approach has several drawbacks:

  • Because the client must access each distributed component individually, there is a tight coupling between the client and the distributed components of the model over the network
  • The client accesses the distributed components via the network layer, and this can lead to performance degradation if the model is complex with numerous distributed components. Network and client performance degradation occur when a number of distributed business components implement the application model and the client directly interacts with these components to obtain model data from that component. Each such access results in a remote method call that introduces network overhead and increases the chattiness between the client and the business tier.
  • The client must reconstruct the model after obtaining the model's parts from the distributed components. The client therefore needs to have the necessary business logic to construct the model. If the model construction is complex and numerous objects are involved in its definition, then there may be an additional performance overhead on the client due to the construction process. In addition, the client must contain the business logic to manage the relationships between the components, which results in a more complex, larger client. When the client constructs the application model, the construction happens on the client side. Complex model construction can result in a significant performance overhead on the client side for clients with limited resources.
  • Because the client is tightly coupled to the model, changes to the model require changes to the client. Furthermore, if there are different types of clients, it is more difficult to manage the changes across all client types.
  • When there is tight coupling between the client and model implementation, which occurs when the client has direct knowledge of the model and manages the business component relationships, then changes to the model necessitate changes to the client. There is the further problem of code duplication for model access, which occurs when an application has many types of clients. This duplication makes client (code) management difficult when the model changes.

Forces

  • Separation of business logic is required between the client and the server-side components.
  • Because the model consists of distributed components, access to each component is associated with a network overhead. It is desirable to minimize the number of remote method calls over the network.
  • The client typically needs only to obtain the model to present it to the user. If the client must interact with multiple components to construct the model on the fly, the chattiness between the client and the application increases. Such chattiness may reduce the network performance.
  • Even if the client wants to perform an update, it usually updates only certain parts of the model and not the entire model.
  • Clients do not need to be aware of the intricacies and dependencies in the model implementation. It is desirable to have loose coupling between the clients and the business components that implement the application model.
  • Clients do not otherwise need to have the additional business logic required to construct the model from various business components.

Solution
Use a Value Object Assembler to build the required model or submodel. The Value Object Assembler uses value objects to retrieve data from various business objects and other objects that define the model or part of the model.

The Value Object Assember constructs a composite value object that represents data from different business components. The value object caries the data for the model to the client in a single method call. Since the model data can be complex, it is recommended that this value object be immutable. That is, the client obtains such value objects with the sole purpose of using them for presentation and processing in a read-only manner. Clients are not allowed to make changes to the value objects.

When the client needs the model data, and if the model is represented by a single coarse-grained component (such as a Composite Entity), then the process of obtaining the model data is simple. The client simply requests the coarse-grained component for its composite value object. However, most real-world applications have a model composed of a combination of many coarse-grained and fine-grained components. In this case, the client must interact with numerous such business components to obtain all the data necessary to represent the model. The immediate drawbacks of this approach can be seen in that the clients become tightly coupled to the model implementation (model elements) and that the clients tend to make numerous remote method invocations to obtain the data from each individual component.

In some cases, a single coarse-grained component provides the model or parts ofthe model as a single value object (simple or composite). However, when multiple components represent the model, a single value object (simple or composite) may not represent the entire model. To represent the model, it is necessary to obtain value objects from various components and assemble them into a new composite value object. The server, not the client, should perform such “on-the-fly” construction of the model.

Structure
Figure shows the class diagram representing the relationships for the Value Object Assembler pattern.

Figure Value Object Assembler class diagram

Figure Value Object Assembler class diagram

Participants and Responsibilities
The sequence diagram in Figure shows the interaction between the various participants in the Value Object Assembler pattern.

Figure Value Object Assembler sequence diagram

Figure Value Object Assembler sequence diagram

ValueObjectAssembler
The ValueObjectAssembler is the main class of this pattern. The ValueObjectAssembler constructs a new value object based on the requirements of the application when the client requests a composite value object. The ValueObjectAssembler then locates the required BusinessObject instances to retrieve data to build the composite value object. BusinessObjects are business-tier components such as entity beans and session beans, DAOs, and so forth.

Client
If the ValueObjectAssembler is implemented as an arbitrary Java object, then the client is typically a Session Facade that provides the controller layer to the business tier. If the ValueObjectAssembler is implemented as a session bean, then the client can be a Session Facade or a Business Delegate.

BusinessObject
The BusinessObject participates in the construction of the new value object by providing the required data to the ValueObjectAssembler. Therefore, the BusinessObject is a role that can be fulfilled by a session bean, an entity bean, a DAO, or a regular Java object.

ValueObject
The ValueObject is a composite value object that is constructed by the ValueObjectAssembler and returned to the client. This represents the complex data from various components that define the application model.

BusinessObject
BusinessObject is a role that can be fulfilled by a session bean, entity bean, or DAO. When the assembler needs to obtain data directly from the persistent storage to build the value object, it can use a DAO. This is shown as the DataAccessObject object in the diagrams.

Strategies
This section explains different strategies for implementing a Value Object Assembler pattern.

Java Object Strategy
The ValueObjectAssembler can be an arbitrary Java object and need not be an enterprise bean. In such implementations, a session bean usually fronts the ValueObjectAssembler. This session bean is typically a Session Facade that performs its other duties related to providing business services. The ValueObjectAssembler runs in the business tier, regardless of the implementation strategies. The motivation for this is to prevent the remote invocations from the ValueObjectAssembler to the source objects from crossing the tier.

Session Bean Strategy
This strategy implements the ValueObjectAssembler as a session bean (as shown in the class diagram). If a session bean implementation is preferred to provide the ValueObjectAssembler as a business service, it is typically implemented as a stateless session bean. The business components that make up the application model are constantly involved in transactions with various clients. As a result, when a ValueObjectAssembler constructs a new composite value object from various business components, it produces a snapshot of the model at the time of construction. The model could change immediately thereafter if another client changes one or more business components, effectively changing the business application model.

Therefore, implementing ValueObjectAssembler as a stateful session bean provides no benefits over implementing it as a stateless session bean, as preserving the state of the composite model data value when the underlying model is changing is futile. If the underlying model changes, it causes the value object held by the assembler to become stale. The ValueObjectAssembler, when next asked for the value object, either returns a stale state or reconstructs the value object to obtain the most recent snapshot. Therefore, it is recommended that the assembler be a stateless session bean to leverage the benefits of stateless over stateful session beans. However, if the underlying model rarely changes, then the assembler may be a stateful session bean and retain the newly constructed value object. In this case, the ValueObjectAssembler must include mechanisms to recognize changes to the underlying model and to reconstruct the model for the next client request.

Business Object Strategy
The BusinessObject role in this pattern can be supported by different types of objects, as explained below.

  • The BusinessObject can be a session bean. The Value Object Assembler may use a Service Locator (see “Service Locator”) to locate the required session bean. The Value Object Assembler requests this session bean to provide the data to construct the composite value object.
  • The BusinessObject can be an entity bean. The Value Object Assembler may use a Service Locator to locate the required entity bean. The Value Object Assembler requests this entity bean to provide the data to construct the composite value object.
  • The BusinessObject can be a DAO. The Value Object Assembler requests this DAO to provide the data to construct the composite value object.
  • The BusinessObject can be an arbitrary Java object. The Value Object Assembler requests this Java object to provide the data to construct the composite value object.
  • The BusinessObject can be another Value Object Assembler. The first Value Object Assembler requests the second Value Object Assembler to provide the data to construct the composite value object.

Consequences

  • Separates Business Logic
    When the client includes logic to manage the interactions with distributed components, it becomes difficult to clearly separate business logic from the client tier. The Value Object Assembler contains the business logic to maintain the object relationships and to construct the composite value object representing the model. The client needs no knowledge of how to construct the model or the different components that provide data to assemble the model.
  • Reduces Coupling Between Clients and the Application Model
    The Value Object Assembler hides the complexity of the construction of model data from the clients and establishes a loose coupling between clients and the model. With loose coupling, if the model changes, then the Value Object Assembler requires a corresponding change. However, the client is not dependent on the model construction and interrelationships between model business components, so model changes do not directly affect the client. In general, loose coupling is preferred to tight coupling.
  • Improves Network Performance
    The Value Object Assembler drastically reduces the network overhead of remote method calls and chattiness. The client can request the data for the application model from the Value Object Assembler in a single remote method call. The assembler constructs and returns the composite value object for the model. However, the composite value object may contain a large amount of data. Thus, while use of the Value Object Assembler reduces the number of network calls, there is an increase in the amount of data transported in a single call. This trade-off should be considered in applying this pattern.
  • Improves Client Performance
    The server-side Value Object Assembler constructs the model as a composite value object without using any client resources. The client spends no time assembling the model.
  • Improves Transaction Performance
    Typically, updates are isolated to a very small part of the model and can be performed by fine-grained transactions. These transactions focus on isolated parts of the model instead of locking up the coarse-grained object (model). After the client obtains the model and displays or processes it locally, the user (or the client) may need to update or otherwise modify the model. The client can interact directly with a Session Facade to accomplish this at a suitable granularity level. The Value Object Assembler is not involved in the transaction to update or modify the model. There is better performance control because transactional work with the model happens at the appropriate level of granularity.
  • May Introduce Stale Value Objects
    The Value Object Assembler constructs value objects on demand. These value objects are snapshots of the current state of the model, represented by various business components. Once the client obtains a value object from the assembler, that value object is entirely local to the client. Since the value objects are not network-aware, other changes made to the business components used to construct the value object are not reflected in the value objects. Therefore, after the value object is obtained, it can quickly become stale if there are transactions on the business components.

Sample Code
Implementing the Value Object Assembler
Consider a Project Management application where a number of business-tier components define the complex model. Suppose a client wants to obtain the model data composed of data from various business objects, such as:

  • Project Information from the Project component
  • Project Manager information from the ProjectManager component
  • List of Project Tasks from the Project component
  • Resource Information from the Resource component

A composite value object to contain this data can be defined as shown in Example. A Value Object Assembler pattern can be implemented to assemble this composite value object. The Value Object Assembler sample code is listed in Example.

Example Composite Value Object Class

public class ProjectDetailsData {
public ProjectVO projectData;
public ProjectManagerVO projectManagerData;
public Collection listOfTasks;
...
}

The list of tasks in the ProjectDetailsData is a collection of TaskResourceVO objects. The TaskResourceVO is a combination of TaskVO and ResourceVO. These classes are shown in Examples.

Example TaskResourceVO Class

public class TaskResourceVO {
public String projectId;
public String taskId;
public String name;
public String description;
public Date startDate;
public Date endDate;
public ResourceVO assignedResource;
...
public TaskResourceVO(String projectId,
String taskId, String name, String description,
Date startDate, Date endDate, ResourceVO
assignedResource) {
this.projectId = projectId;
this.taskId = taskId;
...
this.assignedResource = assignedResource;
}
...
}

Example TaskVO Class

public class TaskVO {
public String projectId;
public String taskId;
public String name;
public String description;
public Date startDate;
public Date endDate;
public assignedResourceId;
public TaskVO(String projectId, String taskId,
String name, String description, Date startDate,
Date endDate, String assignedResourceId) {
this.projectId = projectId;
this.taskId = taskId;
...
this.assignedResource = assignedResource;
}
...
}

Example ResourceVO Class

public class ResourceVO {
public String resourceId;
public String resourceName;
public String resourceEmail;
...
public ResourceVO (String resourceId, String
resourceName, String resourceEmail, ...) {
this.resourceId = resourceId;
this.resourceName = resourceName;
this.resourceEmail = resourceEmail;
...
}
}

The ProjectDetailsAssembler class that assembles the ProjectDetailsData object is listed in Example.

Example Implementing the Value Object Assembler

public class ProjectDetailsAssembler
implements javax.ejb.SessionBean {
...
public ProjectDetailsData getData(String projectId){
// Construct the composite value object
ProjectDetailsData pData = new
ProjectDetailsData();
//get the project details;
ProjectHome projectHome =
ServiceLocator.getInstance().getHome(
"Project", ProjectEntityHome.class);
ProjectEntity project =
projectHome.findByPrimaryKey(projectId);
ProjectVO projVO = project.getData();
// Add Project Info to ProjectDetailsData
pData.projectData = projVO;
//get the project manager details;
ProjectManagerHome projectManagerHome =
ServiceLocator.getInstance().getHome(
"ProjectManager", ProjectEntityHome.class);
ProjectManagerEntity projectManager =
projectManagerHome.findByPrimaryKey(
projVO.managerId);
ProjectManagerVO projMgrVO =
projectManager.getData();
// Add ProjectManager info to ProjectDetailsData
pData.projectManagerData = projMgrVO;
// Get list of TaskVOs from the Project
Collection projTaskList = project.getTasksList();
// construct a list of TaskResourceVOs
ArrayList listOfTasks = new ArrayList();
Iterator taskIter = projTaskList.iterator();
while (taskIter.hasNext()) {
TaskVO task = (TaskVO) taskIter.next();
//get the Resource details;
ResourceHome resourceHome =
ServiceLocator.getInstance().getHome(
"Resource", ResourceEntityHome.class);
ResourceEntity resource =
resourceHome.findByPrimaryKey(
task.assignedResourceId);
ResourceVO resVO = resource.getResourceData();
// construct a new TaskResourceVO using Task
// and Resource data
TaskResourceVO trVO = new TaskResourceVO(
task.projectId, task.taskId,
task.name, task.description,
task.startDate, task.endDate,
resVO);
// add TaskResourceVO to the list
listOfTasks.add(trVO);
}
// add list of tasks to ProjectDetailsData
pData.listOfTasks = listOfTasks;
// add any other data to the value object
...
// return the composite value object
return pData;
}
...
}

Related Patterns

  • Value Object
    The Value Object Assembler uses the Value Object pattern in order to create and transport value objects to the client. The value objects created carry the data representing the application model from the business tier to the clients requesting the data.
  • Composite Entity
    The Composite Entity pattern promotes a coarse-grained entity bean design, where entities can produce composite value objects similar to the one produced by the Value Object Assembler. However, the Value Object Assembler is more applicable when the composite value object constructed is derived from a number of components (session beans, entity beans, DAOs, and so forth), whereas the Composite Entity pattern constructs the value object from its own data (that is, a single entity bean).
  • Session Facade
    The Value Object Assembler is typically implemented as a stateless session bean. As such, it could be viewed as a limited special application of the Session Facade pattern. More importantly, Value Object Assembler constructs composite value objects that are immutable. Therefore, the client receiving this composite value object can only use the data for its presentation and processing purposes. The client cannot update the value object. If the client needs to update the business objects that derive the composite value object, it may have to access the Session Facade (session bean) that provides that business service.
  • Data Access Object
    A possible strategy for the Value Object Assembler involves obtaining data for the composite value object from the persistent store without enterprise bean involvement. The Data Access Object pattern can be applied, thus leveraging its benefits to provide persistent storage access to the Value Object Assembler.
  • Service Locator
    The Value Object Assembler needs to locate and use various business objects. The Service Locator pattern can be used in conjunction with the Value Object Assembler pattern whenever a business object or a service needs to be located.

All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

J2EE Topics