DATACOUCH-135 - Migrate to Couchbase SDK 2.0 and add N1QL find method.
Adaptation were made to use SDK 2.0: - Reworked the configuration approach (more parts to be configured, like Environment, Cluster and Bucket) - Added a new xml schema for configuration of 2.0 version - Adapted the template - Added N1QL support in the template (findByN1QL) - Removed the cache package - Adapted the repository - Better separated Unit Tests from Integration Tests All integration and unit tests pass, except one (SimpleCouchbaseRepositoryTests.shouldFindCustom). Customisation of a ViewQuery will be addressed in another ticket.
This commit is contained in:
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.cache;
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.SimpleValueWrapper;
|
||||
|
||||
/**
|
||||
* The {@link CouchbaseCache} class implements the Spring Cache interface on top of Couchbase Server and the Couchbase
|
||||
* Java SDK.
|
||||
*
|
||||
* @see <a href="http://static.springsource.org/spring/docs/current/spring-framework-reference/html/cache.html">
|
||||
* Official Spring Cache Reference</a>
|
||||
* @author Michael Nitschinger
|
||||
* @author Konrad Król
|
||||
*/
|
||||
public class CouchbaseCache implements Cache {
|
||||
|
||||
/**
|
||||
* The actual CouchbaseClient instance.
|
||||
*/
|
||||
private final CouchbaseClient client;
|
||||
|
||||
/**
|
||||
* The name of the cache.
|
||||
*/
|
||||
private final String name;
|
||||
|
||||
/**
|
||||
* TTL value for objects in this cache
|
||||
*/
|
||||
private final int ttl;
|
||||
|
||||
/**
|
||||
* Construct the cache and pass in the CouchbaseClient instance.
|
||||
*
|
||||
* @param name the name of the cache reference.
|
||||
* @param client the CouchbaseClient instance.
|
||||
*/
|
||||
public CouchbaseCache(final String name, final CouchbaseClient client) {
|
||||
this.name = name;
|
||||
this.client = client;
|
||||
this.ttl = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct the cache and pass in the CouchbaseClient instance.
|
||||
*
|
||||
* @param name the name of the cache reference.
|
||||
* @param client the CouchbaseClient instance.
|
||||
* @param ttl TTL value for objects in this cache
|
||||
*/
|
||||
public CouchbaseCache(final String name, final CouchbaseClient client, int ttl) {
|
||||
this.name = name;
|
||||
this.client = client;
|
||||
this.ttl = ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the cache.
|
||||
*
|
||||
* @return the name of the cache.
|
||||
*/
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the actual CouchbaseClient instance.
|
||||
*
|
||||
* @return the actual CouchbaseClient instance.
|
||||
*/
|
||||
public final CouchbaseClient getNativeCache() {
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TTL value for this cache.
|
||||
*
|
||||
* @return TTL value
|
||||
*/
|
||||
public final int getTtl() {
|
||||
return ttl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an element from the cache.
|
||||
*
|
||||
* @param key the key to lookup against.
|
||||
* @return the fetched value from Couchbase.
|
||||
*/
|
||||
public final ValueWrapper get(final Object key) {
|
||||
String documentId = key.toString();
|
||||
Object result = client.get(documentId);
|
||||
return (result != null ? new SimpleValueWrapper(result) : null);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T> T get(final Object key, final Class<T> clazz) {
|
||||
String documentId = key.toString();
|
||||
return (T) client.get(documentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a object in Couchbase.
|
||||
*
|
||||
* @param key the Key of the storable object.
|
||||
* @param value the Object to store.
|
||||
*/
|
||||
public final void put(final Object key, final Object value) {
|
||||
if (value != null) {
|
||||
String documentId = key.toString();
|
||||
client.set(documentId, ttl, value);
|
||||
} else {
|
||||
evict(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an object from Couchbase.
|
||||
*
|
||||
* @param key the Key of the object to delete.
|
||||
*/
|
||||
public final void evict(final Object key) {
|
||||
String documentId = key.toString();
|
||||
client.delete(documentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the complete cache.
|
||||
*
|
||||
* Note that this action is very destructive, so only use it with care.
|
||||
* Also note that "flush" may not be enabled on the bucket.
|
||||
*/
|
||||
public final void clear() {
|
||||
client.flush();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.cache.Cache#putIfAbsent(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
public ValueWrapper putIfAbsent(Object key, Object value) {
|
||||
|
||||
if(get(key) == null) {
|
||||
put(key, value);
|
||||
return null;
|
||||
}
|
||||
|
||||
return new SimpleValueWrapper(value);
|
||||
}
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.cache;
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.support.AbstractCacheManager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The {@link CouchbaseCacheManager} orchestrates {@link CouchbaseCache} instances.
|
||||
*
|
||||
* Since more than one current {@link CouchbaseClient} connection can be used for caching, the
|
||||
* {@link CouchbaseCacheManager} orchestrates and handles them for the Spring Cache abstraction layer.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Konrad Król
|
||||
*/
|
||||
public class CouchbaseCacheManager extends AbstractCacheManager {
|
||||
|
||||
/**
|
||||
* Holds the reference to all stored CouchbaseClient cache connections.
|
||||
*/
|
||||
private final HashMap<String, CouchbaseClient> clients;
|
||||
|
||||
/**
|
||||
* Holds the TTL configuration for each cache.
|
||||
*/
|
||||
private final HashMap<String, Integer> ttlConfiguration;
|
||||
|
||||
/**
|
||||
* Construct a new CouchbaseCacheManager.
|
||||
*
|
||||
* @param clients one ore more CouchbaseClients to reference.
|
||||
*/
|
||||
public CouchbaseCacheManager(final HashMap<String, CouchbaseClient> clients) {
|
||||
this.clients = clients;
|
||||
this.ttlConfiguration = new HashMap<String, Integer>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new CouchbaseCacheManager.
|
||||
*
|
||||
* @param clients one ore more CouchbaseClients to reference.
|
||||
* @param ttlConfiguration one or more TTL values (in seconds)
|
||||
*/
|
||||
public CouchbaseCacheManager(final HashMap<String, CouchbaseClient> clients, final HashMap<String, Integer> ttlConfiguration) {
|
||||
this.clients = clients;
|
||||
this.ttlConfiguration = ttlConfiguration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Map of all CouchbaseClients with name.
|
||||
*
|
||||
* @return the actual CouchbaseClient instances.
|
||||
*/
|
||||
public final HashMap<String, CouchbaseClient> getClients() {
|
||||
return clients;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates all caches.
|
||||
*
|
||||
* @return a collection of loaded caches.
|
||||
*/
|
||||
@Override
|
||||
protected final Collection<? extends Cache> loadCaches() {
|
||||
Collection<Cache> caches = new LinkedHashSet<Cache>();
|
||||
|
||||
for (Map.Entry<String, CouchbaseClient> cache : clients.entrySet()) {
|
||||
caches.add(new CouchbaseCache(cache.getKey(), cache.getValue(), getTtl(cache.getKey())));
|
||||
}
|
||||
|
||||
return caches;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TTL value for single cache
|
||||
* @param name cache name
|
||||
* @return either the cache TTL value or 0 as a default value
|
||||
*/
|
||||
private int getTtl ( String name ) {
|
||||
Integer expirationTime = ttlConfiguration.get(name);
|
||||
return (expirationTime != null ? expirationTime : 0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,14 +16,23 @@
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import com.couchbase.client.java.Cluster;
|
||||
import com.couchbase.client.java.CouchbaseCluster;
|
||||
import com.couchbase.client.java.env.CouchbaseEnvironment;
|
||||
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.couchbase.core.CouchbaseFactoryBean;
|
||||
import org.springframework.data.couchbase.core.CouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.core.convert.CustomConversions;
|
||||
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
|
||||
@@ -37,29 +46,21 @@ import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Base class for Spring Data Couchbase configuration using JavaConfig.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
@Configuration
|
||||
public abstract class AbstractCouchbaseConfiguration {
|
||||
|
||||
/**
|
||||
* The list of hostnames (or IP addresses to bootstrap from).
|
||||
* The list of hostnames (or IP addresses) to bootstrap from.
|
||||
*
|
||||
* @return the list of bootstrap hosts.
|
||||
*/
|
||||
protected abstract List<String> bootstrapHosts();
|
||||
protected abstract List<String> getBootstrapHosts();
|
||||
|
||||
/**
|
||||
* The name of the bucket to connect to.
|
||||
@@ -76,39 +77,54 @@ public abstract class AbstractCouchbaseConfiguration {
|
||||
protected abstract String getBucketPassword();
|
||||
|
||||
/**
|
||||
* Return the {@link CouchbaseClient} instance to connect to.
|
||||
* Is the {@link #getEnvironment()} to be destroyed by Spring?
|
||||
*
|
||||
* @return true if Spring should destroy the environment with the context, false otherwise.
|
||||
*/
|
||||
protected boolean isEnvironmentManagedBySpring() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this method if you want a customized {@link CouchbaseEnvironment}.
|
||||
* This environment will be managed by Spring, which will call its shutdown()
|
||||
* method upon bean destruction, unless you override {@link #isEnvironmentManagedBySpring()}
|
||||
* as well to return false.
|
||||
*
|
||||
* @return a customized environment, defaults to a {@link DefaultCouchbaseEnvironment}.
|
||||
*/
|
||||
protected CouchbaseEnvironment getEnvironment() {
|
||||
return DefaultCouchbaseEnvironment.create();
|
||||
}
|
||||
|
||||
@Bean(destroyMethod = "shutdown", name = BeanNames.COUCHBASE_ENV)
|
||||
public CouchbaseEnvironment couchbaseEnvironment() {
|
||||
CouchbaseEnvironment env = getEnvironment();
|
||||
if (isEnvironmentManagedBySpring()) {
|
||||
return env;
|
||||
}
|
||||
return new CouchbaseEnvironmentNoShutdownProxy(env);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Cluster} instance to connect to.
|
||||
*
|
||||
* @throws Exception on Bean construction failure.
|
||||
*/
|
||||
@Bean(destroyMethod = "shutdown")
|
||||
public CouchbaseClient couchbaseClient() throws Exception {
|
||||
setLoggerProperty(couchbaseLogger());
|
||||
|
||||
return new CouchbaseClient(
|
||||
bootstrapUris(bootstrapHosts()),
|
||||
getBucketName(),
|
||||
getBucketPassword()
|
||||
);
|
||||
@Bean(destroyMethod = "disconnect", name = BeanNames.COUCHBASE_CLUSTER)
|
||||
public Cluster couchbaseCluster() throws Exception {
|
||||
return CouchbaseCluster.create(couchbaseEnvironment(), getBootstrapHosts());
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the logger to use (defaults to SLF4J).
|
||||
* Return the {@link Bucket} instance to connect to.
|
||||
*
|
||||
* @return the logger property string.
|
||||
* @throws Exception on Bean construction failure.
|
||||
*/
|
||||
protected String couchbaseLogger() {
|
||||
return CouchbaseFactoryBean.DEFAULT_LOGGER_PROPERTY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the logging property before initializing couchbase.
|
||||
*
|
||||
* @param logger the logger path to use.
|
||||
*/
|
||||
protected static void setLoggerProperty(final String logger) {
|
||||
Properties systemProperties = System.getProperties();
|
||||
systemProperties.setProperty("net.spy.log.LoggerImpl", logger);
|
||||
System.setProperties(systemProperties);
|
||||
@Bean(destroyMethod = "close", name = BeanNames.COUCHBASE_BUCKET)
|
||||
public Bucket couchbaseClient() throws Exception {
|
||||
//@Bean method can use another @Bean method in the same @Configuration by directly invoking it
|
||||
return couchbaseCluster().openBucket(getBucketName(), getBucketPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,7 +132,7 @@ public abstract class AbstractCouchbaseConfiguration {
|
||||
*
|
||||
* @throws Exception on Bean construction failure.
|
||||
*/
|
||||
@Bean
|
||||
@Bean(name = BeanNames.COUCHBASE_TEMPLATE)
|
||||
public CouchbaseTemplate couchbaseTemplate() throws Exception {
|
||||
return new CouchbaseTemplate(couchbaseClient(), mappingCouchbaseConverter(), translationService());
|
||||
}
|
||||
@@ -159,8 +175,6 @@ public abstract class AbstractCouchbaseConfiguration {
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Register custom Converters in a {@link CustomConversions} object if required. These
|
||||
* {@link CustomConversions} will be registered with the {@link #mappingCouchbaseConverter()} and
|
||||
@@ -202,7 +216,7 @@ public abstract class AbstractCouchbaseConfiguration {
|
||||
* will be considered {@code com.acme} unless the method is overridden to implement alternate behavior.</p>
|
||||
*
|
||||
* @return the base package to scan for mapped {@link Document} classes or {@literal null} to not enable scanning for
|
||||
* entities.
|
||||
* entities.
|
||||
*/
|
||||
protected String getMappingBasePackage() {
|
||||
return getClass().getPackage().getName();
|
||||
@@ -225,19 +239,4 @@ public abstract class AbstractCouchbaseConfiguration {
|
||||
protected FieldNamingStrategy fieldNamingStrategy() {
|
||||
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy() : PropertyNameFieldNamingStrategy.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given list of hostnames into parsable URIs.
|
||||
*
|
||||
* @param hosts the list of hosts to convert.
|
||||
* @return the converted URIs.
|
||||
*/
|
||||
protected static List<URI> bootstrapUris(List<String> hosts) throws URISyntaxException {
|
||||
List<URI> uris = new ArrayList<URI>();
|
||||
for (String host : hosts) {
|
||||
uris.add(new URI("http://" + host + ":8091/pools"));
|
||||
}
|
||||
return uris;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -20,22 +20,32 @@ package org.springframework.data.couchbase.config;
|
||||
* Contains default bean names that will be used when no "id" is supplied to the beans.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class BeanNames {
|
||||
class BeanNames {
|
||||
|
||||
/**
|
||||
* Refers to the "<couchbase:couchbase />" bean.
|
||||
* Refers to the "<couchbase:env />" bean.
|
||||
*/
|
||||
static final String COUCHBASE = "couchbase";
|
||||
static final String COUCHBASE_ENV = "couchbaseEnv";
|
||||
/**
|
||||
* Refers to the "<couchbase:cluster />" bean.
|
||||
*/
|
||||
static final String COUCHBASE_CLUSTER = "couchbaseCluster";
|
||||
|
||||
/**
|
||||
* Refers to the "<couchbase:template />" bean.
|
||||
* Refers to the "<couchbase:bucket />" bean.
|
||||
*/
|
||||
static final String COUCHBASE_BUCKET = "couchbaseBucket";
|
||||
|
||||
/**
|
||||
* Refers to the "<couchbase:template />" bean.
|
||||
*/
|
||||
static final String COUCHBASE_TEMPLATE = "couchbaseTemplate";
|
||||
|
||||
/**
|
||||
* Refers to the "<couchbase:translation-service />" bean
|
||||
* Refers to the "<couchbase:translation-service />" bean
|
||||
*/
|
||||
static final String TRANSLATION_SERVICE = "translationService";
|
||||
static final String TRANSLATION_SERVICE = "couchbaseTranslationService";
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import com.couchbase.client.java.Cluster;
|
||||
import com.couchbase.client.java.CouchbaseBucket;
|
||||
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.couchbase.core.CouchbaseExceptionTranslator;
|
||||
|
||||
/**
|
||||
* The Factory Bean to help {@link CouchbaseBucketParser} constructing a {@link Bucket} from a given
|
||||
* {@link Cluster} reference.
|
||||
*
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class CouchbaseBucketFactoryBean extends AbstractFactoryBean<Bucket> implements PersistenceExceptionTranslator {
|
||||
|
||||
private final Cluster cluster;
|
||||
private final String bucketName;
|
||||
private final String bucketPassword;
|
||||
|
||||
private final PersistenceExceptionTranslator exceptionTranslator = new CouchbaseExceptionTranslator();
|
||||
|
||||
public CouchbaseBucketFactoryBean(Cluster cluster) {
|
||||
this(cluster, null, null);
|
||||
}
|
||||
|
||||
public CouchbaseBucketFactoryBean(Cluster cluster, String bucketName) {
|
||||
this(cluster, bucketName, null);
|
||||
}
|
||||
|
||||
public CouchbaseBucketFactoryBean(Cluster cluster, String bucketName, String bucketPassword) {
|
||||
this.cluster = cluster;
|
||||
this.bucketName = bucketName;
|
||||
this.bucketPassword = bucketPassword;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return CouchbaseBucket.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bucket createInstance() throws Exception {
|
||||
if (bucketName == null) {
|
||||
return cluster.openBucket();
|
||||
}
|
||||
else if (bucketPassword == null) {
|
||||
return cluster.openBucket(bucketName);
|
||||
}
|
||||
else {
|
||||
return cluster.openBucket(bucketName, bucketPassword);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(RuntimeException ex) {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import com.couchbase.client.java.Cluster;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* The parser for XML definition of a {@link Bucket}, to be constructed from a {@link Cluster} reference.
|
||||
* If no reference is given, the default reference <code>{@value BeanNames#COUCHBASE_CLUSTER}</code> is used.
|
||||
*
|
||||
* See attributes {@link #CLUSTER_REF_ATTR}, {@link #BUCKETNAME_ATTR} and {@link #BUCKETPASSWORD_ATTR}.
|
||||
*
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class CouchbaseBucketParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* The <code>cluster-ref</code> attribute in a bucket definition defines the cluster to build from.
|
||||
*/
|
||||
public static final String CLUSTER_REF_ATTR = "cluster-ref";
|
||||
|
||||
/**
|
||||
* The <code>bucketName</code> attribute in a bucket definition defines the name of the bucket to open.
|
||||
*/
|
||||
public static final String BUCKETNAME_ATTR = "bucketName";
|
||||
|
||||
/**
|
||||
* The <code>bucketPassword</code> attribute in a bucket definition defines the password of the bucket to open.
|
||||
*/
|
||||
public static final String BUCKETPASSWORD_ATTR = "bucketPassword";
|
||||
|
||||
/**
|
||||
* Resolve the bean ID and assign a default if not set.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param definition the bean definition to work with.
|
||||
* @param parserContext encapsulates the parsing state and configuration.
|
||||
* @return the ID to work with.
|
||||
*/
|
||||
@Override
|
||||
protected String resolveId(final Element element, final AbstractBeanDefinition definition, final ParserContext parserContext) {
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
return StringUtils.hasText(id) ? id : BeanNames.COUCHBASE_BUCKET;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the bean class that will be constructed.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @return the class type to instantiate.
|
||||
*/
|
||||
@Override
|
||||
protected Class getBeanClass(final Element element) {
|
||||
return CouchbaseBucketFactoryBean.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the bean definition and build up the bean.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param builder the builder which builds the bean.
|
||||
*/
|
||||
@Override
|
||||
protected void doParse(final Element element, final BeanDefinitionBuilder builder) {
|
||||
String clusterRef = element.getAttribute(CLUSTER_REF_ATTR);
|
||||
if (!StringUtils.hasText(clusterRef)) {
|
||||
clusterRef = BeanNames.COUCHBASE_CLUSTER;
|
||||
}
|
||||
builder.addConstructorArgReference(clusterRef);
|
||||
|
||||
String bucketName = element.getAttribute(BUCKETNAME_ATTR);
|
||||
if (StringUtils.hasText(bucketName)) {
|
||||
builder.addConstructorArgValue(bucketName);
|
||||
}
|
||||
|
||||
String bucketPassword = element.getAttribute(BUCKETPASSWORD_ATTR);
|
||||
if (StringUtils.hasText(bucketPassword)) {
|
||||
builder.addConstructorArgValue(bucketPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.couchbase.client.java.Cluster;
|
||||
import com.couchbase.client.java.CouchbaseCluster;
|
||||
import com.couchbase.client.java.env.CouchbaseEnvironment;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
|
||||
/**
|
||||
* The XML parser for a {@link Cluster} definition.
|
||||
*
|
||||
* Such a definition can be tuned by either referencing a {@link CouchbaseEnvironment} via
|
||||
* the {@value #CLUSTER_ENVIRONMENT_REF} attribute or define a custom environment inline via
|
||||
* the <{@value #CLUSTER_ENVIRONMENT_TAG}> tag (not recommended, environments should be
|
||||
* shared as possible). If no environment reference or inline description is provided, the
|
||||
* default environment reference {@value BeanNames#COUCHBASE_ENV} is used.
|
||||
*
|
||||
* To bootstrap the connection, one can provide IPs or hostnames of nodes to connect to
|
||||
* via 1 or more <{@value #CLUSTER_NODE_TAG}> tags.
|
||||
*
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class CouchbaseClusterParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* The <node> elements in a cluster definition define the bootstrap hosts to use
|
||||
*/
|
||||
public static final String CLUSTER_NODE_TAG = "node";
|
||||
|
||||
/**
|
||||
* The unique <env> element in a cluster definition define the environment customizations.
|
||||
*
|
||||
* @see CouchbaseEnvironmentParser CouchbaseEnvironmentParser for the possible fields.
|
||||
* @see #CLUSTER_ENVIRONMENT_REF CLUSTER_ENVIRONMENT_REF as an alternative (giving a reference to
|
||||
* an env instead of inline description, lower precedence)
|
||||
*/
|
||||
public static final String CLUSTER_ENVIRONMENT_TAG = "env";
|
||||
|
||||
/**
|
||||
* The <env-ref> attribute allows to use a reference to an {@link CouchbaseEnvironment} to
|
||||
* tune the connection.
|
||||
*
|
||||
* @see #CLUSTER_ENVIRONMENT_TAG CLUSTER_ENVIRONMENT_TAG for an inline alternative
|
||||
* (which takes priority over this reference)
|
||||
*/
|
||||
public static final String CLUSTER_ENVIRONMENT_REF = "env-ref";
|
||||
|
||||
/**
|
||||
* Resolve the bean ID and assign a default if not set.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param definition the bean definition to work with.
|
||||
* @param parserContext encapsulates the parsing state and configuration.
|
||||
* @return the ID to work with.
|
||||
*/
|
||||
@Override
|
||||
protected String resolveId(final Element element, final AbstractBeanDefinition definition, final ParserContext parserContext) {
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
return StringUtils.hasText(id) ? id : BeanNames.COUCHBASE_CLUSTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the bean class that will be constructed.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @return the class type to instantiate.
|
||||
*/
|
||||
@Override
|
||||
protected Class getBeanClass(final Element element) {
|
||||
return CouchbaseCluster.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the bean definition and build up the bean.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param bean the builder which builds the bean.
|
||||
*/
|
||||
@Override
|
||||
protected void doParse(final Element element, final BeanDefinitionBuilder bean) {
|
||||
bean.setFactoryMethod("create");
|
||||
bean.setDestroyMethodName("disconnect");
|
||||
|
||||
parseEnvironment(bean, element);
|
||||
|
||||
List<Element> nodes = DomUtils.getChildElementsByTagName(element, CLUSTER_NODE_TAG);
|
||||
if (nodes != null && nodes.size() > 0) {
|
||||
List<String> bootstrapUrls = new ArrayList<String>(nodes.size());
|
||||
for (int i = 0; i < nodes.size(); i++) {
|
||||
bootstrapUrls.add(nodes.get(i).getTextContent());
|
||||
}
|
||||
bean.addConstructorArgValue(bootstrapUrls);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if a custom environment was parsed and injected (either reference or inline), false if
|
||||
* the default environment reference was used.
|
||||
*/
|
||||
protected boolean parseEnvironment(BeanDefinitionBuilder clusterBuilder, Element clusterElement) {
|
||||
//any inline environment description would take precedence over a reference
|
||||
Element envElement = DomUtils.getChildElementByTagName(clusterElement, CLUSTER_ENVIRONMENT_TAG);
|
||||
if (envElement != null && envElement.hasAttributes()) {
|
||||
injectEnvElement(clusterBuilder, envElement);
|
||||
return true;
|
||||
}
|
||||
|
||||
//secondly try to see if an env has been referenced
|
||||
String envRef = clusterElement.getAttribute(CLUSTER_ENVIRONMENT_REF);
|
||||
if (StringUtils.hasText(envRef)) {
|
||||
injectEnvReference(clusterBuilder, envRef);
|
||||
return true;
|
||||
}
|
||||
|
||||
//if no custom value provided, consider it a reference to the default bean for Couchbase Environment
|
||||
injectEnvReference(clusterBuilder, BeanNames.COUCHBASE_ENV);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void injectEnvElement(BeanDefinitionBuilder clusterBuilder, Element envElement) {
|
||||
BeanDefinitionBuilder envDefinitionBuilder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(CouchbaseEnvironmentFactoryBean.class);
|
||||
new CouchbaseEnvironmentParser().doParse(envElement, envDefinitionBuilder);
|
||||
|
||||
clusterBuilder.addConstructorArgValue(envDefinitionBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
protected void injectEnvReference(BeanDefinitionBuilder clusterBuilder, String envRef) {
|
||||
clusterBuilder.addConstructorArgReference(envRef);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import com.couchbase.client.core.retry.BestEffortRetryStrategy;
|
||||
import com.couchbase.client.core.retry.FailFastRetryStrategy;
|
||||
import com.couchbase.client.core.retry.RetryStrategy;
|
||||
import com.couchbase.client.java.env.CouchbaseEnvironment;
|
||||
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
|
||||
|
||||
import org.springframework.beans.factory.config.AbstractFactoryBean;
|
||||
|
||||
/**
|
||||
* Factory Bean to help create a CouchbaseEnvironment (by offering setters for supported tuning methods).
|
||||
*
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
/*package*/ class CouchbaseEnvironmentFactoryBean extends AbstractFactoryBean<CouchbaseEnvironment> {
|
||||
|
||||
private static final CouchbaseEnvironment DEFAULT_ENV = DefaultCouchbaseEnvironment.create();
|
||||
public static final String RETRYSTRATEGY_FAILFAST = "FailFast";
|
||||
public static final String RETRYSTRATEGY_BESTEFFORT = "BestEffort";
|
||||
|
||||
private long managementTimeout = DEFAULT_ENV.managementTimeout();
|
||||
private long queryTimeout = DEFAULT_ENV.queryTimeout();
|
||||
private long viewTimeout = DEFAULT_ENV.viewTimeout();
|
||||
private long kvTimeout = DEFAULT_ENV.kvTimeout();
|
||||
private long connectTimeout = DEFAULT_ENV.connectTimeout();
|
||||
private long disconnectTimeout = DEFAULT_ENV.disconnectTimeout();
|
||||
private boolean dnsSrvEnabled = DEFAULT_ENV.dnsSrvEnabled();
|
||||
|
||||
private boolean dcpEnabled = DEFAULT_ENV.dcpEnabled();
|
||||
private boolean sslEnabled = DEFAULT_ENV.sslEnabled();
|
||||
private String sslKeystoreFile = DEFAULT_ENV.sslKeystoreFile();
|
||||
private String sslKeystorePassword = DEFAULT_ENV.sslKeystorePassword();
|
||||
private boolean queryEnabled = DEFAULT_ENV.queryEnabled();
|
||||
private int queryPort = DEFAULT_ENV.queryPort();
|
||||
private boolean bootstrapHttpEnabled = DEFAULT_ENV.bootstrapHttpEnabled();
|
||||
private boolean bootstrapCarrierEnabled = DEFAULT_ENV.bootstrapCarrierEnabled();
|
||||
private int bootstrapHttpDirectPort = DEFAULT_ENV.bootstrapHttpDirectPort();
|
||||
private int bootstrapHttpSslPort = DEFAULT_ENV.bootstrapHttpSslPort();
|
||||
private int bootstrapCarrierDirectPort = DEFAULT_ENV.bootstrapCarrierDirectPort();
|
||||
private int bootstrapCarrierSslPort = DEFAULT_ENV.bootstrapCarrierSslPort();
|
||||
private int ioPoolSize = DEFAULT_ENV.ioPoolSize();
|
||||
private int computationPoolSize = DEFAULT_ENV.computationPoolSize();
|
||||
private int responseBufferSize = DEFAULT_ENV.responseBufferSize();
|
||||
private int requestBufferSize = DEFAULT_ENV.requestBufferSize();
|
||||
private int kvEndpoints = DEFAULT_ENV.kvEndpoints();
|
||||
private int viewEndpoints = DEFAULT_ENV.viewEndpoints();
|
||||
private int queryEndpoints = DEFAULT_ENV.queryEndpoints();
|
||||
private RetryStrategy retryStrategy = DEFAULT_ENV.retryStrategy();
|
||||
private long maxRequestLifetime = DEFAULT_ENV.maxRequestLifetime();
|
||||
private long keepAliveInterval = DEFAULT_ENV.keepAliveInterval();
|
||||
private long autoreleaseAfter = DEFAULT_ENV.autoreleaseAfter();
|
||||
private boolean bufferPoolingEnabled = DEFAULT_ENV.bufferPoolingEnabled();
|
||||
|
||||
//These are tunings that are not practical to be exposed in a xml configuration
|
||||
//or not supposed to be modified that easily:
|
||||
// observeIntervalDelay
|
||||
// reconnectDelay
|
||||
// retryDelay
|
||||
// userAgent
|
||||
// packageNameAndVersion
|
||||
// ioPool
|
||||
// scheduler
|
||||
// eventBus
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return DefaultCouchbaseEnvironment.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CouchbaseEnvironment createInstance() throws Exception {
|
||||
return DefaultCouchbaseEnvironment.builder()
|
||||
.managementTimeout(managementTimeout)
|
||||
.queryTimeout(queryTimeout)
|
||||
.viewTimeout(viewTimeout)
|
||||
.kvTimeout(kvTimeout)
|
||||
.connectTimeout(connectTimeout)
|
||||
.disconnectTimeout(disconnectTimeout)
|
||||
.dnsSrvEnabled(dnsSrvEnabled)
|
||||
.dcpEnabled(dcpEnabled)
|
||||
.sslEnabled(sslEnabled)
|
||||
.sslKeystoreFile(sslKeystoreFile)
|
||||
.sslKeystorePassword(sslKeystorePassword)
|
||||
.queryEnabled(queryEnabled)
|
||||
.queryPort(queryPort)
|
||||
.bootstrapHttpEnabled(bootstrapHttpEnabled)
|
||||
.bootstrapCarrierEnabled(bootstrapCarrierEnabled)
|
||||
.bootstrapHttpDirectPort(bootstrapHttpDirectPort)
|
||||
.bootstrapHttpSslPort(bootstrapHttpSslPort)
|
||||
.bootstrapCarrierDirectPort(bootstrapCarrierDirectPort)
|
||||
.bootstrapCarrierSslPort(bootstrapCarrierSslPort)
|
||||
.ioPoolSize(ioPoolSize)
|
||||
.computationPoolSize(computationPoolSize)
|
||||
.responseBufferSize(responseBufferSize)
|
||||
.requestBufferSize(requestBufferSize)
|
||||
.kvEndpoints(kvEndpoints)
|
||||
.viewEndpoints(viewEndpoints)
|
||||
.queryEndpoints(queryEndpoints)
|
||||
.retryStrategy(retryStrategy)
|
||||
.maxRequestLifetime(maxRequestLifetime)
|
||||
.keepAliveInterval(keepAliveInterval)
|
||||
.autoreleaseAfter(autoreleaseAfter)
|
||||
.bufferPoolingEnabled(bufferPoolingEnabled)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link RetryStrategy} to use from an enum-like String value.
|
||||
* Either "FailFast" or "BestEffort" are recognized.
|
||||
*
|
||||
* @param retryStrategy the string value enum from which to choose a strategy.
|
||||
*/
|
||||
public void setRetryStrategy(String retryStrategy) {
|
||||
if (RETRYSTRATEGY_FAILFAST.equals(retryStrategy)){
|
||||
this.retryStrategy = FailFastRetryStrategy.INSTANCE;
|
||||
} else if (RETRYSTRATEGY_BESTEFFORT.equals(retryStrategy)) {
|
||||
this.retryStrategy = BestEffortRetryStrategy.INSTANCE;
|
||||
}
|
||||
}
|
||||
|
||||
//==== SETTERS for the factory bean ====
|
||||
|
||||
public void setManagementTimeout(long managementTimeout) {
|
||||
this.managementTimeout = managementTimeout;
|
||||
}
|
||||
|
||||
public void setQueryTimeout(long queryTimeout) {
|
||||
this.queryTimeout = queryTimeout;
|
||||
}
|
||||
|
||||
public void setViewTimeout(long viewTimeout) {
|
||||
this.viewTimeout = viewTimeout;
|
||||
}
|
||||
|
||||
public void setKvTimeout(long kvTimeout) {
|
||||
this.kvTimeout = kvTimeout;
|
||||
}
|
||||
|
||||
public void setConnectTimeout(long connectTimeout) {
|
||||
this.connectTimeout = connectTimeout;
|
||||
}
|
||||
|
||||
public void setDisconnectTimeout(long disconnectTimeout) {
|
||||
this.disconnectTimeout = disconnectTimeout;
|
||||
}
|
||||
|
||||
public void setDnsSrvEnabled(boolean dnsSrvEnabled) {
|
||||
this.dnsSrvEnabled = dnsSrvEnabled;
|
||||
}
|
||||
|
||||
public void setDcpEnabled(boolean dcpEnabled) {
|
||||
this.dcpEnabled = dcpEnabled;
|
||||
}
|
||||
|
||||
public void setSslEnabled(boolean sslEnabled) {
|
||||
this.sslEnabled = sslEnabled;
|
||||
}
|
||||
|
||||
public void setSslKeystoreFile(String sslKeystoreFile) {
|
||||
this.sslKeystoreFile = sslKeystoreFile;
|
||||
}
|
||||
|
||||
public void setSslKeystorePassword(String sslKeystorePassword) {
|
||||
this.sslKeystorePassword = sslKeystorePassword;
|
||||
}
|
||||
|
||||
public void setQueryEnabled(boolean queryEnabled) {
|
||||
this.queryEnabled = queryEnabled;
|
||||
}
|
||||
|
||||
public void setQueryPort(int queryPort) {
|
||||
this.queryPort = queryPort;
|
||||
}
|
||||
|
||||
public void setBootstrapHttpEnabled(boolean bootstrapHttpEnabled) {
|
||||
this.bootstrapHttpEnabled = bootstrapHttpEnabled;
|
||||
}
|
||||
|
||||
public void setBootstrapCarrierEnabled(boolean bootstrapCarrierEnabled) {
|
||||
this.bootstrapCarrierEnabled = bootstrapCarrierEnabled;
|
||||
}
|
||||
|
||||
public void setBootstrapHttpDirectPort(int bootstrapHttpDirectPort) {
|
||||
this.bootstrapHttpDirectPort = bootstrapHttpDirectPort;
|
||||
}
|
||||
|
||||
public void setBootstrapHttpSslPort(int bootstrapHttpSslPort) {
|
||||
this.bootstrapHttpSslPort = bootstrapHttpSslPort;
|
||||
}
|
||||
|
||||
public void setBootstrapCarrierDirectPort(int bootstrapCarrierDirectPort) {
|
||||
this.bootstrapCarrierDirectPort = bootstrapCarrierDirectPort;
|
||||
}
|
||||
|
||||
public void setBootstrapCarrierSslPort(int bootstrapCarrierSslPort) {
|
||||
this.bootstrapCarrierSslPort = bootstrapCarrierSslPort;
|
||||
}
|
||||
|
||||
public void setIoPoolSize(int ioPoolSize) {
|
||||
this.ioPoolSize = ioPoolSize;
|
||||
}
|
||||
|
||||
public void setComputationPoolSize(int computationPoolSize) {
|
||||
this.computationPoolSize = computationPoolSize;
|
||||
}
|
||||
|
||||
public void setResponseBufferSize(int responseBufferSize) {
|
||||
this.responseBufferSize = responseBufferSize;
|
||||
}
|
||||
|
||||
public void setRequestBufferSize(int requestBufferSize) {
|
||||
this.requestBufferSize = requestBufferSize;
|
||||
}
|
||||
|
||||
public void setKvEndpoints(int kvEndpoints) {
|
||||
this.kvEndpoints = kvEndpoints;
|
||||
}
|
||||
|
||||
public void setViewEndpoints(int viewEndpoints) {
|
||||
this.viewEndpoints = viewEndpoints;
|
||||
}
|
||||
|
||||
public void setQueryEndpoints(int queryEndpoints) {
|
||||
this.queryEndpoints = queryEndpoints;
|
||||
}
|
||||
|
||||
public void setMaxRequestLifetime(long maxRequestLifetime) {
|
||||
this.maxRequestLifetime = maxRequestLifetime;
|
||||
}
|
||||
|
||||
public void setKeepAliveInterval(long keepAliveInterval) {
|
||||
this.keepAliveInterval = keepAliveInterval;
|
||||
}
|
||||
|
||||
public void setAutoreleaseAfter(long autoreleaseAfter) {
|
||||
this.autoreleaseAfter = autoreleaseAfter;
|
||||
}
|
||||
|
||||
public void setBufferPoolingEnabled(boolean bufferPoolingEnabled) {
|
||||
this.bufferPoolingEnabled = bufferPoolingEnabled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import com.couchbase.client.core.event.EventBus;
|
||||
import com.couchbase.client.core.retry.RetryStrategy;
|
||||
import com.couchbase.client.core.time.Delay;
|
||||
import com.couchbase.client.deps.io.netty.channel.EventLoopGroup;
|
||||
import com.couchbase.client.java.env.CouchbaseEnvironment;
|
||||
import rx.Observable;
|
||||
import rx.Scheduler;
|
||||
|
||||
/**
|
||||
* A proxy around a {@link CouchbaseEnvironment} that prevents its {@link #shutdown()} method
|
||||
* to be invoked. Useful when the delegate is not to be lifecycle-managed by Spring.
|
||||
*
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class CouchbaseEnvironmentNoShutdownProxy implements CouchbaseEnvironment {
|
||||
|
||||
private final CouchbaseEnvironment delegate;
|
||||
|
||||
public CouchbaseEnvironmentNoShutdownProxy(CouchbaseEnvironment delegate) {
|
||||
this.delegate = delegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Observable<Boolean> shutdown() {
|
||||
return Observable.just(false);
|
||||
}
|
||||
|
||||
//===== DELEGATION METHODS =====
|
||||
|
||||
@Override
|
||||
public EventLoopGroup ioPool() {
|
||||
return delegate.ioPool();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scheduler scheduler() {
|
||||
return delegate.scheduler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dcpEnabled() {
|
||||
return delegate.dcpEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sslEnabled() {
|
||||
return delegate.sslEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sslKeystoreFile() {
|
||||
return delegate.sslKeystoreFile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sslKeystorePassword() {
|
||||
return delegate.sslKeystorePassword();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean queryEnabled() {
|
||||
return delegate.queryEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int queryPort() {
|
||||
return delegate.queryPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean bootstrapHttpEnabled() {
|
||||
return delegate.bootstrapHttpEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean bootstrapCarrierEnabled() {
|
||||
return delegate.bootstrapCarrierEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bootstrapHttpDirectPort() {
|
||||
return delegate.bootstrapHttpDirectPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bootstrapHttpSslPort() {
|
||||
return delegate.bootstrapHttpSslPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bootstrapCarrierDirectPort() {
|
||||
return delegate.bootstrapCarrierDirectPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int bootstrapCarrierSslPort() {
|
||||
return delegate.bootstrapCarrierSslPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int ioPoolSize() {
|
||||
return delegate.ioPoolSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int computationPoolSize() {
|
||||
return delegate.computationPoolSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Delay observeIntervalDelay() {
|
||||
return delegate.observeIntervalDelay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Delay reconnectDelay() {
|
||||
return delegate.reconnectDelay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Delay retryDelay() {
|
||||
return delegate.retryDelay();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int requestBufferSize() {
|
||||
return delegate.requestBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int responseBufferSize() {
|
||||
return delegate.responseBufferSize();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int kvEndpoints() {
|
||||
return delegate.kvEndpoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int viewEndpoints() {
|
||||
return delegate.viewEndpoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int queryEndpoints() {
|
||||
return delegate.queryEndpoints();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String userAgent() {
|
||||
return delegate.userAgent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String packageNameAndVersion() {
|
||||
return delegate.packageNameAndVersion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public RetryStrategy retryStrategy() {
|
||||
return delegate.retryStrategy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long maxRequestLifetime() {
|
||||
return delegate.maxRequestLifetime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long autoreleaseAfter() {
|
||||
return delegate.autoreleaseAfter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long keepAliveInterval() {
|
||||
return delegate.keepAliveInterval();
|
||||
}
|
||||
|
||||
@Override
|
||||
public EventBus eventBus() {
|
||||
return delegate.eventBus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean bufferPoolingEnabled() {
|
||||
return delegate.bufferPoolingEnabled();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long managementTimeout() {
|
||||
return delegate.managementTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long queryTimeout() {
|
||||
return delegate.queryTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long viewTimeout() {
|
||||
return delegate.viewTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long kvTimeout() {
|
||||
return delegate.kvTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long connectTimeout() {
|
||||
return delegate.connectTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long disconnectTimeout() {
|
||||
return delegate.disconnectTimeout();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dnsSrvEnabled() {
|
||||
return delegate.dnsSrvEnabled();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import static org.springframework.data.config.ParsingUtils.setPropertyValue;
|
||||
|
||||
import com.couchbase.client.core.retry.RetryStrategy;
|
||||
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Allows creation of a {@link DefaultCouchbaseEnvironment} via spring XML configuration.
|
||||
* <p>
|
||||
* The following properties are supported:<br/><ul>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#managementTimeout(long) managementTimeout}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#queryTimeout(long) queryTimeout}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#viewTimeout(long) viewTimeout}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#kvTimeout(long) kvTimeout}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#connectTimeout(long) connectTimeout}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#disconnectTimeout(long) disconnectTimeout}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#dnsSrvEnabled(boolean) dnsSrvEnabled}</li>
|
||||
*
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#dcpEnabled(boolean) dcpEnabled}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#sslEnabled(boolean) sslEnabled}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#sslKeystoreFile(String) sslKeystoreFile}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#sslKeystorePassword(String) sslKeystorePassword}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#queryEnabled(boolean) queryEnabled}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#queryPort(int) queryPort}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#bootstrapHttpEnabled(boolean) bootstrapHttpEnabled}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#bootstrapCarrierEnabled(boolean) bootstrapCarrierEnabled}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#bootstrapHttpDirectPort(int) bootstrapHttpDirectPort}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#bootstrapHttpSslPort(int) bootstrapHttpSslPort}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#bootstrapCarrierDirectPort(int) bootstrapCarrierDirectPort}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#bootstrapCarrierSslPort(int) bootstrapCarrierSslPort}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#ioPoolSize(int) ioPoolSize}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#computationPoolSize(int) computationPoolSize}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#responseBufferSize(int) responseBufferSize}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#requestBufferSize(int) requestBufferSize}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#kvEndpoints(int) kvEndpoints}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#viewEndpoints(int) viewEndpoints}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#queryEndpoints(int) queryEndpoints}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#retryStrategy(RetryStrategy) retryStrategy}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#maxRequestLifetime(long) maxRequestLifetime}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#keepAliveInterval(long) keepAliveInterval}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#autoreleaseAfter(long) autoreleaseAfter}</li>
|
||||
* <li>{@link DefaultCouchbaseEnvironment.Builder#bufferPoolingEnabled(boolean) bufferPoolingEnabled}</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class CouchbaseEnvironmentParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Resolve the bean ID and assign a default if not set.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param definition the bean definition to work with.
|
||||
* @param parserContext encapsulates the parsing state and configuration.
|
||||
* @return the ID to work with.
|
||||
*/
|
||||
@Override
|
||||
protected String resolveId(final Element element, final AbstractBeanDefinition definition, final ParserContext parserContext) {
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
return StringUtils.hasText(id) ? id : BeanNames.COUCHBASE_ENV;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the bean class that will be constructed.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @return the class type to instantiate.
|
||||
*/
|
||||
@Override
|
||||
protected Class getBeanClass(final Element element) {
|
||||
return CouchbaseEnvironmentFactoryBean.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the bean definition and build up the bean.
|
||||
*
|
||||
* @param envElement the XML element which contains the attributes.
|
||||
* @param envDefinitionBuilder the builder which builds the bean.
|
||||
*/
|
||||
@Override
|
||||
protected void doParse(final Element envElement, final BeanDefinitionBuilder envDefinitionBuilder) {
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "managementTimeout", "managementTimeout");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "queryTimeout", "queryTimeout");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "viewTimeout", "viewTimeout");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "kvTimeout", "kvTimeout");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "connectTimeout", "connectTimeout");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "disconnectTimeout", "disconnectTimeout");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "dnsSrvEnabled", "dnsSrvEnabled");
|
||||
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "dcpEnabled", "dcpEnabled");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "sslEnabled", "sslEnabled");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "sslKeystoreFile", "sslKeystoreFile");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "sslKeystorePassword", "sslKeystorePassword");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "queryEnabled", "queryEnabled");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "queryPort", "queryPort");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "bootstrapHttpEnabled", "bootstrapHttpEnabled");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "bootstrapCarrierEnabled", "bootstrapCarrierEnabled");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "bootstrapHttpDirectPort", "bootstrapHttpDirectPort");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "bootstrapHttpSslPort", "bootstrapHttpSslPort");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "bootstrapCarrierDirectPort", "bootstrapCarrierDirectPort");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "bootstrapCarrierSslPort", "bootstrapCarrierSslPort");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "ioPoolSize", "ioPoolSize");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "computationPoolSize", "computationPoolSize");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "responseBufferSize", "responseBufferSize");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "requestBufferSize", "requestBufferSize");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "kvEndpoints", "kvEndpoints");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "viewEndpoints", "viewEndpoints");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "queryEndpoints", "queryEndpoints");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "maxRequestLifetime", "maxRequestLifetime");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "keepAliveInterval", "keepAliveInterval");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "autoreleaseAfter", "autoreleaseAfter");
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "bufferPoolingEnabled", "bufferPoolingEnabled");
|
||||
|
||||
//retry strategy is particular, in the xsd this is an enum (FailFast, BestEffort)
|
||||
setPropertyValue(envDefinitionBuilder, envElement, "retryStrategy", "retryStrategy");
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
@@ -25,15 +28,15 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.couchbase.monitor.ClientInfo;
|
||||
import org.springframework.data.couchbase.monitor.ClusterInfo;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Enables Parsing of the "<couchbase:jmx />" configuration bean.
|
||||
*
|
||||
* <p/>
|
||||
* In order to enable JMX, different JmxComponents need to be registered. The dependency to the original
|
||||
* {@link com.couchbase.client.CouchbaseClient} object is solved by through the "couchbase-ref" attribute.
|
||||
* {@link Bucket} object is solved through the "bucket-ref" attribute.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class CouchbaseJmxParser implements BeanDefinitionParser {
|
||||
|
||||
@@ -45,27 +48,28 @@ public class CouchbaseJmxParser implements BeanDefinitionParser {
|
||||
* @return null, because no bean instance needs to be returned.
|
||||
*/
|
||||
public BeanDefinition parse(final Element element, final ParserContext parserContext) {
|
||||
String name = element.getAttribute("couchbase-ref");
|
||||
if (!StringUtils.hasText(name)) {
|
||||
name = BeanNames.COUCHBASE;
|
||||
String bucketName = element.getAttribute("bucket-ref");
|
||||
if (!StringUtils.hasText(bucketName)) {
|
||||
bucketName = BeanNames.COUCHBASE_BUCKET;
|
||||
}
|
||||
registerJmxComponents(name, element, parserContext);
|
||||
registerJmxComponents(bucketName, element, parserContext);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the JMX components in the context.
|
||||
*
|
||||
* @param refName the reference name to the couchbase client.
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param parserContext encapsulates the parsing state and configuration.
|
||||
* @parma refBucketName the reference name to the couchbase bucket.
|
||||
*/
|
||||
protected void registerJmxComponents(final String refName, final Element element, final ParserContext parserContext) {
|
||||
protected void registerJmxComponents(final String refBucketName,
|
||||
final Element element, final ParserContext parserContext) {
|
||||
Object eleSource = parserContext.extractSource(element);
|
||||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
|
||||
|
||||
createBeanDefEntry(ClientInfo.class, compositeDef, refName, eleSource, parserContext);
|
||||
createBeanDefEntry(ClusterInfo.class, compositeDef, refName, eleSource, parserContext);
|
||||
createBeanDefEntry(ClientInfo.class, compositeDef, refBucketName, eleSource, parserContext);
|
||||
createBeanDefEntry(ClusterInfo.class, compositeDef, refBucketName, eleSource, parserContext);
|
||||
|
||||
parserContext.registerComponent(compositeDef);
|
||||
}
|
||||
@@ -75,12 +79,12 @@ public class CouchbaseJmxParser implements BeanDefinitionParser {
|
||||
*
|
||||
* @param clazz the class type to register.
|
||||
* @param compositeDef component that can hold nested components.
|
||||
* @param refName the reference name to the couchbase client.
|
||||
* @param refName the reference name to the couchbase bucket.
|
||||
* @param eleSource source element to reference.
|
||||
* @param parserContext encapsulates the parsing state and configuration.
|
||||
*/
|
||||
protected void createBeanDefEntry(final Class<?> clazz, final CompositeComponentDefinition compositeDef,
|
||||
final String refName, final Object eleSource, final ParserContext parserContext) {
|
||||
final String refName, final Object eleSource, final ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
|
||||
builder.getRawBeanDefinition().setSource(eleSource);
|
||||
builder.addConstructorArgReference(refName);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,13 +16,11 @@
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import org.springframework.beans.factory.xml.NamespaceHandler;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
import org.springframework.data.couchbase.repository.config.CouchbaseRepositoryConfigurationExtension;
|
||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
|
||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.xml.NamespaceHandler} for Couchbase configuration.
|
||||
* {@link NamespaceHandler} for Couchbase configuration.
|
||||
* <p/>
|
||||
* This handler acts as a container for one or more bean parsers and registers them. During parsing, the elements
|
||||
* get analyzed and the appropriate registered parser is called.
|
||||
@@ -35,9 +33,10 @@ public class CouchbaseNamespaceHandler extends NamespaceHandlerSupport {
|
||||
* Register bean definition parsers in the namespace handler.
|
||||
*/
|
||||
public final void init() {
|
||||
RepositoryConfigurationExtension extension = new CouchbaseRepositoryConfigurationExtension();
|
||||
registerBeanDefinitionParser("repositories", new RepositoryBeanDefinitionParser(extension));
|
||||
registerBeanDefinitionParser("couchbase", new CouchbaseParser());
|
||||
//TODO repositories (CouchbaseRepositoryConfigurationExtension and RepositoryBeanDefinitionParser)
|
||||
registerBeanDefinitionParser("env", new CouchbaseEnvironmentParser());
|
||||
registerBeanDefinitionParser("cluster", new CouchbaseClusterParser());
|
||||
registerBeanDefinitionParser("bucket", new CouchbaseBucketParser());
|
||||
registerBeanDefinitionParser("jmx", new CouchbaseJmxParser());
|
||||
registerBeanDefinitionParser("template", new CouchbaseTemplateParser());
|
||||
registerBeanDefinitionParser("translation-service", new CouchbaseTranslationServiceParser());
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.config.ParsingUtils;
|
||||
import org.springframework.data.couchbase.core.CouchbaseFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Parser for "<couchbase:couchbase />" bean definitions.
|
||||
* <p/>
|
||||
* The outcome of this bean definition parser will be a constructed {@link CouchbaseClient}.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public class CouchbaseParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Defines the bean class that will be constructed.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
*
|
||||
* @return the class type to instantiate.
|
||||
*/
|
||||
@Override
|
||||
protected Class getBeanClass(final Element element) {
|
||||
return CouchbaseFactoryBean.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the bean definition and build up the bean.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param bean the builder which builds the bean.
|
||||
*/
|
||||
@Override
|
||||
protected void doParse(final Element element, final BeanDefinitionBuilder bean) {
|
||||
ParsingUtils.setPropertyValue(bean, element, "host", "host");
|
||||
ParsingUtils.setPropertyValue(bean, element, "bucket", "bucket");
|
||||
ParsingUtils.setPropertyValue(bean, element, "password", "password");
|
||||
|
||||
setLogger();
|
||||
}
|
||||
|
||||
private void setLogger() {
|
||||
Properties systemProperties = System.getProperties();
|
||||
systemProperties.put("net.spy.log.LoggerImpl", CouchbaseFactoryBean.DEFAULT_LOGGER_PROPERTY);
|
||||
System.setProperties(systemProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the bean ID and assign a default if not set.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param definition the bean definition to work with.
|
||||
* @param parserContext encapsulates the parsing state and configuration.
|
||||
*
|
||||
* @return the ID to work with.
|
||||
*/
|
||||
@Override
|
||||
protected String resolveId(final Element element, final AbstractBeanDefinition definition,
|
||||
final ParserContext parserContext) {
|
||||
String id = super.resolveId(element, definition, parserContext);
|
||||
return StringUtils.hasText(id) ? id : BeanNames.COUCHBASE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,13 +16,14 @@
|
||||
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.couchbase.core.CouchbaseTemplate;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Parser for "<couchbase:template />" bean definitions.
|
||||
@@ -39,7 +40,6 @@ public class CouchbaseTemplateParser extends AbstractSingleBeanDefinitionParser
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param definition the bean definition to work with.
|
||||
* @param parserContext encapsulates the parsing state and configuration.
|
||||
*
|
||||
* @return the ID to work with.
|
||||
*/
|
||||
@Override
|
||||
@@ -52,7 +52,6 @@ public class CouchbaseTemplateParser extends AbstractSingleBeanDefinitionParser
|
||||
* Defines the bean class that will be constructed.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
*
|
||||
* @return the class type to instantiate.
|
||||
*/
|
||||
@Override
|
||||
@@ -68,11 +67,11 @@ public class CouchbaseTemplateParser extends AbstractSingleBeanDefinitionParser
|
||||
*/
|
||||
@Override
|
||||
protected void doParse(final Element element, final BeanDefinitionBuilder bean) {
|
||||
String clientRef = element.getAttribute("client-ref");
|
||||
String bucketRef = element.getAttribute("bucket-ref");
|
||||
String converterRef = element.getAttribute("converter-ref");
|
||||
String translationServiceRef = element.getAttribute("translation-service-ref");
|
||||
|
||||
bean.addConstructorArgReference(StringUtils.hasText(clientRef) ? clientRef : BeanNames.COUCHBASE);
|
||||
bean.addConstructorArgReference(StringUtils.hasText(bucketRef) ? bucketRef : BeanNames.COUCHBASE_BUCKET);
|
||||
|
||||
if (StringUtils.hasText(converterRef)) {
|
||||
bean.addConstructorArgReference(converterRef);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,13 +17,14 @@
|
||||
package org.springframework.data.couchbase.config;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.couchbase.core.convert.translation.JacksonTranslationService;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Enables Parsing of the "<couchbase:translation-service />" configuration bean.
|
||||
@@ -36,7 +37,6 @@ public class CouchbaseTranslationServiceParser extends AbstractSingleBeanDefinit
|
||||
* Defines the bean class that will be constructed.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
*
|
||||
* @return the class type to instantiate.
|
||||
*/
|
||||
@Override
|
||||
@@ -55,17 +55,18 @@ public class CouchbaseTranslationServiceParser extends AbstractSingleBeanDefinit
|
||||
final String objectMapper = element.getAttribute("objectMapper");
|
||||
if (StringUtils.hasText(objectMapper)) {
|
||||
bean.addPropertyReference("objectMapper", objectMapper);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
bean.addPropertyValue("objectMapper", new ObjectMapper());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the bean ID and assign a default if not set.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param definition the bean definition to work with.
|
||||
* @param parserContext encapsulates the parsing state and configuration.
|
||||
*
|
||||
* @return the ID to work with (e.g., "translationService")
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* This package contains all classes needed for specific configuration of
|
||||
* Spring Data Couchbase.
|
||||
*/
|
||||
package org.springframework.data.couchbase.config;
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -30,8 +30,8 @@ public interface BucketCallback<T> {
|
||||
* The enclosed body will be executed on the connected bucket.
|
||||
*
|
||||
* @return the result of the enclosed execution.
|
||||
* @throws TimeoutException if the enclosed operation timed out.
|
||||
* @throws ExecutionException if the result could not be retrieved because of a thrown exception before.
|
||||
* @throws TimeoutException if the enclosed operation timed out.
|
||||
* @throws ExecutionException if the result could not be retrieved because of a thrown exception before.
|
||||
* @throws InterruptedException if the enclosed operation was interrupted.
|
||||
*/
|
||||
T doInBucket() throws TimeoutException, ExecutionException, InterruptedException;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013, 2014 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,19 +16,41 @@
|
||||
|
||||
package org.springframework.data.couchbase.core;
|
||||
|
||||
import com.couchbase.client.ObservedException;
|
||||
import com.couchbase.client.ObservedModifiedException;
|
||||
import com.couchbase.client.ObservedTimeoutException;
|
||||
import com.couchbase.client.protocol.views.InvalidViewException;
|
||||
import com.couchbase.client.vbucket.ConnectionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.couchbase.client.core.BackpressureException;
|
||||
import com.couchbase.client.core.BucketClosedException;
|
||||
import com.couchbase.client.core.DocumentConcurrentlyModifiedException;
|
||||
import com.couchbase.client.core.ReplicaNotConfiguredException;
|
||||
import com.couchbase.client.core.RequestCancelledException;
|
||||
import com.couchbase.client.core.ServiceNotAvailableException;
|
||||
import com.couchbase.client.core.config.ConfigurationException;
|
||||
import com.couchbase.client.core.endpoint.SSLException;
|
||||
import com.couchbase.client.core.endpoint.kv.AuthenticationException;
|
||||
import com.couchbase.client.core.env.EnvironmentException;
|
||||
import com.couchbase.client.core.state.NotConnectedException;
|
||||
import com.couchbase.client.java.error.BucketDoesNotExistException;
|
||||
import com.couchbase.client.java.error.CASMismatchException;
|
||||
import com.couchbase.client.java.error.DesignDocumentException;
|
||||
import com.couchbase.client.java.error.DocumentAlreadyExistsException;
|
||||
import com.couchbase.client.java.error.DurabilityException;
|
||||
import com.couchbase.client.java.error.InvalidPasswordException;
|
||||
import com.couchbase.client.java.error.RequestTooBigException;
|
||||
import com.couchbase.client.java.error.TemporaryFailureException;
|
||||
import com.couchbase.client.java.error.TemporaryLockFailureException;
|
||||
import com.couchbase.client.java.error.TranscodingException;
|
||||
import com.couchbase.client.java.error.ViewDoesNotExistException;
|
||||
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.dao.QueryTimeoutException;
|
||||
import org.springframework.dao.TransientDataAccessResourceException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
|
||||
import java.util.concurrent.CancellationException;
|
||||
|
||||
|
||||
/**
|
||||
* Simple {@link PersistenceExceptionTranslator} for Couchbase.
|
||||
@@ -38,6 +60,7 @@ import java.util.concurrent.CancellationException;
|
||||
* should not be translated.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class CouchbaseExceptionTranslator implements PersistenceExceptionTranslator {
|
||||
|
||||
@@ -45,28 +68,59 @@ public class CouchbaseExceptionTranslator implements PersistenceExceptionTransla
|
||||
* Translate Couchbase specific exceptions to spring exceptions if possible.
|
||||
*
|
||||
* @param ex the exception to translate.
|
||||
*
|
||||
* @return the translated exception or null.
|
||||
*/
|
||||
@Override
|
||||
public final DataAccessException translateExceptionIfPossible(final RuntimeException ex) {
|
||||
|
||||
if (ex instanceof ConnectionException) {
|
||||
if (ex instanceof InvalidPasswordException
|
||||
|| ex instanceof NotConnectedException
|
||||
|| ex instanceof ConfigurationException
|
||||
|| ex instanceof EnvironmentException
|
||||
|| ex instanceof InvalidPasswordException
|
||||
|| ex instanceof SSLException
|
||||
|| ex instanceof ServiceNotAvailableException
|
||||
|| ex instanceof BucketClosedException
|
||||
|| ex instanceof BucketDoesNotExistException
|
||||
|| ex instanceof AuthenticationException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof ObservedException
|
||||
|| ex instanceof ObservedTimeoutException
|
||||
|| ex instanceof ObservedModifiedException) {
|
||||
if (ex instanceof DocumentAlreadyExistsException) {
|
||||
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof CASMismatchException
|
||||
|| ex instanceof DocumentConcurrentlyModifiedException
|
||||
|| ex instanceof ReplicaNotConfiguredException
|
||||
|| ex instanceof DurabilityException) {
|
||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof CancellationException) {
|
||||
throw new OperationCancellationException(ex.getMessage(), ex);
|
||||
if (ex instanceof RequestCancelledException
|
||||
|| ex instanceof BackpressureException) {
|
||||
return new OperationCancellationException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof InvalidViewException) {
|
||||
throw new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||
if (ex instanceof ViewDoesNotExistException
|
||||
|| ex instanceof RequestTooBigException
|
||||
|| ex instanceof DesignDocumentException) {
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof TemporaryLockFailureException
|
||||
|| ex instanceof TemporaryFailureException) {
|
||||
return new TransientDataAccessResourceException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if ((ex instanceof RuntimeException && ex.getCause() instanceof TimeoutException)) {
|
||||
return new QueryTimeoutException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
if (ex instanceof TranscodingException) {
|
||||
//note: the more specific CouchbaseQueryExecutionException should be thrown by the template
|
||||
//when dealing with TranscodingException in the query/n1ql methods.
|
||||
return new DataRetrievalFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
// Unable to translate exception, therefore just throw the original!
|
||||
|
||||
@@ -1,318 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core;
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import com.couchbase.client.CouchbaseConnectionFactory;
|
||||
import com.couchbase.client.CouchbaseConnectionFactoryBuilder;
|
||||
import net.spy.memcached.FailureMode;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Convenient Factory for configuring a {@link CouchbaseClient}.
|
||||
*
|
||||
* To set the properties correctly on the {@link CouchbaseClient} a {@link CouchbaseConnectionFactoryBuilder} is used.
|
||||
* After all properties are set, the client is constructed and used.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public class CouchbaseFactoryBean implements FactoryBean<CouchbaseClient>, InitializingBean,
|
||||
DisposableBean, PersistenceExceptionTranslator {
|
||||
|
||||
/**
|
||||
* Defines the default hostname to be used if no other list is supplied.
|
||||
*/
|
||||
public static final String DEFAULT_NODE = "127.0.0.1";
|
||||
|
||||
/**
|
||||
* Defines the default bucket name to be used if no other bucket name is supplied.
|
||||
*/
|
||||
public static final String DEFAULT_BUCKET = "default";
|
||||
|
||||
/**
|
||||
* Defines the password of the default bucket.
|
||||
*/
|
||||
public static final String DEFAULT_PASSWORD = "";
|
||||
|
||||
/**
|
||||
* The name of the default shutdown method to call when the context is destroyed.
|
||||
*/
|
||||
public static final String DEFAULT_DESTROY_METHOD = "shutdown";
|
||||
|
||||
/**
|
||||
* Use SLF4J as the default logger if not instructed otherwise.
|
||||
*/
|
||||
public static final String DEFAULT_LOGGER_PROPERTY = "net.spy.memcached.compat.log.SLF4JLogger";
|
||||
|
||||
/**
|
||||
* Holds the enclosed {@link CouchbaseClient}.
|
||||
*/
|
||||
private CouchbaseClient couchbaseClient;
|
||||
|
||||
/**
|
||||
* The exception translator is used to properly map exceptions to spring-type exceptions.
|
||||
*/
|
||||
private PersistenceExceptionTranslator exceptionTranslator = new CouchbaseExceptionTranslator();
|
||||
|
||||
/**
|
||||
* Contains the actual bucket name.
|
||||
*/
|
||||
private String bucket;
|
||||
|
||||
/**
|
||||
* Contains the actual bucket password.
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* Contains the list of nodes to connect to.
|
||||
*/
|
||||
private List<URI> nodes;
|
||||
|
||||
/**
|
||||
* The builder which allows to customize client settings.
|
||||
*/
|
||||
private final CouchbaseConnectionFactoryBuilder builder = new CouchbaseConnectionFactoryBuilder();
|
||||
|
||||
/**
|
||||
* Set the observe poll interval in miliseconds.
|
||||
*
|
||||
* @param interval the observe poll interval.
|
||||
*/
|
||||
public void setObservePollInterval(final int interval) {
|
||||
builder.setObsPollInterval(interval);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of polls.
|
||||
*
|
||||
* @param max the maximum number of polls.
|
||||
*/
|
||||
public void setObservePollMax(final int max) {
|
||||
builder.setObsPollMax(max);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the reconnect threshold time in seconds.
|
||||
*
|
||||
* @param time the reconnect threshold time.
|
||||
*/
|
||||
public void setReconnectThresholdTime(final int time) {
|
||||
builder.setReconnectThresholdTime(time, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the view timeout in miliseconds.
|
||||
*
|
||||
* @param timeout the view timeout.
|
||||
*/
|
||||
public void setViewTimeout(final int timeout) {
|
||||
builder.setViewTimeout(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the failure mode if memcached buckets are used.
|
||||
*
|
||||
* See the proper values of {@link FailureMode} to use.
|
||||
*
|
||||
* @param mode the failure mode.
|
||||
*/
|
||||
public void setFailureMode(final String mode) {
|
||||
builder.setFailureMode(FailureMode.valueOf(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the operation timeout in miliseconds.
|
||||
*
|
||||
* @param timeout the operation timeout.
|
||||
*/
|
||||
public void setOpTimeout(final int timeout) {
|
||||
builder.setOpTimeout(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the operation queue maximum block time in miliseconds.
|
||||
*
|
||||
* @param time the operation queue maximum block time.
|
||||
*/
|
||||
public void setOpQueueMaxBlockTime(final int time) {
|
||||
builder.setOpQueueMaxBlockTime(time);
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown the client when the bean is destroyed.
|
||||
*
|
||||
* @throws Exception if shutdown failed.
|
||||
*/
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
couchbaseClient.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the underlying {@link CouchbaseClient}.
|
||||
*
|
||||
* @return the client object.
|
||||
* @throws Exception if returning the client failed.
|
||||
*/
|
||||
@Override
|
||||
public CouchbaseClient getObject() throws Exception {
|
||||
return couchbaseClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the object type of the client.
|
||||
*
|
||||
* @return the {@link CouchbaseClient} class.
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return CouchbaseClient.class;
|
||||
}
|
||||
|
||||
/**
|
||||
* The client should be returned as a singleton.
|
||||
*
|
||||
* @return returns true.
|
||||
*/
|
||||
@Override
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the bucket to be used.
|
||||
*
|
||||
* @param bucket the bucket to use.
|
||||
*/
|
||||
public void setBucket(final String bucket) {
|
||||
this.bucket = bucket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the password.
|
||||
*
|
||||
* @param password the password to use.
|
||||
*/
|
||||
public void setPassword(final String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the array of nodes from a delimited list of hosts.
|
||||
*
|
||||
* @param hosts a comma separated list of hosts.
|
||||
*/
|
||||
public void setHost(final String hosts) {
|
||||
this.nodes = convertHosts(hosts);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a list of hosts into a URI format that can be used by the {@link CouchbaseClient}.
|
||||
*
|
||||
* To make it simple to use, the list of hosts can be passed in as a comma separated list. This list gets parsed
|
||||
* and converted into a URI format that is suitable for the underlying {@link CouchbaseClient} object.
|
||||
*
|
||||
* @param hosts the host list to convert.
|
||||
* @return the converted list with URIs.
|
||||
*/
|
||||
private List<URI> convertHosts(final String hosts) {
|
||||
String[] split = hosts.split(",");
|
||||
List<URI> nodes = new ArrayList<URI>();
|
||||
|
||||
try {
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
nodes.add(new URI("http://" + split[i] + ":8091/pools"));
|
||||
}
|
||||
} catch (URISyntaxException ex) {
|
||||
throw new BeanCreationException("Could not convert host list." + ex);
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the nodes as an array of URIs.
|
||||
*
|
||||
* @param nodes the nodes to connect to.
|
||||
*/
|
||||
public void setNodes(final URI[] nodes) {
|
||||
this.nodes = filterNonNullElementsAsList(nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the array of elements to a list and filter empty or null elements.
|
||||
*
|
||||
* @param elements the elements to convert.
|
||||
* @param <T> the type of the elements.
|
||||
* @return the converted list.
|
||||
*/
|
||||
private <T> List<T> filterNonNullElementsAsList(T[] elements) {
|
||||
if (elements == null) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<T> candidateElements = new ArrayList<T>();
|
||||
for (T element : elements) {
|
||||
if (element != null) {
|
||||
candidateElements.add(element);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(candidateElements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate the {@link CouchbaseClient}.
|
||||
*
|
||||
* @throws Exception if something goes wrong during instantiation.
|
||||
*/
|
||||
@Override
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
nodes = nodes != null ? nodes : Arrays.asList(new URI("http://" + DEFAULT_NODE + ":8091/pools"));
|
||||
bucket = bucket != null ? bucket : DEFAULT_BUCKET;
|
||||
password = password != null ? password : DEFAULT_PASSWORD;
|
||||
|
||||
CouchbaseConnectionFactory factory = builder.buildCouchbaseConnection(nodes, bucket, password);
|
||||
couchbaseClient = new CouchbaseClient(factory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate exception if possible.
|
||||
*
|
||||
* @param ex the exception to translate.
|
||||
* @return the translate exception.
|
||||
*/
|
||||
@Override
|
||||
public DataAccessException translateExceptionIfPossible(final RuntimeException ex) {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -17,20 +17,26 @@
|
||||
package org.springframework.data.couchbase.core;
|
||||
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import com.couchbase.client.protocol.views.Query;
|
||||
import com.couchbase.client.protocol.views.ViewResponse;
|
||||
import net.spy.memcached.PersistTo;
|
||||
import net.spy.memcached.ReplicateTo;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import com.couchbase.client.java.PersistTo;
|
||||
import com.couchbase.client.java.ReplicateTo;
|
||||
import com.couchbase.client.java.query.Query;
|
||||
import com.couchbase.client.java.query.QueryParams;
|
||||
import com.couchbase.client.java.query.QueryResult;
|
||||
import com.couchbase.client.java.query.Statement;
|
||||
import com.couchbase.client.java.view.ViewQuery;
|
||||
import com.couchbase.client.java.view.ViewResult;
|
||||
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
|
||||
/**
|
||||
* Defines common operations on the Couchbase data source, most commonly implemented by {@link CouchbaseTemplate}.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public interface CouchbaseOperations {
|
||||
|
||||
@@ -169,50 +175,71 @@ public interface CouchbaseOperations {
|
||||
*
|
||||
* @param id the unique ID of the document.
|
||||
* @param entityClass the entity to map to.
|
||||
*
|
||||
* @return returns the found object or null otherwise.
|
||||
*/
|
||||
<T> T findById(String id, Class<T> entityClass);
|
||||
|
||||
//TODO add javadoc link to setIncludeDocs when GA
|
||||
|
||||
/**
|
||||
* Query a View for a list of documents of type T.
|
||||
* <p/>
|
||||
* <p>There is no need to {@link Query#setIncludeDocs(boolean)} explicitely, because it will be set to true all the
|
||||
* time. It is valid to pass in a empty constructed {@link Query} object.</p>
|
||||
* <p>There is no need to setIncludeDocs(boolean) explicitly, because it will be set to true all the
|
||||
* time. It is valid to pass in a empty constructed {@link ViewQuery} object.</p>
|
||||
* <p/>
|
||||
* <p>This method does not work with reduced views, because they by design do not contain references to original
|
||||
* objects. Use the provided {@link #queryView} method for more flexibility and direct access.</p>
|
||||
*
|
||||
* @param design the name of the design document.
|
||||
* @param view the name of the viewName.
|
||||
* @param query the Query object to customize the viewName query.
|
||||
* @param query the Query object (also specifying view design document and view name).
|
||||
* @param entityClass the entity to map to.
|
||||
*
|
||||
* @return the converted collection
|
||||
*/
|
||||
<T> List<T> findByView(String design, String view, Query query, Class<T> entityClass);
|
||||
<T> List<T> findByView(ViewQuery query, Class<T> entityClass);
|
||||
|
||||
|
||||
/**
|
||||
* Query a View with direct access to the {@link ViewResponse}.
|
||||
* Query a View with direct access to the {@link ViewResult}.
|
||||
* <p>This method is available to ease the working with views by still wrapping exceptions into the Spring
|
||||
* infrastructure.</p>
|
||||
* <p>It is especially needed if you want to run reduced viewName queries, because they can't be mapped onto entities
|
||||
* directly.</p>
|
||||
*
|
||||
* @param design the name of the designDocument document.
|
||||
* @param view the name of the viewName.
|
||||
* @param query the Query object to customize the viewName query.
|
||||
*
|
||||
* @return ViewResponse containing the results of the query.
|
||||
* @param query the Query object (also specifying view design document and view name).
|
||||
* @return ViewResult containing the results of the query.
|
||||
*/
|
||||
ViewResponse queryView(String design, String view, Query query);
|
||||
ViewResult queryView(ViewQuery query);
|
||||
|
||||
/**
|
||||
* Query the N1QL Service for JSON data of type T. This is done via a {@link Query} that can
|
||||
* contain a {@link Statement}, additional query parameters ({@link QueryParams})
|
||||
* and placeholder values if the statement contains placeholders.
|
||||
* <p>Use {@link Query}'s factory methods to construct this.</p>
|
||||
*
|
||||
* @param n1ql the N1QL query.
|
||||
* @param entityClass the target class for the returned entities.
|
||||
* @param <T> the entity class
|
||||
* @return the list of entities matching this query.
|
||||
*/
|
||||
<T> List<T> findByN1QL(Query n1ql, Class<T> entityClass);
|
||||
|
||||
/**
|
||||
* Query the N1QL Service with direct access to the {@link QueryResult}.
|
||||
* <p>
|
||||
* This is done via a {@link Query} that can
|
||||
* contain a {@link Statement}, additional query parameters ({@link QueryParams})
|
||||
* and placeholder values if the statement contains placeholders.</p>
|
||||
* <p>
|
||||
* Use {@link Query}'s factory methods to construct this.</p>
|
||||
*
|
||||
* @param n1ql the N1QL query.
|
||||
* @return {@link QueryResult} containing the results of the n1ql query.
|
||||
*/
|
||||
QueryResult queryN1QL(Query n1ql);
|
||||
|
||||
/**
|
||||
* Checks if the given document exists.
|
||||
*
|
||||
* @param id the unique ID of the document.
|
||||
*
|
||||
* @return whether the document could be found or not.
|
||||
*/
|
||||
boolean exists(String id);
|
||||
@@ -262,11 +289,17 @@ public interface CouchbaseOperations {
|
||||
*
|
||||
* @param action the action to execute in the callback.
|
||||
* @param <T> the return type.
|
||||
*
|
||||
* @return the return type.
|
||||
*/
|
||||
<T> T execute(BucketCallback<T> action);
|
||||
|
||||
/**
|
||||
* Returns the linked {@link Bucket} to this template.
|
||||
*
|
||||
* @return the client used for the template.
|
||||
*/
|
||||
Bucket getCouchbaseBucket();
|
||||
|
||||
/**
|
||||
* Returns the underlying {@link CouchbaseConverter}.
|
||||
*
|
||||
@@ -274,11 +307,4 @@ public interface CouchbaseOperations {
|
||||
*/
|
||||
CouchbaseConverter getConverter();
|
||||
|
||||
/**
|
||||
* Returns the linked {@link CouchbaseClient} to this template.
|
||||
*
|
||||
* @return the client used for the template.
|
||||
*/
|
||||
CouchbaseClient getCouchbaseClient();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core;
|
||||
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
|
||||
/**
|
||||
* An {@link DataRetrievalFailureException} that denotes an error during a query (N1QL).
|
||||
*/
|
||||
public class CouchbaseQueryExecutionException extends DataRetrievalFailureException {
|
||||
|
||||
public CouchbaseQueryExecutionException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public CouchbaseQueryExecutionException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,22 +16,38 @@
|
||||
|
||||
package org.springframework.data.couchbase.core;
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import com.couchbase.client.protocol.views.Query;
|
||||
import com.couchbase.client.protocol.views.View;
|
||||
import com.couchbase.client.protocol.views.ViewResponse;
|
||||
import com.couchbase.client.protocol.views.ViewRow;
|
||||
import net.spy.memcached.CASResponse;
|
||||
import net.spy.memcached.CASValue;
|
||||
import net.spy.memcached.PersistTo;
|
||||
import net.spy.memcached.ReplicateTo;
|
||||
import net.spy.memcached.internal.OperationFuture;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import com.couchbase.client.java.PersistTo;
|
||||
import com.couchbase.client.java.ReplicateTo;
|
||||
import com.couchbase.client.java.document.Document;
|
||||
import com.couchbase.client.java.document.RawJsonDocument;
|
||||
import com.couchbase.client.java.document.json.JsonObject;
|
||||
import com.couchbase.client.java.error.CASMismatchException;
|
||||
import com.couchbase.client.java.error.TranscodingException;
|
||||
import com.couchbase.client.java.query.Query;
|
||||
import com.couchbase.client.java.query.QueryResult;
|
||||
import com.couchbase.client.java.query.QueryRow;
|
||||
import com.couchbase.client.java.view.ViewQuery;
|
||||
import com.couchbase.client.java.view.ViewResult;
|
||||
import com.couchbase.client.java.view.ViewRow;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.context.ApplicationEventPublisher;
|
||||
import org.springframework.context.ApplicationEventPublisherAware;
|
||||
import org.springframework.dao.OptimisticLockingFailureException;
|
||||
import org.springframework.dao.QueryTimeoutException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.couchbase.core.convert.CouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.convert.MappingCouchbaseConverter;
|
||||
import org.springframework.data.couchbase.core.convert.translation.JacksonTranslationService;
|
||||
@@ -50,34 +66,16 @@ import org.springframework.data.couchbase.core.mapping.event.CouchbaseMappingEve
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.BeanWrapper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
/**
|
||||
* @author Michael Nitschinger
|
||||
* @author Oliver Gierke
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventPublisherAware {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(CouchbaseTemplate.class);
|
||||
private static final Collection<String> ITERABLE_CLASSES;
|
||||
private static final WriteResultChecking DEFAULT_WRITE_RESULT_CHECKING = WriteResultChecking.NONE;
|
||||
|
||||
private final CouchbaseClient client;
|
||||
protected final MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext;
|
||||
private final CouchbaseExceptionTranslator exceptionTranslator = new CouchbaseExceptionTranslator();
|
||||
private final TranslationService translationService;
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
|
||||
private CouchbaseConverter couchbaseConverter;
|
||||
private WriteResultChecking writeResultChecking = DEFAULT_WRITE_RESULT_CHECKING;
|
||||
private static final Collection<String> ITERABLE_CLASSES;
|
||||
|
||||
static {
|
||||
final Set<String> iterableClasses = new HashSet<String>();
|
||||
@@ -87,181 +85,66 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
ITERABLE_CLASSES = Collections.unmodifiableCollection(iterableClasses);
|
||||
}
|
||||
|
||||
public void setWriteResultChecking(final WriteResultChecking resultChecking) {
|
||||
writeResultChecking = resultChecking == null ? DEFAULT_WRITE_RESULT_CHECKING : resultChecking;
|
||||
}
|
||||
private final Bucket client;
|
||||
private final CouchbaseConverter converter;
|
||||
private final TranslationService translationService;
|
||||
|
||||
public CouchbaseTemplate(final CouchbaseClient client) {
|
||||
|
||||
private ApplicationEventPublisher eventPublisher;
|
||||
private WriteResultChecking writeResultChecking = DEFAULT_WRITE_RESULT_CHECKING;
|
||||
private PersistenceExceptionTranslator exceptionTranslator = new CouchbaseExceptionTranslator();
|
||||
|
||||
protected final MappingContext<? extends CouchbasePersistentEntity<?>, CouchbasePersistentProperty> mappingContext;
|
||||
|
||||
public CouchbaseTemplate(final Bucket client) {
|
||||
this(client, null, null);
|
||||
}
|
||||
|
||||
public CouchbaseTemplate(final CouchbaseClient client, final TranslationService translationService) {
|
||||
public CouchbaseTemplate(final Bucket client, final TranslationService translationService) {
|
||||
this(client, null, translationService);
|
||||
}
|
||||
|
||||
public CouchbaseTemplate(final CouchbaseClient client, final CouchbaseConverter couchbaseConverter, final TranslationService translationService) {
|
||||
public CouchbaseTemplate(final Bucket client, final CouchbaseConverter converter,
|
||||
final TranslationService translationService) {
|
||||
this.client = client;
|
||||
this.couchbaseConverter = couchbaseConverter == null ? getDefaultConverter() : couchbaseConverter;
|
||||
this.converter = converter == null ? getDefaultConverter() : converter;
|
||||
this.translationService = translationService == null ? getDefaultTranslationService() : translationService;
|
||||
mappingContext = this.couchbaseConverter.getMappingContext();
|
||||
this.mappingContext = this.converter.getMappingContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(final ApplicationEventPublisher eventPublisher) {
|
||||
this.eventPublisher = eventPublisher;
|
||||
private TranslationService getDefaultTranslationService() {
|
||||
JacksonTranslationService t = new JacksonTranslationService();
|
||||
t.afterPropertiesSet();
|
||||
return t;
|
||||
}
|
||||
|
||||
private static CouchbaseConverter getDefaultConverter() {
|
||||
final MappingCouchbaseConverter converter = new MappingCouchbaseConverter(new CouchbaseMappingContext());
|
||||
converter.afterPropertiesSet();
|
||||
return converter;
|
||||
private CouchbaseConverter getDefaultConverter() {
|
||||
MappingCouchbaseConverter c = new MappingCouchbaseConverter(new CouchbaseMappingContext());
|
||||
c.afterPropertiesSet();
|
||||
return c;
|
||||
}
|
||||
|
||||
private static TranslationService getDefaultTranslationService() {
|
||||
final JacksonTranslationService jacksonTranslationService = new JacksonTranslationService();
|
||||
jacksonTranslationService.afterPropertiesSet();
|
||||
return jacksonTranslationService;
|
||||
}
|
||||
|
||||
private Object translateEncode(final CouchbaseStorable source) {
|
||||
return translationService.encode(source);
|
||||
}
|
||||
|
||||
|
||||
private CouchbaseStorable translateDecode(final String source, final CouchbaseStorable target) {
|
||||
return translationService.decode(source, target);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void insert(final Object objectToInsert) {
|
||||
insert(objectToInsert, PersistTo.ZERO, ReplicateTo.ZERO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void insert(final Collection<?> batchToInsert) {
|
||||
for (final Object toInsert : batchToInsert) {
|
||||
insert(toInsert);
|
||||
/**
|
||||
* Encode a {@link CouchbaseDocument} into a storable representation (JSON) then prepare
|
||||
* it for storage as a {@link Document}.
|
||||
*/
|
||||
private Document<String> encodeAndWrap(final CouchbaseDocument source, Long version) {
|
||||
String encodedContent = translationService.encode(source);
|
||||
if (version == null) {
|
||||
return RawJsonDocument.create(source.getId(), source.getExpiration(), encodedContent);
|
||||
}
|
||||
else {
|
||||
return RawJsonDocument.create(source.getId(), source.getExpiration(), encodedContent, version);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final Object objectToSave) {
|
||||
save(objectToSave, PersistTo.ZERO, ReplicateTo.ZERO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(final Collection<?> batchToSave) {
|
||||
for (final Object toSave : batchToSave) {
|
||||
save(toSave);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final Object objectToUpdate) {
|
||||
update(objectToUpdate, PersistTo.ZERO, ReplicateTo.ZERO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(final Collection<?> batchToUpdate) {
|
||||
for (final Object toUpdate : batchToUpdate) {
|
||||
update(toUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final <T> T findById(final String id, final Class<T> entityClass) {
|
||||
CASValue result = execute(new BucketCallback<CASValue>() {
|
||||
@Override
|
||||
public CASValue doInBucket() {
|
||||
return client.gets(id);
|
||||
}
|
||||
});
|
||||
|
||||
if (result == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CouchbaseDocument converted = new CouchbaseDocument(id);
|
||||
Object readEntity = couchbaseConverter.read(entityClass, (CouchbaseDocument) translateDecode(
|
||||
(String) result.getValue(), converted));
|
||||
|
||||
final BeanWrapper<Object> beanWrapper = BeanWrapper.create(readEntity, couchbaseConverter.getConversionService());
|
||||
CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(readEntity.getClass());
|
||||
if (persistentEntity.hasVersionProperty()) {
|
||||
beanWrapper.setProperty(persistentEntity.getVersionProperty(), result.getCas());
|
||||
}
|
||||
|
||||
return (T) readEntity;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> List<T> findByView(final String designName, final String viewName, final Query query, final Class<T> entityClass) {
|
||||
|
||||
if (query.willIncludeDocs()) {
|
||||
query.setIncludeDocs(false);
|
||||
}
|
||||
if (query.willReduce()) {
|
||||
query.setReduce(false);
|
||||
}
|
||||
|
||||
final ViewResponse response = queryView(designName, viewName, query);
|
||||
|
||||
final List<T> result = new ArrayList<T>(response.size());
|
||||
for (final ViewRow row : response) {
|
||||
result.add(findById(row.getId(), entityClass));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewResponse queryView(final String designName, final String viewName, final Query query) {
|
||||
return execute(new BucketCallback<ViewResponse>() {
|
||||
@Override
|
||||
public ViewResponse doInBucket() {
|
||||
final View view = client.getView(designName, viewName);
|
||||
return client.query(view, query);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final Object objectToRemove) {
|
||||
remove(objectToRemove, PersistTo.ZERO, ReplicateTo.ZERO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final Collection<?> batchToRemove) {
|
||||
for (final Object toRemove : batchToRemove) {
|
||||
remove(toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T execute(final BucketCallback<T> action) {
|
||||
try {
|
||||
return action.doInBucket();
|
||||
} catch (RuntimeException e) {
|
||||
throw exceptionTranslator.translateExceptionIfPossible(e);
|
||||
} catch (TimeoutException e) {
|
||||
throw new QueryTimeoutException(e.getMessage(), e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new OperationInterruptedException(e.getMessage(), e);
|
||||
} catch (ExecutionException e) {
|
||||
throw new OperationInterruptedException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(final String id) {
|
||||
final String result = execute(new BucketCallback<String>() {
|
||||
@Override
|
||||
public String doInBucket() {
|
||||
return (String) client.get(id);
|
||||
}
|
||||
});
|
||||
return result != null;
|
||||
/**
|
||||
* Decode a {@link Document Document<String>} containing a JSON string
|
||||
* into a {@link CouchbaseStorable}
|
||||
*/
|
||||
private CouchbaseStorable decodeAndUnwrap(final Document<String> source, final CouchbaseStorable target) {
|
||||
return translationService.decode(source.content(), target); //TODO rework and check
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,201 +160,31 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CouchbaseConverter getConverter() {
|
||||
return couchbaseConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Object objectToSave, final PersistTo persistTo, final ReplicateTo replicateTo) {
|
||||
ensureNotIterable(objectToSave);
|
||||
|
||||
final BeanWrapper<Object> beanWrapper = BeanWrapper.create(objectToSave, couchbaseConverter.getConversionService());
|
||||
CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(objectToSave.getClass());
|
||||
final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
final Long version = versionProperty != null ? beanWrapper.getProperty(versionProperty, Long.class) : null;
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<Object>(objectToSave));
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
couchbaseConverter.write(objectToSave, converted);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<Object>(objectToSave, converted));
|
||||
execute(new BucketCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInBucket() throws InterruptedException, ExecutionException {
|
||||
if (version == null) {
|
||||
OperationFuture<Boolean> setFuture = client.set(converted.getId(), converted.getExpiration(),
|
||||
translateEncode(converted), persistTo, replicateTo);
|
||||
boolean future = setFuture.get();
|
||||
if (!future) {
|
||||
handleWriteResultError("Saving document failed: " + setFuture.getStatus().getMessage());
|
||||
}
|
||||
return future;
|
||||
} else {
|
||||
OperationFuture<CASResponse> casFuture = client.asyncCas(converted.getId(), version,
|
||||
converted.getExpiration(), translateEncode(converted), persistTo, replicateTo);
|
||||
CASResponse cas = casFuture.get();
|
||||
if (cas == CASResponse.EXISTS) {
|
||||
throw new OptimisticLockingFailureException("Saving document with version value failed: " + cas);
|
||||
} else {
|
||||
long newCas = casFuture.getCas();
|
||||
beanWrapper.setProperty(versionProperty, newCas);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
maybeEmitEvent(new AfterSaveEvent<Object>(objectToSave, converted));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Collection<?> batchToSave, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
for (Object toSave : batchToSave) {
|
||||
save(toSave, persistTo, replicateTo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Object objectToInsert, final PersistTo persistTo, final ReplicateTo replicateTo) {
|
||||
ensureNotIterable(objectToInsert);
|
||||
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(objectToInsert.getClass());
|
||||
final BeanWrapper<Object> beanWrapper = BeanWrapper.create(objectToInsert, couchbaseConverter.getConversionService());
|
||||
|
||||
if (persistentEntity != null && persistentEntity.hasVersionProperty()) {
|
||||
final Long version = beanWrapper.getProperty(persistentEntity.getVersionProperty(), Long.class);
|
||||
if (version == 0) {
|
||||
beanWrapper.setProperty(persistentEntity.getVersionProperty(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<Object>(objectToInsert));
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
couchbaseConverter.write(objectToInsert, converted);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<Object>(objectToInsert, converted));
|
||||
execute(new BucketCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInBucket() throws InterruptedException, ExecutionException {
|
||||
OperationFuture<Boolean> addFuture = client.add(converted.getId(), converted.getExpiration(),
|
||||
translateEncode(converted), persistTo, replicateTo);
|
||||
boolean result = addFuture.get();
|
||||
if(result == false) {
|
||||
handleWriteResultError("Inserting document failed: "
|
||||
+ addFuture.getStatus().getMessage());
|
||||
}
|
||||
|
||||
if (result && persistentEntity.hasVersionProperty()) {
|
||||
beanWrapper.setProperty(persistentEntity.getVersionProperty(), addFuture.getCas());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
});
|
||||
maybeEmitEvent(new AfterSaveEvent<Object>(objectToInsert, converted));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Collection<?> batchToInsert, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
for (Object toInsert : batchToInsert) {
|
||||
insert(toInsert, persistTo,replicateTo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Object objectToUpdate, final PersistTo persistTo, final ReplicateTo replicateTo) {
|
||||
ensureNotIterable(objectToUpdate);
|
||||
|
||||
final BeanWrapper<Object> beanWrapper = BeanWrapper.create(objectToUpdate, couchbaseConverter.getConversionService());
|
||||
CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(objectToUpdate.getClass());
|
||||
final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
final Long version = versionProperty != null ? beanWrapper.getProperty(versionProperty, Long.class) : null;
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<Object>(objectToUpdate));
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
couchbaseConverter.write(objectToUpdate, converted);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<Object>(objectToUpdate, converted));
|
||||
execute(new BucketCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInBucket() throws InterruptedException, ExecutionException {
|
||||
if (version == null) {
|
||||
return client.replace(converted.getId(), converted.getExpiration(), translateEncode(converted), persistTo,
|
||||
replicateTo).get();
|
||||
} else {
|
||||
OperationFuture<CASResponse> casFuture = client.asyncCas(converted.getId(), version,
|
||||
converted.getExpiration(), translateEncode(converted), persistTo, replicateTo);
|
||||
CASResponse cas = casFuture.get();
|
||||
|
||||
if (cas == CASResponse.EXISTS) {
|
||||
throw new OptimisticLockingFailureException("Updating document with version value failed: " + cas);
|
||||
} else {
|
||||
long newCas = casFuture.getCas();
|
||||
beanWrapper.setProperty(versionProperty, newCas);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
maybeEmitEvent(new AfterSaveEvent<Object>(objectToUpdate, converted));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Collection<?> batchToUpdate, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
for (Object toUpdate : batchToUpdate) {
|
||||
update(toUpdate, persistTo, replicateTo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(final Object objectToRemove, final PersistTo persistTo, final ReplicateTo replicateTo) {
|
||||
ensureNotIterable(objectToRemove);
|
||||
|
||||
maybeEmitEvent(new BeforeDeleteEvent<Object>(objectToRemove));
|
||||
if (objectToRemove instanceof String) {
|
||||
execute(new BucketCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInBucket() throws InterruptedException, ExecutionException {
|
||||
return client.delete((String) objectToRemove, persistTo, replicateTo).get();
|
||||
}
|
||||
});
|
||||
maybeEmitEvent(new AfterDeleteEvent<Object>(objectToRemove));
|
||||
return;
|
||||
}
|
||||
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
couchbaseConverter.write(objectToRemove, converted);
|
||||
|
||||
execute(new BucketCallback<OperationFuture<Boolean>>() {
|
||||
@Override
|
||||
public OperationFuture<Boolean> doInBucket() {
|
||||
return client.delete(converted.getId());
|
||||
}
|
||||
});
|
||||
maybeEmitEvent(new AfterDeleteEvent<Object>(objectToRemove));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Collection<?> batchToRemove, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
for (Object toRemove : batchToRemove) {
|
||||
remove(toRemove, persistTo, replicateTo);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle write errors according to the set {@link #writeResultChecking} setting.
|
||||
*
|
||||
* @param message the message to use.
|
||||
*/
|
||||
private void handleWriteResultError(String message) {
|
||||
private void handleWriteResultError(String message, Exception cause) {
|
||||
if (writeResultChecking == WriteResultChecking.NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (writeResultChecking == WriteResultChecking.EXCEPTION) {
|
||||
throw new CouchbaseDataIntegrityViolationException(message);
|
||||
} else {
|
||||
LOGGER.error(message);
|
||||
throw new CouchbaseDataIntegrityViolationException(message, cause);
|
||||
}
|
||||
else {
|
||||
LOGGER.error(message, cause);
|
||||
}
|
||||
}
|
||||
|
||||
public void setWriteResultChecking(WriteResultChecking writeResultChecking) {
|
||||
this.writeResultChecking = writeResultChecking == null ? DEFAULT_WRITE_RESULT_CHECKING : writeResultChecking;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setApplicationEventPublisher(final ApplicationEventPublisher eventPublisher) {
|
||||
this.eventPublisher = eventPublisher;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -487,7 +200,315 @@ public class CouchbaseTemplate implements CouchbaseOperations, ApplicationEventP
|
||||
}
|
||||
|
||||
@Override
|
||||
public CouchbaseClient getCouchbaseClient() {
|
||||
return client;
|
||||
public void save(Object objectToSave) {
|
||||
save(objectToSave, PersistTo.NONE, ReplicateTo.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Object objectToSave, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
doPersist(objectToSave, persistTo, replicateTo, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Collection<?> batchToSave) {
|
||||
save(batchToSave, PersistTo.NONE, ReplicateTo.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void save(Collection<?> batchToSave, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
for (Object o : batchToSave) {
|
||||
doPersist(o, persistTo, replicateTo, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Object objectToInsert) {
|
||||
insert(objectToInsert, PersistTo.NONE, ReplicateTo.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Object objectToInsert, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
doPersist(objectToInsert, persistTo, replicateTo, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Collection<?> batchToInsert) {
|
||||
insert(batchToInsert, PersistTo.NONE, ReplicateTo.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(Collection<?> batchToInsert, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
for (Object o : batchToInsert) {
|
||||
doPersist(o, persistTo, replicateTo, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Object objectToUpdate) {
|
||||
update(objectToUpdate, PersistTo.NONE, ReplicateTo.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Object objectToUpdate, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
doPersist(objectToUpdate, persistTo, replicateTo, false, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Collection<?> batchToUpdate) {
|
||||
update(batchToUpdate, PersistTo.NONE, ReplicateTo.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(Collection<?> batchToUpdate, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
for (Object o : batchToUpdate) {
|
||||
doPersist(o, persistTo, replicateTo, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T findById(final String id, Class<T> entityClass) {
|
||||
RawJsonDocument result = execute(new BucketCallback<RawJsonDocument>() {
|
||||
@Override
|
||||
public RawJsonDocument doInBucket() {
|
||||
return client.get(id, RawJsonDocument.class);
|
||||
}
|
||||
});
|
||||
|
||||
return mapToEntity(id, result, entityClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> findByView(ViewQuery query, Class<T> entityClass) {
|
||||
query.includeDocs(false);
|
||||
query.reduce(false);
|
||||
|
||||
try {
|
||||
final ViewResult response = queryView(query);
|
||||
if (response.error() != null) {
|
||||
throw new CouchbaseQueryExecutionException("Unable to execute view query due to the following view error: " +
|
||||
response.error().toString());
|
||||
}
|
||||
|
||||
List<ViewRow> allRows = response.allRows();
|
||||
|
||||
final List<T> result = new ArrayList<T>(allRows.size());
|
||||
for (final ViewRow row : allRows) {
|
||||
result.add(mapToEntity(row.id(), row.document(RawJsonDocument.class), entityClass));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (TranscodingException e) {
|
||||
throw new CouchbaseQueryExecutionException("Unable to execute view query", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ViewResult queryView(final ViewQuery query) {
|
||||
return execute(new BucketCallback<ViewResult>() {
|
||||
@Override
|
||||
public ViewResult doInBucket() {
|
||||
return client.query(query);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> findByN1QL(Query n1ql, Class<T> entityClass) {
|
||||
try {
|
||||
QueryResult queryResult = queryN1QL(n1ql);
|
||||
|
||||
if (queryResult.finalSuccess()) {
|
||||
List<QueryRow> allRows = queryResult.allRows();
|
||||
List<T> result = new ArrayList<T>(allRows.size());
|
||||
for (QueryRow row : allRows) {
|
||||
String json = row.value().toString();
|
||||
T decoded = translationService.decodeFragment(json, entityClass);
|
||||
result.add(decoded);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
else {
|
||||
StringBuilder message = new StringBuilder("Unable to execute query due to the following n1ql errors: ");
|
||||
for (JsonObject error : queryResult.errors()) {
|
||||
message.append('\n').append(error);
|
||||
}
|
||||
throw new CouchbaseQueryExecutionException(message.toString());
|
||||
}
|
||||
}
|
||||
catch (TranscodingException e) {
|
||||
throw new CouchbaseQueryExecutionException("Unable to execute query", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryResult queryN1QL(final Query query) {
|
||||
return execute(new BucketCallback<QueryResult>() {
|
||||
@Override
|
||||
public QueryResult doInBucket() throws TimeoutException, ExecutionException, InterruptedException {
|
||||
return client.query(query);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(final String id) {
|
||||
return execute(new BucketCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInBucket() throws TimeoutException, ExecutionException, InterruptedException {
|
||||
return client.exists(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Object objectToRemove) {
|
||||
remove(objectToRemove, PersistTo.NONE, ReplicateTo.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Object objectToRemove, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
doRemove(objectToRemove, persistTo, replicateTo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Collection<?> batchToRemove) {
|
||||
remove(batchToRemove, PersistTo.NONE, ReplicateTo.NONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(Collection<?> batchToRemove, PersistTo persistTo, ReplicateTo replicateTo) {
|
||||
for (Object o : batchToRemove) {
|
||||
doRemove(o, persistTo, replicateTo);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T execute(BucketCallback<T> action) {
|
||||
try {
|
||||
return action.doInBucket();
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
throw exceptionTranslator.translateExceptionIfPossible(e);
|
||||
}
|
||||
catch (TimeoutException e) {
|
||||
throw new QueryTimeoutException(e.getMessage(), e);
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
throw new OperationInterruptedException(e.getMessage(), e);
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
throw new OperationInterruptedException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
private void doPersist(Object objectToPersist, final PersistTo persistTo, final ReplicateTo replicateTo,
|
||||
final boolean failOnExist, final boolean failOnMissing) {
|
||||
ensureNotIterable(objectToPersist);
|
||||
|
||||
final String operationDesc = failOnExist ? "Insert" : failOnMissing ? "Update" : "Upsert";
|
||||
|
||||
final BeanWrapper<Object> beanWrapper = BeanWrapper.create(objectToPersist, converter.getConversionService());
|
||||
final CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(objectToPersist.getClass());
|
||||
final CouchbasePersistentProperty versionProperty = persistentEntity.getVersionProperty();
|
||||
final Long version = versionProperty != null ? beanWrapper.getProperty(versionProperty, Long.class) : null;
|
||||
|
||||
maybeEmitEvent(new BeforeConvertEvent<Object>(objectToPersist));
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
converter.write(objectToPersist, converted);
|
||||
|
||||
maybeEmitEvent(new BeforeSaveEvent<Object>(objectToPersist, converted));
|
||||
execute(new BucketCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInBucket() throws InterruptedException, ExecutionException {
|
||||
Document<String> doc = encodeAndWrap(converted, version);
|
||||
Document<String> storedDoc;
|
||||
try {
|
||||
if (!failOnExist && !failOnMissing) {
|
||||
storedDoc = client.upsert(doc, persistTo, replicateTo);
|
||||
}
|
||||
else if (failOnMissing) {
|
||||
storedDoc = client.replace(doc, persistTo, replicateTo);
|
||||
}
|
||||
else {
|
||||
storedDoc = client.insert(doc, persistTo, replicateTo);
|
||||
}
|
||||
|
||||
if (persistentEntity.hasVersionProperty() && storedDoc != null && storedDoc.cas() != 0) {
|
||||
//inject new cas into the bean
|
||||
beanWrapper.setProperty(versionProperty, storedDoc.cas());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
catch (CASMismatchException e) {
|
||||
throw new OptimisticLockingFailureException(operationDesc +
|
||||
" document with version value failed: " + version);
|
||||
}
|
||||
catch (Exception e) {
|
||||
handleWriteResultError(operationDesc + " document failed: " + e.getMessage(), e);
|
||||
return false; //this could be skipped if WriteResultChecking.EXCEPTION
|
||||
}
|
||||
}
|
||||
});
|
||||
maybeEmitEvent(new AfterSaveEvent<Object>(objectToPersist, converted));
|
||||
}
|
||||
|
||||
private void doRemove(final Object objectToRemove, final PersistTo persistTo, final ReplicateTo replicateTo) {
|
||||
ensureNotIterable(objectToRemove);
|
||||
|
||||
maybeEmitEvent(new BeforeDeleteEvent<Object>(objectToRemove));
|
||||
if (objectToRemove instanceof String) {
|
||||
execute(new BucketCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInBucket() throws InterruptedException, ExecutionException {
|
||||
RawJsonDocument deletedDoc = client.remove((String) objectToRemove, persistTo, replicateTo,
|
||||
RawJsonDocument.class);
|
||||
return deletedDoc != null;
|
||||
}
|
||||
});
|
||||
maybeEmitEvent(new AfterDeleteEvent<Object>(objectToRemove));
|
||||
return;
|
||||
}
|
||||
|
||||
final CouchbaseDocument converted = new CouchbaseDocument();
|
||||
converter.write(objectToRemove, converted);
|
||||
|
||||
execute(new BucketCallback<Boolean>() {
|
||||
@Override
|
||||
public Boolean doInBucket() {
|
||||
RawJsonDocument deletedDoc = client.remove(converted.getId(), persistTo, replicateTo
|
||||
, RawJsonDocument.class);
|
||||
return deletedDoc != null;
|
||||
}
|
||||
});
|
||||
maybeEmitEvent(new AfterDeleteEvent<Object>(objectToRemove));
|
||||
}
|
||||
|
||||
private <T> T mapToEntity(String id, Document<String> data, Class<T> entityClass) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final CouchbaseDocument converted = new CouchbaseDocument(id);
|
||||
Object readEntity = converter.read(entityClass, (CouchbaseDocument) decodeAndUnwrap(data, converted));
|
||||
|
||||
final BeanWrapper<Object> beanWrapper = BeanWrapper.create(readEntity, converter.getConversionService());
|
||||
CouchbasePersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(readEntity.getClass());
|
||||
if (persistentEntity.hasVersionProperty()) {
|
||||
beanWrapper.setProperty(persistentEntity.getVersionProperty(), data.cas());
|
||||
}
|
||||
|
||||
return (T) readEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bucket getCouchbaseBucket() {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CouchbaseConverter getConverter() {
|
||||
return this.converter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -27,6 +27,7 @@ public class OperationCancellationException extends TransientDataAccessException
|
||||
|
||||
/**
|
||||
* Constructor for OperationCancellationException.
|
||||
*
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public OperationCancellationException(final String msg) {
|
||||
@@ -35,6 +36,7 @@ public class OperationCancellationException extends TransientDataAccessException
|
||||
|
||||
/**
|
||||
* Constructor for OperationCancellationException.
|
||||
*
|
||||
* @param msg the detail message
|
||||
* @param cause the root cause from the data access API in use
|
||||
*/
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -27,6 +27,7 @@ public class OperationInterruptedException extends TransientDataAccessException
|
||||
|
||||
/**
|
||||
* Constructor for OperationInterruptedException.
|
||||
*
|
||||
* @param msg the detail message
|
||||
*/
|
||||
public OperationInterruptedException(final String msg) {
|
||||
@@ -35,6 +36,7 @@ public class OperationInterruptedException extends TransientDataAccessException
|
||||
|
||||
/**
|
||||
* Constructor for OperationInterruptedException.
|
||||
*
|
||||
* @param msg the detail message
|
||||
* @param cause the root cause from the data access API in use
|
||||
*/
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013, 2014 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -86,7 +86,7 @@ class ConverterRegistration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the source type is a Mongo simple one.
|
||||
* Returns whether the source type is a Couchbase simple one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@@ -95,7 +95,7 @@ class ConverterRegistration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the target type is a Mongo simple one.
|
||||
* Returns whether the target type is a Couchbase simple one.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
@@ -104,7 +104,7 @@ class ConverterRegistration {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the given type is a type that Mongo can handle basically.
|
||||
* Returns whether the given type is a type that Couchbase can handle basically.
|
||||
*
|
||||
* @param type
|
||||
* @return
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -28,8 +28,8 @@ import org.springframework.data.couchbase.core.mapping.CouchbasePersistentProper
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public interface CouchbaseConverter
|
||||
extends EntityConverter<CouchbasePersistentEntity<?>,
|
||||
CouchbasePersistentProperty, Object, CouchbaseDocument>,
|
||||
CouchbaseWriter<Object, CouchbaseDocument>,
|
||||
EntityReader<Object, CouchbaseDocument> {
|
||||
extends EntityConverter<CouchbasePersistentEntity<?>,
|
||||
CouchbasePersistentProperty, Object, CouchbaseDocument>,
|
||||
CouchbaseWriter<Object, CouchbaseDocument>,
|
||||
EntityReader<Object, CouchbaseDocument> {
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,13 +16,13 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.convert;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.TypedValue;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A property accessor for document properties.
|
||||
*
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -24,5 +24,5 @@ import org.springframework.data.convert.EntityWriter;
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public interface CouchbaseWriter<T, ConvertedCouchbaseDocument> extends
|
||||
EntityWriter<T, ConvertedCouchbaseDocument> {
|
||||
EntityWriter<T, ConvertedCouchbaseDocument> {
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,26 +16,30 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.JodaTimeConverters;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
* Value object to capture custom conversion.
|
||||
*
|
||||
* <p/>
|
||||
* <p>Types that can be mapped directly onto JSON are considered simple ones, because they neither need deeper
|
||||
* inspection nor nested conversion.</p>
|
||||
*
|
||||
@@ -69,6 +73,7 @@ public class CustomConversions {
|
||||
|
||||
/**
|
||||
* Create a new instance with a given list of conversers.
|
||||
*
|
||||
* @param converters the list of custom converters.
|
||||
*/
|
||||
public CustomConversions(final List<?> converters) {
|
||||
@@ -155,10 +160,12 @@ public class CustomConversions {
|
||||
for (GenericConverter.ConvertiblePair pair : genericConverter.getConvertibleTypes()) {
|
||||
register(new ConverterRegistration(pair, isReading, isWriting));
|
||||
}
|
||||
} else if (converter instanceof Converter) {
|
||||
}
|
||||
else if (converter instanceof Converter) {
|
||||
Class<?>[] arguments = GenericTypeResolver.resolveTypeArguments(converter.getClass(), Converter.class);
|
||||
register(new ConverterRegistration(arguments[0], arguments[1], isReading, isWriting));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unsupported Converter type!");
|
||||
}
|
||||
}
|
||||
@@ -279,7 +286,7 @@ public class CustomConversions {
|
||||
}
|
||||
|
||||
/**
|
||||
* Inspects the given {@link org.springframework.core.convert.converter.GenericConverter.ConvertiblePair} for ones
|
||||
* Inspects the given {@link GenericConverter.ConvertiblePair} for ones
|
||||
* that have a source compatible type as source. Additionally checks assignability of the target type if one is
|
||||
* given.
|
||||
*
|
||||
@@ -289,7 +296,7 @@ public class CustomConversions {
|
||||
* @return
|
||||
*/
|
||||
private static Class<?> getCustomTarget(Class<?> sourceType, Class<?> requestedTargetType,
|
||||
Iterable<GenericConverter.ConvertiblePair> pairs) {
|
||||
Iterable<GenericConverter.ConvertiblePair> pairs) {
|
||||
Assert.notNull(sourceType);
|
||||
Assert.notNull(pairs);
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,21 +16,22 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.convert;
|
||||
|
||||
import org.joda.time.DateMidnight;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.joda.time.DateMidnight;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.LocalDate;
|
||||
import org.joda.time.LocalDateTime;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.convert.ReadingConverter;
|
||||
import org.springframework.data.convert.WritingConverter;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Out of the box conversions for java dates and calendars.
|
||||
*
|
||||
@@ -38,7 +39,8 @@ import java.util.List;
|
||||
*/
|
||||
public final class DateConverters {
|
||||
|
||||
private DateConverters() {}
|
||||
private DateConverters() {
|
||||
}
|
||||
|
||||
private static final boolean JODA_TIME_IS_PRESENT = ClassUtils.isPresent("org.joda.time.LocalDate", null);
|
||||
|
||||
@@ -85,7 +87,7 @@ public final class DateConverters {
|
||||
|
||||
@Override
|
||||
public Long convert(Calendar source) {
|
||||
return source == null ? null : source.getTimeInMillis() / 1000;
|
||||
return source == null ? null : source.getTimeInMillis() / 1000;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,6 +16,13 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.convert;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.CollectionFactory;
|
||||
@@ -31,14 +38,20 @@ import org.springframework.data.mapping.AssociationHandler;
|
||||
import org.springframework.data.mapping.PreferredConstructor.Parameter;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.*;
|
||||
import org.springframework.data.mapping.model.BeanWrapper;
|
||||
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.ParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
|
||||
import org.springframework.data.mapping.model.PropertyValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELContext;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.SpELExpressionParameterValueProvider;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A mapping converter for Couchbase.
|
||||
*
|
||||
@@ -154,7 +167,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
protected <R> R read(final CouchbasePersistentEntity<R> entity, final CouchbaseDocument source, final Object parent) {
|
||||
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(source, spELContext);
|
||||
ParameterValueProvider<CouchbasePersistentProperty> provider =
|
||||
getParameterProvider(entity, source, evaluator, parent);
|
||||
getParameterProvider(entity, source, evaluator, parent);
|
||||
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||
|
||||
R instance = instantiator.createInstance(entity, provider);
|
||||
@@ -197,7 +210,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
* @return the actual property value.
|
||||
*/
|
||||
protected Object getValueInternal(final CouchbasePersistentProperty property, final CouchbaseDocument source,
|
||||
final Object parent) {
|
||||
final Object parent) {
|
||||
return new CouchbasePropertyValueProvider(source, spELContext, parent).getPropertyValue(property);
|
||||
}
|
||||
|
||||
@@ -211,14 +224,14 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
* @return a new parameter value provider.
|
||||
*/
|
||||
private ParameterValueProvider<CouchbasePersistentProperty> getParameterProvider(
|
||||
final CouchbasePersistentEntity<?> entity, final CouchbaseDocument source,
|
||||
final DefaultSpELExpressionEvaluator evaluator, final Object parent) {
|
||||
final CouchbasePersistentEntity<?> entity, final CouchbaseDocument source,
|
||||
final DefaultSpELExpressionEvaluator evaluator, final Object parent) {
|
||||
CouchbasePropertyValueProvider provider = new CouchbasePropertyValueProvider(source, evaluator, parent);
|
||||
PersistentEntityParameterValueProvider<CouchbasePersistentProperty> parameterProvider =
|
||||
new PersistentEntityParameterValueProvider<CouchbasePersistentProperty>(entity, provider, parent);
|
||||
new PersistentEntityParameterValueProvider<CouchbasePersistentProperty>(entity, provider, parent);
|
||||
|
||||
return new ConverterAwareSpELExpressionParameterValueProvider(evaluator, conversionService, parameterProvider,
|
||||
parent);
|
||||
parent);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +244,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Map<Object, Object> readMap(final TypeInformation<?> type, final CouchbaseDocument source,
|
||||
final Object parent) {
|
||||
final Object parent) {
|
||||
Assert.notNull(source);
|
||||
|
||||
Class<?> mapType = typeMapper.readType(source, type).getType();
|
||||
@@ -368,7 +381,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
* @param entity the persistent entity to convert from.
|
||||
*/
|
||||
protected void writeInternal(final Object source, final CouchbaseDocument target,
|
||||
final CouchbasePersistentEntity<?> entity) {
|
||||
final CouchbasePersistentEntity<?> entity) {
|
||||
if (source == null) {
|
||||
return;
|
||||
}
|
||||
@@ -377,7 +390,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
throw new MappingException("No mapping metadata found for entity of type " + source.getClass().getName());
|
||||
}
|
||||
|
||||
final BeanWrapper<Object> wrapper = BeanWrapper.create(source, conversionService);
|
||||
final BeanWrapper<Object> wrapper = BeanWrapper.create(source, conversionService);
|
||||
final CouchbasePersistentProperty idProperty = entity.getIdProperty();
|
||||
final CouchbasePersistentProperty versionProperty = entity.getVersionProperty();
|
||||
|
||||
@@ -428,7 +441,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private void writePropertyInternal(final Object source, final CouchbaseDocument target,
|
||||
final CouchbasePersistentProperty prop) {
|
||||
final CouchbasePersistentProperty prop) {
|
||||
if (source == null) {
|
||||
return;
|
||||
}
|
||||
@@ -459,7 +472,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
addCustomTypeKeyIfNecessary(type, source, propertyDoc);
|
||||
|
||||
CouchbasePersistentEntity<?> entity = isSubtype(prop.getType(), source.getClass()) ? mappingContext
|
||||
.getPersistentEntity(source.getClass()) : mappingContext.getPersistentEntity(type);
|
||||
.getPersistentEntity(source.getClass()) : mappingContext.getPersistentEntity(type);
|
||||
writeInternal(source, propertyDoc, entity);
|
||||
target.put(name, propertyDoc);
|
||||
}
|
||||
@@ -487,7 +500,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
* @return the written couchbase document.
|
||||
*/
|
||||
private CouchbaseDocument writeMapInternal(final Map<Object, Object> source, final CouchbaseDocument target,
|
||||
final TypeInformation<?> type) {
|
||||
final TypeInformation<?> type) {
|
||||
for (Map.Entry<Object, Object> entry : source.entrySet()) {
|
||||
Object key = entry.getKey();
|
||||
Object val = entry.getValue();
|
||||
@@ -533,7 +546,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
* @return the created couchbase list.
|
||||
*/
|
||||
private CouchbaseList writeCollectionInternal(final Collection<?> source, final CouchbaseList target,
|
||||
final TypeInformation<?> type) {
|
||||
final TypeInformation<?> type) {
|
||||
TypeInformation<?> componentType = type == null ? null : type.getComponentType();
|
||||
|
||||
for (Object element : source) {
|
||||
@@ -573,7 +586,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
|
||||
collectionType = Collection.class.isAssignableFrom(collectionType) ? collectionType : List.class;
|
||||
Collection<Object> items = targetType.getType().isArray() ? new ArrayList<Object>() : CollectionFactory
|
||||
.createCollection(collectionType, source.size(false));
|
||||
.createCollection(collectionType, source.size(false));
|
||||
TypeInformation<?> componentType = targetType.getComponentType();
|
||||
Class<?> rawComponentType = componentType == null ? null : componentType.getType();
|
||||
|
||||
@@ -709,12 +722,12 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
private final Object parent;
|
||||
|
||||
public CouchbasePropertyValueProvider(final CouchbaseDocument source, final SpELContext factory,
|
||||
final Object parent) {
|
||||
final Object parent) {
|
||||
this(source, new DefaultSpELExpressionEvaluator(source, factory), parent);
|
||||
}
|
||||
|
||||
public CouchbasePropertyValueProvider(final CouchbaseDocument source,
|
||||
final DefaultSpELExpressionEvaluator evaluator, final Object parent) {
|
||||
final DefaultSpELExpressionEvaluator evaluator, final Object parent) {
|
||||
Assert.notNull(source);
|
||||
Assert.notNull(evaluator);
|
||||
|
||||
@@ -744,7 +757,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
* A expression parameter value provider.
|
||||
*/
|
||||
private class ConverterAwareSpELExpressionParameterValueProvider extends
|
||||
SpELExpressionParameterValueProvider<CouchbasePersistentProperty> {
|
||||
SpELExpressionParameterValueProvider<CouchbasePersistentProperty> {
|
||||
|
||||
private final Object parent;
|
||||
|
||||
@@ -757,7 +770,7 @@ public class MappingCouchbaseConverter extends AbstractCouchbaseConverter
|
||||
|
||||
@Override
|
||||
protected <T> T potentiallyConvertSpelValue(final Object object,
|
||||
final Parameter<T, CouchbasePersistentProperty> parameter) {
|
||||
final Parameter<T, CouchbasePersistentProperty> parameter) {
|
||||
return readValue(object, parameter.getType(), parent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,12 +16,18 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.convert.translation;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParseException;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseList;
|
||||
@@ -29,9 +35,6 @@ import org.springframework.data.couchbase.core.mapping.CouchbaseStorable;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A Jackson JSON Translator that implements the {@link TranslationService} contract.
|
||||
*
|
||||
@@ -58,11 +61,10 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
* Encode a {@link CouchbaseStorable} to a JSON string.
|
||||
*
|
||||
* @param source the source document to encode.
|
||||
*
|
||||
* @return the encoded JSON String.
|
||||
*/
|
||||
@Override
|
||||
public final Object encode(final CouchbaseStorable source) {
|
||||
public final String encode(final CouchbaseStorable source) {
|
||||
Writer writer = new StringWriter();
|
||||
|
||||
try {
|
||||
@@ -70,7 +72,8 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
encodeRecursive(source, generator);
|
||||
generator.close();
|
||||
writer.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException("Could not encode JSON", ex);
|
||||
}
|
||||
|
||||
@@ -82,7 +85,6 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
*
|
||||
* @param source the source document
|
||||
* @param generator the JSON generator.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private void encodeRecursive(final CouchbaseStorable source, final JsonGenerator generator) throws IOException {
|
||||
@@ -101,7 +103,8 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
|
||||
if (simpleTypeHolder.isSimpleType(clazz) && !isEnumOrClass(clazz)) {
|
||||
generator.writeObject(value);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
objectMapper.writeValue(generator, value);
|
||||
}
|
||||
|
||||
@@ -119,11 +122,10 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
*
|
||||
* @param source the source formatted document.
|
||||
* @param target the target of the populated data.
|
||||
*
|
||||
* @return the decoded structure.
|
||||
*/
|
||||
@Override
|
||||
public final CouchbaseStorable decode(final Object source, final CouchbaseStorable target) {
|
||||
public final CouchbaseStorable decode(final String source, final CouchbaseStorable target) {
|
||||
try {
|
||||
JsonParser parser = factory.createParser((String) source);
|
||||
while (parser.nextToken() != null) {
|
||||
@@ -131,14 +133,17 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
|
||||
if (currentToken == JsonToken.START_OBJECT) {
|
||||
return decodeObject(parser, (CouchbaseDocument) target);
|
||||
} else if (currentToken == JsonToken.START_ARRAY) {
|
||||
}
|
||||
else if (currentToken == JsonToken.START_ARRAY) {
|
||||
return decodeArray(parser, new CouchbaseList());
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw new MappingException("JSON to decode needs to start as array or object!");
|
||||
}
|
||||
}
|
||||
parser.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException("Could not decode JSON", ex);
|
||||
}
|
||||
return target;
|
||||
@@ -149,7 +154,6 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
*
|
||||
* @param parser the JSON parser with the content.
|
||||
* @param target the target where the content should be stored.
|
||||
*
|
||||
* @throws IOException
|
||||
* @returns the decoded object.
|
||||
*/
|
||||
@@ -160,11 +164,14 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
while (currentToken != null && currentToken != JsonToken.END_OBJECT) {
|
||||
if (currentToken == JsonToken.START_OBJECT) {
|
||||
target.put(fieldName, decodeObject(parser, new CouchbaseDocument()));
|
||||
} else if (currentToken == JsonToken.START_ARRAY) {
|
||||
}
|
||||
else if (currentToken == JsonToken.START_ARRAY) {
|
||||
target.put(fieldName, decodeArray(parser, new CouchbaseList()));
|
||||
} else if (currentToken == JsonToken.FIELD_NAME) {
|
||||
}
|
||||
else if (currentToken == JsonToken.FIELD_NAME) {
|
||||
fieldName = parser.getCurrentName();
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
target.put(fieldName, decodePrimitive(currentToken, parser));
|
||||
}
|
||||
|
||||
@@ -179,7 +186,6 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
*
|
||||
* @param parser the JSON parser with the content.
|
||||
* @param target the target where the content should be stored.
|
||||
*
|
||||
* @throws IOException
|
||||
* @returns the decoded list.
|
||||
*/
|
||||
@@ -189,9 +195,11 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
while (currentToken != null && currentToken != JsonToken.END_ARRAY) {
|
||||
if (currentToken == JsonToken.START_OBJECT) {
|
||||
target.put(decodeObject(parser, new CouchbaseDocument()));
|
||||
} else if (currentToken == JsonToken.START_ARRAY) {
|
||||
}
|
||||
else if (currentToken == JsonToken.START_ARRAY) {
|
||||
target.put(decodeArray(parser, new CouchbaseList()));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
target.put(decodePrimitive(currentToken, parser));
|
||||
}
|
||||
|
||||
@@ -206,9 +214,7 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
*
|
||||
* @param token the type of token.
|
||||
* @param parser the parser with the content.
|
||||
*
|
||||
* @return the decoded primitve.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
private Object decodePrimitive(final JsonToken token, final JsonParser parser) throws IOException {
|
||||
@@ -221,7 +227,8 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
case VALUE_NUMBER_INT:
|
||||
try {
|
||||
return parser.getValueAsInt();
|
||||
} catch (final JsonParseException e) {
|
||||
}
|
||||
catch (final JsonParseException e) {
|
||||
return parser.getValueAsLong();
|
||||
}
|
||||
case VALUE_NUMBER_FLOAT:
|
||||
@@ -229,7 +236,17 @@ public class JacksonTranslationService implements TranslationService, Initializi
|
||||
case VALUE_NULL:
|
||||
return null;
|
||||
default:
|
||||
throw new MappingException("Could not decode primitve value " + token);
|
||||
throw new MappingException("Could not decode primitive value " + token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T decodeFragment(String source, Class<T> target) {
|
||||
try {
|
||||
return objectMapper.readValue(source, target);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException("Cannot decode ad-hoc JSON", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.convert.translation;
|
||||
|
||||
import com.couchbase.client.java.query.QueryRow;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseStorable;
|
||||
|
||||
@@ -27,12 +29,12 @@ import org.springframework.data.couchbase.core.mapping.CouchbaseStorable;
|
||||
public interface TranslationService {
|
||||
|
||||
/**
|
||||
* Encodes a {@link CouchbaseDocument} into the target format.
|
||||
* Encodes a JSON String into the target format.
|
||||
*
|
||||
* @param source the source document to encode.
|
||||
* @param source the source contents to encode.
|
||||
* @return the encoded document representation.
|
||||
*/
|
||||
Object encode(CouchbaseStorable source);
|
||||
String encode(CouchbaseStorable source);
|
||||
|
||||
/**
|
||||
* Decodes the target format into a {@link CouchbaseDocument}
|
||||
@@ -41,5 +43,15 @@ public interface TranslationService {
|
||||
* @param target the target of the populated data.
|
||||
* @return a properly populated document to work with.
|
||||
*/
|
||||
CouchbaseStorable decode(Object source, CouchbaseStorable target);
|
||||
CouchbaseStorable decode(String source, CouchbaseStorable target);
|
||||
|
||||
/**
|
||||
* Decodes an ad-hoc JSON object into a corresponding "case" class.
|
||||
*
|
||||
* @param source the JSON for the ad-hoc JSON object (from a N1QL {@link QueryRow} for instance).
|
||||
* @param target the target class information.
|
||||
* @param <T> the target class.
|
||||
* @return an ad-hoc instance of the decoded JSON into the corresponding "case" class.
|
||||
*/
|
||||
<T> T decodeFragment(String source, Class<T> target);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -31,7 +31,7 @@ import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public class BasicCouchbasePersistentEntity<T> extends BasicPersistentEntity<T, CouchbasePersistentProperty>
|
||||
implements CouchbasePersistentEntity<T>, ApplicationContextAware {
|
||||
implements CouchbasePersistentEntity<T>, ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Contains the evaluation context.
|
||||
@@ -40,6 +40,7 @@ public class BasicCouchbasePersistentEntity<T> extends BasicPersistentEntity<T,
|
||||
|
||||
/**
|
||||
* Create a new entity.
|
||||
*
|
||||
* @param typeInformation the type information of the entity.
|
||||
*/
|
||||
public BasicCouchbasePersistentEntity(final TypeInformation<T> typeInformation) {
|
||||
@@ -55,9 +56,9 @@ public class BasicCouchbasePersistentEntity<T> extends BasicPersistentEntity<T,
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
|
||||
context.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
context.setRootObject(applicationContext);
|
||||
context.addPropertyAccessor(new BeanFactoryAccessor());
|
||||
context.setBeanResolver(new BeanFactoryResolver(applicationContext));
|
||||
context.setRootObject(applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,9 +67,9 @@ public class BasicCouchbasePersistentEntity<T> extends BasicPersistentEntity<T,
|
||||
* @return the expiration time.
|
||||
*/
|
||||
public int getExpiry() {
|
||||
org.springframework.data.couchbase.core.mapping.Document annotation =
|
||||
getType().getAnnotation(org.springframework.data.couchbase.core.mapping.Document.class);
|
||||
org.springframework.data.couchbase.core.mapping.Document annotation =
|
||||
getType().getAnnotation(org.springframework.data.couchbase.core.mapping.Document.class);
|
||||
return annotation == null ? 0 : annotation.expiry();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
@@ -24,20 +27,17 @@ import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Implements annotated property representations of a given Field instance.
|
||||
*
|
||||
* <p/>
|
||||
* <p>This object is used to gather information out of properties on objects that need to be persisted. For example, it
|
||||
* supports overriding of the actual property name by providing custom annotations.</p>
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public class BasicCouchbasePersistentProperty
|
||||
extends AnnotationBasedPersistentProperty<CouchbasePersistentProperty>
|
||||
implements CouchbasePersistentProperty {
|
||||
extends AnnotationBasedPersistentProperty<CouchbasePersistentProperty>
|
||||
implements CouchbasePersistentProperty {
|
||||
|
||||
private final FieldNamingStrategy fieldNamingStrategy;
|
||||
|
||||
@@ -50,11 +50,11 @@ public class BasicCouchbasePersistentProperty
|
||||
* @param simpleTypeHolder the type holder.
|
||||
*/
|
||||
public BasicCouchbasePersistentProperty(final Field field, final PropertyDescriptor propertyDescriptor,
|
||||
final CouchbasePersistentEntity<?> owner, final SimpleTypeHolder simpleTypeHolder,
|
||||
final FieldNamingStrategy fieldNamingStrategy) {
|
||||
final CouchbasePersistentEntity<?> owner, final SimpleTypeHolder simpleTypeHolder,
|
||||
final FieldNamingStrategy fieldNamingStrategy) {
|
||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
||||
this.fieldNamingStrategy = fieldNamingStrategy == null ? PropertyNameFieldNamingStrategy.INSTANCE
|
||||
: fieldNamingStrategy;
|
||||
: fieldNamingStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,14 +67,14 @@ public class BasicCouchbasePersistentProperty
|
||||
|
||||
/**
|
||||
* Returns the field name of the property.
|
||||
*
|
||||
* <p/>
|
||||
* The field name can be different from the actual property name by using a
|
||||
* custom annotation.
|
||||
*/
|
||||
@Override
|
||||
public String getFieldName() {
|
||||
org.springframework.data.couchbase.core.mapping.Field annotation = getField().
|
||||
getAnnotation(org.springframework.data.couchbase.core.mapping.Field.class);
|
||||
getAnnotation(org.springframework.data.couchbase.core.mapping.Field.class);
|
||||
|
||||
if (annotation != null && StringUtils.hasText(annotation.value())) {
|
||||
return annotation.value();
|
||||
@@ -84,7 +84,7 @@ public class BasicCouchbasePersistentProperty
|
||||
|
||||
if (!StringUtils.hasText(fieldName)) {
|
||||
throw new MappingException(String.format("Invalid (null or empty) field name returned for property %s by %s!",
|
||||
this, fieldNamingStrategy.getClass()));
|
||||
this, fieldNamingStrategy.getClass()));
|
||||
}
|
||||
|
||||
return fieldName;
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,20 +16,20 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping;
|
||||
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
/**
|
||||
* A {@link CouchbaseDocument} is an abstract representation of a document stored inside Couchbase Server.
|
||||
*
|
||||
* <p/>
|
||||
* <p>It acts like a {@link HashMap}, but only allows those types to be written that are supported by the underlying
|
||||
* storage format, which is currently JSON. Note that JSON conversion is not happening here, but performed at a
|
||||
* different stage based on the payload stored in the {@link CouchbaseDocument}.</p>
|
||||
*
|
||||
* <p/>
|
||||
* <p>In addition to the actual content, meta data is also stored. This especially refers to the document ID and its
|
||||
* expiration time. Note that this information is not mandatory, since documents can be nested and therefore only the
|
||||
* topmost document most likely has an ID.</p>
|
||||
@@ -115,7 +115,7 @@ public class CouchbaseDocument implements CouchbaseStorable {
|
||||
*
|
||||
* @param key the key of the attribute.
|
||||
* @return the value to which the specified key is mapped, or
|
||||
* null if does not contain a mapping for the key.
|
||||
* null if does not contain a mapping for the key.
|
||||
*/
|
||||
public final Object get(final String key) {
|
||||
return payload.get(key);
|
||||
@@ -123,7 +123,7 @@ public class CouchbaseDocument implements CouchbaseStorable {
|
||||
|
||||
/**
|
||||
* Returns the current payload, including all recursive elements.
|
||||
*
|
||||
* <p/>
|
||||
* It either returns the raw results or makes sure that the recusrive elements
|
||||
* are also exported properly.
|
||||
*
|
||||
@@ -134,7 +134,8 @@ public class CouchbaseDocument implements CouchbaseStorable {
|
||||
for (Map.Entry<String, Object> entry : payload.entrySet()) {
|
||||
if (entry.getValue() instanceof CouchbaseDocument) {
|
||||
toExport.put(entry.getKey(), ((CouchbaseDocument) entry.getValue()).export());
|
||||
} else if (entry.getValue() instanceof CouchbaseList) {
|
||||
}
|
||||
else if (entry.getValue() instanceof CouchbaseList) {
|
||||
toExport.put(entry.getKey(), ((CouchbaseList) entry.getValue()).export());
|
||||
}
|
||||
}
|
||||
@@ -187,7 +188,8 @@ public class CouchbaseDocument implements CouchbaseStorable {
|
||||
for (Object value : payload.values()) {
|
||||
if (value instanceof CouchbaseDocument) {
|
||||
totalSize += ((CouchbaseDocument) value).size(true);
|
||||
} else if (value instanceof CouchbaseList) {
|
||||
}
|
||||
else if (value instanceof CouchbaseList) {
|
||||
totalSize += ((CouchbaseList) value).size(true);
|
||||
}
|
||||
}
|
||||
@@ -197,7 +199,7 @@ public class CouchbaseDocument implements CouchbaseStorable {
|
||||
|
||||
/**
|
||||
* Returns the underlying payload.
|
||||
*
|
||||
* <p/>
|
||||
* <p>Note that unlike {@link #export()}, the nested objects are not converted, so the "raw" map is returned.</p>
|
||||
*
|
||||
* @return the underlying payload.
|
||||
@@ -208,7 +210,7 @@ public class CouchbaseDocument implements CouchbaseStorable {
|
||||
|
||||
/**
|
||||
* Returns the expiration time of the document.
|
||||
*
|
||||
* <p/>
|
||||
* If the expiration time is 0, then the document will be persisted until
|
||||
* deleted manually ("forever").
|
||||
*
|
||||
@@ -220,7 +222,7 @@ public class CouchbaseDocument implements CouchbaseStorable {
|
||||
|
||||
/**
|
||||
* Set the expiration time of the document.
|
||||
*
|
||||
* <p/>
|
||||
* If the expiration time is 0, then the document will be persisted until
|
||||
* deleted manually ("forever").
|
||||
*
|
||||
@@ -255,19 +257,19 @@ public class CouchbaseDocument implements CouchbaseStorable {
|
||||
/**
|
||||
* Verifies that only values of a certain and supported type
|
||||
* can be stored.
|
||||
*
|
||||
* <p/>
|
||||
* <p>If this is not the case, a {@link IllegalArgumentException} is
|
||||
* thrown.</p>
|
||||
*
|
||||
* @param value the object to verify its type.
|
||||
*/
|
||||
private void verifyValueType(final Object value) {
|
||||
if(value == null) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
final Class<?> clazz = value.getClass();
|
||||
if (simpleTypeHolder.isSimpleType(clazz)) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
throw new IllegalArgumentException("Attribute of type " + clazz.getCanonicalName() + " cannot be stored and must be converted.");
|
||||
}
|
||||
@@ -280,9 +282,9 @@ public class CouchbaseDocument implements CouchbaseStorable {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CouchbaseDocument{" +
|
||||
"id=" + id +
|
||||
", exp=" + expiration +
|
||||
", payload=" + payload +
|
||||
'}';
|
||||
"id=" + id +
|
||||
", exp=" + expiration +
|
||||
", payload=" + payload +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,16 +16,16 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping;
|
||||
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
/**
|
||||
* A {@link CouchbaseList} is an abstract list that represents an array stored in a (most of the times JSON) document.
|
||||
*
|
||||
* <p/>
|
||||
* <p>This {@link CouchbaseList} is part of the potentially nested structure inside one or more
|
||||
* {@link CouchbaseDocument}s. It can also contain them recursively, depending on how the document is modeled.</p>
|
||||
*/
|
||||
@@ -78,9 +78,10 @@ public class CouchbaseList implements CouchbaseStorable {
|
||||
additionalTypes.add(CouchbaseDocument.class);
|
||||
additionalTypes.add(CouchbaseList.class);
|
||||
if (simpleTypeHolder != null) {
|
||||
this.simpleTypeHolder = new SimpleTypeHolder(additionalTypes, simpleTypeHolder);
|
||||
} else {
|
||||
this.simpleTypeHolder = new SimpleTypeHolder(additionalTypes, true);
|
||||
this.simpleTypeHolder = new SimpleTypeHolder(additionalTypes, simpleTypeHolder);
|
||||
}
|
||||
else {
|
||||
this.simpleTypeHolder = new SimpleTypeHolder(additionalTypes, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,7 +134,8 @@ public class CouchbaseList implements CouchbaseStorable {
|
||||
for (Object value : payload) {
|
||||
if (value instanceof CouchbaseDocument) {
|
||||
totalSize += ((CouchbaseDocument) value).size(true);
|
||||
} else if (value instanceof CouchbaseList) {
|
||||
}
|
||||
else if (value instanceof CouchbaseList) {
|
||||
totalSize += ((CouchbaseList) value).size(true);
|
||||
}
|
||||
}
|
||||
@@ -143,7 +145,7 @@ public class CouchbaseList implements CouchbaseStorable {
|
||||
|
||||
/**
|
||||
* Returns the current payload, including all recursive elements.
|
||||
*
|
||||
* <p/>
|
||||
* It either returns the raw results or makes sure that the recusrive elements
|
||||
* are also exported properly.
|
||||
*
|
||||
@@ -157,7 +159,8 @@ public class CouchbaseList implements CouchbaseStorable {
|
||||
if (entry instanceof CouchbaseDocument) {
|
||||
toExport.remove(elem);
|
||||
toExport.add(elem, ((CouchbaseDocument) entry).export());
|
||||
} else if (entry instanceof CouchbaseList) {
|
||||
}
|
||||
else if (entry instanceof CouchbaseList) {
|
||||
toExport.remove(elem);
|
||||
toExport.add(elem, ((CouchbaseList) entry).export());
|
||||
}
|
||||
@@ -188,14 +191,14 @@ public class CouchbaseList implements CouchbaseStorable {
|
||||
/**
|
||||
* Verifies that only values of a certain and supported type
|
||||
* can be stored.
|
||||
*
|
||||
* <p/>
|
||||
* <p>If this is not the case, a {@link IllegalArgumentException} is
|
||||
* thrown.</p>
|
||||
*
|
||||
* @param value the object to verify its type.
|
||||
*/
|
||||
private void verifyValueType(final Object value) {
|
||||
if(value == null) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -205,7 +208,7 @@ public class CouchbaseList implements CouchbaseStorable {
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Attribute of type "
|
||||
+ clazz.getCanonicalName() + "can not be stored and must be converted.");
|
||||
+ clazz.getCanonicalName() + "can not be stored and must be converted.");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,7 +219,7 @@ public class CouchbaseList implements CouchbaseStorable {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CouchbaseList{" +
|
||||
"payload=" + payload +
|
||||
'}';
|
||||
"payload=" + payload +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
@@ -25,9 +28,6 @@ import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* Default implementation of a {@link org.springframework.data.mapping.context.MappingContext} for Couchbase using
|
||||
* {@link BasicCouchbasePersistentEntity} and {@link BasicCouchbasePersistentProperty} as primary abstractions.
|
||||
@@ -35,8 +35,8 @@ import java.lang.reflect.Field;
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public class CouchbaseMappingContext
|
||||
extends AbstractMappingContext<BasicCouchbasePersistentEntity<?>, CouchbasePersistentProperty>
|
||||
implements ApplicationContextAware {
|
||||
extends AbstractMappingContext<BasicCouchbasePersistentEntity<?>, CouchbasePersistentProperty>
|
||||
implements ApplicationContextAware {
|
||||
|
||||
/**
|
||||
* Contains the application context to configure the application.
|
||||
@@ -58,7 +58,7 @@ public class CouchbaseMappingContext
|
||||
* Defaults to a strategy using the plain property name.
|
||||
*
|
||||
* @param fieldNamingStrategy the {@link FieldNamingStrategy} to be used to determine the field name if no manual
|
||||
* mapping is applied.
|
||||
* mapping is applied.
|
||||
*/
|
||||
public void setFieldNamingStrategy(final FieldNamingStrategy fieldNamingStrategy) {
|
||||
this.fieldNamingStrategy = fieldNamingStrategy == null ? DEFAULT_NAMING_STRATEGY : fieldNamingStrategy;
|
||||
@@ -91,7 +91,7 @@ public class CouchbaseMappingContext
|
||||
*/
|
||||
@Override
|
||||
protected CouchbasePersistentProperty createPersistentProperty(final Field field, final PropertyDescriptor descriptor,
|
||||
final BasicCouchbasePersistentEntity<?> owner, final SimpleTypeHolder simpleTypeHolder) {
|
||||
final BasicCouchbasePersistentEntity<?> owner, final SimpleTypeHolder simpleTypeHolder) {
|
||||
return new BasicCouchbasePersistentProperty(field, descriptor, owner, simpleTypeHolder, fieldNamingStrategy);
|
||||
}
|
||||
|
||||
@@ -101,9 +101,9 @@ public class CouchbaseMappingContext
|
||||
* @param applicationContext the application context to be assigned.
|
||||
* @throws BeansException if the context can not be set properly.
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
|
||||
context = applicationContext;
|
||||
}
|
||||
@Override
|
||||
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException {
|
||||
context = applicationContext;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -24,13 +24,13 @@ import org.springframework.data.mapping.PersistentEntity;
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public interface CouchbasePersistentEntity<T> extends
|
||||
PersistentEntity<T, CouchbasePersistentProperty> {
|
||||
PersistentEntity<T, CouchbasePersistentProperty> {
|
||||
|
||||
/**
|
||||
* Returns the expiry time for the document.
|
||||
*
|
||||
* @return the expiration time.
|
||||
*/
|
||||
int getExpiry();
|
||||
int getExpiry();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -27,7 +27,7 @@ public interface CouchbasePersistentProperty extends PersistentProperty<Couchbas
|
||||
|
||||
/**
|
||||
* Returns the field name of the property.
|
||||
*
|
||||
* <p/>
|
||||
* The field name can be different from the actual property name by using a custom annotation.
|
||||
*/
|
||||
String getFieldName();
|
||||
|
||||
@@ -1,18 +1,37 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping;
|
||||
|
||||
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.couchbase.client.java.document.RawJsonDocument;
|
||||
import com.couchbase.client.java.document.json.JsonArray;
|
||||
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
|
||||
public abstract class CouchbaseSimpleTypes {
|
||||
|
||||
static {
|
||||
Set<Class<?>> simpleTypes = new HashSet<Class<?>>();
|
||||
simpleTypes.add(CouchbaseDocument.class);
|
||||
simpleTypes.add(CouchbaseList.class);
|
||||
simpleTypes.add(RawJsonDocument.class);
|
||||
simpleTypes.add(JsonArray.class);
|
||||
COUCHBASE_SIMPLE_TYPES = Collections.unmodifiableSet(simpleTypes);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping;
|
||||
|
||||
/**
|
||||
* Marker Interface to identify either a {@link CouchbaseDocument} or a {@link CouchbaseList}.
|
||||
*
|
||||
* <p/>
|
||||
* This interface will be extended in the future to refactor the needed infrastructure into the common interface.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,9 +16,13 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping;
|
||||
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
|
||||
/**
|
||||
* Identifies a domain object to be persisted to Couchbase.
|
||||
@@ -28,9 +32,9 @@ import java.lang.annotation.*;
|
||||
@Persistent
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.TYPE })
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface Document {
|
||||
|
||||
|
||||
/**
|
||||
* An optional expiry time for the document.
|
||||
*/
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
@@ -42,25 +43,28 @@ public class AbstractCouchbaseEventListener<E> implements ApplicationListener<Co
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void onApplicationEvent(CouchbaseMappingEvent<?> event) {
|
||||
|
||||
E source = (E) event.getSource();
|
||||
// Check for matching domain type and invoke callbacks
|
||||
if (source != null && !domainClass.isAssignableFrom(source.getClass())) {
|
||||
return;
|
||||
}
|
||||
E source = (E) event.getSource();
|
||||
// Check for matching domain type and invoke callbacks
|
||||
if (source != null && !domainClass.isAssignableFrom(source.getClass())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event instanceof BeforeDeleteEvent) {
|
||||
onBeforeDelete(event.getSource(), event.getDocument());
|
||||
return;
|
||||
} else if (event instanceof AfterDeleteEvent) {
|
||||
}
|
||||
else if (event instanceof AfterDeleteEvent) {
|
||||
onAfterDelete(event.getSource(), event.getDocument());
|
||||
return;
|
||||
}
|
||||
|
||||
if (event instanceof BeforeConvertEvent) {
|
||||
onBeforeConvert(source);
|
||||
} else if (event instanceof BeforeSaveEvent) {
|
||||
}
|
||||
else if (event instanceof BeforeSaveEvent) {
|
||||
onBeforeSave(source, event.getDocument());
|
||||
} else if (event instanceof AfterSaveEvent) {
|
||||
}
|
||||
else if (event instanceof AfterSaveEvent) {
|
||||
onAfterSave(source, event.getDocument());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -18,6 +18,7 @@ package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
|
||||
@@ -31,10 +32,14 @@ public class LoggingEventListener extends AbstractCouchbaseEventListener<Object>
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoggingEventListener.class);
|
||||
|
||||
@Override
|
||||
public void onBeforeDelete(Object source, CouchbaseDocument doc) { LOGGER.info("onBeforeDelete: {}, {}", source, doc); }
|
||||
public void onBeforeDelete(Object source, CouchbaseDocument doc) {
|
||||
LOGGER.info("onBeforeDelete: {}, {}", source, doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterDelete(Object source, CouchbaseDocument doc) { LOGGER.info("onAfterDelete: {} {}", source, doc); }
|
||||
public void onAfterDelete(Object source, CouchbaseDocument doc) {
|
||||
LOGGER.info("onAfterDelete: {} {}", source, doc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAfterSave(Object source, CouchbaseDocument doc) {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,14 +16,16 @@
|
||||
|
||||
package org.springframework.data.couchbase.core.mapping.event;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.util.Assert;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.validation.ConstraintViolationException;
|
||||
import javax.validation.Validator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.data.couchbase.core.mapping.CouchbaseDocument;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* javax.validation dependant entities validator. When it is registered as Spring component its automatically invoked
|
||||
@@ -49,10 +51,12 @@ public class ValidatingCouchbaseEventListener extends AbstractCouchbaseEventList
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void onBeforeSave(Object source, CouchbaseDocument dbo) {
|
||||
|
||||
LOG.debug("Validating object: {}", source);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Validating object: {}", source);
|
||||
}
|
||||
Set violations = validator.validate(source);
|
||||
|
||||
if (!violations.isEmpty()) {
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This package contains the specific implementations and core classes for
|
||||
* Spring Data Couchbase internals. It also contains Couchbase implementation
|
||||
* to support the Spring Data template abstraction.
|
||||
* <br/>
|
||||
* The template provides lower level access to the underlying database and also serves as the foundation for
|
||||
* repositories. Any time a repository is too high-level for you needs chances are good that the templates will serve
|
||||
* you well.
|
||||
*/
|
||||
package org.springframework.data.couchbase.core;
|
||||
@@ -1,74 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.couchbase.monitor;
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Base class to encapsulate common configuration settings.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public abstract class AbstractMonitor {
|
||||
|
||||
private CouchbaseClient client;
|
||||
|
||||
private RestTemplate template = new RestTemplate();
|
||||
|
||||
protected AbstractMonitor(final CouchbaseClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public CouchbaseClient getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
protected RestTemplate getTemplate() {
|
||||
return template;
|
||||
}
|
||||
|
||||
protected String randomAvailableHostname() {
|
||||
List<SocketAddress> available = (ArrayList<SocketAddress>) client.getAvailableServers();
|
||||
Collections.shuffle(available);
|
||||
return ((InetSocketAddress) available.get(0)).getHostName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches stats for all nodes.
|
||||
*
|
||||
* @return stats for each node
|
||||
*/
|
||||
protected Map<SocketAddress, Map<String, String>> getStats() {
|
||||
return client.getStats();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns stats for an individual node.
|
||||
*/
|
||||
protected Map<String, String> getStats(SocketAddress node) {
|
||||
return getStats().get(node);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,28 +16,35 @@
|
||||
|
||||
package org.springframework.data.couchbase.monitor;
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import java.net.InetAddress;
|
||||
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import com.couchbase.client.java.bucket.BucketInfo;
|
||||
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
|
||||
import java.net.SocketAddress;
|
||||
|
||||
/**
|
||||
* Exposes basic client information.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
@ManagedResource(description = "Client Information")
|
||||
public class ClientInfo extends AbstractMonitor {
|
||||
@ManagedResource(description = "Client Information")
|
||||
public class ClientInfo {
|
||||
|
||||
public ClientInfo(final CouchbaseClient client) {
|
||||
super(client);
|
||||
private final Bucket bucket;
|
||||
private final BucketInfo info;
|
||||
|
||||
public ClientInfo(final Bucket bucket) {
|
||||
this.bucket = bucket;
|
||||
this.info = bucket.bucketManager().info();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Hostnames of connected nodes")
|
||||
public String getHostNames() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (SocketAddress node : getStats().keySet()) {
|
||||
for (InetAddress node : info.nodeList()) {
|
||||
result.append(node.toString()).append(",");
|
||||
}
|
||||
return result.toString();
|
||||
@@ -45,17 +52,9 @@ public class ClientInfo extends AbstractMonitor {
|
||||
|
||||
@ManagedAttribute(description = "Number of connected nodes")
|
||||
public int getNumberOfNodes() {
|
||||
return getStats().keySet().size();
|
||||
return info.nodeCount();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Number of connected active nodes")
|
||||
public int getNumberOfActiveNodes() {
|
||||
return getClient().getAvailableServers().size();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Number of connected inactive nodes")
|
||||
public int getNumberOfInactiveNodes() {
|
||||
return getClient().getUnavailableServers().size();
|
||||
}
|
||||
//TODO obtain count of available nodes vs unavailable ones and expose it
|
||||
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright 2013 the original author or authors.
|
||||
* Copyright 2012-2015 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -16,23 +16,36 @@
|
||||
|
||||
package org.springframework.data.couchbase.monitor;
|
||||
|
||||
import com.couchbase.client.CouchbaseClient;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import com.couchbase.client.java.bucket.BucketInfo;
|
||||
|
||||
import org.springframework.jmx.export.annotation.ManagedAttribute;
|
||||
import org.springframework.jmx.export.annotation.ManagedMetric;
|
||||
import org.springframework.jmx.export.annotation.ManagedResource;
|
||||
|
||||
import java.util.HashMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Exposes basic cluster information.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
@ManagedResource(description = "Cluster Information")
|
||||
public class ClusterInfo extends AbstractMonitor {
|
||||
@ManagedResource(description = "Cluster Information")
|
||||
public class ClusterInfo {
|
||||
|
||||
public ClusterInfo(final CouchbaseClient client) {
|
||||
super(client);
|
||||
private final RestTemplate template;
|
||||
private final Bucket bucket;
|
||||
private final BucketInfo info;
|
||||
|
||||
public ClusterInfo(final Bucket bucket) {
|
||||
this.template = new RestTemplate();
|
||||
this.bucket = bucket;
|
||||
this.info = bucket.bucketManager().info();
|
||||
}
|
||||
|
||||
@ManagedMetric(description = "Total RAM assigned")
|
||||
@@ -80,27 +93,34 @@ public class ClusterInfo extends AbstractMonitor {
|
||||
* converted to long.
|
||||
*
|
||||
* @param value the value to convert.
|
||||
*
|
||||
* @return the converted value.
|
||||
*/
|
||||
private long convertPotentialLong(Object value) {
|
||||
if (value instanceof Integer) {
|
||||
return new Long((Integer) value);
|
||||
} else if (value instanceof Long) {
|
||||
}
|
||||
else if (value instanceof Long) {
|
||||
return (Long) value;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Cannot convert value to long: " + value);
|
||||
}
|
||||
}
|
||||
|
||||
protected String randomAvailableHostname() {
|
||||
List<InetAddress> available = info.nodeList();
|
||||
Collections.shuffle(available);
|
||||
return available.get(0).getHostName();
|
||||
}
|
||||
|
||||
private HashMap<String, Object> fetchPoolInfo() {
|
||||
return getTemplate().getForObject("http://"
|
||||
+ randomAvailableHostname() + ":8091/pools/default", HashMap.class);
|
||||
return template.getForObject("http://"
|
||||
+ randomAvailableHostname() + ":8091/pools/default", HashMap.class);
|
||||
}
|
||||
|
||||
private HashMap<String, HashMap> parseStorageTotals() {
|
||||
HashMap<String, Object> stats = fetchPoolInfo();
|
||||
return (HashMap<String, HashMap>) stats.get("storageTotals");
|
||||
return (HashMap<String, HashMap>) stats.get("storageTotals");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* This package contains all classes related to monitoring the Couchbase cluster,
|
||||
* statistics that will be exposed as JMX beans.
|
||||
*/
|
||||
package org.springframework.data.couchbase.monitor;
|
||||
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* This package contains the Couchbase implementation to support the Spring Data repository abstraction.
|
||||
* <br/>
|
||||
* The goal of Spring Data repository abstraction is to significantly reduce the amount of boilerplate code required to
|
||||
* implement data access layers for various persistence stores.
|
||||
*/
|
||||
package org.springframework.data.couchbase.repository;
|
||||
@@ -16,7 +16,8 @@
|
||||
|
||||
package org.springframework.data.couchbase.repository.query;
|
||||
|
||||
import com.couchbase.client.protocol.views.Query;
|
||||
import com.couchbase.client.java.view.ViewQuery;
|
||||
|
||||
import org.springframework.data.couchbase.core.CouchbaseOperations;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
@@ -39,21 +40,21 @@ public class ViewBasedCouchbaseQuery implements RepositoryQuery {
|
||||
|
||||
@Override
|
||||
public Object execute(Object[] runtimeParams) {
|
||||
Query query = null;
|
||||
ViewQuery query = null;
|
||||
for (Object param : runtimeParams) {
|
||||
if (param instanceof Query) {
|
||||
query = (Query) param;
|
||||
if (param instanceof ViewQuery) {
|
||||
query = (ViewQuery) param;
|
||||
} else {
|
||||
throw new IllegalStateException("Unknown query param: " + param);
|
||||
}
|
||||
}
|
||||
|
||||
if (query == null) {
|
||||
query = new Query();
|
||||
query = ViewQuery.from(designDocName(), viewName());
|
||||
}
|
||||
query.setReduce(false);
|
||||
query.reduce(false);
|
||||
|
||||
return operations.findByView(designDocName(), viewName(), query, method.getEntityInformation().getJavaType());
|
||||
return operations.findByView(query, method.getEntityInformation().getJavaType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,20 +16,21 @@
|
||||
|
||||
package org.springframework.data.couchbase.repository.support;
|
||||
|
||||
import com.couchbase.client.protocol.views.ComplexKey;
|
||||
import com.couchbase.client.protocol.views.Query;
|
||||
import com.couchbase.client.protocol.views.ViewResponse;
|
||||
import com.couchbase.client.protocol.views.ViewRow;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.couchbase.client.java.document.json.JsonArray;
|
||||
import com.couchbase.client.java.view.ViewQuery;
|
||||
import com.couchbase.client.java.view.ViewResult;
|
||||
import com.couchbase.client.java.view.ViewRow;
|
||||
|
||||
import org.springframework.data.couchbase.core.CouchbaseOperations;
|
||||
import org.springframework.data.couchbase.core.view.View;
|
||||
import org.springframework.data.couchbase.repository.CouchbaseRepository;
|
||||
import org.springframework.data.couchbase.repository.query.CouchbaseEntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Repository base implementation for Couchbase.
|
||||
*
|
||||
@@ -130,30 +131,36 @@ public class SimpleCouchbaseRepository<T, ID extends Serializable> implements Co
|
||||
@Override
|
||||
public Iterable<T> findAll() {
|
||||
final ResolvedView resolvedView = determineView();
|
||||
return couchbaseOperations.findByView(resolvedView.getDesignDocument(), resolvedView.getViewName(), new Query().setReduce(false), entityInformation.getJavaType());
|
||||
ViewQuery query = ViewQuery.from(resolvedView.getDesignDocument(), resolvedView.getViewName());
|
||||
query.reduce(false);
|
||||
return couchbaseOperations.findByView(query, entityInformation.getJavaType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<T> findAll(final Iterable<ID> ids) {
|
||||
Query query = new Query();
|
||||
query.setReduce(false);
|
||||
query.setKeys(ComplexKey.of(ids));
|
||||
|
||||
final ResolvedView resolvedView = determineView();
|
||||
return couchbaseOperations.findByView(resolvedView.getDesignDocument(), resolvedView.getViewName(), query, entityInformation.getJavaType());
|
||||
ViewQuery query = ViewQuery.from(resolvedView.getDesignDocument(), resolvedView.getViewName());
|
||||
query.reduce(false);
|
||||
JsonArray keys = JsonArray.create();
|
||||
for (ID id : ids) {
|
||||
keys.add(id);
|
||||
}
|
||||
query.keys(keys);
|
||||
|
||||
return couchbaseOperations.findByView(query, entityInformation.getJavaType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long count() {
|
||||
Query query = new Query();
|
||||
query.setReduce(true);
|
||||
|
||||
final ResolvedView resolvedView = determineView();
|
||||
ViewResponse response = couchbaseOperations.queryView(resolvedView.getDesignDocument(), resolvedView.getViewName(), query);
|
||||
ViewQuery query = ViewQuery.from(resolvedView.getDesignDocument(), resolvedView.getViewName());
|
||||
query.reduce(true);
|
||||
|
||||
ViewResult response = couchbaseOperations.queryView(query);
|
||||
|
||||
long count = 0;
|
||||
for (ViewRow row : response) {
|
||||
count += Long.parseLong(row.getValue());
|
||||
count += Long.parseLong(String.valueOf(row.value()));
|
||||
}
|
||||
|
||||
return count;
|
||||
@@ -161,13 +168,13 @@ public class SimpleCouchbaseRepository<T, ID extends Serializable> implements Co
|
||||
|
||||
@Override
|
||||
public void deleteAll() {
|
||||
Query query = new Query();
|
||||
query.setReduce(false);
|
||||
|
||||
final ResolvedView resolvedView = determineView();
|
||||
ViewResponse response = couchbaseOperations.queryView(resolvedView.getDesignDocument(), resolvedView.getViewName(), query);
|
||||
ViewQuery query = ViewQuery.from(resolvedView.getDesignDocument(), resolvedView.getViewName());
|
||||
query.reduce(false);
|
||||
|
||||
ViewResult response = couchbaseOperations.queryView(query);
|
||||
for (ViewRow row : response) {
|
||||
couchbaseOperations.remove(row.getId());
|
||||
couchbaseOperations.remove(row.id());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user