Over a million developers have joined DZone.

Mediator Pattern: Reducing Page Dependencies in JSF

DZone's Guide to

Mediator Pattern: Reducing Page Dependencies in JSF

· Java Zone
Free Resource

What every Java engineer should know about microservices: Reactive Microservices Architecture.  Brought to you in partnership with Lightbend.

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:



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) {
} 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:


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}"/>
<f:facet name="header"><h:outputText value="Client Address"/></f:facet>
<h:outputText value="#{client.address}"/>

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) {
List<Person> persons = DataSource.getPersons();
for(Person person: persons) {
return result;

The managed-beans are defined with the session scope:


All other pages have the similar behavior.


In order to use “Select Address” page for both “Add Person” and “Add Company” pages it is desirable to keep it independent on the latter ones. Also if assume using another page (strategy) for selecting address it is desirable to keep “Add Person” and “Add Company” pages independent on this “Select Address” page. This is where the Mediator pattern comes up. The next diagrams show the role of the mediator object:


Mediator object is implemented as managed-bean. “Select address” button has an attached action listener that points to method of the Mediator object. This method tunes up “Select Address” page behavior using the Service which stores preferences data in session. Mediator also adds listener that should be fired when address is selected. The code below will help better understanding of the action flow.

The “select address” button is defined inside of the page as follows:

<h:commandButton immediate="true"
value="Select Address"/>

Below is the code of the Mediator class:

public class SelectAddressForPersonBB {
private SelectAddressService selectAddressService;
public String selectAddress() {
// Reset selection for "select address page"
// Set navigation outcome
// Add listener
selectAddressService.setAddressSelectedListener(new Listener() {
public void fire(FacesContext facesContext) {
Application app = facesContext.getApplication();
SelectAddressService selectAddressService =
(SelectAddressService) app.evaluateExpressionGet(facesContext, "#{selectAddressService}", SelectAddressService.class);
PersonService personService =
(PersonService) app.evaluateExpressionGet(facesContext, "#{personService}", PersonService.class);
Address address = selectAddressService.getSelectedAddress();
// Set person's address
// Remove listener
return "selectAddress";
public void setSelectAddressService(final SelectAddressService selectAddressService) {
this.selectAddressService = selectAddressService;

It is configured as a backing bean (note: all managed beans, except for the userSession, are defined with the request scope):


The Service of the “Select Address” page stores preferences and listener in session. The service itself defines interface for tuning the page’s behavior (e.g. it gives the ability to set the success navigation outcome).

public class SelectAddressService {
private static final String SELECTED_ADDRESS = "selected_address";
private static final String SUCCESS_OUTCOME = "success_outcome";
private static final String SELECTED_ LISTENER = "address_selected_listener";
private UserSession userSession;
public List<Address> getAddresses() {
return DataSource.getAddresses();
public void setAddressSelectedListener(Listener listener) {
userSession.setAttribute(SELECTED_LISTENER, listener);
public void setSelectedAddress(Address address) {
userSession.setAttribute(SELECTED_ADDRESS, address);
Object listener = userSession.getAttribute(SELECTED_LISTENER);
if(listener != null) {
((Listener) listener).fire(FacesContext.getCurrentInstance());
public Address getSelectedAddress() {
Object address = userSession.getAttribute(SELECTED_ADDRESS);
return address == null ? null : (Address) address;
public void setSuccessNavigationOutcome(String navigationOutcome) {
userSession.setAttribute(SUCCESS_OUTCOME, navigationOutcome);
public String getSuccessNavigationOutcome() {
Object navigationOutcome = userSession.getAttribute(SUCCESS_OUTCOME);
return navigationOutcome == null ? null : (String) navigationOutcome;
public void setUserSession(final UserSession userSession) {
this.userSession = userSession;

The diagram below explains what happens when user selects address on the “Select Address” page:


After address is selected it is stored and listener that was added by mediator is invoked. This listener retrieves selected address and sets it to the person using the corresponding Service:

public void fire(FacesContext facesContext) {
Application app = facesContext.getApplication();
SelectAddressService selectAddressService =
(SelectAddressService) app.evaluateExpressionGet(facesContext, "#{selectAddressService}", SelectAddressService.class);
CompanyService companyService =
(CompanyService) app.evaluateExpressionGet(facesContext, "#{companyService}", CompanyService.class);
Address address = selectAddressService.getSelectedAddress();
// Set company's address
// Remove listener


The article explored an example of applying the well-known Mediator pattern for Web application development. The examples provided in this article, along with the source code, can help you implement this pattern in almost any JSF-based application.

You are free to download sources  http://java.dzone.com/sites/all/files/mediator_in_jsf_app-src.zip

Microservices for Java, explained. Revitalize your legacy systems (and your career) with Reactive Microservices Architecture, a free O'Reilly book. Brought to you in partnership with Lightbend.


Opinions expressed by DZone contributors are their own.


Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.


{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}