Creating an Android app for your website with Spring Android and REST

by Roberto van der LindenFebruary 7, 2011

As Android is really hot at the moment (and I have an Android phone), I wanted to create an Android app for my website. In this blog post I will explain the changes I had to make on the part of my web application and how I used Spring Android to interact from Android to my web application.

Website

My website is just a simple Spring application with Spring MVC 3.0.5, JPA, Hibernate and MySQL. In order to create a REST api that is understandable for my Android app, I needed to add a little more configuration to the web application.

Spring Security

As I have Spring Security in place, I had to add a security rule for my REST api. If you really want to do it the right way, than make sure you use the OAuth implementation as Spring Android also provides you to use OAuth in your Android app.

But being a bit lazy I just configured the REST api to be public and therefor does not require any authentication. This is good for now.

So in my security-context.xml I added the following rule:

<br>
<intercept-url access="hasRole('ROLE_ANONYMOUS')" pattern="/rest/**"><br>

As you can see I specified all the URL’s that match on /rest/** can be accessed without any authentication.

ContentNegotiatingViewResolver

Spring provides us with the ContentNegotiatingViewResolver. This is an implementation of ViewResolver that resolves a view based on the file extension, parameter, or Accept header.

<br>
    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
<map>
                <entry value="application/json" key="json"><br>
                <entry value="text/html" key="html"><br>
            </entry></entry></map>
</property></bean></p><p>
        <property name="viewResolvers">
<list>
                <bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
                    <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
                    <property name="prefix" value="/WEB-INF/jsp/"></property>
                    <property name="suffix" value=".jsp"></property>
                </bean>
            </list>
        </property>
        <property name="defaultViews">
<list>
                <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
            </bean></list>
        </property>
    <br>

As you can see in the code above, I have configured two mediaTypes. The json mediatype will be used by our Android app and the html mediatype will be used by any browser.

The defaultViews property allows us to override the views provided by the view resolvers. Which is necessary in order resolve the correct view for JSON.

Converting data

Later on this post I will show how you can POST data to your controllers via Spring Android. To do this we need to configure the MappingJacksonHttpMessageConverter that allows us to convert data of  the media type application/json.

<br>
    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
<list>
                <ref bean="jsonConverter">
            </ref></list>
        </property>
    </bean></p>
<p>    <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        <property name="supportedMediaTypes" value="application/json"></property>
    </bean><br>

Controller

Now that we have the ContentNegotiatingViewResolver in place, we can call any URL in our web application with the .json extension and give you a JSON representation of your data. Let’s take a look at an example of a Controller method.

<br>
    @RequestMapping("/rest/matches/played")<br>
    public ModelAndView getAllPlayedMatches() {<br>
        Competition competition = competitionService.findCompetitionByDescription(CURRENT_COMPETITION_DESCRIPTION);<br>
        List<match> matches = matchService.getAllMatchesByCompetitionAndStatusDesc(competition, true);</match></p>
<p>        List<matchdto> matchesDto = getMatches(matches);</matchdto></p>
<p>        ModelAndView mav = new ModelAndView();<br>
        mav.addObject("matches", matchesDto);<br>
        return mav;<br>
    }<br>

If I want to call this method via my browser, I can simple call /rest/matches/played.json. This will simply work for all your request mappings. In this example I convert the list of matches to a list of matchDto objects. These objects contain less data, so that I don’t send any unnecessary data to our Android app.

The JSON output will look like this:

{<br>
   "matches": [<br>
    {<br>
        "id": 125,<br>
        "comment": "Match nr 137667",<br>
        "date": "2 february 2011 at 21:05",<br>
        "home_team": "VVGA 2",<br>
        "away_team": "Badhoevedorp 2",<br>
        "home_goals": 6,<br>
        "away_goals": 9,<br>
        "location": "Zuid"<br>
    }, </p>
<p>    {<br>
        "id": 124,<br>
        "comment": "Match nr 137684",<br>
        "date": "26 january 2011 at 20:15",<br>
        "home_team": "DCG 7",<br>
        "away_team": "VVGA 2",<br>
        "home_goals": 7,<br>
        "away_goals": 4,<br>
        "location": "Zuid"<br>
    }<br>
..<br>
}<br>

Well that’s basically it for the web application part. I have created separate controllers for my REST api, but you could easily reuse your existing controller if it contains all your data.

Android app

Spring Android

Spring Android provides us with a Rest Client and Commons Logging adapter for Android. I don’t want to spend any time on how to set-up an Android project, as everyone prefers their own IDE. But it is clear that we need the Spring Android jars in our project.

You can either download them from the Spring Android site of you can use Maven to include them into your project.

RestTemplate – GET

Retrieving data from our web application is really simple thanks to the RestTemplate.

<br>
public Matches getPlayedMatches() {<br>
    RestTemplate restTemplate = new RestTemplate();<br>
    restTemplate.setRequestFactory(new CommonsClientHttpRequestFactory());<br>
    String url = BASE_URL + "/rest/matches/played.json";<br>
    return restTemplate.getForObject(url, Matches.class);<br>
}<br>

The code above uses the getForObject() method to invoke the REST api from our web application and expects an object of the type Matches. This object contains an array of Match objects. The Match object contains all fields that are present in the JSON output.

RestTemplate – POST

Posting data to our web application is as easy as retrieving data.

<br>
public boolean getUser(String username, String password) {<br>
    String url = BASE_URL + "/rest/login.json";</p>
<p>    Credentials credentials = new Credentials(username, password);<br>
    return restTemplate.postForObject(url, credentials, Boolean.class);<br>
}<br>

You can just use the postForObject() method to POST any object to your web application. In this example I post a Credentials object which contains the username and password. This is not really secure, but fits it’s purpose for now.

@RequestBody and @ResponseBody

One thing that I want to mention is the use of @RequestBody and @ResponseBody in a controller in the web application part. In my web application I have the exact same Credentials object as in my Android app. This allows us to use the following controller code:

<br>
@RequestMapping(value = "/rest/login", method = RequestMethod.POST)<br>
public @ResponseBody boolean login(@RequestBody Credentials credentials) {<br>
    String username = credentials.getUsername();<br>
    String password = credentials.getPassword();</p>
<p>    boolean isValidUser = // check if user exist.</p>
<p>    return isValidUser;<br>
}<br>

Because of the jsonConverter we configured earlier, the object in the request is mapped to the Credentials object in the web application.

With @ResponseBody I directly bind my method return value to the web response body. So there is no need for creating a model and as you could see in the corresponding Android part I can just expect a boolean to be returned.

Next time

Now that we are able to communicate from an Android app to a web application and vice versa, it is time to create a great Android app. In my next blog post I will explain how I applied a few layout patterns and Android how I tackled a few of my problems during the development of my Android app.