12
Jun

Development and testing of Java REST web-services

Posted by eugene as Web Services

Introduction

In order to develop REST web services, Java provides a JSR-311 – JAX-RS: The Java ™ API for RESTful Web Services. As it usually happens in the world of Enterprise Java there are several implementations of this specification:

  • Jersey is the reference implementation of the specification from Sun Oracle
  • Apache CXF
  • JBoss RESTEasy

In the latest example of implementation I’ll show you how to write the REST-service.

Let’s write the REST-service

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
 
@Path("/service/entity")
@Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
public interface EntityRestService {
    @GET
    @Path("/all")
    EntityList listAll();
 
    @GET
    @Path("/{id}")
    Entity findById(@PathParam("id") Integer id);
}

Let’s create an interface where we arrange the JAX-RS annotations.

  • The @Path annotation specifies the path that will be available to our service.
  • The @GET annotation specifies which HTTP-request will be processed by this method.
  • The @Produces annotation allows to specify the format in which the service provides the results.

Configuring JBoss RESTEasy

Configuration is very simple. At first, we need to update pom.xml and add the necessary dependencies:

Updating pom.xml
Add the compile-time dependency on JAX-RS API

org.jboss.resteasy
jaxrs-api

and runtime depending on the implementation

org.jboss.resteasy
resteasy-jaxrs
${resteasy-jaxrs.version}
runtime
 
org.jboss.resteasy
resteasy-jackson-provider
${resteasy-jaxrs.version}
runtime

Modify web.xml as follows

org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrap
 
resteasy.servlet.mapping.prefix
/rest
 
REST Easy
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
 
REST Easy
/rest/*

This code declares the HttpServletDispatcher servlet which will handle all the requests that come in the / rest / *. Listener ResteasyBootstrap performs all necessary initialization JBoss RESTEasy.

Support for SpringIn order to use the Spring Framework, we need to make the following changes: 1. Add a dependency in pom.xml

org.jboss.resteasy
resteasy-spring
${resteasy-jaxrs.version}
runtime

2. Add Spring-a marketing student to web.xml

org.jboss.resteasy.plugins.spring.SpringContextLoaderListener

Following these changes, JBoss RESTEasy will be aware of Spring, this will allow the implementation of REST-full services to use all the opportunities provided by Spring Framework.

Writing tests

Writing tests is a very useful thing, here I’ll show an example of test for REST-service. Under this test, we have built up a web server TJWSEmbeddedJaxrsServer to which we will refer to test our REST-services.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/applicationContext-test.xml"})
@TestExecutionListeners({DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
public class TestEntityServiceRest {
 
    private static final int PORT = 8081;
    private static final String BASE_URL = "http://localhost:" + PORT;
 
    @Autowired
    EntityService entityService;
 
    @Autowired
    ConfigurableApplicationContext applicationContext;
 
    protected HttpClient client;
 
    protected TJWSEmbeddedJaxrsServer server;
 
    @Before
    public void setUpClient() throws Exception {
        client = new DefaultHttpClient();
    }
 
    @Before
    public void setUpServer() throws Exception {
        server = new TJWSEmbeddedJaxrsServer();
        server.setPort(PORT);
        ResteasyDeployment deployment = server.getDeployment();
        server.start();
        Dispatcher dispatcher = deployment.getDispatcher();
        SpringBeanProcessor processor = new SpringBeanProcessor(dispatcher, deployment.getRegistry(), deployment.getProviderFactory());
        applicationContext.addBeanFactoryPostProcessor(processor);
        SpringResourceFactory noDefaults = new SpringResourceFactory("entityServiceRestImpl", applicationContext, EntityRestServiceImpl.class);
        dispatcher.getRegistry().addResourceFactory(noDefaults);
    }
 
    @After
    public void stop() {
        server.stop();
    }
 
    @Test
    public void testListAll() throws Exception {
        int i = 0;
        final List returnedList = new ArrayList();
        int EXPECTED_SIZE = 6;
 
        while (i < EXPECTED_SIZE) {
            i++;
            final Entity entity = new Entity();
            entity.setId(i);
            entity.setName("test" + i);
            returnedList.add(entity);
        }
 
        when(entityService.findAll()).thenReturn(returnedList);
        HttpGet get = new HttpGet(BASE_URL + "/service/entity/");
        HttpResponse response = client.execute(get);
        InputStream content = response.getEntity().getContent();
        EntityList result = fromString(EntityList.class, content);
        content.close();
 
        Assert.assertNotNull(result);
        Assert.assertEquals(EXPECTED_SIZE, result.getEntities().size());
    }
 
    @Test
    public void testFindById() throws Exception {
        final Entity validEntity = getValidEntity();
        validEntity.setId(2);
        when(entityService.findById(validEntity.getId())).thenAnswer(new Answer...
    }
}

Running the Tests

Half of work is done, now we need to set up the infrastructure for testing of our newly written REST-services. To do this, we need to make the following modifications in pom.xml

org.apache.maven.plugins
maven-surefire-plugin
2.11
 
Unit tests
test
 
test
 
**/IT*.java
 
Integration tests
integration-test
 
test
 
**/IT*.java
 
org.apache.httpcomponents
httpclient
4.1.2
test
 
org.jboss.resteasy
resteasy-jaxrs
test
 
org.jboss.resteasy
resteasy-spring
test
 
org.jboss.resteasy
tjws
${resteasy-jaxrs.version}
 
javax.servlet
servlet-api
test
 
commons-io
commons-io
test

Conclusion

In general, nothing complicated, important to do everything carefully. Have a good code!


No Comments