If you are in the JEE space and want a modern data management layer for your NoSql applications, you might find yourself quickly limited. There are some interesting projects like Hibernate OGM or Deltaspike's Data module but none of them support Couchbase and are as advanced as Spring Data.

But everything is fine because Spring Data projects have CDI extensions. Which means you can use them in JEE containers. Bringing another DI framework like Spring does bring some overhead as CDI is already here, but it's worth the overhead when you get all the goodness that comes from Spring Data.

So let's see how this work. I will use the hibernate5 example available in the wildfly quickstart guides and replace Hibernate Core by Spring Data Couchbase. Original code can be found here and final migrated code here.

Connect to Couchbase with CDI

The first thing you will want to setup is a connection to a Couchbase cluster. Since you are using CDI, you can create a @Producer. I won't go into details on how you can externalise properties for the IP adress, bucket name, admin login and password. I will use defaults. If you don't provide any adress or bucket name, the SDK assumes you have Couchbase Server running on localhost with a bucket called default.

@Produces public CouchbaseOperations createCouchbaseTemplate() throws UnknownHostException, CouchbaseException { CouchbaseCluster cluster = CouchbaseCluster.create(); Bucket bucket = cluster.openBucket(); ClusterInfo clusterInfo = cluster.clusterManager("default","").info(); return new CouchbaseTemplate(clusterInfo, bucket); } 1 2 3 4 5 6 7 8 @ Produces public CouchbaseOperations createCouchbaseTemplate ( ) throws UnknownHostException , CouchbaseException { CouchbaseCluster cluster = CouchbaseCluster . create ( ) ; Bucket bucket = cluster . openBucket ( ) ; ClusterInfo clusterInfo = cluster . clusterManager ( "default" , "" ) . info ( ) ; return new CouchbaseTemplate ( clusterInfo , bucket ) ; }

This should give you everything you need to have working Couchbase repositories. Be aware though that there is a bug in latest version of Weld. So you might run into troubles. A quick fix can be found here. Basically the problem is that Weld changed the way they store qualifiers, wich is not compatible anymore with the Bean lookup method(based on qualifiers). So I fixed it temporarily by changing the way annotations are processed in the CDI extension directly. Sample code looks like this:

<T> void processBean(@Observes ProcessBean<T> processBean) { Bean<T> bean = processBean.getBean(); for (Type type : bean.getTypes()) { if (type instanceof Class<?> && CouchbaseOperations.class.isAssignableFrom((Class<?>) type)) { Set<Annotation> qualifiers = bean.getQualifiers().stream() .sorted((e1, e2) -> Integer.compare(e1.hashCode(), e2.hashCode())).collect(Collectors.toSet()); couchbaseOperationsMap.put(qualifiers, ((Bean<CouchbaseOperations>) bean)); } } } 1 2 3 4 5 6 7 8 9 10 11 12 < T > void processBean ( @ Observes ProcessBean < T > processBean ) { Bean < T > bean = processBean . getBean ( ) ; for ( Type type : bean . getTypes ( ) ) { if ( type instanceof Class <? > && CouchbaseOperations . class . isAssignableFrom ( ( Class <? > ) type ) ) { Set < Annotation > qualifiers = bean . getQualifiers ( ) . stream ( ) . sorted ( ( e1 , e2 ) - > Integer . compare ( e1 . hashCode ( ) , e2 . hashCode ( ) ) ) . collect ( Collectors . toSet ( ) ) ; couchbaseOperationsMap . put ( qualifiers , ( ( Bean < CouchbaseOperations > ) bean ) ) ; } } }

You are most likely to encounter this bug if you use Wildfly 10 or Jboss EAP 7.

Integrate the Spring Repository

Once you have your producer for the CouchbaseOperations class, you can start creating repositories. You don't have to implement anything, which is part of the beauty in Spring Data. You just create an interface extending the CouchbasePagingAndSortingRepository interface, specifying the Entity class you want to manage as well as the type of the key. In the exemple it's . Which means the repository stores Members entities using a Long as key.

I will just add a method called findAll that takes a Sort object as parameter.

public interface MemberRepository extends CouchbasePagingAndSortingRepository { Iterable<Member> findAll(Sort sort); } 1 2 3 4 public interface MemberRepository extends CouchbasePagingAndSortingRepository { Iterable < Member > findAll ( Sort sort ) ; }

This requires a change in the MemberListProducer to use that particular method. A Sort object lets you define the Sort direction as well as the fields to use for the Sort.

@PostConstruct public void retrieveAllMembersOrderedByName() { members = memberRepository.findAll(new Sort(Sort.Direction.ASC, "name")); } 1 2 3 4 5 @ PostConstruct public void retrieveAllMembersOrderedByName ( ) { members = memberRepository . findAll ( new Sort ( Sort . Direction . ASC , "name" ) ) ; }

Now you should be ready to deploy that project to your JEE container. If you use Wildfly and the code in this github repository, you can run mvn wildfly:deploy and go to the following URL: http://localhost:8080/wildfly-springdata.

Please let us know if you encounter any issues or have any suggestions in the comment section bellow!