Skip to content
This repository has been archived by the owner on Jan 14, 2018. It is now read-only.

Commit

Permalink
Add jackson 2 support for Spring Android Module. Issu #61
Browse files Browse the repository at this point in the history
  • Loading branch information
stephanenicolas committed Mar 9, 2013
1 parent fc07443 commit 1f531fb
Show file tree
Hide file tree
Showing 8 changed files with 331 additions and 4 deletions.
7 changes: 7 additions & 0 deletions extensions/robospice-spring-android-parent/pom.xml
Expand Up @@ -30,6 +30,7 @@
<simplexmlserializer.version>2.6.9</simplexmlserializer.version>
<gson.version>2.2.2</gson.version>
<jackson.version>1.9.11</jackson.version>
<jackson2.version>2.1.4</jackson2.version>
</properties>

<dependencyManagement>
Expand All @@ -46,6 +47,12 @@
<version>${jackson.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson2.version}</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.simpleframework</groupId>
<artifactId>simple-xml</artifactId>
Expand Down
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
Expand Down Expand Up @@ -39,6 +40,11 @@
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-mapper-asl</artifactId>
</dependency>
<!-- Dependency when using jacson 2 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<!-- Dependency when using gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
Expand Down
@@ -0,0 +1,178 @@
package com.octo.android.robospice.persistence.springandroid.json.jackson2;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import android.app.Application;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.SmallTest;

import com.octo.android.robospice.persistence.DurationInMillis;
import com.octo.android.robospice.persistence.file.InFileObjectPersister;
import com.octo.android.robospice.springandroid.test.model.json.CurrenWeather;
import com.octo.android.robospice.springandroid.test.model.json.Weather;
import com.octo.android.robospice.springandroid.test.model.json.WeatherResult;

