Thursday, December 7, 2017

JSF (2.X+) + Spring 4 (3.X+) Integration

Here we discover the simplest solution for JSF and Spring integration. All required details configurations with full source are available in here. We use very simple configuration. Environment details are listed below:

Environment:

1. Maven Project: maven-archetype-webapp

2. JSF 2.2 and Spring 4 [All details are in pom.xml]

3. Dynamic Web Module: 3.0

4. JSF configuration just in web.xml [see in the repository]

5. All Spring related configurations are done in class WebAppInitializer.java. And bean  is configured on SpringConfig.java which also configures the component-scan package. 

package com.component.config;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration.Dynamic;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.request.RequestContextListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class WebAppInitializer  implements WebApplicationInitializer{

@Override
public void onStartup(ServletContext servletContext)
throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();  
        ctx.register(SpringConfig.class);  
        ctx.setServletContext(servletContext);    
        servletContext.addListener(new ContextLoaderListener(ctx));
        servletContext.addListener(new RequestContextListener());
        Dynamic dynamic = servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));  
        dynamic.addMapping("/");  
        dynamic.setLoadOnStartup(1);
}

}


package com.component.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.component.dao.UserManagementDao;
import com.component.dao.UserManagementDaoImpl;
import com.service.StudentService;
import com.service.StudentServiceImpl;

@Configuration
@ComponentScan("com.component")
public class SpringConfig {
@Bean
public StudentService studentService() {
return new StudentServiceImpl();
}
}

Bean classes are very simple POJO.

package com.service;

public interface StudentService {
String getStudent(Integer id);
}

package com.service;

import java.util.HashMap;
import java.util.Map;

public class StudentServiceImpl implements StudentService {

Map<Integer, String> map = new HashMap<Integer, String>();
{
map.put(1, "Ashik");
map.put(2, "Ibraim Khan");
map.put(3, "Muhammad Ashik Ali Khan");
}
@Override
public String getStudent(Integer id) {
return map.get(id);
}
}


6. For Spring Addition Just add the following entry in faces-config.xml. 

<application>
   <el-resolver>
        org.springframework.web.jsf.el.SpringBeanFacesELResolver
   </el-resolver>

</application>

7. JSF managed beans are under component-scan package [com.component].

8. All JSF pages [*.xhtml] loads text (both regular and parameterized) from messages.properties created under package com.jsf.properties in resources [src/main/resource] folder.


header=Welcome to JSF framework integration with Spring framework

greeting_text=Welcome to JSF Framework
project_type=JSF integration with Spring
greeting_custom=Welcome to {0} for our framework
index_command=Type Name and Click
std_id=Enter Student Id:
std_name=Student Name: {0}
usr_id=Enter User Id:
usr_name=User Name: {0}

9. Java: SE 7

10. Application Server: JBOSS EAP 6.3

11. Eclipse Luna (4.4.0) or above.


Project File Structure:



















Now, we create a very simple JSF page (student.xhtml) under webapp folder.

Here,

student.xhtml --> Input : ID [Integer] --> Managed Bean: StudentBean.java

result.xhtml--> Output: Name [String] --> Managed Bean: StudentBean.java

So, StudentBean.java [JSF managed bean] is very important. It is under hierarchy of component-scan package [com.component]. It links the bean StudentService by @Autowired annotation and declare it as a component i.e. @Component of spring framework.

1. It [StudentBean.java] takes the value of ID from JSF [student.xhtml],

2. passes the value to spring bean [StudentService] to retrieve the student name.

3. sets the value to bean property i.e. name. And continues the page to another with that value.

Now take a look of StudentBean.java.

package com.component.bean;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.service.StudentService;

@ManagedBean(name="studentBean")
@RequestScoped
@Component
public class StudentBean {
@Autowired
public StudentService studentService;
private String name;
private Integer id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String showResult(){
name = studentService.getStudent(id);
return "result";
}
}

Moreover, Two JSF pages (student.xhtml & result.xhtml) are shown below.

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html  xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jsf/composite"
    xmlns:fac="http://java.sun.com/jsf/facelets">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>JSF 2 + Spring 4 Integration</title>
<f:loadBundle var="mymsg" basename="com.jsf.properties.messages"/>
</head>
<body>
<h:form>
<h:outputText value="#{mymsg.std_id}"/>
<h:inputText value="#{studentBean.id}"/>
<h:commandButton value="Show Name" action="#{studentBean.showResult}"/>
</h:form>
</body>
</html>

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html  xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:c="http://java.sun.com/jsf/composite"
    xmlns:fac="http://java.sun.com/jsf/facelets">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>JSF 2 + Spring 4 Integration</title>
<f:loadBundle var="mymsg" basename="com.jsf.properties.messages"/>
</head>
<body>
<h3>
<h:outputFormat value="#{mymsg.std_name}">
<f:param value="#{studentBean.name}"/>
</h:outputFormat> 
</h3>
</body>
</html>

 Sample Input:







