Chapter 7. Integrating with Other Web Frameworks

The flexibility offered by Spring Framework to pick third-party products is one of the core value propositions of Spring and Spring supports integration with third-party presentation frameworks. While Spring's presentation layer framework—Spring MVC, brings the maximum extent of flexibility and efficiency to the development of web applications, Spring lets you integrate most popular presentation frameworks.

Spring can be integrated with far too many of Java's web frameworks to be included in this chapter, and only the most popular ones, JSF and Struts, will be explained.

Spring's JSF integration

A JSF web application can be easily integrated with Spring by loading a Spring context file within web.xml (through a context loader listener). Since JSF 1.2, Spring's SpringBeanFacesELResolver object reads Spring beans as JSF managed beans. JSF only deals with the presentation tier and has a controller named FacesServlet. All we need to do is register FacesServlet in the application deployment descriptor or web.xml (in this section, we use JavaConfig to register it) and map any request with the desired extension (.xhtml here) to go through FacesServlet.

First, we should include the JSF API and its implementation in the project dependencies:

<properties>
  <spring-framework-version>4.1.6.RELEASE</spring-framework-version>
  <mojarra-version>2.2.12</mojarra-version>
</properties>
  ...
<dependency>
  <groupId>com.sun.faces</groupId>
  <artifactId>jsf-api</artifactId>
  <version>${mojarra-version}</version>
</dependency>
<dependency>
  <groupId>com.sun.faces</groupId>
  <artifactId>jsf-impl</artifactId>
  <version>${mojarra-version}</version>
</dependency>
...

The dispatcher Servlet initializer is the location to register FacesServlet. Notice that we set a mapping request to FacesServlet here. Since we use JavaConfig to register settings, we register FacesServlet in the AnnotationConfigDispchServletInit class, as follows:

@Configuration
@Order(2)
public class AnnotationConfigDispchServletInit extends AbstractAnnotationConfigDispatcherServletInitializer {
  @Override
  protected Class<?>[] getRootConfigClasses() {
    return new Class<?>[] { AppConfig.class };
  }
  @Override
  protected Class<?>[] getServletConfigClasses() {
    return null;
  }
  @Override
  protected String[] getServletMappings() {
    return new String[] { "*.xhtml" };
  }
  @Override
  protected Filter[] getServletFilters() {
    return new Filter[] { new CharacterEncodingFilter() };
  }
  @Override
  public void onStartup(ServletContext servletContext) throws ServletException {
    // Use JSF view templates saved as *.xhtml, for use with // Facelets
    servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
    // Enable special Facelets debug output during development
    servletContext.setInitParameter("javax.faces.PROJECT_STAGE", "Development");
    // Causes Facelets to refresh templates during development
    servletContext.setInitParameter("javax.faces.FACELETS_REFRESH_PERIOD", "1");
    servletContext.setInitParameter("facelets.DEVELOPMENT", "true");
    servletContext.setInitParameter("javax.faces.STATE_SAVING_METHOD", "server");
    servletContext.setInitParameter(
      "javax.faces.PARTIAL_STATE_SAVING_METHOD", "true");
      servletContext.addListener(com.sun.faces.config.ConfigureListener.class);
    ServletRegistration.Dynamic facesServlet = servletContext.addServlet("Faces Servlet", FacesServlet.class);
    facesServlet.setLoadOnStartup(1);
    facesServlet.addMapping("*.xhtml");
    // Let the DispatcherServlet be registered
    super.onStartup(servletContext);
  }
}

Note

We must set FacesServlet to start up on load prior to the others (notice facesServlet.setLoadOnStartup).

Another important setting is configuring the listener to read the faces-config XML file. By default, it looks for faces-config.xml under the WEB-INF folder. By setting org.springframework.web.jsf.el.SpringBeanFacesELResolver as ELResolver, we access Spring POJOs as JSF beans. By registering DelegatingPhaseListenerMulticaster, any Spring's bean that implements the PhaseListener interface, JSF's phase events will be broadcasted to corresponding implemented methods of PhaseListener in the Spring's bean.

Here is the faces-config.xml file:

<?xml version="1.0" encoding="UTF-8"?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
version="2.2">
  <application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
  </application>
  <lifecycle>
    <phase-listener>org.springframework.web.jsf.DelegatingPhaseListenerMulticaster</phase-listener>
  </lifecycle>
</faces-config>

In JSF, we can define beans with a session, request, or application scope and the bean values retained within the specific scope. Setting the eager flag to false implies lazy initialization, which creates beans when the first request arrives, whereas true implies creating the beans on startup. The code for the OrderBean class is:

@ManagedBean(name = "orderBean", eager = true)
@RequestScoped
@Component
public class OrderBean {
  private String orderName;
  private Integer orderId;

  @Autowired
  public OrderServiceorder Service;
  public String placeAnOrder(){
    orderName=orderService.placeAnOrder(orderId);
    return "confirmation";
  }
  
  public String getOrderName() {
    return orderName;
  }
  public void setOrderName(String orderName) {
    this.orderName = orderName;
  }
  public Integer getOrderId() {
    return orderId;
  }
  public void setOrderId(Integer orderId) {
    this.orderId = orderId;
  }

}

Also, these beans are available in the presentation layer to interact with the backend. On the first screen (order.xhtml), we call the bean's method (placeAnOrder):

<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
  <h:body>
  <h3>input: JSF 2 and Spring Integration</h3>
    <h:form id="orderForm">
      <h:outputLabel value="Enter order id:" />
      <h:inputText value="#{orderBean.orderId}" /> <br/>
      <h:commandButton value="Submit" action="#{orderBean.placeAnOrder}"/>
    </h:form>
  </h:body>
</html>

The method returns a confirmation as a string and specify navigation in the action attribute means the next page is confirmation.xhtml, which looks like this:

<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html">
  <h:body>
  <h3>Confirmation of an order</h3>
  Product Name: #{orderBean.orderName}
  </h:body>
</html>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset