Hobione's Weblog

Living & Breathing in Web 2.0 Era

Dependency Injection in JSF and ‘new’ is a dirty word

I am going to write some explanation that I have learned from training and discussed with my cohort. Please go get a cup of coffee before you start this journey. Yes, using ‘new’ is a dirty word in a sense that in this example, you wont see using ‘new’ to instantiate an object instead use the injection capability in the faces-config.xml file.  Please read these articles before proceed.  Spring into JavaServer Faces and JSF-Spring


1. What does this following code mean?

<managed-bean>
        <managed-bean-name>applicantEditor</managed-bean-name>
        <managed-bean-class>training.jobapplication.bean.backing.ApplicantEditor</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>

    </managed-bean>

It means to create an instance of ApplicantEditor.java and make it available in request scope.

ApplicantEditor applicantEditor = new ApplicantEditor();

Here the ApplicantEditor.java looks like.

public class ApplicantEditor {

	private boolean formRendered = false;

	public boolean isFormRendered() {
		return formRendered;
	}

	public void setFormRendered(boolean formRendered) {
		this.formRendered = formRendered;
	}
}

2. Let me explain these following code snippets

<managed-bean>
		<managed-bean-name>applicantList</managed-bean-name>
		<managed-bean-class>training.jobapplication.bean.backing.ApplicantList</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
		<managed-property>
<property-name>applicantEditor</property-name>
			<value>#{applicantEditor}</value>
		</managed-property>
		<managed-property>
<property-name>applicantListModel</property-name>
			<value>#{applicantListModel}</value>
		</managed-property>
	</managed-bean>

First of all, an instance has been created for ApplicantList in a request scope. Now, by looking at the line 6, I can tell that ApplicantList.java has a property/instance variable name applicantEditor <property-name> (it is a type of ApplicantEditor.java). Line 7, it’s calling setApplicantEditor() to set the value <#value>. Also same things are happening in line 10 and 11 for applicantListModel.  Declare the property name using this tag <property-name>, and set the value by using this value tag <value> .  ApplicantList contains a ‘has-a’ relationship of ApplicantEditor type.  Easy, piece of cake and here is the proof:

package training.jobapplication.bean.backing;

import training.jobapplication.bean.model.ApplicantListModel;

import training.jobapplication.transfer.Applicant;

import javax.faces.component.UICommand;
import javax.faces.event.ActionEvent;

public class ApplicantList {

	private ApplicantForm applicantForm;
	private ApplicantEditor applicantEditor;
	private ApplicantListModel applicantListModel;

	public ApplicantForm getApplicantForm() {
		return applicantForm;
	}

	public void setApplicantForm(ApplicantForm applicantForm) {
		this.applicantForm = applicantForm;
	}

	public ApplicantListModel getApplicantListModel() {
		return applicantListModel;
	}

	public void setApplicantListModel(ApplicantListModel applicantListModel) {
		this.applicantListModel = applicantListModel;
	}

	public void checkAll(ActionEvent actionEvent) {
		getApplicantListModel().checkAll();
	}

	public void create(ActionEvent actionEvent) {
		getApplicantListModel().setSelectedAsNew();
		getApplicantEditor().setFormRendered(true);
	}

	public void deleteChecked(ActionEvent actionEvent) {
		getApplicantListModel().deleteChecked();
	}

	public void edit(ActionEvent actionEvent) {
		UICommand uiCommand = (UICommand)actionEvent.getComponent();
		Applicant applicant = (Applicant)uiCommand.getValue();
		getApplicantListModel().setSelected(applicant);
		getApplicantEditor().setFormRendered(true);
	}

	public void uncheckAll(ActionEvent actionEvent) {
		getApplicantListModel().uncheckAll();
	}

	public ApplicantEditor getApplicantEditor() {
		return applicantEditor;
	}

	public void setApplicantEditor(ApplicantEditor applicantEditor) {
		this.applicantEditor = applicantEditor;
	}
}

3. These snippets are the most confusing to me:

<managed-bean>
		<managed-bean-name>applicantListModel</managed-bean-name>
		<managed-bean-class>training.jobapplication.bean.model.ApplicantLazyListModel</managed-bean-class>
		<managed-bean-scope>session</managed-bean-scope>
		<managed-property>