@SmallTest
public class InFileWeatherPersisterTest extends InstrumentationTestCase {
private static final long FIVE_SECONDS = 5 * DurationInMillis.ONE_SECOND;
private static final String TEST_TEMP_UNIT = "C";
private static final String TEST_TEMP = "28";
private static final String TEST_TEMP2 = "30";
private static final String FILE_NAME = "toto";
private static final String FILE_NAME2 = "tutu";
private InFileObjectPersister<WeatherResult> dataPersistenceManager;

@Override
protected void setUp() throws Exception {
super.setUp();
Application application = (Application) getInstrumentation().getTargetContext().getApplicationContext();
Jackson2ObjectPersisterFactory factory = new Jackson2ObjectPersisterFactory(application);
dataPersistenceManager = factory.createObjectPersister(WeatherResult.class);
}

@Override
protected void tearDown() throws Exception {
dataPersistenceManager.removeAllDataFromCache();
super.tearDown();
}

public void test_canHandleClientRequestStatus() {
boolean canHandleClientWeatherResult = dataPersistenceManager.canHandleClass(WeatherResult.class);
assertEquals(true, canHandleClientWeatherResult);
}

public void test_saveDataAndReturnData() throws Exception {
// GIVEN
WeatherResult weatherRequestStatus = buildWeather(TEST_TEMP, TEST_TEMP_UNIT);

// WHEN
WeatherResult weatherReturned = dataPersistenceManager.saveDataToCacheAndReturnData(weatherRequestStatus, "weather.json");

// THEN
assertEquals(TEST_TEMP, weatherReturned.getWeather().getCurren_weather().get(0).getTemp());
}

public void test_loadDataFromCache_no_expiracy() throws Exception {
// GIVEN
WeatherResult weatherRequestStatus = buildWeather(TEST_TEMP, TEST_TEMP_UNIT);

dataPersistenceManager.saveDataToCacheAndReturnData(weatherRequestStatus, FILE_NAME);

// WHEN
WeatherResult weatherReturned = dataPersistenceManager.loadDataFromCache(FILE_NAME, DurationInMillis.ALWAYS_RETURNED);

// THEN
assertEquals(TEST_TEMP, weatherReturned.getWeather().getCurren_weather().get(0).getTemp());
}

public void test_loadDataFromCache_not_expired() throws Exception {
// GIVEN
WeatherResult weatherRequestStatus = buildWeather(TEST_TEMP, TEST_TEMP_UNIT);

dataPersistenceManager.saveDataToCacheAndReturnData(weatherRequestStatus, FILE_NAME);

// WHEN
WeatherResult weatherReturned = dataPersistenceManager.loadDataFromCache(FILE_NAME, FIVE_SECONDS);

// THEN
assertEquals(TEST_TEMP, weatherReturned.getWeather().getCurren_weather().get(0).getTemp());
}

public void test_loadDataFromCache_expired() throws Exception {
// GIVEN
WeatherResult weatherRequestStatus = buildWeather(TEST_TEMP2, TEST_TEMP_UNIT);

dataPersistenceManager.saveDataToCacheAndReturnData(weatherRequestStatus, FILE_NAME);
File cachedFile = ((Jackson2ObjectPersister<?>) dataPersistenceManager).getCacheFile(FILE_NAME);
cachedFile.setLastModified(System.currentTimeMillis() - FIVE_SECONDS);

// WHEN
WeatherResult weatherReturned = dataPersistenceManager.loadDataFromCache(FILE_NAME, DurationInMillis.ONE_SECOND);

// THEN
assertNull(weatherReturned);
}

public void test_loadAllDataFromCache_with_one_request_in_cache() throws Exception {
// GIVEN
WeatherResult weatherRequestStatus = buildWeather(TEST_TEMP, TEST_TEMP_UNIT);

dataPersistenceManager.saveDataToCacheAndReturnData(weatherRequestStatus, FILE_NAME);

// WHEN
List<WeatherResult> listWeatherResult = dataPersistenceManager.loadAllDataFromCache();

// THEN
assertNotNull(listWeatherResult);
assertEquals(1, listWeatherResult.size());
assertEquals(weatherRequestStatus, listWeatherResult.get(0));
}

public void test_loadAllDataFromCache_with_two_requests_in_cache() throws Exception {
// GIVEN
WeatherResult weatherRequestStatus = buildWeather(TEST_TEMP, TEST_TEMP_UNIT);

dataPersistenceManager.saveDataToCacheAndReturnData(weatherRequestStatus, FILE_NAME);

WeatherResult weatherRequestStatus2 = buildWeather(TEST_TEMP2, TEST_TEMP_UNIT);

dataPersistenceManager.saveDataToCacheAndReturnData(weatherRequestStatus2, FILE_NAME2);

// WHEN
List<WeatherResult> listWeatherResult = dataPersistenceManager.loadAllDataFromCache();

// THEN
assertNotNull(listWeatherResult);
assertEquals(2, listWeatherResult.size());
assertTrue(listWeatherResult.contains(weatherRequestStatus));
assertTrue(listWeatherResult.contains(weatherRequestStatus2));
}

public void test_loadAllDataFromCache_with_no_requests_in_cache() throws Exception {
// GIVEN

// WHEN
List<WeatherResult> listWeatherResult = dataPersistenceManager.loadAllDataFromCache();

// THEN
assertNotNull(listWeatherResult);
assertTrue(listWeatherResult.isEmpty());
}

public void test_removeDataFromCache_when_two_requests_in_cache_and_one_removed() throws Exception {
// GIVEN
WeatherResult weatherRequestStatus = buildWeather(TEST_TEMP, TEST_TEMP_UNIT);

dataPersistenceManager.saveDataToCacheAndReturnData(weatherRequestStatus, FILE_NAME);

WeatherResult weatherRequestStatus2 = buildWeather(TEST_TEMP2, TEST_TEMP_UNIT);

dataPersistenceManager.saveDataToCacheAndReturnData(weatherRequestStatus2, FILE_NAME2);

dataPersistenceManager.removeDataFromCache(FILE_NAME2);

// WHEN
List<WeatherResult> listWeatherResult = dataPersistenceManager.loadAllDataFromCache();

// THEN
assertNotNull(listWeatherResult);
assertEquals(1, listWeatherResult.size());
assertTrue(listWeatherResult.contains(weatherRequestStatus));
assertFalse(listWeatherResult.contains(weatherRequestStatus2));
}

private WeatherResult buildWeather(String temp, String tempUnit) {
WeatherResult weatherRequestStatus = new WeatherResult();
Weather weather = new Weather();
List<CurrenWeather> currents = new ArrayList<CurrenWeather>();
CurrenWeather current_weather = new CurrenWeather();
current_weather.setTemp(temp);
current_weather.setTemp_unit(tempUnit);
currents.add(current_weather);
weather.setCurren_weather(currents);
weatherRequestStatus.setWeather(weather);
return weatherRequestStatus;
}
}
@@ -0,0 +1,4 @@
Version 1.4.1 (to be released)

* Add Jackson 2.1 support. Feature suggested by James Campbell.

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
Expand Down Expand Up @@ -42,6 +43,11 @@
<artifactId>jackson-mapper-asl</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand Down Expand Up @@ -69,7 +75,7 @@
</plugin>
</plugins>
</build>

