Dab has posted 2 posts at DZone. View Full User Profile

Mediator Pattern: Reducing Page Dependencies in JSF

04.29.2008
| 18193 views |
  • submit to reddit

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 session

There 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.

AttachmentSize
bd_sts_top10.jpg56.83 KB
1.PNG8.8 KB
2.PNG7.22 KB
3.PNG7.11 KB
4.PNG7.55 KB
5.PNG6.17 KB
6.PNG9.52 KB
Published at DZone with permission of its author, Dab Snooper.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Barry Stevenson replied on Mon, 2008/10/20 - 12:57pm

Please post the source code for your JSPs and your faces-config.xml file.  Thanks.

Dab Snooper replied on Tue, 2008/10/28 - 12:54pm

Please see the link at the end of the article for downloading the sources.

Gregory Leb replied on Thu, 2011/12/01 - 11:56am

This is a high level Java type of discussion. It can’t follow the discussion pretty well because my knowledge of the subject is limited if not very marginal. - Gregory Leb

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.