diff --git a/src/main/java/org/springframework/data/couchbase/config/BeanNames.java b/src/main/java/org/springframework/data/couchbase/config/BeanNames.java index 006fd1866..47100c83c 100644 --- a/src/main/java/org/springframework/data/couchbase/config/BeanNames.java +++ b/src/main/java/org/springframework/data/couchbase/config/BeanNames.java @@ -22,31 +22,30 @@ * @author Michael Nitschinger * @author Simon Baslé */ -public class BeanNames { +class BeanNames { /** - * Refers to the bean. + * Refers to the "<couchbase:env />" bean. */ static final String COUCHBASE_ENV = "couchbaseEnv"; /** - * Refers to the "" bean. + * Refers to the "<couchbase:cluster />" bean. */ static final String COUCHBASE_CLUSTER = "couchbaseCluster"; /** - * Refers to the "" bean. + * Refers to the "<couchbase:bucket />" bean. */ static final String COUCHBASE_BUCKET = "couchbaseBucket"; /** - * Refers to the "" bean. + * Refers to the "<couchbase:template />" bean. */ static final String COUCHBASE_TEMPLATE = "couchbaseTemplate"; /** - * Refers to the "" bean + * Refers to the "<couchbase:translation-service />" bean */ static final String TRANSLATION_SERVICE = "couchbaseTranslationService"; - } diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseBucketFactoryBean.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseBucketFactoryBean.java new file mode 100644 index 000000000..560ac6d6f --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseBucketFactoryBean.java @@ -0,0 +1,66 @@ +/* + * 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; + +/** + * 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 { + + private final Cluster cluster; + private final String bucketName; + private final String bucketPassword; + + 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); + } + } +} diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseBucketParser.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseBucketParser.java new file mode 100644 index 000000000..431b24567 --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseBucketParser.java @@ -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 {@value BeanNames#COUCHBASE_CLUSTER} is used. + * + * See attributes {@link #CLUSTER_REF_ATTR}, {@link #BUCKETNAME_ATTR} and {@link #BUCKETPASSWORD_ATTR}. + * + * @author Simon Baslé + */ +public class CouchbaseBucketParser extends AbstractSingleBeanDefinitionParser { + + /** + * The cluster-ref attribute in a bucket definition defines the cluster to build from. + */ + public static final String CLUSTER_REF_ATTR = "cluster-ref"; + + /** + * The bucketName attribute in a bucket definition defines the name of the bucket to open. + */ + public static final String BUCKETNAME_ATTR = "bucketName"; + + /** + * The bucketPassword 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); + } + } +} diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseClusterParser.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseClusterParser.java new file mode 100644 index 000000000..1e78bf08f --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseClusterParser.java @@ -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 nodes = DomUtils.getChildElementsByTagName(element, CLUSTER_NODE_TAG); + if (nodes != null && nodes.size() > 0) { + List bootstrapUrls = new ArrayList(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); + } +} diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseEnvironmentFactoryBean.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseEnvironmentFactoryBean.java new file mode 100644 index 000000000..e452b50ef --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseEnvironmentFactoryBean.java @@ -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 { + + 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; + } +} diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseEnvironmentParser.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseEnvironmentParser.java new file mode 100644 index 000000000..b4bf013ff --- /dev/null +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseEnvironmentParser.java @@ -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. + *

+ * The following properties are supported:

    + *
  • {@link DefaultCouchbaseEnvironment.Builder#managementTimeout(long) managementTimeout}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#queryTimeout(long) queryTimeout}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#viewTimeout(long) viewTimeout}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#kvTimeout(long) kvTimeout}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#connectTimeout(long) connectTimeout}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#disconnectTimeout(long) disconnectTimeout}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#dnsSrvEnabled(boolean) dnsSrvEnabled}
  • + * + *
  • {@link DefaultCouchbaseEnvironment.Builder#dcpEnabled(boolean) dcpEnabled}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#sslEnabled(boolean) sslEnabled}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#sslKeystoreFile(String) sslKeystoreFile}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#sslKeystorePassword(String) sslKeystorePassword}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#queryEnabled(boolean) queryEnabled}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#queryPort(int) queryPort}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#bootstrapHttpEnabled(boolean) bootstrapHttpEnabled}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#bootstrapCarrierEnabled(boolean) bootstrapCarrierEnabled}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#bootstrapHttpDirectPort(int) bootstrapHttpDirectPort}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#bootstrapHttpSslPort(int) bootstrapHttpSslPort}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#bootstrapCarrierDirectPort(int) bootstrapCarrierDirectPort}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#bootstrapCarrierSslPort(int) bootstrapCarrierSslPort}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#ioPoolSize(int) ioPoolSize}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#computationPoolSize(int) computationPoolSize}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#responseBufferSize(int) responseBufferSize}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#requestBufferSize(int) requestBufferSize}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#kvEndpoints(int) kvEndpoints}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#viewEndpoints(int) viewEndpoints}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#queryEndpoints(int) queryEndpoints}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#retryStrategy(RetryStrategy) retryStrategy}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#maxRequestLifetime(long) maxRequestLifetime}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#keepAliveInterval(long) keepAliveInterval}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#autoreleaseAfter(long) autoreleaseAfter}
  • + *
  • {@link DefaultCouchbaseEnvironment.Builder#bufferPoolingEnabled(boolean) bufferPoolingEnabled}
  • + *
+ * + * @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"); + } +} diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseJmxParser.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseJmxParser.java index 22c2969de..98653eda1 100644 --- a/src/main/java/org/springframework/data/couchbase/config/CouchbaseJmxParser.java +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseJmxParser.java @@ -79,7 +79,7 @@ protected void registerJmxComponents(final String refBucketName, * * @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. */ diff --git a/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java b/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java index 6e4d50d69..ee2ae1546 100644 --- a/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java +++ b/src/main/java/org/springframework/data/couchbase/config/CouchbaseNamespaceHandler.java @@ -34,8 +34,9 @@ public class CouchbaseNamespaceHandler extends NamespaceHandlerSupport { */ public final void init() { //TODO repositories (CouchbaseRepositoryConfigurationExtension and RepositoryBeanDefinitionParser) - //TODO bucket - //TODO cluster + registerBeanDefinitionParser("env", new CouchbaseEnvironmentParser()); + registerBeanDefinitionParser("cluster", new CouchbaseClusterParser()); + registerBeanDefinitionParser("bucket", new CouchbaseBucketParser()); registerBeanDefinitionParser("jmx", new CouchbaseJmxParser()); registerBeanDefinitionParser("template", new CouchbaseTemplateParser()); //TODO translation service diff --git a/src/main/resources/META-INF/spring.handlers b/src/main/resources/META-INF/spring.handlers new file mode 100644 index 000000000..abeeba428 --- /dev/null +++ b/src/main/resources/META-INF/spring.handlers @@ -0,0 +1 @@ +http\://www.springframework.org/schema/data/couchbase=org.springframework.data.couchbase.config.CouchbaseNamespaceHandler \ No newline at end of file diff --git a/src/main/resources/META-INF/spring.schemas b/src/main/resources/META-INF/spring.schemas new file mode 100644 index 000000000..6b43469ea --- /dev/null +++ b/src/main/resources/META-INF/spring.schemas @@ -0,0 +1,4 @@ +http\://www.springframework.org/schema/data/couchbase/spring-couchbase-1.0.xsd=org/springframework/data/couchbase/config/spring-couchbase-1.0.xsd +http\://www.springframework.org/schema/data/couchbase/spring-couchbase-2.0.xsd=org/springframework/data/couchbase/config/spring-couchbase-2.0.xsd +http\://www.springframework.org/schema/data/couchbase/spring-couchbase-env-2.0.xsd=org/springframework/data/couchbase/config/spring-couchbase-env-2.0.xsd +http\://www.springframework.org/schema/data/couchbase/spring-couchbase.xsd=org/springframework/data/couchbase/config/spring-couchbase-2.0.xsd \ No newline at end of file diff --git a/src/main/resources/META-INF/spring.tooling b/src/main/resources/META-INF/spring.tooling new file mode 100644 index 000000000..382c2816e --- /dev/null +++ b/src/main/resources/META-INF/spring.tooling @@ -0,0 +1,4 @@ +# Tooling related information for the Couchbase DB namespace +http\://www.springframework.org/schema/data/couchbase@name=Couchbase Namespace +http\://www.springframework.org/schema/data/couchbase@prefix=couchbase +http\://www.springframework.org/schema/data/couchbase@icon=org/springframework/jdbc/config/spring-jdbc.gif \ No newline at end of file diff --git a/src/main/resources/org/springframework/data/couchbase/config/spring-couchbase-1.0.xsd b/src/main/resources/org/springframework/data/couchbase/config/spring-couchbase-1.0.xsd new file mode 100644 index 000000000..4c6a998ba --- /dev/null +++ b/src/main/resources/org/springframework/data/couchbase/config/spring-couchbase-1.0.xsd @@ -0,0 +1,200 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a CouchbaseClient object. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a CouchbaseTemplate. Will default to 'couchbaseTemplate'. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/org/springframework/data/couchbase/config/spring-couchbase-2.0.xsd b/src/main/resources/org/springframework/data/couchbase/config/spring-couchbase-2.0.xsd new file mode 100644 index 000000000..669cb5f1b --- /dev/null +++ b/src/main/resources/org/springframework/data/couchbase/config/spring-couchbase-2.0.xsd @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference to a Bucket object. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/org/springframework/data/couchbase/config/spring-couchbase-env-2.0.xsd b/src/main/resources/org/springframework/data/couchbase/config/spring-couchbase-env-2.0.xsd new file mode 100644 index 000000000..91e8f61fb --- /dev/null +++ b/src/main/resources/org/springframework/data/couchbase/config/spring-couchbase-env-2.0.xsd @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/java/org/springframework/data/couchbase/config/CouchbaseBucketParserTest.java b/src/test/java/org/springframework/data/couchbase/config/CouchbaseBucketParserTest.java new file mode 100644 index 000000000..932e1d290 --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/config/CouchbaseBucketParserTest.java @@ -0,0 +1,136 @@ +/* + * 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.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import java.util.List; + +import com.couchbase.client.java.env.CouchbaseEnvironment; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.BeanDefinitionReader; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.core.io.ClassPathResource; + +public class CouchbaseBucketParserTest { + + + private static DefaultListableBeanFactory factory; + + @BeforeClass + public static void setUp() { + factory = new DefaultListableBeanFactory(); + BeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); + int n = reader.loadBeanDefinitions(new ClassPathResource("configurations/couchbaseBucket-bean.xml")); + System.out.println(n); + } + + @AfterClass + public static void tearDown() { + } + + @Test + public void testDefaultBucketNoCluster() { + BeanDefinition def = factory.getBeanDefinition("bucketDefaultNoCluster"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(1))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, Object.class); + assertThat(holder.getValue(), is(instanceOf(RuntimeBeanReference.class))); + + RuntimeBeanReference clusterRef = (RuntimeBeanReference) holder.getValue(); + + assertThat(clusterRef.getBeanName(), is(equalTo(BeanNames.COUCHBASE_CLUSTER))); + } + + @Test + public void testDefaultBucket() throws Exception { + BeanDefinition def = factory.getBeanDefinition("bucketDefault"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(1))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, Object.class); + assertThat(holder.getValue(), is(instanceOf(RuntimeBeanReference.class))); + + RuntimeBeanReference clusterRef = (RuntimeBeanReference) holder.getValue(); + + assertThat(clusterRef.getBeanName(), is(equalTo("clusterDefault"))); + } + + @Test + public void testBucketWithName() throws Exception { + BeanDefinition def = factory.getBeanDefinition("bucketWithName"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(2))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, Object.class); + assertThat(holder.getValue(), is(instanceOf(RuntimeBeanReference.class))); + + RuntimeBeanReference clusterRef = (RuntimeBeanReference) holder.getValue(); + assertThat(clusterRef.getBeanName(), is(equalTo("clusterDefault"))); + + ConstructorArgumentValues.ValueHolder nameHolder = def.getConstructorArgumentValues() + .getArgumentValue(1, Object.class); + assertThat(nameHolder.getValue(), is(instanceOf(String.class))); + assertThat(nameHolder.getValue().toString(), is((equalTo("toto")))); + } + + @Test + public void testBucketWithNameAndPassword() throws Exception { + BeanDefinition def = factory.getBeanDefinition("bucketWithNameAndPassword"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(3))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, Object.class); + assertThat(holder.getValue(), is(instanceOf(RuntimeBeanReference.class))); + + RuntimeBeanReference clusterRef = (RuntimeBeanReference) holder.getValue(); + assertThat(clusterRef.getBeanName(), is(equalTo("clusterDefault"))); + + ConstructorArgumentValues.ValueHolder nameHolder = def.getConstructorArgumentValues() + .getArgumentValue(1, Object.class); + assertThat(nameHolder.getValue(), is(instanceOf(String.class))); + assertThat(nameHolder.getValue().toString(), is((equalTo("test")))); + + ConstructorArgumentValues.ValueHolder passwordHolder = def.getConstructorArgumentValues() + .getArgumentValue(2, Object.class); + assertThat(passwordHolder.getValue(), is(instanceOf(String.class))); + assertThat(passwordHolder.getValue().toString(), is((equalTo("123")))); + } +} \ No newline at end of file diff --git a/src/test/java/org/springframework/data/couchbase/config/CouchbaseClusterParserTest.java b/src/test/java/org/springframework/data/couchbase/config/CouchbaseClusterParserTest.java new file mode 100644 index 000000000..1cfdcb167 --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/config/CouchbaseClusterParserTest.java @@ -0,0 +1,154 @@ +/* + * 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.hamcrest.CoreMatchers.*; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.core.Is.is; + +import java.util.List; + +import com.couchbase.client.java.env.CouchbaseEnvironment; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.ConstructorArgumentValues; +import org.springframework.beans.factory.config.RuntimeBeanReference; +import org.springframework.beans.factory.support.BeanDefinitionReader; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.support.GenericBeanDefinition; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.core.io.ClassPathResource; + +public class CouchbaseClusterParserTest { + + + private static DefaultListableBeanFactory factory; + + @BeforeClass + public static void setUp() { + factory = new DefaultListableBeanFactory(); + BeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); + int n = reader.loadBeanDefinitions(new ClassPathResource("configurations/couchbaseCluster-bean.xml")); + System.out.println(n); + } + + @AfterClass + public static void tearDown() { + } + + @Test + public void testClusterWithoutSpecificEnv() { + BeanDefinition def = factory.getBeanDefinition("clusterDefault"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(1))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + assertThat(def.getFactoryMethodName(), is(equalTo("create"))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, CouchbaseEnvironment.class); + + assertThat(holder.getValue(), instanceOf(RuntimeBeanReference.class)); + RuntimeBeanReference envRef = (RuntimeBeanReference) holder.getValue(); + + assertThat(envRef.getBeanName(), is(equalTo("couchbaseEnv"))); + } + + @Test + public void testClusterWithNodes() { + BeanDefinition def = factory.getBeanDefinition("clusterWithNodes"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(2))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + assertThat(def.getFactoryMethodName(), is(equalTo("create"))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(1, List.class); + assertThat(holder.getValue(), is(instanceOf(List.class))); + List nodes = (List) holder.getValue(); + + assertThat(nodes.size(), is(equalTo(2))); + assertThat((String) nodes.get(0), is(equalTo("192.1.2.3"))); + assertThat((String) nodes.get(1), is(equalTo("192.4.5.6"))); + } + + @Test + public void testClusterWithEnvInline() { + BeanDefinition def = factory.getBeanDefinition("clusterWithEnvInline"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(1))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, CouchbaseEnvironment.class); + GenericBeanDefinition envDef = (GenericBeanDefinition) holder.getValue(); + + assertThat(envDef.getBeanClassName(), is(equalTo(CouchbaseEnvironmentFactoryBean.class.getName()))); + assertThat("unexpected attribute", envDef.getPropertyValues().contains("managementTimeout")); + } + + @Test + public void testClusterWithEnvRef() { + BeanDefinition def = factory.getBeanDefinition("clusterWithEnvRef"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(1))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + + ConstructorArgumentValues.ValueHolder holder = def.getConstructorArgumentValues() + .getArgumentValue(0, CouchbaseEnvironment.class); + + assertThat(holder.getValue(), instanceOf(RuntimeBeanReference.class)); + RuntimeBeanReference envRef = (RuntimeBeanReference) holder.getValue(); + + assertThat(envRef.getBeanName(), is(equalTo("someEnv"))); + } + @Test + public void testClusterConfigurationPrecedence() { + BeanDefinition def = factory.getBeanDefinition("clusterWithAll"); + + assertThat(def, is(notNullValue())); + assertThat(def.getConstructorArgumentValues().getArgumentCount(), is(equalTo(2))); + assertThat(def.getPropertyValues().size(), is(equalTo(0))); + assertThat(def.getFactoryMethodName(), is(equalTo("create"))); + + assertThat(def.getConstructorArgumentValues().getIndexedArgumentValues().get(0).getValue(), + instanceOf(GenericBeanDefinition.class)); + assertThat(def.getConstructorArgumentValues().getIndexedArgumentValues().get(1).getValue(), + instanceOf(List.class)); + + ConstructorArgumentValues.ValueHolder holderEnv = def.getConstructorArgumentValues() + .getArgumentValue(0, CouchbaseEnvironment.class); + GenericBeanDefinition envDef = (GenericBeanDefinition) holderEnv.getValue(); + + assertThat(envDef.getBeanClassName(), is(equalTo(CouchbaseEnvironmentFactoryBean.class.getName()))); + assertThat("unexpected attribute", envDef.getPropertyValues().contains("autoreleaseAfter")); + + ConstructorArgumentValues.ValueHolder holderNodes = def.getConstructorArgumentValues() + .getArgumentValue(1, List.class); + List nodes = (List) holderNodes.getValue(); + + assertThat(nodes.size(), is(equalTo(2))); + assertThat((String) nodes.get(0), is(equalTo("2.2.2.2"))); + assertThat((String) nodes.get(1), is(equalTo("4.4.4.4"))); + } +} \ No newline at end of file diff --git a/src/test/java/org/springframework/data/couchbase/config/CouchbaseEnvironmentParserTest.java b/src/test/java/org/springframework/data/couchbase/config/CouchbaseEnvironmentParserTest.java new file mode 100644 index 000000000..ad0766f2f --- /dev/null +++ b/src/test/java/org/springframework/data/couchbase/config/CouchbaseEnvironmentParserTest.java @@ -0,0 +1,109 @@ +/* + * 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.hamcrest.CoreMatchers.*; +import static org.junit.Assert.assertThat; + +import com.couchbase.client.core.retry.BestEffortRetryStrategy; +import com.couchbase.client.core.retry.FailFastRetryStrategy; +import com.couchbase.client.java.env.CouchbaseEnvironment; +import com.couchbase.client.java.env.DefaultCouchbaseEnvironment; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import org.springframework.beans.factory.support.BeanDefinitionReader; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.io.ClassPathResource; + +public class CouchbaseEnvironmentParserTest { + + private static GenericApplicationContext context; + + @BeforeClass + public static void setUp() { + DefaultListableBeanFactory factory = new DefaultListableBeanFactory(); + BeanDefinitionReader reader = new XmlBeanDefinitionReader(factory); + reader.loadBeanDefinitions(new ClassPathResource("configurations/couchbaseEnv-bean.xml")); + context = new GenericApplicationContext(factory); + context.refresh(); + } + + @Test + public void testParsingRetryStrategyFailFast() throws Exception { + CouchbaseEnvironment env = context.getBean("envWithFailFast", CouchbaseEnvironment.class); + + assertThat(env.retryStrategy(), is(instanceOf(FailFastRetryStrategy.class))); + } + + @Test + public void testParsingRetryStrategyBestEffort() throws Exception { + CouchbaseEnvironment env = context.getBean("envWithBestEffort", CouchbaseEnvironment.class); + + assertThat(env.retryStrategy(), is(instanceOf(BestEffortRetryStrategy.class))); + } + + @Test + public void testAllDefaultsOverridden() { + CouchbaseEnvironment env = context.getBean("envWithNoDefault", CouchbaseEnvironment.class); + CouchbaseEnvironment defaultEnv = DefaultCouchbaseEnvironment.create(); + + assertThat(env, is(instanceOf(DefaultCouchbaseEnvironment.class))); + + assertThat(env.managementTimeout(), is(equalTo(1L))); + assertThat(env.queryTimeout(), is(equalTo(2L))); + assertThat(env.viewTimeout(), is(equalTo(3L))); + assertThat(env.kvTimeout(), is(equalTo(4L))); + assertThat(env.connectTimeout(), is(equalTo(5L))); + assertThat(env.disconnectTimeout(), is(equalTo(6L))); + assertThat(env.dnsSrvEnabled(), allOf(equalTo(true), not(defaultEnv.dnsSrvEnabled()))); + + //TODO activate test when dcp can be enabled on the environment (add it in the xml) +// assertThat(env.dcpEnabled(), allOf(equalTo(true), not(defaultEnv.dcpEnabled()))); + assertThat(env.sslEnabled(), allOf(equalTo(true), not(defaultEnv.sslEnabled()))); + assertThat(env.sslKeystoreFile(), is(equalTo("test"))); + assertThat(env.sslKeystorePassword(), is(equalTo("test"))); + assertThat(env.queryEnabled(), allOf(equalTo(true), not(defaultEnv.queryEnabled()))); + assertThat(env.queryPort(), is(equalTo(7))); + assertThat(env.bootstrapHttpEnabled(), allOf(equalTo(false), not(defaultEnv.bootstrapHttpEnabled()))); + assertThat(env.bootstrapCarrierEnabled(), allOf(equalTo(false), not(defaultEnv.bootstrapCarrierEnabled()))); + assertThat(env.bootstrapHttpDirectPort(), is(equalTo(8))); + assertThat(env.bootstrapHttpSslPort(), is(equalTo(9))); + assertThat(env.bootstrapCarrierDirectPort(), is(equalTo(10))); + assertThat(env.bootstrapCarrierSslPort(), is(equalTo(11))); + assertThat(env.ioPoolSize(), is(equalTo(12))); + assertThat(env.computationPoolSize(), is(equalTo(13))); + assertThat(env.responseBufferSize(), is(equalTo(14))); + assertThat(env.requestBufferSize(), is(equalTo(15))); + assertThat(env.kvEndpoints(), is(equalTo(16))); + assertThat(env.viewEndpoints(), is(equalTo(17))); + assertThat(env.queryEndpoints(), is(equalTo(18))); + assertThat(env.retryStrategy(), is(instanceOf(FailFastRetryStrategy.class))); + assertThat(env.maxRequestLifetime(), is(equalTo(19L))); + assertThat(env.keepAliveInterval(), is(equalTo(20L))); + assertThat(env.autoreleaseAfter(), is(equalTo(21L))); + assertThat(env.bufferPoolingEnabled(), allOf(equalTo(false), not(defaultEnv.bufferPoolingEnabled()))); + } + + @AfterClass + public static void tearDown() { + context.close(); + } +} \ No newline at end of file diff --git a/src/test/resources/configurations/couchbaseBucket-bean.xml b/src/test/resources/configurations/couchbaseBucket-bean.xml new file mode 100644 index 000000000..2c7e9e4de --- /dev/null +++ b/src/test/resources/configurations/couchbaseBucket-bean.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/configurations/couchbaseCluster-bean.xml b/src/test/resources/configurations/couchbaseCluster-bean.xml new file mode 100644 index 000000000..2ad55028d --- /dev/null +++ b/src/test/resources/configurations/couchbaseCluster-bean.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + 192.1.2.3 + 192.4.5.6 + + + + 2.2.2.2 + 4.4.4.4 + + + \ No newline at end of file diff --git a/src/test/resources/configurations/couchbaseEnv-bean.xml b/src/test/resources/configurations/couchbaseEnv-bean.xml new file mode 100644 index 000000000..07fedf936 --- /dev/null +++ b/src/test/resources/configurations/couchbaseEnv-bean.xml @@ -0,0 +1,48 @@ + + + + + + + + + + \ No newline at end of file