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

Using SSH tunnels and Selenium to test web applications on a continuous delivery pipeline

Developers often have a need to test their web applications. In particular they often have a need to automate these tests as part of a continuous integration (CI) pipeline. One such tool that helps facilitate this test requirement is Selenium. Selenium is a piece of software which is designed to automate browser behaviour, in that you can program it to visit a particular web page and then perform a series of actions on that web page. Most often this is leveraged to test web applications, although its functionality is not limited to that single use case. With a default configuration, however, this isn’t possible as the Selenium Server has no way of reaching an application that has been started within a CI container.

Continue reading

Integrate and Analyze Diagnostic Logs with IBM Cloud Log Analysis

Analyzing diagnostic logs, monitoring application health and keeping track of security-related events are at the foundation of successfully running apps and services. IBM Cloud offers services for that purpose. Today, I am going to show you how to use IBM Cloud Log Analysis to integrate, search and analyze as well as visualize diagnostic logs in the IBM Cloud.

Continue reading

Obey your commands: Home automation using Watson and PubNub

Integration of voice control in smart devices is buzzing, and adoption continues to grow. Voice control provides a more natural way of interacting with connected apps and devices ranging from news feeds, traffic information to acting as personal assistants in the home. These intelligent devices respond to commands spoken in our own voice and act immediately.

Continue reading