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.

Add Comment
No Comments

Leave a Reply

Your email address will not be published.Required fields are marked *

More Uncategorized stories

IBM Cloud Functions: we’re doubling the time limit on executing actions

If you work with Cloud Functions, you know that building serverless applications mainly happens by creating actions–small pieces of code that each do one thing well. You can of course sequence actions together or create event-driven workflows. Through our work with customers, we have realized that some scenarios (for example, image processing, file processing, data pipelines) require more time […]

Continue reading

Plan, create and update deployment environments with IBM Cloud CLI and Terraform

Developers do not like to write the same thing twice. The DRY principle is one example of this. Similarly they don't like having to go through tons of clicks in a user interface to setup an environment. Consequently shell scripts have been long used by system administrators and developers to automate repetitive, error-prone and uninteresting tasks.

Continue reading

Access Groups

IBM Cloud introduces access groups in April 2018 as the platform’s newest feature that makes organizing users and streamlining the assignment of access easier than ever! Previously, IBM Cloud Identity Access and Management (IAM) required access policies to be set for individual users and service IDs. Now with access groups, you can organize users and service IDs into a group and manage access by assigning policies to the group. This will save you time and effort and make your IBM Cloud security efforts more efficient!

Continue reading