Abstract
Spring Data is yet another extremely useful Spring subproject which is so tightly coupled with the Spring-specific container features, that deploying it in Blueprint is a non-trivial task.
The alternative to an adaptation to Blueprint is (once again) mixing Spring DM and Blueprint bundles and importing Spring DM services into Blueprint contexts.
Spring Data MongoDB in Spring DM
Excluding the Compendium marker for loading the properties file, the Spring DM configuration for MongoDB does not deviate much:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgi="http://www.springframework.org/schema/osgi" xmlns:osgix="http://www.springframework.org/schema/osgi-compendium" xmlns:context="http://www.springframework.org/schema/context" xmlns:mongo="http://www.springframework.org/schema/data/mongo" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd http://www.springframework.org/schema/osgi-compendium http://www.springframework.org/schema/osgi-compendium/spring-osgi-compendium.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo.xsd"> <osgix:cm-properties id="properties" persistent-id="io.modio.blog.osgi.spring.data.mongodb"/> <context:property-placeholder properties-ref="properties" /> <!-- Mongo DB --> <mongo:mongo id="mongo" host="${io.modio.blog.osgi.spring.data.mongodb.host}" port="${io.modio.blog.osgi.spring.data.mongodb.port}"> </mongo:mongo> <mongo:db-factory id="mongoDbFactory" mongo-ref="mongo" dbname="${io.modio.blog.osgi.spring.data.mongodb.db}"/> <bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate"> <constructor-arg name="mongoDbFactory" ref="mongoDbFactory"/> </bean> <mongo:repositories mongo-template-ref="mongoTemplate" base-package="io.modio.blog.osgi.spring.data.mongodb.repository"/> <osgi:service interface="io.modio.blog.osgi.spring.data.mongodb.repository.TaskRepository" ref="taskRepository"/> </beans>
The TaskRepository is minimal but all the standard Spring Data query method annotations are supported:
@Document public class Task { @Id private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } public interface TaskRepository extends MongoRepository<Task,String>{ Page<Task> findByName(String name, Pageable pageable); @Query("{ 'id': { $in : ?0 } }") List<Task> findByIds(List<String> ids); }
In addition, custom repository implementations also work as expected:
... <bean id="taskRepositoryImpl" class="io.modio.blog.osgi.spring.data.mongodb.repository.TaskRepositoryImpl"> <property name="mongoTemplate" ref="mongoTemplate"/> </bean> ...
public interface TaskRepositoryExt { Page<Task> findByNameSimilar(String query, Pageable pageable); } public class TaskRepositoryImpl implements TaskRepositoryExt { private MongoTemplate mongoTemplate; @Override public Page<Task> findByNameSimilar(String value, Pageable pageable) { Query query = new Query().with(pageable); if (!StringUtils.isEmpty(value)) { query.addCriteria(Criteria.where("name").regex( ".*"+value+".*", "i")); } long count = mongoTemplate.count(query, Task.class); List<Task> list = mongoTemplate.find(query, Task.class); Page<Task> page = new org.springframework.data.domain.PageImpl<Task>( list, pageable, count); return page; } public void setMongoTemplate(MongoTemplate mongoTemplate) { this.mongoTemplate = mongoTemplate; } }
The Maven pom.xml file for building the repository bundle is more elaborate due to all the explicit Import-Package directives, since BND cannot pickup import dependencies from the context-osgi.xml file:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>io.modio.blog</groupId> <artifactId>io.modio.blog.osgi.spring.data.mongodb.repository</artifactId> <packaging>bundle</packaging> <build> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> <version>2.3.7</version> <configuration> <instructions> <Export-Package> io.modio.blog.osgi.spring.data.mongodb.entity, io.modio.blog.osgi.spring.data.mongodb.repository </Export-Package> <Import-Package> com.mongodb, org.aopalliance.aop, org.springframework.aop, org.springframework.aop.framework, org.springframework.data.domain, org.springframework.data.mongodb.config, org.springframework.data.mongodb.repository.support, org.springframework.data.repository, org.springframework.data.repository.core.support, * </Import-Package> <Private-Package> </Private-Package> </instructions> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.3.5.RELEASE</version> </dependency> </dependencies> </project>
This issue is expected to be resolved. The ServiceMix community has already released OSGi bundles for Spring 3.2.8.RELEASE, so these will probably be included in a future release of Apache Karaf too.
Spring Data Repository in Blueprint
Consuming the repository service from Blueprint is now simply a matter of importing the service into the Blueprint context:
<blueprint default-activation="eager" xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <reference id="taskRepository" interface="io.modio.blog.osgi.spring.data.mongodb.repository.TaskRepository"/> <bean id="taskQueue" class="io.modio.blog.osgi.spring.data.mongodb.TaskQueue"> <property name="repository" ref="taskRepository"/> </bean> </blueprint>
Features
Spring Data MongoDB carries non-trivial dependencies, so it useful to create a Karaf feature for this:
<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0" name="spring-data-${project.version}"> <feature name="spring-data-mongodb" version="1.3.5.RELEASE" resolver='(obr)'> <feature version="[3.2.4.RELEASE,4)">spring</feature> <feature version="[3.2.4.RELEASE,4)">spring-tx</feature> <feature version="[3.2.4.RELEASE,4)">spring-web</feature> <bundle>mvn:org.mongodb/mongo-java-driver/2.12.0</bundle> <bundle>mvn:org.springframework.data/spring-data-commons/1.6.5.RELEASE</bundle> <bundle>mvn:org.springframework.data/spring-data-mongodb/1.3.5.RELEASE</bundle> </feature> </features>
do you have working example for the same?