Date post: | 15-Dec-2015 |
Category: |
Documents |
Upload: | shaun-duncan |
View: | 219 times |
Download: | 2 times |
Bridging Java Presentation and Business Logic with an
Application Model
Nathan Carpenter
RABA Technologies
Purpose
Show how the Application Model design pattern provides a session-based state management solution that bridges the gap between the presentation and business tiers in a Web application
Agenda
Background
Problems Addressed
The Application Model Pattern
Implementing an Application Model
Conclusion
Background
Three Tier systems are very common today– Presentation Tier displays data to the
user (JSP, Swing GUI)– Business Tier provides rules and logic
for manipulating the data (Servlets, Session Beans)
– Data Tier handles persistence of data (Entity Beans, Data Access Objects, JDBC)
Background
Many patterns exist for Business and Data Tiers and communications between them– Session Façade, Value Object, Data
Transfer Object, others
Limited patterns exist for Presentation Tier or for its communication with Business Tier– Business Delegate
Agenda
Background
Problems Addressed
The Application Model Pattern
Implementing an Application Model
Conclusion
Problem
Three major problems between Presentation and Business Tiers
– Properly designed Business Tier is client-agnostic
– Stateless nature of Web-based interfaces makes keeping client state difficult
– Presentation components must be decoupled from business communication logic
Client Agnosticism
Business Tier interfaces should be developed to be useful to any number of clients– Client requirements often creep into
Business Tier code– Decreases broad utility of Business
Tier– Changes to the business logic may
affect clients negatively
Stateless Clients
Web interfaces are inherently statelessClients often need to maintain some kind of state
– State should not be managed by the business tier, since it is a client-specific need
– State management in Web interfaces can be done with the Session
– Namespace conflicts and state validation problems can become an issue in a large system
Decoupling Presentation Components
JSPs, Custom Tags, and Struts Actions should contain no business logic or ties to the business interface– Limits impact of changes in
presentation logic and business logic– Both change often during system
development
Need an adapter between presentation API and business API
The Application Model Pattern
Provides a session-based state management solution that bridges the gap between the Presentation and Business tiers
Works hand-in-hand with Business Delegate pattern to provide a client-specific interface to the Business Tier
Used by Web-based display components such as JSPs, custom tags, and Struts actions
Agenda
Background
Problems Addressed
The Application Model Pattern
Implementing an Application Model
Conclusion
The Application Model Pattern
Forces
Solution
Participants and Responsibilities
Strategy
Consequences
Related Patterns
Forces
Business tiers are client-agnostic and provide data in least-common-denominator fashion
Web-based interfaces are inherently stateless and need a standard way to manage state information
It is desirable for clients to cache data from the server to reduce round trips
Display components such as JSPs, custom tags, and Struts actions should not perform data translation and composition
Solution
Use an Application Model to provide a client-specific interface to one or more business services, with caching and manipulation of the server-provided data encapsulated within a client-oriented model
Benefits of Solution
Provides the interface that display-oriented components use to access the business tiers
Yields a highly client-oriented interface that acts as a façade to multiple Business Delegates and Service Locators
Acts as the Model while the display components act as the View and the web framework acts as the Controller
Client submits a request to the
Controller (usually a Servlet or JSP)
Participants And Responsibilities
Controller retrieves an instance of the
Application Model from the Session
Participants And Responsibilities
Controller executes method to access state
maintained by the Application Model
Participants And Responsibilities
Application Model returns stored state or uses Business
Delegate to get remote information
Participants And Responsibilities
Strategy
Implement the Application Model as a Session Singleton– One instance of the Application Model
per user– Instance stored in the user’s Session– Expires when session is invalidated
Details in the Implementation section
Consequences
Provides a client-oriented API for display components– Takes the client-agnostic APIs
generally provided by Business Delegates or Session Facades and creates a client-specific API
– Within the Application Model, data is transformed based on client-specific requirements and cached if needed
Consequences
Allows the Web application to maintain state using a consistent strategy– Reduces risk of namespace conflicts
between developers in complex systems
– Allows for related data to be logically grouped in the session and in code, which simplifies debugging and maintenance
Consequences
Gives the Web application a consistent means for checking for loss of state– State validity checking is encapsulated
into the instance retrieval method– Application Model can ensure that it is
in the proper state before responding to any call
Related Patterns
Business Delegate– Encapsulates the remote
communications methods– Maps network exceptions into
business exceptions
Service Locator– Looks up remote objects if a Business
Delegate does not exist for the remote interface
Agenda
Background
Problems Addressed
The Application Model Pattern
Implementing an Application Model
Conclusion
Basic Requirements
Must be Serializable to store in the Session
Needs a unique handle to prevent namespace conflicts in the Session
Has to be able to tell if the Session was invalidated between calls to the instance
Needs a method to retrieve an instance from the Session
public class MyAppModel implements Serializable
{
private static final String SESSION_NAME =
MyAppModel.class.getName();
private boolean transient isModelValid = false;
private DemoBusinessDelegate delegate = null;
// Other member variables go here
// Mark any nonserializable ones as transient!
Core Implementation
protected MyAppModel(HttpSession session)
{
// Initialize the business delegate(s)
this.delegate = new DemoBusinessDelegate();
// Initialize other models or members
// Set the model state to valid
this.isModelValid = true;
}
Core Implementation (cont.)
public synchronized static MyAppModel getSessionInstance(HttpSession session)
{ Object o = session.getAttribute(SESSION_NAME);
if (o == null || !(o instanceof MyAppModel) || !(((MyAppModel)o).isModelValid)) { o = new MyAppModel(session); session.setAttribute(SESSION_NAME, o); }
return ((MyAppModel)o);}
Core Implementation (cont.)
Implementation Notes
Constructor must be protected to ensure singleton status
All non-serializable members must be marked transient
All public methods that manipulate member variables must be synchronized in case a user makes many requests rapidly
Demonstration Model
Build an application model to interface to a simple personnel database
• Employee has name and address• Server API has following methods:
public Employee getEmployee(employeeId)
public Employee[] getEmployees()
public void addEmployee(Employee employee)
Build Client API
Add code to support these client functions• Retrieve a single employee and display
their information• Retrieve employee names and
addresses from the server and cache them for display
• Create a wizard allowing entry of an employee record
Retrieve Employee
Make a call to the business delegate passing the employee’s ID
Let’s also figure that the client will want to operate multiple times on the same employee, so we should cache the result
private Employee cachedEmployee = null;
public synchronized Employee getEmployee(String id) {
if (this.cachedEmployee == null ||
!(this.cachedEmployee.getEmployeeId().equals(id)))
{
this.cachedEmployee = delegate.getEmployee(id);
}
return this.cachedEmployee;
}
Model Implementation
<%
MyAppModel myAppModel =
MyAppModel.getSessionInstance(session);
String id = request.getParameter(“employeeId”);
Employee employee = myAppModel.getEmployee(id);
%>
<UL>
<LI>Name: <%= employee.getLastName() + “, ”
+ employee.getFirstName()%></LI>
<UL>
JSP Implementation
Retrieve Employee List
Make a call to the business delegate and get the array back
Let’s also figure that the client will want to operate multiple times on the same list, so we should cache the result
private Employee[] cachedEmployees = null;
public synchronized Employee[] getEmployees() {
if (this.cachedEmployees == null)
{
this.cachedEmployees = delegate.getEmployees();
}
return this.cachedEmployees;
}
Model Implementation
<%
MyAppModel myAppModel =
MyAppModel.getSessionInstance(session);
Employee[] employeeList = myAppModel.getEmployeeList();
%>
<!-- Now iterate over the records and display them -->
<% for (int i = 0; i < employeeList.length; i ++) { %>
<!-- Display one record -->
<% } %>
JSP Implementation
Adding Employee
Previous examples focused on caching – this example will focus on state management
Data Entry is often a multistage, branching process
Real power of Application Model is here
Desired Outcome
We’ll simulate a “wizard” for entering employee information
• First, enter first and last name and continue
• Next enter address and save record
Real application would be more complex
Strategy
We’ll create a “working” Employee object managed by the Application Model
When all information is complete, this will be passed to the Business Delegate for saving
private Employee workingEmployee = null;
public void setWorkingEmployee(Employee e) { … }
public Employee getWorkingEmployee() { … }
public synchronized void addEmployee(Employee employee) {
delegate.addEmployee(employee);
this.employees = null;
this.currentEmployee = employee;
}
Model Implementation
The first step in the Wizard would fire the following Controller action
/** setup action **/
Employee employee = new Employee();
employee.setEmployeeId(String.valueOf(new java.util.Date().getTime()));
employee.setFirstName(form.getFirstName());
employee.setLastName(form.getLastName());
myAppModel.setWorkingEmployee(employee);
/** rest of action **/
Controller Implementation
The second step in the Wizard would fire the following Controller action
/** setup action **/
Employee employee = myAppModel.getWorkingEmployee();
employee.setStreet(form.getStreet());
employee.setCity(form.getCity());
employee.setState(form.getState());
employee.setZip(form.getZip());
myAppModel.setWorkingEmployee(null); // We’re done
myAppModel.addEmployee(employee);
/** rest of action **/
Controller Implementation
When To Use
Use when you have complicated branching of requests while building up enough state information for a submission– Redundant for simple form state
management problems since Web framework such as Struts and JSF provide standard constructs for this
When To Use
Use when Presentation Tier use cases do not map well to Business Tier use cases– Adds needless level of indirection if
you have a one-to-one method and exception mapping in your Application Model with no additional logic
When To Use
Use for caching of server information when it doesn’t involve very complicated rules or huge data sets– Complicated caching logic is best
handled by an off-the-shelf caching solution
– Large data sets will overwhelm the session and are better handled by a focused caching solution
Agenda
Background
Problems Addressed
The Application Model Pattern
Implementing an Application Model
Conclusion
Conclusion
The use of an Application Model– Allows Web client developers to create a
client-oriented API– Encapsulates caching and data
transformation specific to the client’s needs– Maintains state in a more predictable way
than simply storing data in the session– Takes advantage of the Business Delegate
and Service Locator patterns as best practices
Questions
Contact Me– [email protected]
Get The Code– http://www.jugaccino.org
Thanks For Attending!