Sample Output:






N.B.: This is not research but only discover of framework. Feel free to contact if any problem occurs to test this example.

Monday, September 25, 2017

Spring MVC – @RequestMapping

Let's start with a simple example - mapping HTTP request to method using some basic criteria.

1. @RequestMapping – by Path 


@RequestMapping(value = "/ex/greetings", method = RequestMethod.GET)
    @ResponseBody
    public String getGreetingsBySimplePath() {
        return "Get Greetings";
    }

 To test out this mapping with a simple curl command, run:


curl -i http://localhost:7001/springapp/ex/greetings

2. @RequestMapping – the HTTP Method

 

Previous example was based on HTTP GET method. Now mapped to HTTP POST method.


@RequestMapping(value = "/ex/greetings", method = RequestMethod.POST)
    @ResponseBody
    public String postGreetings() {
        return "Post Greetings";
    }

To test the POST via a curl command:


curl  -i  -X  POST  http://localhost:7001/springapp/ex/greetings

3. @RequestMapping and HTTP Headers


The mapping can be narrowed even further by specifying a header for the request:

@RequestMapping(value = "/ex/greetings", headers = "key=val", method = RequestMethod.GET)
    @ResponseBody
    public String getGreetingsWithHeader() {
        return "Get Greetings with some header";
    }

To test this via a curl command:


curl -i -H "key:val" "http://localhost:7001/springapp/ex/greetings"

For multiple headers via the header attribute of @RequestMapping:

@RequestMapping(value = "/ex/greetings", headers = { "key1=val1",
            "key2=val2" }, method = RequestMethod.GET)
    @ResponseBody
    public String getGreetingsWithMultipleHeader() {
        return "Get Greetings with multiple header";
    }

To test this via a curl command:


curl -i -H "key1:val1" -H "key2:val2" "http://localhost:7001/springapp/ex/greetings"

4. @RequestMapping Consumes and Produces


@RequestMapping annotation now has the produces and the consumes attributes, specifically for request based on Accept header.

@RequestMapping(value = "/ex/greetings", method = RequestMethod.GET, produces = "application/json")
    @ResponseBody
    public String getGreetingsAsJsonFromREST() {
        return "Get Greetings with header from REST";
    }

To test this via a curl command:


curl -i -H "Accept:application/json"  "http://localhost:7001/springapp/ex/greetings"

5. @RequestMapping with Path Variables


Parts of the mapping URI can be bound to variables via the @PathVariable annotation. A simple example with a single path variable:


@RequestMapping(value = "/ex/greetings/{greetingsId}/locations/{locationId}", method = RequestMethod.GET)
    @ResponseBody
    public String getGreetingsBySimplePathVariable(
            @PathVariable String greetingsId, @PathVariable String locationId) {
        return "Get Greetings with id=" + greetingsId + " and location="+locationId;
    }

To test this via a curl command:


curl "http://localhost:7001/springapp/ex/greetings/1/locations/Motijheel"

6. @RequestMapping with Request Parameters


We are now mapping a request to a URI such as:  http://localhost:7001/springapp/ex/location?id=w

@RequestMapping(value = "/ex/location", method = RequestMethod.GET)
    @ResponseBody
    public String getLocationBySimplePathWithRequestParam(
            @RequestParam("id") String id) {
        return "Get specific location with id = " + id;
    }

For more advanced scenarios, @RequestMapping can optionally define the parameters – as yet another way of narrowing the request mapping:

@RequestMapping(value = "/ex/location", params = "id", method = RequestMethod.GET)
    @ResponseBody
    public String getLocationBySimplePathWithExplicitRequestParam(
            @RequestParam("id") String id) {
        return "Get specific location params with id = " + id;
    }

Even more flexible mappings are allowed – multiple params values can be set to another URL, and not all of them have to be used:

@RequestMapping(value = "/ex/location", params = { "id", "name" }, method = RequestMethod.POST)
    @ResponseBody
    public String getLocationBySimplePathWithExplicitMultipleRequestParam(
            @RequestParam("id") String id) {
        return "Get specific location with multiple params with id = " + id;
    }

To test this via a curl command:


curl  "http://localhost:7001/springapp/ex/location?id=w&name=DHAKA

7. @RequestMapping – a fallback for all requests

 

For all requests:

@RequestMapping(value = "*", method = { RequestMethod.GET,
            RequestMethod.POST })
    @ResponseBody
    public String fallbackMessage() {
        return "Fallback Request";
    }

8. @RequestMapping – multiple paths mapped to the same controller method

 

Multiple requests using different HTTP verbs can be mapped to the same controller method:

@RequestMapping(value = { "/m0", "/m1", "/m2" })
    @ResponseBody
    public String method0() {
        System.out.println(messages.get("method0"));
        return "method0";
    }