Trifork Blog

AngularJS training

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

February 7th, 2011 by
| Reply

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:

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

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.

    <bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="mediaTypes">
            <map>
                <entry value="application/json" key="json" />
                <entry value="text/html" key="html" />
            </map>
        </property>
        <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" />
            </list>
        </property>
    </bean>

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.

    <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
        <property name="messageConverters">
            <list>
                <ref bean="jsonConverter" />
            </list>
        </property>
    </bean>

    <bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
        <property name="supportedMediaTypes" value="application/json"></property>
    </bean>

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.

    @RequestMapping("/rest/matches/played")
    public ModelAndView getAllPlayedMatches() {
        Competition competition = competitionService.findCompetitionByDescription(CURRENT_COMPETITION_DESCRIPTION);
        List<match> matches = matchService.getAllMatchesByCompetitionAndStatusDesc(competition, true);

        List<matchdto> matchesDto = getMatches(matches);

        ModelAndView mav = new ModelAndView();
        mav.addObject("matches", matchesDto);
        return mav;
    }

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:

{
   "matches": [
    {
        "id": 125,
        "comment": "Match nr 137667",
        "date": "2 february 2011 at 21:05",
        "home_team": "VVGA 2",
        "away_team": "Badhoevedorp 2",
        "home_goals": 6,
        "away_goals": 9,
        "location": "Zuid"
    }, 

    {
        "id": 124,
        "comment": "Match nr 137684",
        "date": "26 january 2011 at 20:15",
        "home_team": "DCG 7",
        "away_team": "VVGA 2",
        "home_goals": 7,
        "away_goals": 4,
        "location": "Zuid"
    }
..
}

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.

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

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.

public boolean getUser(String username, String password) {
    String url = BASE_URL + "/rest/login.json";

    Credentials credentials = new Credentials(username, password);
    return restTemplate.postForObject(url, credentials, Boolean.class);
}

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:

@RequestMapping(value = "/rest/login", method = RequestMethod.POST)
public @ResponseBody boolean login(@RequestBody Credentials credentials) {
    String username = credentials.getUsername();
    String password = credentials.getPassword();

    boolean isValidUser = // check if user exist.

    return isValidUser;
}

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.

16 Responses

  1. February 7, 2011 at 18:23 by Sandeep

    Thanks for that tutorial.

    REST is best

  2. February 10, 2011 at 21:16 by xserete

    Great tutorial on this bleeding edge technology!

  3. February 23, 2011 at 12:57 by Sven Haiges

    I'm getting a Request Method "PUT" no supported when I try some similar call like you. GET on some resource works fine though. Did I miss some configuration?

  4. February 23, 2011 at 15:43 by Roberto van der Linden

    Hi Sven,

    Are you sure you're calling the correct method? I once had the same problem for POST. And did you add the message converter (see part of converting data)?

    Cheers,
    Roberto

  5. [...] If you want to know more about creating an app with asynchronous retrieval of data, you can read my previous blog post. #dd_ajax_float{ background:none repeat scroll 0 0 #FFFFFF; border:1px solid #DDDDDD; float:left; [...]

  6. July 21, 2011 at 01:07 by Kenny Timberland

    Great topic and a ton of help. i am actually doing this right now for my site http://www.thedroidapp.com

    thanks again

  7. August 2, 2011 at 12:33 by Harold Frenton

    Have to agree with other comments that this is a great tutorial and even coding dummies like me can follow it!

  8. December 3, 2011 at 02:15 by Lee

    This tutorial is really a great one.
    Could someone post a tutorial that applies Spring security, OAuth, to secure the communication channel between Droid and Spring MVC?
    Thanks in advance.

  9. February 21, 2012 at 10:01 by Warner Piñero

    Is there a book for learning Spring-Android? Can somebody post the link where I can purchase one?

    Thanks

  10. February 29, 2012 at 23:48 by Control Android

    I have the same problem of Sven: Request Method "PUT" no supported
    Did you fix this?

  11. March 6, 2012 at 17:34 by andrefy

    Thanks for the tutorial was great,

    I am trying to use the android spring RestTemplate to interact with Apache and PHP and the server side

    RestTemplate restTemplate = new RestTemplate();
    String result = restTemplate.postForObject(url, [object], String.class);

    Seems to be not working, I get any data at the post request at the server side, I guess I need something like the messageConverter on the server side.

    It works fine if I use the following converters at the android side

    List<HttpMessageConverter> messageConverters = Lists.newArrayList();
    messageConverters.add(new FormHttpMessageConverter());
    messageConverters.add(new StringHttpMessageConverter());

    and them sent the a map of pair values

    MultiValueMap mvm = new LinkedMultiValueMap();

    but I am wonder if there is a way in which I can use the RESTemplate to convert my java object at the android side and build a valid post request without need of the converter on the server, for getForEntity request it is working fine

    Thanks

  12. April 26, 2012 at 17:50 by pranav

    Very nice tutorial Roberto

  13. June 15, 2012 at 10:52 by Rohit

    Hi, i m new for Android. i am working in java/j2EE, I have seen there is spring support in Android at client side(Message Convertor in xml and json,SQLite) , but i am not getting any good resource, So If you have any resource or sample code , can you please send me on my gmail id?

  14. July 18, 2012 at 12:07 by AndroidFace

    I want to develop spring restful application which contains all business services and login/logout services

    My Spring Controller (Client Application) and Android App( Mobile Client application) should use login /logout services which resides spring restful application

    spring or andorid client ---- send registration details including username and password to--> Restful Application (Restful application stores password using some encryption algorithm). How to achieve this ?

    After Registration spring or android client send username and passowrd to rest application through restservice url and in back rest spring application validate against the registered username and password from datasource and send back authorization. How to achieve this?

    Busines Services

    Spring or Android client send request to Restful spring application to get business services to display some data.

    Where should i start ?. How to design this or any sample stuff which does restful registration and authentication and how to make sure that each and every request is accessed by validate user after authorization.

    I understand, that i am asking lot . But please direct me to right place or righ book or blog which will give clear picture

    Thanks in Advance

  15. August 3, 2012 at 13:51 by Roberto van der Linden

    Hi AndroidFace,

    As I mention in my blog, you can use OAuth to do the authentication. Spring Android has support for OAuth.

    Cheers,
    Roberto

Leave a Reply