Presentation Tier Refactorings J2EE

The refactorings in this section apply to the presentation tier.

Introduce a Controller

Control logic is scattered throughout the application, typically duplicated in multiple Java Server Page (JSP) views.

Extract control logic into one or more controller classes that serve as the initial contact point for handling a client request.

Introduce a controller

Introduce a controller

Motivation

Control code that is duplicated in multiple JSPs also needs to be maintained in each JSP. Extracting this code into one or more centralized controller class improves the modularity, reusability, and maintainability of the application.

Mechanics

  • Use the Front Controller pattern as a guide for applying Extract Class to create a controller class, moving duplicate control logic from individual JSPs into this controller.
  • Remember that the controller is a delegation point for controlling the request handling. Partition the code with an eye toward modularity and reuse. Do not necessarily embed all the control code directly within a single controller, but rather consider creating helper components to which it may delegate.
  • Control code may also be encapsulated in command objects that work in coordination with the controller, utilizing the Command pattern.

Example
Assume we have the structure shown in Example 1 in many of our JSPs.

Example: Introduce a Controller – JSP Structure

The three vertical dots represent the body of each JSP, which is not being shown in this example. While this body portion differs for each JSP, the helper at the top of the page, implemented as a custom tag, is the same. This helper is responsible for controlling access to this page. It is an “all-or-nothing” type of control, meaning that a client is either granted access to the whole page or is denied access entirely.

If we change the design and introduce a controller, as described in the mechanics, then each of our JSPs will no longer include the <control:grant_access/> tag, as seen in Example.

Instead, we have a centralized controller that manages this behavior, handling the access control check that we removed from each JSP. Example is a snippet of code from the controller, which is implemented as a servlet.

Example : Introduce a Controller – Controller Structure

Of course, there are some cases where helpers are suitable for control code. For example, if only a small fraction of our JSPs need this type of access control, then it is not unreasonable to include a custom tag helper in each of these few pages to accomplish this goal. Another reason we might use custom tags in individual JSPs is to control access to specific subviews of a composite view.

If we are already using a controller,then we still might want to add this behavior in this centralized place, since the number of pages we want to protect might grow over time. To handle the case of an existing controller, we simply extract control code from our views and add it to the existing controller. In effect, we are moving methods instead of extracting a new class.

Introduce Synchronizer Token

Clients make duplicate resource requests that should be monitored and controlled, or clients access certain views out of order by returning to previously bookmarked pages.
Use a shared token to monitor and control the request flow and client access to certain resources.

Introduce synchronizer token

Introduce synchronizer token

Motivation

There are a number of scenarios in which control of an incoming request is desired. One of the most common reasons is the desire to control duplicate request submissions from a client. Such duplicate submissions may occur when the user clicks the Back or Stop browser buttons and resubmits a form.

While this issue is mainly one of controlling the order or flow of the requests, there is also the issue of controlling access based on permissions.

Mechanics

  • Create one or more helper classes responsible for generating and comparing one-time-use, unique tokens.
  • Alternatively, this logic may be added to already existing control components.
  • The component managing this activity (typically a controller, but possibly a JSP) delegates to these helpers, managing the temporary storage of a fresh token for each client submission.
  • A copy of the token is stored per user on the server and on the client browser. The token is typically stored on the client browser as a hidden field and on the server in a user session.

When Is a Token Generated and Stored? When Is a Token Checked?

A synchronizer token is compared for a match before processing an arriving request. A new token value is generated and stored after processing this request, but before the response is prepared and sent to the client.

Synchronizer token life cycle

Synchronizer token life cycle

  • Add logic to check whether the token arriving with the client request matches the token in the user session.
  • The token arriving from the client in the current request should be the same token that the server sent to the client with its last response.
  • Thus a match of these two values confirms that this is not a duplicate submission, while a mismatch suggests this possibility.
  • As stated, a mismatch might also occur for other reasons, such as a user navigating directly to a bookmarked page, but a duplicate request submission is the most common reason.
  • A controller typically manages token generation and comparison. Consider introducing a controller, if one does not already exist.
  • Without a controller to centralize management of token generation and comparison, this behavior must be referenced from each JSP.
  • Typically, the JSP delegates to a helper component, implemented as either a JavaBean or custom tag , which encapsulates the responsibilities token management.

The source code excerpts in Introduce Synchronizer Token are reprinted with permission under the Apache Software License, Version 1.1.

Example

The Struts presentation framework applies several of the J2EE patterns and refactorings. It introduces this exact type of request flow control, and we use excerpts from this open source framework in our example.

Instead of creating a separate utility class to encapsulate the token generation and matching logic, Struts simply adds this functionality to a preexisting class that is part of its control mechanism. The class is called Action,and it is a common superclass for all actions. Actions are Command objects that extend the controller functionality. This is an application of the Front Controller pattern, Command and Controller strategy.

As shown in Example, the saveToken() method, which is part of the Action class, generates and stores token values.

Example : Generate and Store Token

Copyright(c)1999 The Apache Software Foundation. All rights reserved.

This method generates a unique token, calculated using the session ID and the current time, and stores this value into the user session.

At some point(usually immediately) prior to generating the HTML display for the client responsible for submitting a request that we do not want to duplicate (this display typically includes a form to be posted back to the server), a one-time token value is set, as previously described, by making the following method invocation:

saveToken(request);

Additionally, the JSP responsible for generating this HTML display also includes logic that delegates to a helper class to generate a hidden field that includes this token value. Thus, the page sent to the client, which typically includes a form that will be submitted back to the server,includes a hidden field of the following form:

The value attribute of this hidden field is the value of the token that was generated by the saveToken() method.

