Posts Tagged ‘jax-ws2

01
Mar
16

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.

Background

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
  • HSQLDB
  • 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 javax.ws.rs.core.Application. 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/WarehouseApplication.java

package com.test;

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("/services")
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/SpringContext.java

package com.test;

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

@Component
public class SpringContext implements ApplicationContextAware {

	private static ApplicationContext appContext;

    private SpringContext() {}
    
	@Override
	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/CompanyResource.java

package com.test;

import java.util.List;

import javax.annotation.PostConstruct;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;

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

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

@Path("companies")
@Produces("application/json")
public class CompanyResource {
	private static final Logger logger = LoggerFactory.getLogger(CompanyResource.class);

	private CompanyDataManager companyDataManager;

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

	@POST
	@Transactional
	public Company create() {
		return companyDataManager.create();
	}
	
	@GET
	public List<Company> getAll() {
		return companyDataManager.getAll();
	}

	@PUT
	@Transactional
	public Company update(Company selectedCompany) {
		return companyDataManager.update(selectedCompany);
	}

	@DELETE
	@Path("{id}")
	@Transactional
	public void delete(@PathParam("id")  Long id) {
		companyDataManager.deleteById(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:
http://localhost:8080/JSFJPASpringCRUDBasic/services/companies

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.

Advertisements



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

Join 77 other followers

November 2017
S M T W T F S
« Oct    
 1234
567891011
12131415161718
19202122232425
2627282930  

Blog Stats

  • 842,358 hits