Fixes for using custom ClassLoaders, try/catch for getting metadata
This commit is contained in:
@@ -39,6 +39,7 @@ import org.springframework.http.converter.json.MappingJacksonHttpMessageConverte
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.client.ResourceAccessException;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.client.support.RestGatewaySupport;
|
||||
|
||||
@@ -93,7 +94,8 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
/**
|
||||
* For converting objects to/from other kinds of objects.
|
||||
*/
|
||||
protected ConversionService conversionService = ConversionServiceFactory.createDefaultConversionService();
|
||||
protected ConversionService conversionService = ConversionServiceFactory
|
||||
.createDefaultConversionService();
|
||||
/**
|
||||
* For caching objects based on ETags.
|
||||
*/
|
||||
@@ -123,6 +125,9 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
*/
|
||||
protected QosParameters defaultQosParameters = null;
|
||||
|
||||
protected Class<?> defaultType = String.class;
|
||||
protected ClassLoader classLoader = null;
|
||||
|
||||
/**
|
||||
* Take all the defaults.
|
||||
*/
|
||||
@@ -187,6 +192,42 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
this.defaultQosParameters = defaultQosParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default type to use if none can be inferred.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Class<?> getDefaultType() {
|
||||
return defaultType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default type to use if none can be inferred.
|
||||
*
|
||||
* @param defaultType
|
||||
*/
|
||||
public void setDefaultType(Class<?> defaultType) {
|
||||
this.defaultType = defaultType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@link ClassLoader} to use when trying to load objects from the store.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public ClassLoader getClassLoader() {
|
||||
return classLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ClassLoader} to use when trying to load objects from the store.
|
||||
*
|
||||
* @param classLoader
|
||||
*/
|
||||
public void setClassLoader(ClassLoader classLoader) {
|
||||
this.classLoader = classLoader;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
Matcher m = prefix.matcher(defaultUri);
|
||||
if (m.matches()) {
|
||||
@@ -278,7 +319,7 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
|
||||
protected MediaType extractMediaType(Object value) {
|
||||
MediaType mediaType = (value instanceof byte[] ? MediaType.APPLICATION_OCTET_STREAM : MediaType.APPLICATION_JSON);
|
||||
if (value.getClass().getAnnotations().length > 0) {
|
||||
if (null != value && value.getClass().getAnnotations().length > 0) {
|
||||
KeyValueStoreMetaData meta = value.getClass()
|
||||
.getAnnotation(KeyValueStoreMetaData.class);
|
||||
if (null != meta) {
|
||||
@@ -327,7 +368,8 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected <T> RiakValue<T> extractValue(final ResponseEntity<?> response, Class<?> origType, Class<T> requiredType) throws
|
||||
protected <T> RiakValue<T> extractValue(final ResponseEntity<?> response, Class<?> origType,
|
||||
Class<T> requiredType) throws
|
||||
IOException {
|
||||
if (response.hasBody()) {
|
||||
RiakMetaData meta = extractMetaData(response.getHeaders());
|
||||
@@ -346,8 +388,9 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
o = conv.read(requiredType, new HttpInputMessage() {
|
||||
public InputStream getBody() throws IOException {
|
||||
Object body = response.getBody();
|
||||
return new ByteArrayInputStream((body instanceof byte[] ? (byte[]) body : ((String) body)
|
||||
.getBytes()));
|
||||
return new ByteArrayInputStream(
|
||||
(body instanceof byte[] ? (byte[]) body : ((String) body)
|
||||
.getBytes()));
|
||||
}
|
||||
|
||||
public HttpHeaders getHeaders() {
|
||||
@@ -360,7 +403,8 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
|
||||
}
|
||||
} else {
|
||||
throw new DataStoreOperationException("Cannot convert object of type " + origType + " to type " + requiredType);
|
||||
throw new DataStoreOperationException(
|
||||
"Cannot convert object of type " + origType + " to type " + requiredType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -377,19 +421,23 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
String bucketName = (null != bucketKeyPair.getBucket() ? bucketKeyPair.getBucket()
|
||||
.toString() : requiredType.getName());
|
||||
RestTemplate restTemplate = getRestTemplate();
|
||||
HttpHeaders resp = restTemplate.headForHeaders(defaultUri,
|
||||
bucketName,
|
||||
bucketKeyPair.getKey());
|
||||
if (!obj.getMetaData()
|
||||
.getProperties()
|
||||
.get("ETag")
|
||||
.toString()
|
||||
.equals(resp.getETag())) {
|
||||
obj = null;
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Returning CACHED object: " + obj);
|
||||
try {
|
||||
HttpHeaders resp = restTemplate.headForHeaders(defaultUri,
|
||||
bucketName,
|
||||
bucketKeyPair.getKey());
|
||||
if (!obj.getMetaData()
|
||||
.getProperties()
|
||||
.get("ETag")
|
||||
.toString()
|
||||
.equals(resp.getETag())) {
|
||||
obj = null;
|
||||
} else {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Returning CACHED object: " + obj);
|
||||
}
|
||||
}
|
||||
} catch (ResourceAccessException ignored) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -411,17 +459,20 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
List<String> params = new LinkedList<String>();
|
||||
if (null != qosParams.getReadThreshold()) {
|
||||
params.add(String.format("r=%s", qosParams.<Object>getReadThreshold()));
|
||||
} else if (null != defaultQosParameters && null != defaultQosParameters.getReadThreshold()) {
|
||||
} else if (null != defaultQosParameters && null != defaultQosParameters
|
||||
.getReadThreshold()) {
|
||||
params.add(String.format("r=%s", defaultQosParameters.getReadThreshold()));
|
||||
}
|
||||
if (null != qosParams.getWriteThreshold()) {
|
||||
params.add(String.format("w=%s", qosParams.<Object>getWriteThreshold()));
|
||||
} else if (null != defaultQosParameters && null != defaultQosParameters.getWriteThreshold()) {
|
||||
} else if (null != defaultQosParameters && null != defaultQosParameters
|
||||
.getWriteThreshold()) {
|
||||
params.add(String.format("w=%s", defaultQosParameters.getWriteThreshold()));
|
||||
}
|
||||
if (null != qosParams.getDurableWriteThreshold()) {
|
||||
params.add(String.format("dw=%s", qosParams.<Object>getDurableWriteThreshold()));
|
||||
} else if (null != defaultQosParameters && null != defaultQosParameters.getDurableWriteThreshold()) {
|
||||
} else if (null != defaultQosParameters && null != defaultQosParameters
|
||||
.getDurableWriteThreshold()) {
|
||||
params.add(String.format("dw=%s", defaultQosParameters.getDurableWriteThreshold()));
|
||||
}
|
||||
|
||||
@@ -443,27 +494,39 @@ public abstract class AbstractRiakTemplate extends RestGatewaySupport implements
|
||||
}
|
||||
|
||||
protected <B, K> Class<?> getType(B bucket, K key) {
|
||||
HttpHeaders headers = getRestTemplate().headForHeaders(defaultUri, bucket, key);
|
||||
return getType(bucket, key, getClass().getClassLoader());
|
||||
}
|
||||
|
||||
protected <B, K> Class<?> getType(B bucket, K key, ClassLoader classLoader) {
|
||||
Class<?> clazz = null;
|
||||
if (null != headers) {
|
||||
String s = headers.getFirst(RIAK_META_CLASSNAME);
|
||||
if (null != s) {
|
||||
try {
|
||||
clazz = Class.forName(s);
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
try {
|
||||
HttpHeaders headers = getRestTemplate().headForHeaders(defaultUri, bucket, key);
|
||||
if (null != headers) {
|
||||
String s = headers.getFirst(RIAK_META_CLASSNAME);
|
||||
if (null != s) {
|
||||
try {
|
||||
if (null != classLoader) {
|
||||
clazz = Class.forName(s, false, classLoader);
|
||||
} else {
|
||||
clazz = Class.forName(s);
|
||||
}
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (null == clazz) {
|
||||
if (headers.getContentType().equals(MediaType.APPLICATION_JSON)) {
|
||||
clazz = Map.class;
|
||||
} else if (headers.getContentType().equals(MediaType.TEXT_PLAIN)) {
|
||||
clazz = String.class;
|
||||
} else {
|
||||
// handle as bytes
|
||||
log.error("Need to handle bytes!");
|
||||
clazz = byte[].class;
|
||||
if (null == clazz) {
|
||||
if (headers.getContentType().equals(MediaType.APPLICATION_JSON)) {
|
||||
clazz = Map.class;
|
||||
} else if (headers.getContentType().equals(MediaType.TEXT_PLAIN)) {
|
||||
clazz = String.class;
|
||||
} else {
|
||||
// handle as bytes
|
||||
log.error("Need to handle bytes!");
|
||||
clazz = byte[].class;
|
||||
}
|
||||
}
|
||||
} catch (ResourceAccessException notFound) {
|
||||
clazz = String.class;
|
||||
}
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@@ -104,7 +104,8 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
return setWithMetaData(bucket, key, value, null, null);
|
||||
}
|
||||
|
||||
public <B, K, V> BucketKeyValueStoreOperations set(B bucket, K key, V value, QosParameters qosParams) {
|
||||
public <B, K, V> BucketKeyValueStoreOperations set(B bucket, K key, V value,
|
||||
QosParameters qosParams) {
|
||||
return setWithMetaData(bucket, key, value, null, qosParams);
|
||||
}
|
||||
|
||||
@@ -112,11 +113,14 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
return setAsBytes(bucket, key, value, null);
|
||||
}
|
||||
|
||||
public <B, K> BucketKeyValueStoreOperations setAsBytes(B bucket, K key, byte[] value, QosParameters qosParams) {
|
||||
public <B, K> BucketKeyValueStoreOperations setAsBytes(B bucket, K key, byte[] value,
|
||||
QosParameters qosParams) {
|
||||
return setWithMetaData(bucket, key, value, null, qosParams);
|
||||
}
|
||||
|
||||
public <B, K, V> BucketKeyValueStoreOperations setWithMetaData(B bucket, K key, V value, Map<String, String> metaData, QosParameters qosParams) {
|
||||
public <B, K, V> BucketKeyValueStoreOperations setWithMetaData(B bucket, K key, V value,
|
||||
Map<String, String> metaData,
|
||||
QosParameters qosParams) {
|
||||
Assert.notNull(key, "Key cannot be null!");
|
||||
// Get a key name that may or may not include the QOS parameters.
|
||||
String keyName = (null != qosParams ? key.toString() + extractQosParameters(qosParams) : key
|
||||
@@ -130,6 +134,9 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
RestTemplate restTemplate = getRestTemplate();
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("X-Riak-ClientId", RIAK_CLIENT_ID);
|
||||
if (log.isDebugEnabled() && null == value) {
|
||||
log.debug("bucket=" + bucket + ", key=" + key);
|
||||
}
|
||||
headers.setContentType(extractMediaType(value));
|
||||
if (null != vclock) {
|
||||
headers.set(RIAK_VCLOCK, vclock);
|
||||
@@ -139,7 +146,8 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
headers.set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
headers.set(RIAK_META_CLASSNAME, value.getClass().getName());
|
||||
headers.set(RIAK_META_CLASSNAME,
|
||||
(null != value ? value.getClass().getName() : defaultType.getName()));
|
||||
HttpEntity<V> entity = new HttpEntity<V>(value, headers);
|
||||
try {
|
||||
restTemplate.put(defaultUri, entity, bucket, keyName);
|
||||
@@ -152,7 +160,8 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
return this;
|
||||
}
|
||||
|
||||
public <B, K, V> BucketKeyValueStoreOperations setWithMetaData(B bucket, K key, V value, Map<String, String> metaData) {
|
||||
public <B, K, V> BucketKeyValueStoreOperations setWithMetaData(B bucket, K key, V value,
|
||||
Map<String, String> metaData) {
|
||||
return setWithMetaData(bucket, key, value, metaData, null);
|
||||
}
|
||||
|
||||
@@ -233,7 +242,7 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
key,
|
||||
requiredType.getName()));
|
||||
}
|
||||
Class<?> origType = getType(bucket, key);
|
||||
Class<?> origType = getType(bucket, key, classLoader);
|
||||
RiakValue<T> val = null;
|
||||
try {
|
||||
ResponseEntity<?> result = restTemplate.getForEntity(defaultUri,
|
||||
@@ -301,7 +310,7 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <B, K, T> T get(B bucket, K key) {
|
||||
Class targetClass = getType(bucket, key);
|
||||
Class targetClass = getType(bucket, key, classLoader);
|
||||
RiakValue<T> obj = getWithMetaData(bucket, key, targetClass);
|
||||
return (null != obj ? obj.get() : null);
|
||||
}
|
||||
@@ -443,7 +452,8 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
return this;
|
||||
}
|
||||
|
||||
public <B, K> BucketKeyValueStoreOperations setIfKeyNonExistentAsBytes(B bucket, K key, byte[] value) {
|
||||
public <B, K> BucketKeyValueStoreOperations setIfKeyNonExistentAsBytes(B bucket, K key,
|
||||
byte[] value) {
|
||||
if (!containsKey(bucket, key)) {
|
||||
setAsBytes(bucket, key, value);
|
||||
} else {
|
||||
@@ -523,7 +533,8 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
return conv.convert(obj, targetType);
|
||||
} else {
|
||||
throw new DataAccessResourceFailureException(
|
||||
"Can't find a converter to to convert " + obj.getClass() + " returned from M/R job to required type " + targetType);
|
||||
"Can't find a converter to to convert " + obj
|
||||
.getClass() + " returned from M/R job to required type " + targetType);
|
||||
}
|
||||
} else {
|
||||
return (T) obj;
|
||||
@@ -557,7 +568,8 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <B1, K1, B2, K2> RiakTemplate link(B1 destBucket, K1 destKey, B2 sourceBucket, K2 sourceKey, String tag) {
|
||||
public <B1, K1, B2, K2> RiakTemplate link(B1 destBucket, K1 destKey, B2 sourceBucket,
|
||||
K2 sourceKey, String tag) {
|
||||
RestTemplate restTemplate = getRestTemplate();
|
||||
|
||||
// Skip all conversion on the data since all we care about is the Link header.
|
||||
@@ -677,11 +689,12 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
}
|
||||
Class<?> clazz = requiredType;
|
||||
if (null == clazz) {
|
||||
clazz = getType(bucketName, key);
|
||||
clazz = getType(bucketName, key, classLoader);
|
||||
}
|
||||
|
||||
// Can convert message?
|
||||
for (HttpMessageConverter converter : restTemplate.getMessageConverters()) {
|
||||
for (HttpMessageConverter converter : restTemplate
|
||||
.getMessageConverters()) {
|
||||
if (converter.canRead(clazz, MediaType.parseMediaType(partType))) {
|
||||
HttpInputMessage msg = new HttpInputMessage() {
|
||||
public InputStream getBody() throws IOException {
|
||||
@@ -745,7 +758,8 @@ public class RiakTemplate extends AbstractRiakTemplate implements BucketKeyValue
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public <B> BucketKeyValueStoreOperations updateBucketSchema(B bucket, Map<String, Object> props) {
|
||||
public <B> BucketKeyValueStoreOperations updateBucketSchema(B bucket,
|
||||
Map<String, Object> props) {
|
||||
Map<Object, Object> bucketProps = new LinkedHashMap<Object, Object>();
|
||||
bucketProps.put("props", props);
|
||||
RestTemplate restTemplate = getRestTemplate();
|
||||
|
||||
Reference in New Issue
Block a user