When the client submits the page that includes this hidden field,the controller delegates to a Command object(again, a subclass of the Action class)that compares the token value in the user session with the value in the request object parameter that came from the hidden field in the page. The Command object uses the method shown in Example, also excerpted from its superclass (the Action class again),to compare the values.

Example : Check For a Valid Token

Copyright(c)1999 The Apache Software Foundation. All rights reserved.

If there is a match,then we are certain that this request submission is not a duplicate. If the tokens do not match, then we are able to take appropriate action to deal with this potentially duplicate form submission.

Localize Disparate Logic
Business logic and presentation formatting are intermingled within a JSP view.

Extract business logic into one or more helper classes that can be used by the JSP or by a controller.

Figure shows logic being extracted from a view and into helpers.

Localize Disparate Logic: Factor Back

Localize Disparate Logic: Factor Back

Figure shows logic being extracted from a view and into a controller, a command object, and helpers.

Localize Disparate Logic: Factor Forward

Localize Disparate Logic: Factor Forward

Motivation
To create cleaner abstractions, increase cohesion and reduce coupling, which improves modularity and reusability. Well-partitioned, modular applications also provide better separation of developer roles, since Web developers own formatting code, while software developers own business logic.

Example
We start with the sample code listed in Example. It is a JSP that includes lots of scriptlet code, intermingling business logic with the view.

Example : JSP with Scriptlet Code

This JSP generates an HTML table that lists employees at a certain salary level. The JSP encapsulates formatting and business logic, as shown in Figure.

View with intermingled business logic and formatting code

View with intermingled business logic and formatting code

As Example shows, we apply the View Helper pattern, changing the design and extracting scriptlet code from the JSP view.

Example : JSP with Scriptlet Code Extracted

Additionally, we have written two custom tag helpers to encapsulate our business and presentation formatting processing logic by adapting the data model into the rows and columns of our HTML table.

The two helpers are the <corepatterns:employeelist> tag and the
<corepatterns:employee> tag.

Figure shows that we have moved from the design represented by the left side of the arrow to the one represented on the right side.

Extracting business logic into helper classes

Extracting business logic into helper classes

Business logic has been extracted into helper classes instead of being embedded directly within the JSP. These helpers handle a variety of tasks, including content retrieval, access control, and adapting model state for display. In the second case, the helper actually encapsulates some of the presentation processing logic, such as formatting a result set into an HTML table. This helps us meet our goal of extracting as much programming logic from the view as possible, thus using the JSP to ask the helper for the completed table, instead of including scriptlet code in the JSP to generate the table.

Helper components may be implemented as JavaBeans or custom tags. JavaBean helpers are well suited to encapsulating content retrieval logic and storing the results, while custom tag helpers are well suited to the aforementioned task of converting the model for display, such as creating a table from a result set. There is quite a bit of overlap, though, so other factors, such as developer experience and manageability issues, may affect the decision about how to implement a helper.

Applying the second bullet of the mechanics, we simply delegate the work to the helpers, as shown in Figure.

Delegate work to helpers

Delegate work to helpers

The JSP view uses the helper classes to perform the view processing and generation. Typically, a controller is used in front of the JSP as the initial contact point for client requests. The controller dispatches to the view, but prior to doing so, the controller may also delegate work to the helper components. Having introduced a controller, we have made the transition shown in Figure.

Introducing a controller

Introducing a controller

Hide Presentation Tier-Specific Details From the Business Tier

Request handling and/or protocol-related data structures are exposed from the presentation tier to the business tier.

Remove all references to request handling and protocol-related presentation tier data structures from the business tier. Pass values between tiers using more generic data structures.

Hide presentation tier-specific details from the business tier

Hide presentation tier-specific details from the business tier

Motivation

Implementation details specific to one tier should not be introduced in another tier. The service API exposed by the business tier to the presentation tier will likely be used by other clients as well. If the service API accepts parameters with types, such as HttpServletRequest, then every client to the service is forced to package its data in a servlet request data structure. This drastically reduces the service's reusability.

Mechanics

  • Replace all references to presentation-tier data structures in the business tier with references to more generic data structures and types.
  • These are typically business-tier methods accepting parameters with types such as HttpServletRequest that might be replaced with parameters of more generic types, such as String, int, or UserInfo.
  • Modify client code in the presentation tier that invokes these methods.
  • Pieces of the presentation tier data structure may be passed to the business tier methods as individual arguments. For example, if the HttpServletRequest has parameters x, y, and z, a method in the business tier, instead of accepting the HttpServletRequest as a parameter, might accept these three arguments individually as Strings. One drawback of passing fine-grained, individual arguments is that this strategy more tightly couples the details of the presentation tier with the business service API. Thus, if the state required by the service changes, then the service API must change.
  • A slightly more flexible alternative is to copy the relevant state from the presentation tier data structure into a more generic data structure, such as a value object, which is passed into the business tier. In this case the service API continues to accept this object, even if its implementation details change.
  • Alternatively, implement a strategy of overlaying interface types, if a presentation-tier framework, such as the popular Struts project, is used.

When handling a request, frameworks typically create numerous data structures. For example, typically a framework will transparently complete the step of copying the relevant state from the HttpServletRequest data structure to a more generic data structure, massaging request parameters into a framework-specific data type.While this data type may fulfill the same basic role as a value object, it is a framework-specific data type. Thus, passing this data structure into the business tier introduces coupling between the request-handling framework and the business services. In this case, one could still take the approach just described and copy the framework-specific data structure into a generic structure before passing it to the business tier. Instead, a more efficient solution is to simply create a generic type of interface that mirrors the methods of the framework-specific type. If this interface type is overlaid onto the framework-specific object, then this object can be shared with the business tier without any coupling to the specific framework.

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

J2EE Topics