I am trying to write a sample in order to learn couchbase. I am trying to use it with spring boot and it’s crud repositories .
So I have downloaded latest docker ima
Couchbase driver supports connection to Couchbase 5 buckets using username/password. Problem is that spring-data-couchbase
is not developed fast enough to cover all the new features Couchbase introduces. So, we need to help Spring
to use a new bucket connection, doing it by overriding Couchbase cluster instantiation method of spring-data-couchbase
configuration base class - org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration
. This is the method we are looking at :
@Override
@Bean(name = BeanNames.COUCHBASE_CLUSTER_INFO)
public ClusterInfo couchbaseClusterInfo() throws Exception {
return couchbaseCluster().clusterManager(getBucketName(), getBucketPassword()).info();
}
as we can see, it's not using username, just bucket and password, so in our configuration we will override it as following :
@Override
@Bean(name = BeanNames.COUCHBASE_CLUSTER_INFO)
public ClusterInfo couchbaseClusterInfo() throws Exception {
return couchbaseCluster().authenticate(couchbaseUsername, couchbasePassword).clusterManager().info();
}
that's it. Here is the full code of my spring-data-couchbase
configuration :
import com.couchbase.client.java.Bucket;
import com.couchbase.client.java.cluster.ClusterInfo;
import com.couchbase.client.java.env.CouchbaseEnvironment;
import com.couchbase.client.java.env.DefaultCouchbaseEnvironment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.data.couchbase.config.AbstractCouchbaseConfiguration;
import org.springframework.data.couchbase.config.BeanNames;
import org.springframework.data.couchbase.repository.config.EnableCouchbaseRepositories;
import javax.inject.Inject;
import java.security.KeyStore;
import java.util.List;
/**
* @author by avoinovan
*/
@Configuration
@EnableCouchbaseRepositories
public class ModelConfig extends AbstractCouchbaseConfiguration {
private final static int DEFAULT_HTTP_PORT = 8091;
private final static int DEFAULT_HTTP_SSL_PORT = 18091;
private final static int DEFAULT_CARRIER_PORT = 11210;
private final static int DEFAULT_CARRIER_SSL_PORT = 11207;
private final static long DEFAULT_KEEP_ALIVE_INTERVAL = 30000;
private final static int DEFAULT_SOCKET_CONNECT_TIMEOUT_MS = 5000;
private final static long DEFAULT_CONNECT_TIMEOUT_MS = 5000;
private final static long DEFAULT_MANAGEMENT_TIMEOUT_MS = 75000;
private final static long DEFAULT_DISCONNECT_TIMEOUT_MS = 25000;
private final static String PROPERTY_KEEP_ALIVE_INTERVAL_MS = "couchbase.keep_alive_interval_ms";
private final static String PROPERTY_SOCKET_CONNECT_TIMEOUT_MS = "couchbase.socket_connect_timeout_ms";
private final static String PROPERTY_CONNECT_TIMEOUT_MS = "couchbase.connect_timeout_ms";
private final static String PROPERTY_MANAGEMENT_TIMEOUT_MS = "couchbase.management_timeout_ms";
private final static String PROPERTY_DISCONNECT_TIMEOUT_MS = "couchbase.disconnect_timeout_ms";
private final static String PROPERTY_SSL_ENABLED = "couchbase.ssl.enabled";
private final static String PROPERTY_SSL_KEYSTORE_FILE = "couchbase.ssl.keystore.file";
private final static String PROPERTY_SSL_KEYSTORE_PASSWORD = "couchbase.ssl.keystore.password";
private final static String PROPERTY_SSL_TRUSTSTORE_FILE = "couchbase.ssl.truststore.file";
private final static String PROPERTY_SSL_TRUSTSTORE_PASSWORD = "couchbase.ssl.truststore.password";
private final static String PROPERTY_BOOTSTRAP_HTTP_ENABLED = "couchbase.bootstrap.http.enabled";
private final static String PROPERTY_BOOTSTRAP_HTTP_PORT = "couchbase.bootstrap.http.port";
private final static String PROPERTY_BOOTSTRAP_HTTP_SSL_PORT = "couchbase.bootstrap.http.ssl.port";
private final static String PROPERTY_BOOTSTRAP_CARRIER_ENABLED = "couchbase.bootstrap.carrier.enabled";
private final static String PROPERTY_BOOTSTRAP_CARRIER_PORT = "couchbase.bootstrap.carrier.port";
private final static String PROPERTY_BOOTSTRAP_CARRIER_SSL_PORT = "couchbase.bootstrap.carrier.ssl.port";
@Value("#{'${spring.couchbase.bootstrap-hosts}'.split(',')}")
private List<String> couchbaseBootstrapHosts;
@Value("${spring.couchbase.bucket.name}")
private String bucketName;
@Value("${spring.couchbase.password}")
private String couchbasePassword;
@Value("${spring.couchbase.username}")
private String couchbaseUsername;
private final Environment environment;
private final ResourceLoader resourceLoader;
@Inject
public ModelConfig(final Environment environment,
final ResourceLoader resourceLoader) {
this.environment = environment;
this.resourceLoader = resourceLoader;
}
protected List<String> getBootstrapHosts() {
return couchbaseBootstrapHosts;
}
protected String getBucketName() {
return bucketName;
}
protected String getBucketPassword() {
return couchbasePassword;
}
protected CouchbaseEnvironment getEnvironment() {
return DefaultCouchbaseEnvironment.builder()
.keepAliveInterval(environment.getProperty(PROPERTY_KEEP_ALIVE_INTERVAL_MS,
Long.class,
DEFAULT_KEEP_ALIVE_INTERVAL))
// timeout settings
.socketConnectTimeout(environment.getProperty(PROPERTY_SOCKET_CONNECT_TIMEOUT_MS,
Integer.class,
DEFAULT_SOCKET_CONNECT_TIMEOUT_MS))
.connectTimeout(environment.getProperty(PROPERTY_CONNECT_TIMEOUT_MS,
Long.class,
DEFAULT_CONNECT_TIMEOUT_MS))
.managementTimeout(environment.getProperty(PROPERTY_MANAGEMENT_TIMEOUT_MS,
Long.class,
DEFAULT_MANAGEMENT_TIMEOUT_MS))
.disconnectTimeout(environment.getProperty(PROPERTY_DISCONNECT_TIMEOUT_MS,
Long.class,
DEFAULT_DISCONNECT_TIMEOUT_MS))
// port and ssl
.sslEnabled(environment.getProperty(PROPERTY_SSL_ENABLED, Boolean.class, false))
.bootstrapHttpEnabled(environment.getProperty(PROPERTY_BOOTSTRAP_HTTP_ENABLED,
Boolean.class,
Boolean.TRUE))
.bootstrapHttpDirectPort(environment.getProperty(PROPERTY_BOOTSTRAP_HTTP_PORT,
Integer.class,
DEFAULT_HTTP_PORT))
.bootstrapHttpSslPort(environment.getProperty(PROPERTY_BOOTSTRAP_HTTP_SSL_PORT,
Integer.class,
DEFAULT_HTTP_SSL_PORT))
.bootstrapCarrierEnabled(environment.getProperty(PROPERTY_BOOTSTRAP_CARRIER_ENABLED,
Boolean.class,
Boolean.TRUE))
.bootstrapCarrierDirectPort(environment.getProperty(PROPERTY_BOOTSTRAP_CARRIER_PORT,
Integer.class,
DEFAULT_CARRIER_PORT))
.bootstrapCarrierSslPort(environment.getProperty(PROPERTY_BOOTSTRAP_CARRIER_SSL_PORT,
Integer.class,
DEFAULT_CARRIER_SSL_PORT))
// keystore and trust store
.sslKeystore(createKeyStore(environment, resourceLoader))
.sslTruststore(createTrustStore(environment, resourceLoader))
.build();
}
@Override
@Bean(name = BeanNames.COUCHBASE_CLUSTER_INFO)
public ClusterInfo couchbaseClusterInfo() throws Exception {
return couchbaseCluster().authenticate(couchbaseUsername, couchbasePassword).clusterManager().info();
}
/**
* Return the {@link Bucket} instance to connect to.
*
* @throws Exception on Bean construction failure.
*/
@Override
@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());
}
private KeyStore createKeyStore(final Environment environment, final ResourceLoader resourceLoader) {
return loadKeyStore(environment, resourceLoader, PROPERTY_SSL_KEYSTORE_FILE, PROPERTY_SSL_KEYSTORE_PASSWORD);
}
private KeyStore createTrustStore(final Environment environment, final ResourceLoader resourceLoader) {
return loadKeyStore(environment, resourceLoader, PROPERTY_SSL_TRUSTSTORE_FILE, PROPERTY_SSL_TRUSTSTORE_PASSWORD);
}
private KeyStore loadKeyStore(final Environment environment,
final ResourceLoader resourceLoader,
final String fileProperty,
final String passwordProperty) {
String file = environment.getProperty(fileProperty);
String password = environment.getProperty(passwordProperty);
if (file != null) {
Resource resource = resourceLoader.getResource(file);
if (resource != null) {
try {
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(resource.getInputStream(), password == null ? null : password.toCharArray());
return keyStore;
} catch (final Exception e) {
throw new RuntimeException(e);
}
}
}
return null;
}
}
I faced the same issue. I started debugging by getting into AbstractCouchbaseConfiguration and there i found
public abstract class AbstractCouchbaseConfiguration
extends AbstractCouchbaseDataConfiguration implements CouchbaseConfigurer {
....//some other configuration
@Override
@Bean(name = BeanNames.COUCHBASE_CLUSTER_INFO)
public ClusterInfo couchbaseClusterInfo() throws Exception {
return couchbaseCluster().clusterManager(getBucketName(), getBucketPassword()).info();
}
What i did is created a bucket with the same name as of my couchbase user.
couchbase username : userdetail
couchbase password : ******
bucket name : userdetail
Spring Data Couchbase is compatible with Couchbase Server 5.0. You can achieve the same auth as 4.x by creating a user with the same name as the bucket, then just use that bucket name and password from Spring Data if it's prior to 3.0/Kay.
The docs should cover this and if there's anything confusing there, please click the "feedback" button and offer what could be improved!
https://developer.couchbase.com/documentation/server/5.0/security/security-authorization.html https://developer.couchbase.com/documentation/server/5.0/security/concepts-rba-for-apps.html https://developer.couchbase.com/documentation/server/5.0/security/security-resources-under-access-control.html