Mediator Pattern: Reducing Page Dependencies in JSF
Using the mediator pattern gives you the ability to develop JSF pages as fine-grained components in your application, allowing them to be tied together clearly and easily.
Mediator Pattern
Usually a web application is made up of a (sometimes large) number of pages with a number of underlying classes (backing beans, etc.). So the different functionality is distributed among these pages. However, as more pages are developed in a program, especially during maintenance and/or refactoring, the problem of communication between these pages and underlying classes may become more complex. This makes the program harder to read and maintain. Furthermore, it can become difficult to change the program, since any change may affect code in several other classes.
With the mediator pattern communication between objects is encapsulated with a mediator object. Objects no longer communicate directly with each other, but instead communicate through the mediator. This reduces the dependencies between communicating objects, thereby lowering the coupling.
Sample Application
The example application is made up from the several pages. The first represents list of the clients. The client can be a private person or a company.
The client can be added by clicking on the “Add Person” or on the “Add Company” link. On the next step the page with editable details is opened:
or
Next, the user should select address for client on the separate form with the list of addresses:
After he or she selected address, other details should be added and client can be added with “Add” button.
The example application is quite simple and its only purpose is to show the usage of the pattern.
Applying Pattern
User sessionThere are two commonly used ways to organize interaction between pages in JSF: via session scope or request. The example introduced in the article is based on the first approach and uses session scope bean as a session:
public class UserSession {
private Map<String, Object> sessionMap = new HashMap<String, Object>();
public synchronized void setAttribute(String key, Object value){
if(value == null) {
sessionMap.remove(key);
} else {
sessionMap.put(key, value);
}
}
public synchronized Object getAttribute(String key){
return sessionMap.get(key);
}
}
It is defined in the JSF configuration file as follows:
<managed-bean> <managed-bean-name>userSession</managed-bean-name> <managed-bean-class>example.session.UserSession</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean>Page Service
Page’s backing bean uses the Service that retrieves all needed data for the page. Let’s discover the page displaying the client list as the example. Here is the part of the JSP page that displays client table:
<h:dataTable value="#{clientsBB.clients}" var="client" style="border:solid 1px gray">
<h:column >
<f:facet name="header"><h:outputText value="Client Name"/></f:facet>
<h:outputText value="#{client.name}"/>
</h:column>
<h:column>
<f:facet name="header"><h:outputText value="Client Address"/></f:facet>
<h:outputText value="#{client.address}"/>
</h:column>
</h:dataTable>
The page gets data from its backing bean’s getClientsMethod:
public class ClientsBB {
private ClientsService clientsService;
public List<ClientListItem> getClients() {
return clientsService.getClients();
}
public void setClientsService(final ClientsService clientsService) {
this.clientsService = clientsService;
}
}
ClientsService implements business logic of the page. It retrieves data from data source (or from user session) and composes objects to be displayed:
public class ClientsService {
public List<ClientListItem> getClients() {
List<ClientListItem> result = new ArrayList<ClientListItem>();
List<Company> companies = DataSource.getCompanies();
for(Company company: companies) {
result.add(ClientListItem.valueOf(company));
}
List<Person> persons = DataSource.getPersons();
for(Person person: persons) {
result.add(ClientListItem.valueOf(person));
}
return result;
}
}
The managed-beans are defined with the session scope:
<managed-bean>
<managed-bean-name>clientsBB</managed-bean-name>
<managed-bean-class>example.backingbean.ClientsBB</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>clientsService</property-name>
<value>#{clientsService}</value>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>clientsService</managed-bean-name>
<managed-bean-class>example.service.ClientsService</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
All other pages have the similar behavior.
| Attachment | Size |
|---|---|
| bd_sts_top10.jpg | 56.83 KB |
| 1.PNG | 8.8 KB |
| 2.PNG | 7.22 KB |
| 3.PNG | 7.11 KB |
| 4.PNG | 7.55 KB |
| 5.PNG | 6.17 KB |
| 6.PNG | 9.52 KB |
- Login or register to post comments
- 3225 reads
- Printer-friendly version
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)






