Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Extreme Laziness: Developing Jax-RS Services With Spring Boot

DZone's Guide to

Extreme Laziness: Developing Jax-RS Services With Spring Boot

There is a lot to be said about Spring Boot, including its seamless integration with Spring projects. But its capabilities go far beyond that, supporting first-class integration with popular Java frameworks.

· Java Zone
Free Resource

Just released, a free O’Reilly book on Reactive Microsystems: The Evolution of Microservices at Scale. Brought to you in partnership with Lightbend.

I think it would be fair to state that we, as software developers, are always looking for the ways to write less code which does more stuff, automagically or not. With this in mind, the Spring Boot project, a proud member of the Spring portfolio, disrupted the traditional approaches, dramatically speeding up and simplifying Spring-based applications development.

There is a lot to be said about Spring Boot, including intrinsic details of how it works and its seamless integration with most if not all Spring projects. But its capabilities go far beyond that, supporting first-class integration with popular Java frameworks.

In this post we are going to take a look at how we can use Spring Boot in conjunction with Apache CXF for rapid REST(ful) web services development. As we are going to see very soon, Spring Boot takes care of quite a lot of boilerplate, letting us concentrate on the parts of the application which have real value. Hopefully, at the end of this post the benefits of adopting Spring Boot for your projects becomes apparent.

With that, let us get started by developing a simple people management REST(ful) web service, wrapped up into familiar PeopleRestService JAX-RS resource:

@Path("/people")
@Component
public class PeopleRestService {
 @GET
 @Produces({MediaType.APPLICATION_JSON})
 public Collection<Person> getPeople() {
 return Collections.singletonList(new Person("a@b.com", "John", "Smith"));
 }
}

Not much to add here; pretty simple implementation which returns the hard-coded collection of people. There are a couple of ways we can package and deploy this JAX-RS service, but arguably the simplest one is by hosting it inside an embedded servlet container like Tomcat, Jetty or Undertow. With that comes the routine: container initialization, configuring Spring context locations, registering listeners, ... Let us see how Spring Boot can help here by dissecting the Spring context configuration below.

@Configuration
@EnableAutoConfiguration
@ComponentScan(basePackageClasses = PeopleRestService.class)
public class AppConfig {
 @Autowired private PeopleRestService peopleRestService;

 @Bean(destroyMethod = "shutdown")
 public SpringBus cxf() {
 return new SpringBus();
 }

 @Bean(destroyMethod = "destroy") @DependsOn("cxf")
 public Server jaxRsServer() {
 final JAXRSServerFactoryBean factory = new JAXRSServerFactoryBean();

 factory.setServiceBean(peopleRestService);
 factory.setProvider(new JacksonJsonProvider());
 factory.setBus(cxf());
 factory.setAddress("/");

 return factory.create();
 }

 @Bean
 public ServletRegistrationBean cxfServlet() {
 final ServletRegistrationBean servletRegistrationBean = 
 new ServletRegistrationBean(new CXFServlet(), "/api/*");
 servletRegistrationBean.setLoadOnStartup(1);
 return servletRegistrationBean;
 }
}

The AppConfig class looks like a typical Spring Java-based configuration except for this unusual @EnableAutoConfiguration annotation, which with no surprise comes from Spring Boot module. Under the hood, this annotation enables a complex and intelligent process of guessing, among many other things, what kind of application we are going to run and what kind of Spring beans we may need for our application. With this configuration in place, we just need to have a runner for our application, also with a bit of Spring Boot flavor:

@SpringBootApplication
public class Application {
 public static void main(String[] args) {
 SpringApplication.run(AppConfig.class, args);
 }
}

Having the @SpringBootApplication meta-annotation and using SpringApplication to initialize our Spring context, we have a full-fledged runnable Java application, which could be run from Apache Maven using the Spring Boot plugin:

mvn spring-boot:run

Or packaged as a single runnable uber- JAR and invoked from command line:

mvn package
java -jar target/jax-rs-2.0-cxf-spring-boot-0.0.1-SNAPSHOT.jar

And that's it; just a couple of annotations along with a single line of code (in the main method). Once we run the application, we can make sure that our people management REST(ful) web service is deployed properly and is fully operational:

$ curl -i http://localhost:8080/api/people

HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
Transfer-Encoding: chunked
Server: Jetty(9.3.8.v20160314)

[{"email":"a@b.com","firstName":"John","lastName":"Smith"}]

At this point you may wonder, "how does it work?" We have not dealt with a servlet container anywhere, so how come Jetty is serving our requests? The truth is, we only need to include our container of choice as a dependency, for example using Apache Maven's pom.xml file:

<dependency>
 <groupId>org.eclipse.jetty</groupId>
 <artifactId>jetty-server</artifactId>
 <version>9.3.8.v20160314</version>
</dependency>

 Spring Boot along with @EnableAutoConfiguration/@SpringBootApplication does the rest: it detects the presence of Jetty in the classpath, comes to a valid conclusion that our intention is to run a web application, and complements the Spring context with the necessary pieces. Isn't it just brilliant?

It would be unfair to finish up without covering yet another important feature of the Spring Boot project: integration testing support. In this regard Spring Boot takes the same approach and provides a couple of annotations to take off all the scaffolding we would otherwise have to write ourselves. For example:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = AppConfig.class)
@WebIntegrationTest(randomPort = true)
public class PeopleRestServiceIntegrationTest {
 @Value("${local.server.port}") private int port;

 @Before
 public void setUp() {
 RestAssured.port = port;
 }

 @Test
 public void testListOfPersonsIsBeingReturnedSuccessfuly() {
 given()
 .when() 
 .contentType(ContentType.JSON)
 .get("/api/people")
 .then()
 .statusCode(200)
 .log()
 .ifValidationFails();
 }
}

Just two annotations, @SpringApplicationConfiguration (please notice that we are using the same configuration in test as for the main application) and @WebIntegrationTest (which takes the specifics of the web application testing into account and runs the embedded servlet container on a random port), and we have full-fledged integration test against our people management JAX-RS service. The port which the servlet container is running on is available through the local.server.port environment property so we can configure REST-assured in the test background. Easy and simple.

In this post we have looked at one specific use case of using Spring Boot to increase the development velocity of your JAX-RS projects. Many, many things become very trivial with Spring Boot, with more and more intelligence being added with every single release, not to mention excellent integration with your IDE of choice. I hope you got really excited about Spring Boot and are eager to learn more about it. It is worth the time and effort.

The complete project is available on Github.

Strategies and techniques for building scalable and resilient microservices to refactor a monolithic application step-by-step, a free O'Reilly book. Brought to you in partnership with Lightbend.

Topics:
jax-rs ,spring boot

Published at DZone with permission of Andriy Redko, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}