JSF2 Using Spring PDF
JSF2 Using Spring PDF
JSF2 Using Spring PDF
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
/ </listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener o g.sp g a e o . eb.co te t. equest. equestCo te t ste e
</listener-class>
</listener>
<!-- Normal JSF settings:
- servlet/servlet-mapping for FacesServlet
- PROJECT_STAGE settings
-->>
17
Configuring JSF to Recognize
Spring Beans: Idea Spring Beans: Idea
Not good to call getBean
It would be technically legal to get the
ApplicationContext and call getBean explicitly (probably
from the backing beans action controller method). But from the backing bean s action controller method). But
this is a bad idea since JSF is geared around declaring
beans in config files only.
JSF l d t d d i j ti JSF already supports dependency injection
The managed-property element lets you insert other beans
inside newly created ones. inside newly created ones.
The only trick is to be able to refer to Spring beans
Use DelegatingVariableResolver
Declare in faces-config.xml. Now, whenever JSF sees a
bean name, it uses JSF rules first, then Spring rules next.
18
Configuring JSF to Recognize
Spring Beans: faces-config xml Spring Beans: faces-config.xml
<?xml version="1.0"?>
<faces-config version="2 0> <faces config version= 2.0 >
<application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
</application>
</faces-config>
19
2010 Marty Hall
JSF/Spring Example 1: JSF/Spring Example 1:
Beans in Two Config Files
Customized Java EE Training: http://courses.coreservlets.com/
Servlets, JSP, JSF 2.0, Struts, Ajax, GWT 2.0, Spring, Hibernate, SOAP & RESTful Web Services, Java 6.
Developed and taught by well-known author and developer. At public venues or onsite at your location.
Example: Overview
Input form
C ll t ID d d Collects user ID and password
Required
Collects preferred foreground
and background colors and background colors
Optional
Results pages
Sh d b l f t Shows name and balance of customer
with given ID
Uses preferred colors
F di l d ith if Form redisplayed with errors if:
User ID or password missing
Uses required and requiredMessage
User ID is unknown
Sets FacesMessage in action controller
21
Example: Overview (Continued)
Service interface
CustomerLookupService
Maps customer IDs to Customers
Service implementation Service implementation
MapCustomerLookupService
Uses fixed HashMap of a few sample customers
Color preferences object
ColorPreferences
Stores the users foreground and background colors
Backing bean (JSF managed bean)
Accepts a customer ID and password Accepts a customer ID and password
Needs the service implementation and color preferences
object to be injected into it
22
Example: Overview (Continued)
applicationContext.xml
Defines color preferences object and injects initial
foreground and background colors into it
In session scope In session scope
Defines customer lookup service as a Map and injects all
the keys and values into it
I i l t In singleton scope
faces-config.xml
Declares the DelegatingVariableResolver Declares the DelegatingVariableResolver
Creates the main backing bean in request scope and
injects the two Spring beans (lookup service and color
f bj ) i i preferences object) into it.
But, a later example will move even this part to
applicationContext.xml
23
web.xml: Defining Listeners
<?xml version="1.0" encoding="UTF-8"?>
<web-app > pp
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
/ </listener-class>
</listener>
Loads /WEB-INF/applicationContext.xml and puts reference to it in servlet context. Can be
accessed with WebApplicationContextUtils.getRequiredWebApplicationContext
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener
/ </listener-class>
</listener>
<!-- Normal JSF settings -->
Lets you give request or session scopes to beans in
<! Normal JSF settings >
</web-app>
24
applicationContext.xml. If you dont use these scopes, this listener is
not required. But you should probably have this entry commented
out in web.xml just in case you want those scopes later.
Color Preferences Bean
public class ColorPreferences implements Serializable {
private String foreground, background; private String foreground, background;
public String getForeground() {
return(foreground);
In Web apps in general, session data
should be Serializable. This is partly to
support distributed apps, but the more
important reason is that Tomcat and other
servers will let session data live across
server restarts if the data is Serializable
}
public void setForeground(String foreground) {
this.foreground = foreground;
server restarts if the data is Serializable.
The foreground and background
properties are tied to the textfields.
}
// getBackground and setBackground
public String getStyle() {
p p
public String getStyle() {
String style =
String.format("color: %s; background-color: %s",
foreground, background); g , g );
return(style);
}
}
25
h:body does not support the bgcolor and text attributes
that the regular body tag has. So, produce a CSS style
string to supply to the style attribute of h:body.
Customer Lookup Service:
Interface Interface
public interface CustomerLookupService {
public Customer findCustomer(String id);
public Customer getRichestCustomer(); public Customer getRichestCustomer();
}
26
Customer Lookup Service:
One Concrete Implementation One Concrete Implementation
public class MapCustomerLookupService
implements CustomerLookupService { p p
private Map<String,Customer> sampleCustomers;
public Map<String,Customer> getSampleCustomers() {
return sampleCustomers; return sampleCustomers;
}
public void setSampleCustomers(Map<String,Customer> sampleCustomers) {
this.sampleCustomers = sampleCustomers;
}}
public Customer findCustomer(String id) {
if (id == null) {
This will be set via
<property name="sampleCustomers">
in applicationContext.xml
id = "unknown";
}
return(sampleCustomers.get(id.toLowerCase()));
}}
public Customer getRichestCustomer() { }
}
27
Customer Bean
public class Customer {
private String customerID firstName lastName; private String customerID, firstName, lastName;
private double balance;
// Simple getters and setters // Simple getters and setters
public String getFormattedBalance() {
t (St i f t("$% 2f" tB l ())) return(String.format("$%,.2f", getBalance()));
}
}
28
Backing Bean: Properties
public class CustomerBackingBean {
private String inputID, password;
Corresponding setters called
by JSF when form submitted.
private String inputID, password;
private Customer customer;
private ColorPreferences colorPreferences;
private CustomerLookupService lookupService;
Filled in by action controller method
(shown on next slide).
// Getters and setters
// for above 5 properties
Setter methods called when bean created
because of managed bean property in // for above 5 properties because of managed-bean-property in
faces-config.xml. The incoming values are
Spring beans.
29
Backing Bean:
Action Controller Method Action Controller Method
public String findBalance() {
customer = lookupService.findCustomer(inputID); p ( p );
FacesContext context =
FacesContext.getCurrentInstance();
if (customer == null) {
S i
Since the form used prependId="false", this is just the id
of the h:inputText element. Otherwise, you would put
"formId:customerId" here.
String message =
String.format("Unknown ID '%s'", inputID);
context.addMessage("customerId", new FacesMessage(message));
} }
if (!password.equals("secret")) {
String message = "Incorrect password";
context.addMessage("password", new FacesMessage(message));
}}
if (context.getMessageList().size() > 0) {
return(null);
} else {
return ("show-balance");
}
}
30
faces-config: Variable Resolver
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE > <!DOCTYPE >
<faces-config>
<application> <application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver> /
</application>
31
faces-config: Backing Bean
<managed-bean>
<managed-bean-name>formBean</managed-bean-name> <managed bean name>formBean</managed bean name>
<managed-bean-class>
coreservlets.CustomerBackingBean
</managed-bean-class> </managed bean class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>lookupService</property-name> p p y p /p p y
<value>#{sampleLookupService}</value>
</managed-property>
<managed-property> g p p y
<property-name>colorPreferences</property-name>
<value>#{colorPreferences}</value>
</managed-property>
Gets the Spring bean called sampleLookupService
and passes it to the setLookupService method of the
JSF backing bean called formBean (i.e., injects it
into the lookupService property).
</managed-bean>
32
into the lookupService property).
Gets the Spring bean called colorPreferences and injects
it into the colorPreferences property of the backing bean.
applicationContext.xml:
Defining Color Preferences Defining Color Preferences
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" p // p g g/ /
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="colorPreferences" class="coreservlets.ColorPreferences"
scope="session">
<property name="foreground" value="black"/> p ope ty a e o eg ou d a ue b ac /
<property name="background" value="#fdf5e6"/>
</bean>
33
applicationContext.xml:
Defining Lookup Service Defining Lookup Service
<bean id="sampleLookupService"
class="coreservlets.MapCustomerLookupService"> p p
<property name="sampleCustomers">
<map>
<entry key="a1234">
<bean class="coreservlets.Customer">
<property name="customerID" value="a1234"/>
<property name="firstName" value="Rod"/>
<property name="lastName" value="Johnson"/> p ope ty a e ast a e a ue Jo so /
<property name="balance" value="123.45"/>
</bean>
</entry>
</map>
</property>
</bean> </bean>
</beans>
34
Input Form: Top
(customer-lookup xhtml) (customer-lookup.xhtml)
<h:form prependId="false">
<label>
Using prependId makes it easier to refer to the input
element ID in the action controller method when setting a
custom error message.
<label>
<font color="red">*</font> Customer ID:
<h:inputText value="#{formBean.inputID}"
required="true" required="true"
requiredMessage="Missing customer ID"
id="customerId"/>
<h message for "c stomerId" st leClass "error"/> <h:message for="customerId" styleClass="error"/>
</label><br/>
35
If no user ID is entered, the form is redisplayed and Missing customer ID is shown. If an
unknown ID is entered, the action controller method sets a custom FacesMessage and
returns null so that the form is redisplayed and Unknown ID is shown. If a recognized ID is
entered, will navigate to page showing name and balance (using preferred colors).
Input Form: Bottom
(customer-lookup xhtml) (customer-lookup.xhtml)
<label>
<font color="red">*</font> Password: /
<h:inputSecret value="#{formBean.password}"
required="true"
requiredMessage="Missing password"
id d / id="password"/>
<h:message for="password" styleClass="error"/>
</label><br/>
<label>
Preferred foreground color:
<h:inputText value="#{formBean.colorPreferences.foreground}"/>
</label><br/>
<l b l> <label>
Preferred background color:
<h:inputText value="#{formBean.colorPreferences.background}"/>
</label><br/>
<h:commandButton value="Show Balance"
action="#{formBean.findBalance}"/>
</h:form>
36
Input Form (Initial Result)
37
Results Page
(show-balance xhtml) (show-balance.xhtml)
...
<h:body style="#{formBean colorPreferences style}"> <h:body style= #{formBean.colorPreferences.style} >
<table border="5" align="center">
<tr><th class="title">Spring Bank: Your Balance</th></tr>
</table> </table>
<p/>
<ul>
<li>ID: #{formBean.customer.customerID}</li> { }
<li>First name: #{formBean.customer.firstName}</li>
<li>Last name: #{formBean.customer.lastName}</li>
<li>Balance: #{formBean.customer.formattedBalance}</li>
</ul>
</h:body></html>
38
Results: Bad Data
39
Results: Good Data
40
2010 Marty Hall
JSF/Spring Example 2: JSF/Spring Example 2:
Beans in One Config File
Customized Java EE Training: http://courses.coreservlets.com/
Servlets, JSP, JSF 2.0, Struts, Ajax, GWT 2.0, Spring, Hibernate, SOAP & RESTful Web Services, Java 6.
Developed and taught by well-known author and developer. At public venues or onsite at your location.
Overview
Issue with previous example
Beans defined in two different files
Some using Spring syntax, some using JSF syntax
Approach Approach
applicationContext.xml
Defines the Spring beans as before g
Defines session-scoped ColorPreferences and
singleton-scoped CustomerLookupService
Also defines the backing bean
faces-config.xml
Defines only non-beans entries
Variable resolver, navigation rules, properties files, etc. Variable resolver, navigation rules, properties files, etc.
Functionality and appearance
Exactly the same as in previous app
42
Changes from Previous
Example Example
faces-config.xml
Deleted the entire <managed-bean> entry
applicationContext.xml
Add d h f ll i i l Added the following simpler entry
<bean id="formBean"
class="coreservlets.CustomerBackingBean" g
scope="request">
<property name="lookupService" ref="sampleLookupService"/>
<property name="colorPreferences" ref="colorPreferences"/> property name colorPreferences ref colorPreferences /
</bean>
Two advantages
D d i j ti t i i l d f l Dependency injection syntax is simpler and more powerful
All bean definitions in the same file
43
faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE > <!DOCTYPE >
<faces-config>
<application> <application>
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver> /
</application>
</faces-config>
44
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans > <beans >
<bean id="colorPreferences" >
<!-- Unchanged from last example -->
</bean>
<bean id="sampleLookupService" >
<!-- Unchanged from last example -->
</bean>
<bean id="formBean"
class="coreservlets.CustomerBackingBean"
scope="request">
<property name="lookupService" ref="sampleLookupService"/> <property name= lookupService ref= sampleLookupService />
<property name="colorPreferences" ref="colorPreferences"/>
</bean>
</beans> /
45
Results: Bad Data
46
Results: Good Data
47
2010 Marty Hall
Wrap-up
Customized Java EE Training: http://courses.coreservlets.com/
Servlets, JSP, JSF 2.0, Struts, Ajax, GWT 2.0, Spring, Hibernate, SOAP & RESTful Web Services, Java 6.
Developed and taught by well-known author and developer. At public venues or onsite at your location.
Summary
Basic setup
Start with same setup as regular JSF apps
Add Spring JAR files and applicationContext.xml
faces config xml faces-config.xml
Declare DelegatingVariableResolver
Option 1 Option 1
Declare Spring beans in applicationContext.xml
Declare backing beans in faces-config.xml g g
Refer to Spring beans with managed-bean-property
Option 2
Declare all beans in applicationContext.xml
Refer to other beans with ref and normal Spring syntax
49
2010 Marty Hall
Questions?
Customized Java EE Training: http://courses.coreservlets.com/
Servlets, JSP, JSF 2.0, Struts, Ajax, GWT 2.0, Spring, Hibernate, SOAP & RESTful Web Services, Java 6.
Developed and taught by well-known author and developer. At public venues or onsite at your location.