How-tos

Using Spring for REST on Liberty Buildpack

Share this post:

During a recent development sprint our team was investigating frameworks in place to support Social Login for a RESTful application.  In our research, we found that the common social login areas we were looking at Twitter, Facebook and Google all provided solid documentation on how to integrate into an application.

As we dug deeper to find previous artifacts and frameworks that we could take advantage of, we found Spring Social as one of the Spring Projects.   It has core support for both Twitter and Facebook and linked to a community project for Google Social.

All of our previous RESTful implementations on Liberty Buildpack had used JAX-RS and we have found using that framework simple and powerful.  The annotations were simple and for the most part our apps were simple enough to utilize just that and be successful.

As a team, we discussed if we wanted to mix JAX-RS and Spring Social, or did we set this project up with Spring REST and use one set of annotations. It’s important to note here that you can very much combine both Spring and JAX-RS, our decision was primarily being made based on code style and developer convenience rather than technical factors.

 

Setting up a Sprint REST app

 

One of the many attractions we had with JAX-RS was the simplicity of setting up and RESTful providers and associated methods for handling GET, POST, PUT and DELETE requests; annotate the method and done. Spring REST, unsurprisingly, does it the same way. Below you can see the annotations on a JAX-RS class and how that maps to the Spring annotations to achieve the same goal.

 

JAX-RS

@Provider
@Path("/helloworld")
public class PreferencesProvider {
@Path("/{text}");
@GET
public Response getPreferences(@PathParam(“text”) String text) {
return Response.ok(text);
}
}
</code>
Spring REST
<code>
@RestController
@RequestMapping("/helloworld")
public class PreferencesProvider {
@RequestMapping(value = "/{text}", , method = RequestMethod.POST)
public ResponseEntity&lt;?&gt; getPreferences(@PathVariable String text) {
return ResponseEntity.ok(text);
}
}

As you can see, from a code perspective, there isn’t much of a change to the general approach; the annotations are different but their use is obvious.

 

The real difference is how you then tell Spring to activate the application as a RESTful app.

 

Setting up web.xml

 

If you had previous experience with JAX-RS you will be familiar with the following web.xml fragment:

&lt;servlet&gt;
&lt;servlet-name&gt;javax.ws.rs.core.Application&lt;/servlet-name&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;enabled&gt;true&lt;/enabled&gt;
&lt;/servlet&gt;
&lt;servlet-mapping&gt;
&lt;servlet-name&gt;javax.ws.rs.core.Application&lt;/servlet-name&gt;
&lt;url-pattern&gt;/<u>api</u>/*&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;

This provided the info to liberty as it loaded the war, it told it the context path to use and then said “hey I am JAX-RS” and the code scan of the annotations then loaded in the appropriate providers.

Spring isn’t a million miles away from this, however the approach is a little different.

The web.xml looks like this:

&lt;?xml version="1.0" encoding="UTF-8"?&gt;&lt;web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"&gt;
&lt;servlet&gt;
&lt;servlet-name&gt;spring&lt;/servlet-name&gt;
&lt;servlet-class&gt;
org.springframework.web.servlet.DispatcherServlet
&lt;/servlet-class&gt;
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
&lt;/servlet&gt;

&lt;servlet-mapping&gt;
&lt;servlet-name&gt;spring&lt;/servlet-name&gt;
&lt;url-pattern&gt;/api&lt;/url-pattern&gt;
&lt;/servlet-mapping&gt;
&lt;/web-app&gt;

Then, along with web.xml, we add a spring-servlet.xml into the WEB-INF directory of your project:

&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd"></code>

&lt;context:component-scan base-package="com.ibm.your.package.with.providers" /&gt;
&lt;mvc:annotation-driven /&gt;

&lt;/beans&gt;

The context:component-scan tag tells spring where to go find components with the annotations.  You should set the base-package attribute to the name of your package in your war file.

Deploying to Bluemix

Now, as always with bluemix, the easy part; the deployment.  Build your war and push to bluemix with either the Bluemix CLI or the Dev Ops tools.

Gradle

We are deploying our apps with gradle, for reference here is our gradle build file in case the dependencies prove useful.  You can start the with the web-starter-boot from spring but our dependancies just list what is needed for Spring REST to work.

buildscript {
repositories {
mavenCentral()
}
dependencies {
<u>classpath</u> "org.springframework.boot:spring-boot-<u>gradle</u>-<u>plugin</u>:1.5.7.RELEASE"
}
}

apply <u>plugin</u>: 'java'
apply <u>plugin</u>: 'eclipse'
apply <u>plugin</u>: 'idea'
apply <u>plugin</u>: 'org.springframework.boot'
apply <u>plugin</u>: 'war'

war {
baseName = 'NameOfYourApp'
version =  '0.0.1'
}

repositories {
mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
compile group: 'org.springframework', name: 'spring-core', version: '4.3.11.RELEASE'
compile group: 'org.springframework', name: 'spring-context', version: '4.3.11.RELEASE'
compile group: 'org.springframework', name: 'spring-beans', version: '4.3.11.RELEASE'
compile group: 'org.springframework', name: 'spring-expression', version: '4.3.11.RELEASE'
compile group: 'org.springframework', name: 'spring-web', version: '4.3.11.RELEASE'
compile group: 'org.springframework', name: 'spring-<u>webmvc</u>', version: '4.3.11.RELEASE'
compile group: 'org.springframework', name: 'spring-<u>aop</u>', version: '4.3.11.RELEASE'
compile group: 'org.springframework', name: 'spring-context', version: '4.3.11.RELEASE'
compile group: 'com.fasterxml.jackson.core', name: '<u>jackson</u>-core', version: '2.9.1'
compile group: 'com.fasterxml.jackson.core', name: '<u>jackson</u>-annotations', version: '2.9.1'
compile group: 'com.fasterxml.jackson.core', name: '<u>jackson</u>-<u>databind</u>', version: '2.9.1'
compile group: 'org.slf4j', name: '<u>jcl</u>-over-slf4j', version: '1.7.25'
}

Conclusion

We hope this is a useful starter for getting Spring REST up and running on the liberty buildpack, as we said before we don’t see a huge difference between Spring and JAX-RS in terms of ease of development it was more a developer familiarity choice.  Moving our code to spring certainly allows us to take advantage of the other areas of usefulness that spring provides.

More How-tos stories

Configuring IBM Cloud App ID From the Toolchain

Learn how to configure the IBM Cloud App ID from a toolchain as part of continuous delivery process. This post gives some background and the script we use.

Continue reading

How to Backup Your IBM Cloud Linux Server

This post covers how to backup entire partitions in Linux systems. The process utilizes the tar command in IBM Cloud's unique rescue environment and showcases the simplicity and flexibility of the process.

Continue reading

Speed up your WordPress with IBM Cloud

WordPress is one of the most popular content management systems available, but the many websites and blogs that use it experience issues with speed. At IBM Cloud, there are several solutions that can help alleviate some of these issues and allow you to have a better and faster WordPress experience.

Continue reading