The Maven Dependency Dance with Spring Android, Spring Social and Spring Security
Join the DZone community and get the full member experience.
Join For FreeOriginally authored by Josh Long at the SpringSource blog
Roy Clarkson (@royclarkson) and I gave a talk at SpringOne2GX 2013 in which we talked about building REST services with an eye towards consuming those services on mobile platforms like Android and iOS. This talk demonstrates the progressive evolution of an application using Spring MVC, Spring HATEOAS, Spring Data REST, Spring Security, Spring Security OAuth, and Spring Android. The code's benefited from a lot of help from Rob Winch,
Layout of the Code
The code for the talk is on my GitHub account (github.com/joshlong/**the-spring-rest-stack**). Importantly, the code lives in the code
directory. Beneath that there are two choices: web
(where you'll find the rest
, hateoas
, hateoas-data
, and oauth
, social
modules) andclient
(where you can load the Android module and the iOS module). The modules in theweb
folder in respective order, demonstrate the evolution of a simple REST service which incorporates hypermedia, Spring Data repositories and OAuth security. The social
module demonstrates how to build an OAuth client that consumes the service.
Building and Editing the Code
The project is all, at the moment, Maven based, though moving to Gradle seems imminent as that is the Google-endorsed route for Android builds. I know the Android client to be importable and buildable using IntelliJ IDEA's Android support (which in theory should work inAndroid Studio, which is freely available).
The Dependency Dance and Android
We used up-to-date revisions of major libraries in our build file, linked for reference. Up-to-date and sometimes bleeding edge. The Android application uses the Spring Android project, which - basically - provides an API compatible implementation of the RestTemplate
found in Spring core.
It does not however provide the entire framework, and if you bring in certain libraries from the core you'll get weird issues because some classes in the Spring Android modules are mostlythe same in Spring Android and in the core, but they're not identical, due to the differing natures of the environments in which they run. The easiest way to ensure everything's OK is to explicitly exclude all Spring modules except the Spring Android dependencies then,selectively, re-introduce the types as you need them.
The types in the Spring Android RestTemplate module provides more than enough compatibility to let Spring Social's client machinery work unchanged on Android. This, of course, means that we can use the Spring Social-powered OAuth client in the social
module in our Android application. Awesome!
For example, while I needed the Spring Social core types and implementations, I didn't need the core Spring libraries that it brought in. So, we get this rather dramatic stanza:
<dependency> <groupId>org.springframework.social</groupId> <artifactId>spring-social-core</artifactId> <version>${spring-social.version}</version> <exclusions> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> </exclusion> <exclusion> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-expression</artifactId> </exclusion> <exclusion> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> </exclusion> <exclusion> <groupId>aopalliance</groupId> <artifactId>aopalliance</artifactId> </exclusion> <exclusion> <groupId>com.joshlong.restfuliterations</groupId> <artifactId>services</artifactId> </exclusion> </exclusions> </dependency>
These dependencies can be hard to find. Use the mvn dependency:tree
command to see where things are being imported transitively. Spring Security, another library whose top level types we wanted on the CLASSPATH
, also required exclusion
elements because it drags in Spring core.
Some Classes - like JAXB - You Just Can't Avoid
Any class that's not in Android's JDK-class whitelist is not available on Android and thus renders code that depends on it incompatible. Some classes, like those in the JAXB module, are hard to ignore as they're pervasive. I wanted to use the Spring HATEOAS Resource
,Link
, types. These types are used as representations of various entities in REST responses that are sometimes rendered as XML using JAXB, they could not be loaded in Android! So, Ihad to copy those types locally and mirror the package structure and remove the offending annotations. Hopefully I can clean this up going forward.
Published at DZone with permission of Pieter Humphrey, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments