The EJB advocate analyzed the service-oriented architecture from top to bottom to determine whether to use the session EJB component or the entity EJB component to assemble the data transmission objects returned by the Service.
In each column, EJB advocates put forward key points. Customers and developers use a unique dialog box to communicate with each other in the process of proposing a solution to a design question of interest. It ignores any deterministic details and does not provide "Innovative" or proprietary architecture. For more information, see Introduction to EJB advocates.
Role of entity EJB component in Service
In the previous column, we introduced some features of the service-oriented architecture. For example, to minimize frequent conversations between services and their clients, the service must be a coarse-grained stateless service and a data transfer peer (DTO) must be properly assembled. Such objects collect all the attributes returned from the client application. We understand how well-designed EJB methods demonstrate these features (by associating with Session EJB instances or the real EJB home interface ). However, this month, a reader asked us if we thought the entity EJB component was also designed as a stateless service.
Q: Which data transmission object is returned by which entity?
Dear EJB advocates:
I have read your recent article about data transmission objects (DTO. I agree with what you mean, data transmission objects are very important in the service layer (which requires various coarse-grained methods), especially for the appearance of services that indicate hidden implementations, this is especially true for the remote appearance (because the remote call overhead is much larger than the local call.
In addition, the recommended code looks very reasonable and is well encapsulated so that you can ask the entity EJB component to "give me your own DTO ". However, there is a problem. For two different use cases, one may need to specify some attributes of the entity EJB component, and the other may need different attributes, therefore, two DTO classes are required. Which DTO type should be returned by the getdto () method?
There is another problem. Different use cases may need to be DTO composed of multiple instances of the same type or different types (customers, delayed delivery orders, products in orders. In this case, which entity EJB needs to implement the composite function?
In the appearance of a session, it seems that you cannot avoid using a single getter (and setter) for the entity EJB component ). One of the advantages of putting the assembled DTO logic into the session bean (or, in my favorite way, put it into the helper class used by the session) is that, when, for some reason (such as adding a new attribute required by another service), you need to delete or regenerate an entity, so you do not have to worry about non-synchronization of custom code.
I think, what I really want to ask is: when you suggest using the local interface of the entity EJB component, is it "shouting" to return DTO from the entity CMP "? I understand your point of view on trying to reduce frequent conversations between layers, but it seems that you are at the cost of maintainability in exchange for performance improvement.
Please use this name to name us,
Never cry wolf
Benefit from good Packaging Technology
Dear never:
You have put forward a good point of view and it is worth noting. Let's answer your question from top to bottom:
- Assume that the two use cases require different data. Which DTO type should the getdto () method return?
My answer is: getdto () should certainly return the DTO instance. Seriously, the name you selected for DTO should clearly indicate the data it returns. If the two use cases require different datasets, The DTO class name should indicate this: usecase1dto or usecase2dto. Therefore, the two method signatures in the interface will be:
Code snippet 1. Multiple signatures of the DTO Method
public UseCase1DTO getUseCase1DTO(); public UseCase2DTO getUseCase2DTO();
|
Or, more abstract:
Code snippet 2. Display abstract examples in a more confusing way
The final point of the Decision is: If you want to associate the getdto () method with the object, one way is to retain the name of this method for the method that returns the <entity> DTO instance, this DTO contains all the non-standard attributes of the associated object (the maximum base of these attributes is 1 ). Your team may choose to use another convention to ensure consistency.
- Assume that data from multiple entities (such as customers, delayed delivery orders, products in orders) is required. which entity should "own" Get <composeddto> () method?
To answer this question from the perspective of defining the composite DTO method on the entity EJB, it involves the best practices of object-oriented design. In this column, we make the entity EJB component meet the requirements. In section 2nd, we briefly discuss oo delegation. The choice of an object depends on the relationship between the object and the data to be returned. Generally, you need to select an entity that can be delegated to other entities as needed to form a complete structure. In your specific example, You want DTO return products from customers, delayed delivery orders, and orders (represented by a line item, which contains Link Attributes of quantity and total quantity). For the moment, let's assume that the class relationship diagram in Figure 1 describes the business objects and their relationships.
Figure 1. Example class relationship diagram showing entities and relationships
For your example, the entity that "owns" the composite DTO method should be of course customer, because it can delegate to order, while the latter can delegate to line item, line item can be delegated to the product again. For the method name on the customer object, you can select a name similar to getcustomeropenorderdetails :.
Multiple paths are enabled for the link shown in the graph. You can use these paths to retrieve DTO that comprise information of all four object types. For example:
- For a given customer, retrieve the detailed information of the delayed delivery order (as described above ).
- For a given customer, retrieve the details of all relevant orders.
- Give an order and retrieve its customers and details.
- A row-based project is given and its related products are retrieved, including the order and customer of the row-based project.
- For a given product, retrieve all relevant order line projects and customers.
The entity that owns the method is indicated in the above "given a (n) <entity>" clause, which indicates the start point. Therefore, assume that: any service appearance (or EJB home method) associated with this method uses parameters that can identify one or more entity types used to start delegation. I hope this will answer your second question.
- We recommend that you use a local interface when returning DTO from an object EJB. Is it "shouting" (in exchange for performance improvement at the cost of maintainability )?
In the early days of EJB 1.x, we also made interesting Gains and Losses analysis. We found that there are two extreme methods and a neutral method for returning data from the object, so as to get three basic access methods:
- One attribute at a time
On the surface, the best way to maintain maintainability is to completely avoid DTO, and use the method of getting an attribute from the client at a time. However, the maintainability is achieved at the cost of reducing the number and size of messages. Generally, the use case ends with many small messages. When a remote interface is involved, the communication overhead between the end and end will have a great impact on the response time and throughput. Another disadvantage (as you mentioned) is that it also destroys encapsulation. If encapsulation is damaged, the maintainability will be negatively affected. For example, if you decide to construct a set of attributes into a relevant entity, you need to change each client that uses these attributes!
- One size fits all DTO
Another extreme way is to return all non-standard data associated with the target object returned in DTO, as we discussed in answering the first question. In this case, you can minimize the number of remote messages and maintain the maintainability. Call each object only once and obtain all the data that can be obtained at a time. In this way, you have to develop a DTO and a retrieval method for each object. Of course, the compromise plan is that the data contained in DTO is almost always more than the data required for a given unit of work, especially in actual entities with many attributes. Therefore, this method has a great impact on the data volume retrieved and transmitted from the backend data system for each work unit. The advantage of this method is that you only need to modify DTO each time you add or delete an attribute. The deleted attributes must be modified only when the client uses them.
- Custom DTO
The data cube method (EJB advocates think of the story of kingfa girl and three bears) is to customize the DTO structure so that it can accurately return the data you need. One call. Suitable size. Really good. However, the problem is that you must carefully analyze the use cases to obtain an appropriate set of DTO and methods. When implementing a new class of use cases, you must create a new DTO and adjust the EJB to search for it.
When using an EJB 1.x object, option C is considered the best, because distributed object applications are designed to minimize the number of calls (possibly remote calls. Option B is a good compromise and can gain a certain degree of maintainability. In this way, it becomes simpler. There is no annoying CMR, and you do not need to consider "dependent objects" (the attribute cluster actually represents "included" objects in the entity) other things.
But now we have introduced EJB 2.x and CMR with local interfaces. I once thought about whether option A is the best method (we just wrote a column titled making entity EJB components perform, part 1 (Link) mentioned this problem) -- but we always think that for the same performance reason (although they may not be so important ), using the custom DTO described in option C is still the best. We also pointed out that many people are used to EJB 1. X "best practices" are easier (and easier) than training them again ).
I hope this will help you,
Your EJB advocate
Repeat the old saying to raise questions about maintainability
Dear EJB advocates:
I understand and agree with your answers to the first two questions. This benefits me a lot. My understanding of your analysis of my third question is, why do you think that for EJB 1.x, from the performance perspective, option C is the best, however, you have not really answered how to solve the terrible maintainability problem by using EJB 2.x.
Review the simple relationship diagram in your reply. There are five different top-level methods that combine information from all four entities. You did not mention how to process delegation associated with each entity. Let's take a look at the method associated with obtaining delayed delivery orders from customers:
- If an order is given, the order and the line project with the product are returned. This will be delegated:
- A row-based project and product are returned, Which is delegated:
- Returns the DTO of a given product.
Therefore, there is a combination that does not include all four entities. From the customer's perspective, we can propose more than three methods:
- Only data is returned from the customer.
- Returns only the customer and the deferred delivery order (not detailed ).
- Return the customer and all related orders (but not detailed information ).
Now, add all of these to the arrangement of partial attributes obtained from each object. In short, there are many such combinations, especially when considering (as you may say) that there are more attributes associated with each object.
Therefore, the third problem that I don't quite understand is that you seem to have achieved a small amount of performance improvement at the cost of a large amount of maintainability.
Thanks first, but I still have to sign this name:
Never cry wolf
Associate data transmission objects with views
Dear never cry wolf:
A joke. Now you are shouting "Wolf ". It is unlikely that you will see many such replacements in custom-developed applications. To understand the reason for this, let's start with the top-level -- use case. Although this article is not a complete tutorial on object-oriented analysis and design methods, we will still have a brief look at some of the main components to show that the number of components is relatively limited.
The entities displayed in the class relationship diagram in Figure 1 are associated with the order management business process. This process can be described using the status transition chart (STD), as shown in 2, which shows the stages of the lifecycle of a managed single order.
Figure 2. Sample status transition diagram showing the lifecycle of an order
By the way, for reference only, Figure 2 expands using the UML actor notation to display the owner of an instance in a given State. We have been using this simple extension for many years and use it as an organization case and bind it to the business process (in fact, we like to joke that the use case diagram is a state conversion chart that has not yet been "hatched ).
Another slightly unusual method we use is to develop a class relationship diagram for each State in the lifecycle model to show the constraints on the attributes and relationships that are maintained in this state. These constantly changing constraints are easy to lose in the "single-State" Graph without considering the status. For example, the class relationship diagram in Figure 1 shows the relationships and attributes that are kept in the open state of the lifecycle shown in figure 2. The class relationship diagram of an order in the submitted status may be similar to figure 3.
Figure 3. Example class relationship diagram showing the submitted order
This method provides independent class relationship diagrams based on various states, explaining why the class names in figure 3 and figure 1 use [] to indicate the states, bind the "dynamic" state transition model with the "static" class relationship diagram. By comparing figure 1 and figure 3, we can easily find that the "shape" of order changes from open to submitted in the business process (as shown in Figure 2. The status in Figure 2 shows the behavior changes.
Together with the dynamic model, the static model defines the complete service set in the service-oriented architecture. Each State in the lifecycle model can be mapped to the session EJB component one to one. Every transformation in STD maps to the method on the Session Bean associated with the state. Each class in the relational model can map an entity EJB component. The relationships in the relationship graph are naturally mapped to CMR. Therefore, for the open and submitted statuses, we can infer that there will be two session ejbs, and the two session ejbs have three or four update methods respectively. For the displayed relationship between the two classes, we can infer that there will be 15 entity EJB components with many attributes and CMR.
For details, let's take the delayed delivery order status as an example. First, we compile a pure Java interface that can be reused throughout the process, as shown below:
Code snippet 3. Display pure Java interfaces derived from STD Methods
public interface OpenOrder { OrderKey open(CustomerKey cust) throws CustomerNotFound, OrderAlreadyOpen; int addLineItem(CustomerKey cust, ProductKey product, int qty) throws CustomerNotFound, OrderNotOpen, InvalidQuantity; void submit(CustomerKey cust) throws CustomerNotFound, OrderNotOpen, OrderHasNoLineItems; void cancel(CustomerKey cust) throws CustomerNotFound, OrderNotOpen; }
|
This interface can be reused in the session EJB interface and implementation similar to the following:
Code snippet 4. Session Bean interface and implementation class
public interface OpenOrderSession extends javax.ejb.EJBLocalObject, OpenOrder; public class OpenOrderSessionBean implements javax.ejb.SessionBean { // implementations go here }
|
If you want to, you can use the EJB home method instead of session EJB. In this case, the customer entity becomes the "Gateway" of the business logic, because it represents the actor that drives the Business Process in this state. In this case, you can use the above method to process sessions to expand only the same openorder interface, as shown in the following code segment:
Code snippet 5. Reuse the customer object home interface of the openorder Interface
public interface CustomerHome extends javax.ejb.EJBLocalHome, OpenOrder { // other Home methods like findByPrimaryKey() and create() }
|
Regardless of the method selected, these models and mappings provide the components required to implement the update method. If you want to provide each sort listed in your analysis, you can also use these dynamic and static models to derive all the reading methods. However, we found that it is best to generate these reading methods from the user interface (UI) screen genre that provides support for calling the data required by business flow functions.
For writing documents for screen streams, we also want to use the status transition diagram. Screen stream STD can be seen as the life cycle of a typical "session" that captures actor states in the business flow model. The Status display screen and pop-up dialog box are displayed. To illustrate this, figure 4 demonstrates a customer's screen stream that shows how it interacts with the order management process.
Figure 4. Example screen stream of customer order management session
The interaction between models (if any) is specified within {} of the conversion, displaying the side effects of calling the conversion for the business process. Some events (such as submission) enter a confirmation dialog state. Only when the user triggers "OK" Will the side effects of order submission occur. The validation status is in italic.
The other State displayed in italic is "home", which indicates how the role (in this example, customer) starts and ends its session. There is also a special State displayed in italic that is associated with the Business Process-because a given actor may interact with multiple processes. These two States are special, because they only navigate (they usually appear in the form of menus or tabs, depending on the UI style ).
Its status indicates the "actual" screen (or part of the screen; as this involves general J2EE best practices, so we will discuss it in another article ). For each screen (whether it is a special screen or not), you can use the class relationship diagram to capture Visible data in this status, similar to how a class relationship diagram associated with a business flow shows persistent data associated with a state. Figure 5 shows a composite class diagram of all States except the validation status.
Figure 5. Example class relationship diagram showing the Visible data of a session
Now we can understand why there are not many DTO and related methods. Figure 5 shows seven DTO containing content (link count. These DTO maps directly to Java classes. As shown in figure 4, the conversion from a screen stream to a certain state maps to other methods on openorder. The DTO returned by them are described in the class Relation Diagram in Figure 5. The Convention we want to use is <targetstate> data (instead of DTO ). The parameters of this method are displayed as the data stream associated with the conversion; their names are part of the method name. Code snippet 6 shows some examples:
Code snippet 6. Some read-only methods derived from the UI
CustomerHomeData getCustomerHomeData(CustomerKey cust) throws CustomerNotFound; ProductCatalogData getProductData(CustomerKey cust) throws CustomerNotFound; ProductCatalogData getNextProductData( CustomerKey cust, ProductKey last ) throws CustomerNotFound, ProductNotFound; ProductCatalogData getPreviousProductData( CustomerKey cust, ProductKey first ) throws CustomerNotFound, ProductNotFound; OrderDetailsData getOpenOrderDetailData( CustomerKey cust, ) throws CustomerNotFound, OrderNotFound; OrderDetailsData getOrderDetailData( OrderKey order, ) throws OrderNotFound; OrderStatusData getOrderStatusData( CustomerKey cust, ) throws CustomerNotFound;
|
As you can see, there are very few read-only methods. The number of "root" DTO is even less, because these DTO are reused. In the worst case, this example only requires eight DTO support business processes. In addition, even if you perform oo delegation in the Entity EJB component to load the complete structure, the total number of get <DTO> () methods will be relatively small.
Sorry, in order to answer a relatively simple question, I have talked a lot about conventional oo analysis and design technology, but I still think that in practice, the encapsulation advantage caused by returning the required data structure exceeds the related maintenance problems.
Do you agree?
Okay, stop it,
Your EJB advocate.
Performance problems
Dear EJB advocates:
It is interesting that you perform Object-Oriented Analysis and map work results to EJB components. Your method makes me believe that maintainability is not as bad as you think. But I have another question.
After careful consideration, I came up with a completely different problem: If the get <attribute> () method of CMP is called without any performance loss, do you still recommend that you use the get <DTO> () method on the object using the session appearance, DTO assembler, or object home method without directly obtaining the required attributes from the relevant object at a time?
Take detailitemdata DTO in Figure 5 as an example. In my opinion, if I use oo delegation as recommended, the lineitem object will have a getdetailitemdata () method. This method will reference the product according to the guidance of CMR. You are advised not to call getdescription () and getprice () for the product, but to create a new productdescriptionandpricedata object and call getproductdescriptionandpricedata () for the product (). Then I will copy fields from this structure and copy these fields and productid together with quantity (and the calculated amount) to the detailitemdata structure.
I think this method is really a lot more than that, unless the performance is really so bad.
Hope,
Never cry wolf
Trust your intuition, but want to verify
Dear never cry wolf:
Your persistent (meaningless) Inquiry really makes EJB advocates doubt whether they advocate the use of EJB is not enough.
I must admit that if you use the get <attribute> () method for the local entity EJB component, there is no performance problem, the method you use to assemble the required data in the appearance, physical home method, or delegated method is more attractive. This method requires less components to be compiled during production, and less garbage to be collected during runtime. Therefore, I'm glad you believe that you can understand it directly, I think the real question is not answered. The communication between us shows that sometimes it is necessary to thoroughly understand the essence of the problem multiple times.
On the other hand, I had an intuition that the performance impact of local method calls is still considerable. However, I did not use any meaningful method to test the idea. Instead, I believed in the motto "if it ain't broke, don't fix it" (things are not bad yet, don't rush to fix it)-not only because performance testing is very troublesome, but also because it is more difficult to modify all the demo materials about best practices than the existing examples.
This motto is very reasonable for "early" applications, but it is better to verify my original intuition, because new development projects can select the appropriate method when appropriate.
As a result, I asked a team to perform performance tests. As a result, I was pleasantly surprised to find that as long as the client and entity are within the same global transaction scope, the "client" calls the local get <attribute> () method through a local interface and enables the Entity Bean to call its own abstract get <attribute> () method, there is no obvious difference between the two methods.
With this new data, I am very happy to modify my method. If the existing get <DTO> () method of the information is not provided yet, then, use the get <attribute> () method to assemble the required data. This is suitable for entity ejbs, entity home methods, session appearances, or (as you call it) Delegated methods on the DTO Assembly class.
I am very happy to find that someone is more like an EJB advocate than me! If you have a chance to meet, I will invite you to dinner.
Okay, stop it,
Your EJB advocate.
Conclusion
The following are some meaningful principles drawn from the above discussion:
- Your analysis results should cover both the dynamic and static aspects of the business domain and user interface.
- Systematically map your analysis results to the appropriate EJB components and DTO.
- Session beans are ideal for State-related conversions in business processes (updates) or screen streams (READS.
- When associated with a "Gateway" object that represents an actor that has one or more States in a business flow, the solid bean home method is the best choice.
- In both cases, try to use the CMR associated with the gateway object as much as possible, and use get <DTO> (OO delegate) or get <attributes> (procedural assembly) as needed ), to obtain the data to be returned. This depends largely on whether you already have the appropriate DTO.
- Finally, EJB advocates are willing to admit that they are wrong. It may take some time to realize your mistakes.
We believe that you can find more similar problems. Before the next column is published, you will be busy.
Thank you
We would like to thank Bobby Woolf for providing important suggestions and materials for this article. Visit Bobby's blog to learn about J2EE in practice.
References
- For more information, see the original article on the developerworks global site.
- Java 2 platform, Enterprise Edition (J2EE) specification (the most reliable source)
- Preface by Martin Fowler: Kyle Brown, Gary Craig, Greg Hester, Russell stinehour, W. david Pitt, Mark weitzel, jimamsden, Peter M. enterprise Java programming with IBM WebSphere, second edition, co-authored by Jakab and Daniel Berg.
About the author
|
|
|
Geoff HambrickRound Rock from Texas (near Austin) is the chief consultant for IBM software services for WebSphere enablement team. The enablement team usually provides support for the presales process through deep technical briefing and Short-Term Concept verification. Geoff was elected IBM's distinguished engineer (distinguished engineer) in March 2004. His job is to create and disseminate it for developing IBM WebSphere |