<profiles>
<profile>
<!-- copy dependencies for ant users and deploy them to github -->
Expand All @@ -82,7 +88,7 @@
<configuration>
<includeArtifactIds>commons-lang3,commons-io,robospice,
robospice-cache,spring-android-core,spring-android-rest-template,simple-xml,jackson-mapper-asl,jackson-core-asl,gson</includeArtifactIds>
</configuration>
</configuration>
</plugin>
<plugin>
<groupId>com.github.github</groupId>
Expand Down
@@ -0,0 +1,37 @@
package com.octo.android.robospice;

import java.util.List;

import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

import android.app.Application;

import com.octo.android.robospice.persistence.CacheManager;

/**
* A {@link SpringAndroidSpiceService} dedicated to json web services via Jackson. Provides caching.
* @author sni
*/
public class Jackson2SpringAndroidSpiceService extends SpringAndroidSpiceService {
@Override
public CacheManager createCacheManager(Application application) {
CacheManager cacheManager = new CacheManager();
cacheManager.addPersister(new com.octo.android.robospice.persistence.springandroid.json.jackson.JacksonObjectPersisterFactory(application));
return cacheManager;
}

@Override
public RestTemplate createRestTemplate() {
RestTemplate restTemplate = new RestTemplate();

// web services support json responses
MappingJackson2HttpMessageConverter jsonConverter = new MappingJackson2HttpMessageConverter();
final List<HttpMessageConverter<?>> listHttpMessageConverters = restTemplate.getMessageConverters();

listHttpMessageConverters.add(jsonConverter);
restTemplate.setMessageConverters(listHttpMessageConverters);
return restTemplate;
}
}
@@ -0,0 +1,59 @@
package com.octo.android.robospice.persistence.springandroid.json.jackson2;

import java.io.IOException;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.CharEncoding;
import org.apache.commons.lang3.StringUtils;

import android.app.Application;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.octo.android.robospice.persistence.exception.CacheLoadingException;
import com.octo.android.robospice.persistence.exception.CacheSavingException;
import com.octo.android.robospice.persistence.springandroid.SpringAndroidObjectPersister;

public final class Jackson2ObjectPersister<T> extends SpringAndroidObjectPersister<T> {

// ============================================================================================
// ATTRIBUTES
// ============================================================================================

private final ObjectMapper mJsonMapper;

// ============================================================================================
// CONSTRUCTOR
// ============================================================================================
public Jackson2ObjectPersister(Application application, Class<T> clazz, String factoryPrefix) {
super(application, clazz, factoryPrefix);
this.mJsonMapper = new ObjectMapper();
}

// ============================================================================================
// METHODS
// ============================================================================================

@Override
protected T deserializeData(String json) throws CacheLoadingException {
try {
return mJsonMapper.readValue(json, getHandledClass());
} catch (Exception e) {
throw new CacheLoadingException(e);
}
}

@Override
protected void saveData(T data, Object cacheKey) throws IOException, CacheSavingException {
String resultJson;
// transform the content in json to store it in the cache
resultJson = mJsonMapper.writeValueAsString(data);

// finally store the json in the cache
if (!StringUtils.isEmpty(resultJson)) {
FileUtils.writeStringToFile(getCacheFile(cacheKey), resultJson, CharEncoding.UTF_8);
} else {
throw new CacheSavingException("Data was null and could not be serialized in json");
}
}

}
@@ -0,0 +1,30 @@
package com.octo.android.robospice.persistence.springandroid.json.jackson2;

import java.util.List;

import android.app.Application;

import com.octo.android.robospice.persistence.file.InFileObjectPersister;
import com.octo.android.robospice.persistence.file.InFileObjectPersisterFactory;

public class Jackson2ObjectPersisterFactory extends InFileObjectPersisterFactory {

public Jackson2ObjectPersisterFactory(Application application) {
super(application);
}

public Jackson2ObjectPersisterFactory(Application application,
List<Class<?>> listHandledClasses) {
super(application, listHandledClasses);
}

@Override
public <DATA> InFileObjectPersister<DATA> createObjectPersister(
Class<DATA> clazz) {
InFileObjectPersister<DATA> inFileObjectPersister = new Jackson2ObjectPersister<DATA>(
getApplication(), clazz, getCachePrefix());
inFileObjectPersister.setAsyncSaveEnabled(isAsyncSaveEnabled());
return inFileObjectPersister;
}

}

0 comments on commit 1f531fb

Please sign in to comment.