<property-name>applicantService</property-name>
			<value>#{applicantService}</value>
		</managed-property>
		<managed-property>
<property-name>rowsPerPage</property-name>
			<value>#{userPreferences.rowsPerPage}</value>
		</managed-property>
	</managed-bean>

I try my best to explain.  First of all, here’re some basic java polymorphism code.

Car car = new BMW();
car.go(); --> it calls BMW go() method
super.go() --> it calls Car go() method.

We have to use our polymorphic power to understand this part. This is what’s happening in line 2 and 3 in above xml.

ApplicantListModel applicantListModel = new ApplicantLazyListModel();
or,
ListModel applicantListModel = new ApplicantLazyListModel();
or,
ApplicantLazyListModel applicantListModel = new ApplicantLazyListModel();

We dont know what ApplicantLazyListModel will rertun in run time.  You may have noticed that applicantListModel is not the exact same object type as ApplicantLazyListModel.java  but ApplicantLazyListModel.java extends ApplicantListModel.java.  So there is an ‘is-a’ relationship going on. But Line 6, there is no guarantee that applicantService will be an instance variable (property) of ApplicantLazyListModel.java.  Since ApplicantLazyListModel extends ApplicantListModel, we assume applicantService is a member of ApplicantListModel.java not ApplicantLazyListModel.
Okay, got that, if you dont just pretend you do, it will get clear after you see these following code. Now, here is the another fun part.

<managed-property>
<property-name>rowsPerPage</property-name>
			<value>#{userPreferences.rowsPerPage}</value>
		</managed-property>

I cant not find the property, rowsPerPage nor in ApplicantLazyListModel or ApplicantListModel, where it can be?  ApplicantListModel also extends ListModel. So, rowPerPage is a member of ListModel.java. rowPerPage is also a proerty of UserPreferences.java.  In the above xml,  I’d read like this.  rowPerPage is a property of applicantListModel which value has been set by calling get method, userPreferences.rowPerPage. Objects hierarchies are as follows.

UML

public class ApplicantLazyListModel extends ApplicantListModel {
.....
}
public class ApplicantListModel extends ListModel {

private ApplicantService applicantService;
...
}
public abstract class ListModel {
private int rowsPerPage = -1;
...
}
package training.jobapplication.bean.util;

public class UserPreferences {

	private int rowsPerPage = 5;
	private int maxPageNumberNavControls = 3;
	private boolean pageNumberNavControlsShown = true;

	public int getRowsPerPage() {
		return rowsPerPage;
	}
	public void setRowsPerPage(int rowsPerPage) {
		this.rowsPerPage = rowsPerPage;
	}
	public int getMaxPageNumberNavControls() {
		return maxPageNumberNavControls;
	}
	public void setMaxPageNumberNavControls(int maxPageNumberNavControls) {
		this.maxPageNumberNavControls = maxPageNumberNavControls;
	}
	public boolean isPageNumberNavControlsShown() {
		return pageNumberNavControlsShown;
	}
	public void setPageNumberNavControlsShown(boolean pageNumberNavControlsShown) {
		this.pageNumberNavControlsShown = pageNumberNavControlsShown;
	}

}

Man, now my brain hurts to think all these object relations.  Feel free to write comments and more details in concept wise, visit my cohort David Wilson-Burns blog. He explains why we need Injection instantiation vs. using ‘new’ to create an object reference in Java. Here is the full faces-config.xml

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN" "http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
	<application>
		<message-bundle>JSF-override</message-bundle>
		<view-handler>com.icesoft.faces.facelets.D2DFaceletViewHandler</view-handler>
		<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
	</application>
	<!--
	<lifecycle>
<phase-listener>training.jobapplication.lifecycle.LoggingPhaseListener</phase-listener> </lifecycle>
	-->
	<converter>
		<converter-id> provinceIdConverter </converter-id>
		<converter-class> training.jobapplication.converter.ProvinceIdConverter </converter-class>
	</converter>
	<managed-bean>
		<managed-bean-name>applicantEditor</managed-bean-name>
		<managed-bean-class>training.jobapplication.bean.backing.ApplicantEditor</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
	</managed-bean>

	<managed-bean>
		<managed-bean-name>applicantList</managed-bean-name>
		<managed-bean-class>training.jobapplication.bean.backing.ApplicantList</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
		<managed-property>
