Skip to content

Instantly share code, notes, and snippets.

@rudyjahchan
Created March 25, 2012 06:50
Show Gist options
  • Save rudyjahchan/2191950 to your computer and use it in GitHub Desktop.
Save rudyjahchan/2191950 to your computer and use it in GitHub Desktop.
DRY RESTful Resources with Java Generics
package myapp.resource;
import com.google.inject.ImplementedBy;
import myapp.Post;
@ImplementedBy(PostResourceImpl.class)
public interface PostResource extends Resource<Post> {
}
package myapp.resource;
import com.google.inject.Singleton;
import myapp.Post;
@Singleton
public class PostResourceImpl extends RemoteResourceImpl<Post> implements PostResource {
@Override
public String getPath() {
return "posts";
}
}
package myapp.resource;
import android.net.Uri;
import com.google.inject.Inject;
import org.apache.commons.lang.StringUtils;
import org.apache.http.NameValuePair;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestOperations;
import myapp.R;
import roboguice.inject.InjectResource;
import java.lang.reflect.Array;
import java.lang.reflect.ParameterizedType;
import java.net.URI;
import java.net.URISyntaxException;
public abstract class RemoteRESTResourceImpl<T> implements Resource<T> {
@Inject
RestOperations restOperations;
@InjectResource(R.string.authority)
String authority;
@InjectResource(R.string.scheme)
String scheme;
@InjectResource((R.string.apiVersion))
String apiVersion;
private Class<T[]> collectionType = null;
private Class<T> singleType = null;
@Override
public T read(String id) throws ResourceException {
try {
URI uri = buildURI(getPath()+ "/" + id);
HttpHeaders headers = new HttpHeaders();
HttpEntity<T> httpEntity = new HttpEntity<T>(headers);
ResponseEntity<T> response =
restOperations.exchange(uri, HttpMethod.GET,
httpEntity, getSingleType());
return response.getBody();
} catch (RestClientException e) {
throw ResourceException.from(e);
}
}
@Override
public T create(T model) throws ResourceException {
try {
URI uri = buildURI(getPath());
HttpHeaders headers = new HttpHeaders();
HttpEntity<T> entity = new HttpEntity<T>(model, headers);
ResponseEntity<T> response =
restOperations.exchange(uri, HttpMethod.POST,
entity, getSingleType());
return response.getBody();
} catch (RestClientException e) {
throw ResourceException.from(e);
}
}
@Override
public T[] index(NameValuePair... params) throws ResourceException {
try {
URI uri = buildURI(getPath(), params);
HttpHeaders headers = new HttpHeaders();
HttpEntity<T[]> httpEntity = new HttpEntity<T[]>(headers);
ResponseEntity<T[]> response =
restOperations.exchange(uri, HttpMethod.GET,
httpEntity, getCollectionType());
return response.getBody();
} catch (RestClientException e) {
throw ResourceException.from(e);
}
}
protected URI buildURI(String thePath, NameValuePair... params) {
try {
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
.encodedAuthority(authority);
if (!StringUtils.isBlank(apiVersion)) {
builder.appendEncodedPath(apiVersion);
}
builder.appendEncodedPath(thePath);
if (params != null) {
for (NameValuePair param : params) {
builder.appendQueryParameter(param.getName(), param.getValue());
}
}
return new URI(builder.build().toString());
} catch (URISyntaxException e) {
throw new BootyLogException("Can't build URI", e);
}
}
private Class<T[]> getCollectionType() {
if (collectionType == null) {
T[] a = (T[])Array.newInstance(this.getSingleType(), 0);
collectionType = (Class<T[]>) a.getClass();
}
return collectionType;
}
private Class<T> getSingleType() {
if (singleType == null) {
singleType = (Class<T>)((ParameterizedType)this.getClass()
.getGenericSuperclass())
.getActualTypeArguments()[0];
}
return singleType;
}
}
package myapp.resource;
import org.apache.http.NameValuePair;
public interface Resource<T> {
T read(String id) throws ResourceException;
T create(T model) throws ResourceException;
T[] index(NameValuePair... params) throws ResourceException;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment