Merge pull request #41 from simonbasle/configuration
basic configuration (xml parsers and @Configuration)
This commit is contained in:
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* 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.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.Conditional;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.ConfigurationCondition;
|
||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.couchbase.core.CouchbaseTemplate;
|
||||
import org.springframework.data.couchbase.core.mapping.Document;
|
||||
import org.springframework.data.mapping.model.CamelCaseAbbreviatingFieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.FieldNamingStrategy;
|
||||
import org.springframework.data.mapping.model.PropertyNameFieldNamingStrategy;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return the list of bootstrap hosts.
|
||||
*/
|
||||
protected abstract List<String> getBootstrapHosts();
|
||||
|
||||
/**
|
||||
* The name of the bucket to connect to.
|
||||
*
|
||||
* @return the name of the bucket.
|
||||
*/
|
||||
protected abstract String getBucketName();
|
||||
|
||||
/**
|
||||
* The password of the bucket (can be an empty string).
|
||||
*
|
||||
* @return the password of the bucket.
|
||||
*/
|
||||
protected abstract String getBucketPassword();
|
||||
|
||||
/**
|
||||
* 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 = "disconnect", name = BeanNames.COUCHBASE_CLUSTER)
|
||||
public Cluster couchbaseCluster() throws Exception {
|
||||
return CouchbaseCluster.create(couchbaseEnvironment(), getBootstrapHosts());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link Bucket} instance to connect to.
|
||||
*
|
||||
* @throws Exception on Bean construction failure.
|
||||
*/
|
||||
@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());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link CouchbaseTemplate}.
|
||||
*
|
||||
* @throws Exception on Bean construction failure.
|
||||
*/
|
||||
@Bean(name = BeanNames.COUCHBASE_TEMPLATE)
|
||||
public CouchbaseTemplate couchbaseTemplate() throws Exception {
|
||||
//TODO use mappingCouchbaseConverter and translationService when implemented
|
||||
return new CouchbaseTemplate(couchbaseClient());
|
||||
}
|
||||
|
||||
//TODO create beans for mappingCouchbaseConverter, translationService, couchbaseMappingContext when implemented
|
||||
//TODO for mappingCouchbaseConverter, allow registering of customConversions
|
||||
|
||||
/**
|
||||
* Scans the mapping base package for classes annotated with {@link Document}.
|
||||
*
|
||||
* @throws ClassNotFoundException if initial entity sets could not be loaded.
|
||||
*/
|
||||
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
|
||||
String basePackage = getMappingBasePackage();
|
||||
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
|
||||
|
||||
if (StringUtils.hasText(basePackage)) {
|
||||
ClassPathScanningCandidateComponentProvider componentProvider = new ClassPathScanningCandidateComponentProvider(false);
|
||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Document.class));
|
||||
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
|
||||
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {
|
||||
initialEntitySet.add(ClassUtils.forName(candidate.getBeanClassName(), AbstractCouchbaseConfiguration.class.getClassLoader()));
|
||||
}
|
||||
}
|
||||
|
||||
return initialEntitySet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the base package to scan for mapped {@link Document}s. Will return the package name of the configuration
|
||||
* class (the concrete class, not this one here) by default.
|
||||
* <p/>
|
||||
* <p>So if you have a {@code com.acme.AppConfig} extending {@link AbstractCouchbaseConfiguration} the base package
|
||||
* 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.
|
||||
*/
|
||||
protected String getMappingBasePackage() {
|
||||
return getClass().getPackage().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true if field names should be abbreviated with the {@link CamelCaseAbbreviatingFieldNamingStrategy}.
|
||||
*
|
||||
* @return true if field names should be abbreviated, default is false.
|
||||
*/
|
||||
protected boolean abbreviateFieldNames() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a {@link FieldNamingStrategy} on the CouchbaseMappingContext instance created.
|
||||
*
|
||||
* @return the naming strategy.
|
||||
*/
|
||||
protected FieldNamingStrategy fieldNamingStrategy() {
|
||||
//TODO implement a CouchbaseMappingContext, use this method (update link in javadoc)
|
||||
return abbreviateFieldNames() ? new CamelCaseAbbreviatingFieldNamingStrategy() : PropertyNameFieldNamingStrategy.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
|
||||
/**
|
||||
* Refers to the <couchbase:env /> bean.
|
||||
*/
|
||||
static final String COUCHBASE_ENV = "couchbaseEnv";
|
||||
/**
|
||||
* Refers to the "<couchbase:cluster />" bean.
|
||||
*/
|
||||
static final String COUCHBASE_CLUSTER = "couchbaseCluster";
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
static final String TRANSLATION_SERVICE = "couchbaseTranslationService";
|
||||
|
||||
|
||||
}
|
||||
@@ -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,96 @@
|
||||
/*
|
||||
* 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 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;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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 Bucket} object is solved through the "bucket-ref" attribute.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
public class CouchbaseJmxParser implements BeanDefinitionParser {
|
||||
|
||||
/**
|
||||
* Parse the element and dispatch the registration of the JMX components.
|
||||
*
|
||||
* @param element the XML element which contains the attributes.
|
||||
* @param parserContext encapsulates the parsing state and configuration.
|
||||
* @return null, because no bean instance needs to be returned.
|
||||
*/
|
||||
public BeanDefinition parse(final Element element, final ParserContext parserContext) {
|
||||
String bucketName = element.getAttribute("bucket-ref");
|
||||
if (!StringUtils.hasText(bucketName)) {
|
||||
bucketName = BeanNames.COUCHBASE_BUCKET;
|
||||
}
|
||||
registerJmxComponents(bucketName, element, parserContext);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the JMX components in the context.
|
||||
*
|
||||
* @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 refBucketName,
|
||||
final Element element, final ParserContext parserContext) {
|
||||
Object eleSource = parserContext.extractSource(element);
|
||||
CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource);
|
||||
|
||||
createBeanDefEntry(ClientInfo.class, compositeDef, refBucketName, eleSource, parserContext);
|
||||
createBeanDefEntry(ClusterInfo.class, compositeDef, refBucketName, eleSource, parserContext);
|
||||
|
||||
parserContext.registerComponent(compositeDef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Bean Definitions for JMX components and adds them as a nested component.
|
||||
*
|
||||
* @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 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) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
|
||||
builder.getRawBeanDefinition().setSource(eleSource);
|
||||
builder.addConstructorArgReference(refName);
|
||||
BeanDefinition assertDef = builder.getBeanDefinition();
|
||||
String assertName = parserContext.getReaderContext().registerWithGeneratedName(assertDef);
|
||||
compositeDef.addNestedComponent(new BeanComponentDefinition(assertDef, assertName));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 org.springframework.beans.factory.xml.NamespaceHandler;
|
||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||
|
||||
/**
|
||||
* {@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.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public class CouchbaseNamespaceHandler extends NamespaceHandlerSupport {
|
||||
|
||||
/**
|
||||
* Register bean definition parsers in the namespace handler.
|
||||
*/
|
||||
public final void init() {
|
||||
//TODO repositories (CouchbaseRepositoryConfigurationExtension and RepositoryBeanDefinitionParser)
|
||||
//TODO bucket
|
||||
//TODO cluster
|
||||
registerBeanDefinitionParser("jmx", new CouchbaseJmxParser());
|
||||
registerBeanDefinitionParser("template", new CouchbaseTemplateParser());
|
||||
//TODO translation service
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 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;
|
||||
|
||||
/**
|
||||
* Parser for "<couchbase:template />" bean definitions.
|
||||
* <p/>
|
||||
* The outcome of this bean definition parser will be a constructed {@link CouchbaseTemplate}.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
public class CouchbaseTemplateParser 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_TEMPLATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 CouchbaseTemplate.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) {
|
||||
String bucketRef = element.getAttribute("bucket-ref");
|
||||
String converterRef = element.getAttribute("converter-ref");
|
||||
String translationServiceRef = element.getAttribute("translation-service-ref");
|
||||
|
||||
bean.addConstructorArgReference(StringUtils.hasText(bucketRef) ? bucketRef : BeanNames.COUCHBASE_BUCKET);
|
||||
|
||||
if (StringUtils.hasText(converterRef)) {
|
||||
bean.addConstructorArgReference(converterRef);
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(translationServiceRef)) {
|
||||
bean.addConstructorArgReference(translationServiceRef);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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 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 org.springframework.data.annotation.Persistent;
|
||||
|
||||
/**
|
||||
* Identifies a domain object to be persisted to Couchbase.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
@Persistent
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface Document {
|
||||
|
||||
/**
|
||||
* An optional expiry time for the document.
|
||||
*/
|
||||
int expiry() default 0;
|
||||
|
||||
}
|
||||
@@ -0,0 +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 java.lang.annotation.Documented;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
/**
|
||||
* Annotation to define custom metadata for document fields.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Field {
|
||||
|
||||
/**
|
||||
* The key to be used to store the field inside the document.
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.monitor;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Exposes basic client information.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
@ManagedResource(description = "Client Information")
|
||||
public class ClientInfo {
|
||||
|
||||
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 (InetAddress node : info.nodeList()) {
|
||||
result.append(node.toString()).append(",");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Number of connected nodes")
|
||||
public int getNumberOfNodes() {
|
||||
return info.nodeCount();
|
||||
}
|
||||
|
||||
//TODO obtain count of available nodes vs unavailable ones and expose it
|
||||
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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.monitor;
|
||||
|
||||
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 org.springframework.web.client.RestTemplate;
|
||||
|
||||
/**
|
||||
* Exposes basic cluster information.
|
||||
*
|
||||
* @author Michael Nitschinger
|
||||
* @author Simon Baslé
|
||||
*/
|
||||
@ManagedResource(description = "Cluster Information")
|
||||
public class ClusterInfo {
|
||||
|
||||
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")
|
||||
public long getTotalRAMAssigned() {
|
||||
return convertPotentialLong(parseStorageTotals().get("ram").get("total"));
|
||||
}
|
||||
|
||||
@ManagedMetric(description = "Total RAM used")
|
||||
public long getTotalRAMUsed() {
|
||||
return convertPotentialLong(parseStorageTotals().get("ram").get("used"));
|
||||
}
|
||||
|
||||
@ManagedMetric(description = "Total Disk Space assigned")
|
||||
public long getTotalDiskAssigned() {
|
||||
return convertPotentialLong(parseStorageTotals().get("hdd").get("total"));
|
||||
}
|
||||
|
||||
@ManagedMetric(description = "Total Disk Space used")
|
||||
public long getTotalDiskUsed() {
|
||||
return convertPotentialLong(parseStorageTotals().get("hdd").get("used"));
|
||||
}
|
||||
|
||||
@ManagedMetric(description = "Total Disk Space free")
|
||||
public long getTotalDiskFree() {
|
||||
return convertPotentialLong(parseStorageTotals().get("hdd").get("free"));
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Cluster is Balanced")
|
||||
public boolean getIsBalanced() {
|
||||
return (Boolean) fetchPoolInfo().get("balanced");
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Rebalance Status")
|
||||
public String getRebalanceStatus() {
|
||||
return (String) fetchPoolInfo().get("rebalanceStatus");
|
||||
}
|
||||
|
||||
@ManagedAttribute(description = "Maximum Available Buckets")
|
||||
public int getMaxBuckets() {
|
||||
return (Integer) fetchPoolInfo().get("maxBucketCount");
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on the value size, either int or long can be passed in and get
|
||||
* 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) {
|
||||
return (Long) value;
|
||||
}
|
||||
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 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");
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user