<property-name>applicantEditor</property-name>
			<value>#{applicantEditor}</value>
		</managed-property>
		<managed-property>
<property-name>applicantListModel</property-name>
			<value>#{applicantListModel}</value>
		</managed-property>
	</managed-bean>

	<managed-bean>
		<managed-bean-name>applicantForm</managed-bean-name>
		<managed-bean-class>training.jobapplication.bean.backing.ApplicantForm</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
		<managed-property>
<property-name>applicantEditor</property-name>
			<value>#{applicantEditor}</value>
		</managed-property>
		<managed-property>
<property-name>applicantListModel</property-name>
			<value>#{applicantListModel}</value>
		</managed-property>
		<managed-property>
<property-name>citySupport</property-name>
			<value>#{citySupport}</value>
		</managed-property>
	</managed-bean>
	<managed-bean>
		<managed-bean-name>provinceSupport</managed-bean-name>
		<managed-bean-class>training.jobapplication.bean.support.ProvinceSupport</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
		<managed-property>
<property-name>provinceService</property-name>
			<value>#{provinceService}</value>
		</managed-property>
	</managed-bean>
	<managed-bean>
		<managed-bean-name>citySupport</managed-bean-name>
		<managed-bean-class>training.jobapplication.bean.support.CitySupport</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
		<managed-property>
<property-name>cityService</property-name>
			<value>#{cityService}</value>
		</managed-property>
	</managed-bean>

	<managed-bean>
		<managed-bean-name>applicantListModel</managed-bean-name>
		<managed-bean-class>training.jobapplication.bean.model.ApplicantLazyListModel</managed-bean-class>
		<managed-bean-scope>session</managed-bean-scope>
		<managed-property>
<property-name>applicantService</property-name>
			<value>#{applicantService}</value>
		</managed-property>
		<managed-property>
<property-name>rowsPerPage</property-name>
			<value>#{userPreferences.rowsPerPage}</value>
		</managed-property>
	</managed-bean>

	<managed-bean>
		<managed-bean-name>userPreferences</managed-bean-name>
		<managed-bean-class>training.jobapplication.bean.util.UserPreferences</managed-bean-class>
		<managed-bean-scope>session</managed-bean-scope>
	</managed-bean>
	<navigation-rule>
		<from-view-id>/applicantList.xhtml</from-view-id>
		<navigation-case>
			<to-view-id>/applicantForm.xhtml</to-view-id>
		</navigation-case>
	</navigation-rule>
	<navigation-rule>
		<from-view-id>/applicantForm.xhtml</from-view-id>
		<navigation-case>
			<to-view-id>/applicantList.xhtml</to-view-id>
		</navigation-case>
	</navigation-rule>
</faces-config>

Related Topics: What is Dependency Injection (DI) / Inversion of Control (IoC):  “Hollywood Principle”—”don’t call us, we will call you”. – Wiki’s definition

Pros: The dependency injection approach offers more flexibility because it becomes easier to create alternative implementations of a given service type, and then to specify which implementation is to be used via a configuration file, without any change to the objects that use the service. This is especially useful in unit testing, because it is easy to inject a mock implementation of a service into the object being tested.

Cons: The price paid for that additional flexibility is greatly increased complexity and the fact that the program is no longer deterministic: it’s no longer possible to tell what functions will be called just by looking at the code.

Advertisements

January 16, 2009 - Posted by | Java Server Faces, Spring Framework

1 Comment »

  1. Maybe a comment to your cons:

    If you use the Eclipse SpringIDE you get a visual dependency graph of all your bean dependencies. You’ll see that this is pretty brilliant to recognize how the beans dependency is inside the code. You’ll not get this transparency without special static analyzing tools with the “old” object creation way.

    Maybe interesting:

    http://blog.rainer.eschen.name/2008/05/13/lessons-learned-from-springs-autowired/
    http://blog.rainer.eschen.name/2007/08/21/jsf-on-spring-beans/
    http://blog.rainer.eschen.name/2006/11/16/the-observer-pattern-in-mixed-dependency-injection-contexts-spring-jsf/
    http://blog.rainer.eschen.name/2006/12/15/how-to-decontaminate-a-singleton/

    Comment by Rainer Eschen | February 3, 2009 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: