Posts Tagged ‘spring4


Spring 4 JAX-RS based Rest Web Service

This page shows how to integrate a JAX-RS based application with the spring framework so you can use your spring managed beans in your JAX-RS resources. We will use an existing application described in my previous blog post. The App will use pure JAX-RS annotations with very little proprietary spring configuration.


JAX-RS resources often times need to work with Spring managed beans. However it is not very well documented on how to make the spring context available to the JAX-RS stack. Improper techniques will result in a NullPointerException while trying to use a spring managed bean.

Full downloadable source for this page is available here. Corrections and enhancements are welcome, fork, change and push back to GitHub.

This page covers the following software stack.

  • Java 8
  • Spring 4
  • JPA 2
  • JSF 2.1
  • JAX-RS 2
  • JAVA EE 6 level containers like JBoss EAP 6.4

Existing Application

We will use an existing application created in my previous blog article as a baseline. Please check it out for more details. The source for that application is available in the git repository for this page. So please download it now and follow along.

The first thing is to create a class that implements the This class will be automatically picked up by the Servlet 3.0 container on initialization. It will start serving resources at the path specified in the @ApplicationPath annotation. This class is similar to the Servlets that listen to the RESTful requests. Only difference is that this is implementation agnostic.

vi src/main/java/com/test/

package com.test;


public class WarehouseApplication extends Application {}

Integrating the JAX-RS application with the spring framework

In order to get the spring managed beans into the Resources we will create a SpringContext singleton that has access to the spring application context. Each resource will use it to get references to the beans they are interested in. This is not 100% true dependency injection since the resources need to get references to the beans but after a comprehensive search this is the best method I found.

vi src/main/java/com/test/

package com.test;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

public class SpringContext implements ApplicationContextAware {

	private static ApplicationContext appContext;

    private SpringContext() {}
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		appContext = applicationContext;
	public static Object getBean(String beanName) {
		return appContext.getBean(beanName);

The following resource wich is a CDI managed bean will use the SpringContext singleton to get references to the spring managed beans in the @PostConstruct method.

vi src/main/java/com/test/

package com.test;

import java.util.List;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;

import com.test.model.Company;
import com.test.model.CompanyDataManager;

public class CompanyResource {
	private static final Logger logger = LoggerFactory.getLogger(CompanyResource.class);

	private CompanyDataManager companyDataManager;

	public void postConstruct() {
		companyDataManager = (CompanyDataManager) SpringContext.getBean("companyDataManager");
	public Company getCompany(@PathParam("id")  Long id) {
		return companyDataManager.getCompany(id);

	public Company create() {
		return companyDataManager.create();
	public List<Company> getAll() {
		return companyDataManager.getAll();

	public Company update(Company selectedCompany) {
		return companyDataManager.update(selectedCompany);

	public void delete(@PathParam("id")  Long id) {


Since its a CDI managed bean take this time to create a blank beans.xml file in the WEB-INF directory.

Restart the application and you should be able to access the following URLs:

This shows all the companies in JSON format:

Use google Postman or other tools to make POST,PUT,DELETE requests to call the CompanyResource.

A fully working example is available at the github location listed in the beginning of this page.


HTML 5 Responsive AJAX based CRUD application using Spring 4, JPA 2, JSF 2

This page shows how to create a transactional AJAX based HTML 5 responsive CRUD application to manage a company addressbook. In addition we will using annotations wherever possible. For ease of use we will use a HSQLDB in memory database that will automatically create a directory called data in your userid’s home directory.

Full downloadable source for this page is available here. Corrections and enhancements are welcome, fork, change and push back to GitHub.


  • Java 8
  • Spring 4
  • JPA 2
  • JSF 2.1
  • JAVA EE 6 level containers like JBoss EAP 6.4 or Tomcat 7

Create the pom.xml

First step is to create a pom.xml file. If you are using Tomcat 7 then enable the Glassfish dependency. Since Tomcat is only a servlet engine you will need implementation classes that don’t exist in Tomcat but are provided by other more beefy web application servers.

vi pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="" xmlns:xsi=""
		<pluginRepository> <!-- Ignore this repository. Its only used for document publication. -->
	<!-- It is possible to accidentally mix different versions of Spring JARs 
		when using Maven. For example, you may find that a third-party library, or 
		another Spring project, pulls in a transitive dependency to an older release. 
		If you forget to explicitly declare a direct dependency yourself, all sorts 
		of unexpected issues can arise. To overcome such problems Maven supports 
		the concept of a "bill of materials" (BOM) dependency. You can import the 
		spring-framework-bom in your dependencyManagement section to ensure that 
		all spring dependencies (both direct and transitive) are at the same version. 
		An added benefit of using the BOM is that you no longer need to specify the 
		<version> attribute when depending on Spring Framework artifacts -->

			<name>PrimeFaces Maven Repository</name>
<!-- Logging -->
<!-- Data Management -->
<!-- Spring Framework -->
<!-- JSF -->
		<!-- If running this in a Servlet only container like Tomcat 7 enable this dependency 
<!-- APIs for services provided by the containers -->		
			<plugin> <!-- Ignore this plugin. Its only used for document publication. -->

Web Application Initialization

This app depends on the Servlet 3.0 specification. The spec requires web application containers to search the classpath looking for Initializers. Classes that implement the the spring “WebApplicationInitializer” are the ones that will be picked up.

vi src/main/java/com/test/

package com.test;  
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.request.RequestContextListener;

 * The Servlet 3 containers automatically search the classpath for classes that
 * implement the below interface and call the onStartup() method on initialization.
public class WebAppInitializer implements WebApplicationInitializer {  
    public void onStartup(ServletContext servletContext) throws ServletException {  
    	// Initialize the spring framework.
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();  
        servletContext.addListener(new ContextLoaderListener(ctx));
        // required to get spring beans injected into JSF managed beans
        servletContext.addListener(new RequestContextListener());
        // initialize faces (not working...)
//        servletContext.setInitParameter("primefaces.THEME", "bootstrap");
//        servletContext.setInitParameter("javax.faces.DEFAULT_SUFFIX", ".xhtml");
//        ServletRegistration.Dynamic faces = servletContext.addServlet("Faces Servlet", "javax.faces.webapp.FacesServlet");
//        faces.setLoadOnStartup(1);
//        faces.addMapping("*.xhtml");

Spring Configuration (No XML)

vi src/main/java/com/test/

package com.test;  
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.faces.context.FacesContext;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;

import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.CustomScopeConfigurer;
import org.springframework.beans.factory.config.Scope;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;  

 * This class replaces the spring xml configuration.
public class SpringConfig {
	public DataSource getDataSource() {
		DriverManagerDataSource dm = new DriverManagerDataSource();
		dm.setUrl("jdbc:hsqldb:file:"+System.getProperty("user.home") + "/data/JSFJPASpringCRUD"+";shutdown=true");
		return dm;
//	@Bean
//	public DataSource getDataSource() {
//		DriverManagerDataSource dm = new DriverManagerDataSource();
//		dm.setDriverClassName("com.mysql.jdbc.Driver");
//		// change the "/tmp" to be another location on your system.
//		dm.setUrl("jdbc:mysql://localhost:3306/xxxx");
//		dm.setUsername("xxxx");
//		dm.setPassword("xxxx");
//		return dm;
//	}
	public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
		em.setPackagesToScan(new String[] { "com.test.model" });
		JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
		return em;

	public PlatformTransactionManager transactionManager(EntityManagerFactory emf) {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		return transactionManager;

	public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
		return new PersistenceExceptionTranslationPostProcessor();

	Properties additionalProperties() {
		Properties properties = new Properties();
		properties.setProperty("hibernate.dialect", "org.hibernate.dialect.HSQLDialect");
//		properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5InnoDBDialect");
		properties.setProperty("hibernate.flushMode", "FLUSH_AUTO");
		properties.setProperty("", "update");
		properties.setProperty("hibernate.show_sql", "false");
		return properties;

	public CustomScopeConfigurer customScope () {
	    CustomScopeConfigurer configurer = new CustomScopeConfigurer ();
	    Map<String, Object> viewScope = new HashMap<String, Object>();
	    viewScope.put("view", new ViewScope());

	    return configurer;
	class ViewScope implements Scope {
	    public Object get(String name, @SuppressWarnings("rawtypes") ObjectFactory objectFactory) {
	        Map<String,Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap();
	        if(viewMap.containsKey(name)) {
	            return viewMap.get(name);
	        } else {
	            Object object = objectFactory.getObject();
	            viewMap.put(name, object);
	            return object;
	    public Object remove(String name) {
	        return FacesContext.getCurrentInstance().getViewRoot().getViewMap().remove(name);
	    public String getConversationId() {
	        return null;
	    public void registerDestructionCallback(String name, Runnable callback) {
	        //Not supported
	    public Object resolveContextualObject(String key) {
	        return null;

Logging configuration

vi src/main/resources/log4j.xml

<!DOCTYPE log4j:configuration PUBLIC
  "-//APACHE//DTD LOG4J 1.2//EN" "">
<log4j:configuration xmlns:log4j="">
	<appender name="file" class="org.apache.log4j.FileAppender">
	   <param name="maxFileSize" value="1024KB" />
	   <param name="file" value="${user.home}/logs/JSFJPASpringCRUDBasic.log" />
	   <layout class="org.apache.log4j.PatternLayout">
		<param name="ConversionPattern" 
			value="%d %-5p %c:%L - %m%n" />
    <logger name="com.test">
        <level value="DEBUG"/>
    <logger name="com.springframework">
        <level value="INFO"/>
    <logger name="org.hibernate.SQL">
        <level value="DEBUG"/>
        <level value="ERROR"/>
        <appender-ref ref="file"/>

Data Managers and Entities

Used by JPA to define and interact with the database.

vi src/main/java/com/test/model/

package com.test.model;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

public class Company {
	private Long id;
	private String name;
	private String shipToAddress;
	private String shipToAddress2;
	private String shipToCity;
	private String shipToProvence;
	private String shipToZip;
	private String coSignAddress;
	private String coSignAddress2;
	private String coSignCity;
	private String coSignZip;
	private String coSignCountry;

	public Long getId() {
		return id;
	public void setId(Long id) { = id;
	public String getName() {
		return name;
	public void setName(String name) { = name;
	public String getShipToAddress() {
		return shipToAddress;
	public void setShipToAddress(String shipToAddress) {
		this.shipToAddress = shipToAddress;
	public String getShipToAddress2() {
		return shipToAddress2;
	public void setShipToAddress2(String shipToAddress2) {
		this.shipToAddress2 = shipToAddress2;
	public String getShipToCity() {
		return shipToCity;
	public void setShipToCity(String shipToCity) {
		this.shipToCity = shipToCity;
	public String getShipToProvence() {
		return shipToProvence;
	public void setShipToProvence(String shipToProvence) {
		this.shipToProvence = shipToProvence;
	public String getShipToZip() {
		return shipToZip;
	public void setShipToZip(String shipToZip) {
		this.shipToZip = shipToZip;
	public String getCoSignAddress() {
		return coSignAddress;
	public void setCoSignAddress(String coSignAddress) {
		this.coSignAddress = coSignAddress;
	public String getCoSignAddress2() {
		return coSignAddress2;
	public void setCoSignAddress2(String coSignAddress2) {
		this.coSignAddress2 = coSignAddress2;
	public String getCoSignCity() {
		return coSignCity;
	public void setCoSignCity(String coSignCity) {
		this.coSignCity = coSignCity;
	public String getCoSignZip() {
		return coSignZip;
	public void setCoSignZip(String coSignZip) {
		this.coSignZip = coSignZip;
	public String getCoSignCountry() {
		return coSignCountry;
	public void setCoSignCountry(String coSignCountry) {
		this.coSignCountry = coSignCountry;

Spring DataManager Interface.

vi src/main/java/com/test/model/

package com.test.model;

import java.util.List;

public interface CompanyDataManager {
	// C
	Company create(Company selectedCompany);
	// R
	List<Company> getAll();
	// U
	Company update(Company selectedCompany);
	// D
	void delete(Company selectedCompany);

Spring DataManager Implementation

vi src/main/java/com/test/model/

package com.test.model;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.springframework.stereotype.Component;

public class CompanyDataManagerImpl implements CompanyDataManager {
	private EntityManager em;

	public List<Company> getAll() {
		return em.createQuery("SELECT c FROM Company c", Company.class).getResultList();

	public Company update(Company selectedCompany) {
		Company mergedCompany = em.merge(selectedCompany);
		return mergedCompany;

	public void delete(Company selectedCompany) {
		em.remove(em.contains(selectedCompany) ? selectedCompany : em.merge(selectedCompany));
	public Company create(Company selectedCompany) {
		return selectedCompany;

JSF Page and the JSF Managed Bean

The managed bean hold user entered data. This particular bean is in the View Scope. This ia scope between request and session. It stays active as long as the uesr is on the page. We could not use the Request Scope for this because the page makes AJAX call in the background.

vi src/main/java/com/test/

package com.test;

import java.util.List;
import java.util.Random;

import javax.faces.bean.ManagedBean;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import com.test.model.Company;
import com.test.model.CompanyDataManager;


 * The following is a JSF Managed Bean that is actually managed by Spring.

@Scope(value="view") // you can not use JSF Scoped values here since its a spring managed bean
@ManagedBean	// use this to indicate that its a JSF Bean (managed by spring)
public class CompanyMB {

	private static final Logger logger = LoggerFactory.getLogger(CompanyMB.class);

	private CompanyDataManager companyDataManager;
	private Company selectedCompany;
	private List<Company> all;
	private Boolean addState = false;
	public List<Company> getAll() { // getters should NEVER implement DB fetch logic.
		if(all==null) loadAll();
		return all;

	 * This method will be called by the page during preRenderView. Example:
	 * <f:event type="preRenderView" listener="#{companyMB.loadAll}"/>
	public void loadAll() {"getting All");
		if(companyDataManager==null) throw new NullPointerException("dataManager is null");
		all = companyDataManager.getAll();

	public CompanyDataManager getCompanyDataManager() {
		return companyDataManager;

	public Company getSelectedCompany() {
		return selectedCompany;

	public void setSelectedCompany(Company selectedCompany) {
		this.selectedCompany = selectedCompany;
	private int countLines(InputStream file) {
		if(file==null) throw new NullPointerException("file stream should not be null.");
		int lines = 0;
		try (BufferedReader reader = new BufferedReader(new InputStreamReader(file))) {
			while (reader.readLine() != null) lines++;
		} catch (Exception e) {
			throw new RuntimeException(e);
		return lines;
	public void newCompany() {
		Company c = getRandomCompany();
		selectedCompany = companyDataManager.create(c);
		addState = true;

	private Company getRandomCompany() {
		final String DUMMY_COMPANY_LIST_CSV = "/dummyCompanyList.csv";

		Company c = new Company();
		InputStream is = getClass().getResourceAsStream(DUMMY_COMPANY_LIST_CSV);
		if(is==null) return c;
		int lines = countLines(is);
		int randomLine = new Random().nextInt(lines - 2) + 1;
		int index = 0;
		is = getClass().getResourceAsStream(DUMMY_COMPANY_LIST_CSV);
		try (CSVReader reader = new CSVReader(new InputStreamReader(is))) {
			String[] nextLine = null;
			while((nextLine=reader.readNext()) != null) {
				if(index >= randomLine) {
		} catch (Exception ex) {
			throw new RuntimeException("unable to read random address CSV file.", ex);
		return c;
	public void updateSelectedCompany() {
		logger.debug("update Selected Company called.");
	public void deleteSelectedCompany() {
		logger.debug("delete Selected Company called.");
	public void cancel() {
		if(addState) {

This is the only UI page the users will see. Single page HTML5 applications use javascript to show dialogs and submit requests in the background.

vi src/main/webapp/company.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html>
<html xmlns=""
	<title>Acme Distribution</title>
		<b:navBar brand="Acme Wholesale Distributor" brandHref="#"
				<b:dropMenu value="Home" href="index.xhtml">
					<b:navLink value="Companies" href="company.xhtml"></b:navLink>

		<b:panel title="Company Address List" look="primary">

			<h:form id="form">
				<p:dataTable id="companyDt" var="company" value="#{companyMB.all}">
					<f:event type="preRenderView" listener="#{companyMB.loadAll}" />
					<p:column headerText="Name">
						<h:outputText value="#{}" />

					<p:column headerText="Address" priority="2">
						<h:outputText value="#{company.shipToAddress}" />
					<p:column headerText="City" priority="3" width="160">
						<h:outputText value="#{company.shipToCity}" />
					<p:column headerText="State" priority="4" width="160">
						<h:outputText value="#{company.shipToProvence}" />
					<p:column headerText="Zip" priority="5" width="80">
						<h:outputText value="#{company.shipToZip}" />
					<p:column width="55">
						<f:facet name="header">
						<p:commandButton action="#{companyMB.newCompany}" update=":form:companyDetail"
							oncomplete="PF('companyDialog').show()" icon="ui-icon-plusthick"
						<p:commandButton update=":form:companyDetail"
							oncomplete="PF('companyDialog').show()" icon="ui-icon-search"
							<f:setPropertyActionListener value="#{company}"
								target="#{companyMB.selectedCompany}" />

				<!-- AJAX like Pop-up Dialog -->
				<p:dialog header="Company Info" widgetVar="companyDialog"
					modal="true" showEffect="fade" hideEffect="fade" resizable="false" closable="false" >
					<p:outputPanel id="companyDetail" style="text-align:center;">
						<p:panelGrid columns="2"
							rendered="#{not empty companyMB.selectedCompany}"
							<h:outputText value="Id:" />
							<h:outputText value="#{}" />
							<h:outputText value="Name" />
							<h:inputText value="#{}" />
							<h:outputText value="Address 1:" />
							<h:inputText value="#{companyMB.selectedCompany.shipToAddress}" />
							<h:outputText value="City:" />
							<h:inputText value="#{companyMB.selectedCompany.shipToCity}" />
							<h:outputText value="State:" />
							<h:inputText value="#{companyMB.selectedCompany.shipToProvence}" />
							<h:outputText value="Zip:" />
							<h:inputText value="#{companyMB.selectedCompany.shipToZip}" />
						<!-- Save Button -->
						<p:commandButton update="companyDt" 
							action="#{companyMB.updateSelectedCompany}" value="Save"
							oncomplete="PF('companyDialog').hide()" icon="ui-icon-disk" />
						<!-- Delete Button -->
						<p:commandButton update="companyDt"
							action="#{companyMB.deleteSelectedCompany}" value="Delete"
							oncomplete="PF('companyDialog').hide()" icon="ui-icon-trash" />
						<p:commandButton action="#{companyMB.cancel}" update="companyDt" value="Cancel"
							icon="ui-icon-arrowreturn-1-w" />
		 <span class="subitem">Responsive</span>
                        <span class="defaultText dispTable">
        DataTable has two responsive modes. In priority mode, visibility of columns are toggled based on the screen size and their priority (1-6). On the other hand
        in reflow mode, columns are displayed as stacked on smaller screens.

Sample Data (optional)

You can find the file under src/main/resources in the github repository for this page.

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 77 other followers

November 2017
« Oct    

Blog Stats

  • 842,358 hits