Skip to content

Commit cdc8f52

Browse files
committed
DATAMONGO-356 - CDI integration for Mongo repositories.
1 parent 39492da commit cdc8f52

File tree

10 files changed

+393
-0
lines changed

10 files changed

+393
-0
lines changed

spring-data-mongodb/pom.xml

+32
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
<properties>
1515
<mongo.version>2.7.1</mongo.version>
1616
<querydsl.version>2.3.2</querydsl.version>
17+
<cdi.version>1.0</cdi.version>
18+
<webbeans.version>1.1.3</webbeans.version>
1719
</properties>
1820

1921
<dependencies>
@@ -97,6 +99,36 @@
9799
<version>1.0</version>
98100
<optional>true</optional>
99101
</dependency>
102+
103+
<!-- CDI -->
104+
<dependency>
105+
<groupId>javax.enterprise</groupId>
106+
<artifactId>cdi-api</artifactId>
107+
<version>${cdi.version}</version>
108+
<scope>provided</scope>
109+
<optional>true</optional>
110+
</dependency>
111+
112+
<dependency>
113+
<groupId>javax.el</groupId>
114+
<artifactId>el-api</artifactId>
115+
<version>${cdi.version}</version>
116+
<scope>test</scope>
117+
</dependency>
118+
119+
<dependency>
120+
<groupId>org.apache.openwebbeans.test</groupId>
121+
<artifactId>cditest-owb</artifactId>
122+
<version>${webbeans.version}</version>
123+
<scope>test</scope>
124+
</dependency>
125+
126+
<dependency>
127+
<groupId>javax.servlet</groupId>
128+
<artifactId>servlet-api</artifactId>
129+
<version>2.5</version>
130+
<scope>test</scope>
131+
</dependency>
100132

101133
</dependencies>
102134

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*
2+
* Copyright 2012 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.repository.cdi;
17+
18+
import java.lang.annotation.Annotation;
19+
import java.util.Set;
20+
21+
import javax.enterprise.context.spi.CreationalContext;
22+
import javax.enterprise.inject.spi.Bean;
23+
import javax.enterprise.inject.spi.BeanManager;
24+
25+
import org.springframework.data.mongodb.core.MongoOperations;
26+
import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory;
27+
import org.springframework.data.repository.cdi.CdiRepositoryBean;
28+
import org.springframework.util.Assert;
29+
30+
/**
31+
* {@link CdiRepositoryBean} to create Mongo repository instances.
32+
*
33+
* @author Oliver Gierke
34+
*/
35+
public class MongoRepositoryBean<T> extends CdiRepositoryBean<T> {
36+
37+
private final Bean<MongoOperations> operations;
38+
39+
/**
40+
* Creates a new {@link MongoRepositoryBean}.
41+
*
42+
* @param operations must not be {@literal null}.
43+
* @param qualifiers must not be {@literal null}.
44+
* @param repositoryType must not be {@literal null}.
45+
* @param beanManager must not be {@literal null}.
46+
*/
47+
public MongoRepositoryBean(Bean<MongoOperations> operations, Set<Annotation> qualifiers, Class<T> repositoryType,
48+
BeanManager beanManager) {
49+
50+
super(qualifiers, repositoryType, beanManager);
51+
52+
Assert.notNull(operations);
53+
this.operations = operations;
54+
}
55+
56+
/*
57+
* (non-Javadoc)
58+
* @see javax.enterprise.inject.spi.Bean#getScope()
59+
*/
60+
public Class<? extends Annotation> getScope() {
61+
return operations.getScope();
62+
}
63+
64+
/*
65+
* (non-Javadoc)
66+
* @see org.springframework.data.repository.cdi.CdiRepositoryBean#create(javax.enterprise.context.spi.CreationalContext, java.lang.Class)
67+
*/
68+
@Override
69+
protected T create(CreationalContext<T> creationalContext, Class<T> repositoryType) {
70+
71+
MongoOperations mongoOperations = getDependencyInstance(operations, MongoOperations.class);
72+
MongoRepositoryFactory factory = new MongoRepositoryFactory(mongoOperations);
73+
74+
return factory.getRepository(repositoryType);
75+
}
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*
2+
* Copyright 2011 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.repository.cdi;
17+
18+
import java.lang.annotation.Annotation;
19+
import java.lang.reflect.Type;
20+
import java.util.HashMap;
21+
import java.util.HashSet;
22+
import java.util.Map;
23+
import java.util.Map.Entry;
24+
import java.util.Set;
25+
26+
import javax.enterprise.event.Observes;
27+
import javax.enterprise.inject.UnsatisfiedResolutionException;
28+
import javax.enterprise.inject.spi.AfterBeanDiscovery;
29+
import javax.enterprise.inject.spi.Bean;
30+
import javax.enterprise.inject.spi.BeanManager;
31+
import javax.enterprise.inject.spi.ProcessBean;
32+
33+
import org.slf4j.Logger;
34+
import org.slf4j.LoggerFactory;
35+
import org.springframework.data.mongodb.core.MongoOperations;
36+
import org.springframework.data.repository.cdi.CdiRepositoryExtensionSupport;
37+
38+
/**
39+
* CDI extension to export Mongo repositories.
40+
*
41+
* @author Oliver Gierke
42+
*/
43+
public class MongoRepositoryExtension extends CdiRepositoryExtensionSupport {
44+
45+
private static final Logger LOG = LoggerFactory.getLogger(MongoRepositoryExtension.class);
46+
47+
private final Map<Set<Annotation>, Bean<MongoOperations>> mongoOperations = new HashMap<Set<Annotation>, Bean<MongoOperations>>();
48+
49+
public MongoRepositoryExtension() {
50+
LOG.info("Activating CDI extension for Spring Data MongoDB repositories.");
51+
}
52+
53+
@SuppressWarnings("unchecked")
54+
<X> void processBean(@Observes ProcessBean<X> processBean) {
55+
56+
Bean<X> bean = processBean.getBean();
57+
58+
for (Type type : bean.getTypes()) {
59+
if (type instanceof Class<?> && MongoOperations.class.isAssignableFrom((Class<?>) type)) {
60+
if (LOG.isDebugEnabled()) {
61+
LOG.debug(String.format("Discovered %s with qualifiers %s.", MongoOperations.class.getName(),
62+
bean.getQualifiers()));
63+
}
64+
65+
// Store the EntityManager bean using its qualifiers.
66+
mongoOperations.put(new HashSet<Annotation>(bean.getQualifiers()), (Bean<MongoOperations>) bean);
67+
}
68+
}
69+
}
70+
71+
void afterBeanDiscovery(@Observes AfterBeanDiscovery afterBeanDiscovery, BeanManager beanManager) {
72+
73+
for (Entry<Class<?>, Set<Annotation>> entry : getRepositoryTypes()) {
74+
75+
Class<?> repositoryType = entry.getKey();
76+
Set<Annotation> qualifiers = entry.getValue();
77+
78+
// Create the bean representing the repository.
79+
Bean<?> repositoryBean = createRepositoryBean(repositoryType, qualifiers, beanManager);
80+
81+
if (LOG.isInfoEnabled()) {
82+
LOG.info(String.format("Registering bean for %s with qualifiers %s.", repositoryType.getName(), qualifiers));
83+
}
84+
85+
// Register the bean to the container.
86+
afterBeanDiscovery.addBean(repositoryBean);
87+
}
88+
}
89+
90+
/**
91+
* Creates a {@link Bean}.
92+
*
93+
* @param <T> The type of the repository.
94+
* @param repositoryType The class representing the repository.
95+
* @param beanManager The BeanManager instance.
96+
* @return The bean.
97+
*/
98+
private <T> Bean<T> createRepositoryBean(Class<T> repositoryType, Set<Annotation> qualifiers, BeanManager beanManager) {
99+
100+
// Determine the MongoOperations bean which matches the qualifiers of the repository.
101+
Bean<MongoOperations> mongoOperations = this.mongoOperations.get(qualifiers);
102+
103+
if (mongoOperations == null) {
104+
throw new UnsatisfiedResolutionException(String.format("Unable to resolve a bean for '%s' with qualifiers %s.",
105+
MongoOperations.class.getName(), qualifiers));
106+
}
107+
108+
// Construct and return the repository bean.
109+
return new MongoRepositoryBean<T>(mongoOperations, qualifiers, repositoryType, beanManager);
110+
}
111+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
org.springframework.data.mongodb.repository.cdi.MongoRepositoryExtension
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Copyright 2012 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.repository.cdi;
17+
18+
import static org.hamcrest.CoreMatchers.*;
19+
import static org.junit.Assert.*;
20+
21+
import org.apache.webbeans.cditest.CdiTestContainer;
22+
import org.apache.webbeans.cditest.CdiTestContainerLoader;
23+
import org.junit.BeforeClass;
24+
import org.junit.Test;
25+
import org.springframework.data.mongodb.repository.Person;
26+
27+
/**
28+
* Integration tests for {@link MongoRepositoryExtension}.
29+
*
30+
* @author Oliver Gierke
31+
*/
32+
public class CdiExtensionIntegrationTests {
33+
34+
static CdiTestContainer container;
35+
36+
@BeforeClass
37+
public static void setUp() throws Exception {
38+
container = CdiTestContainerLoader.getCdiContainer();
39+
container.bootContainer();
40+
}
41+
42+
@Test
43+
public void bootstrapsRepositoryCorrectly() {
44+
45+
RepositoryClient client = container.getInstance(RepositoryClient.class);
46+
PersonRepository repository = client.getRepository();
47+
48+
assertThat(repository, is(notNullValue()));
49+
50+
repository.deleteAll();
51+
52+
Person person = new Person("Dave", "Matthews");
53+
Person result = repository.save(person);
54+
55+
assertThat(result, is(notNullValue()));
56+
assertThat(repository.findOne(person.getId()).getId(), is(result.getId()));
57+
}
58+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2012 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.repository.cdi;
17+
18+
import java.net.UnknownHostException;
19+
20+
import javax.enterprise.context.ApplicationScoped;
21+
import javax.enterprise.inject.Produces;
22+
23+
import org.springframework.data.mongodb.MongoDbFactory;
24+
import org.springframework.data.mongodb.core.MongoOperations;
25+
import org.springframework.data.mongodb.core.MongoTemplate;
26+
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
27+
28+
import com.mongodb.Mongo;
29+
import com.mongodb.MongoException;
30+
31+
/**
32+
* Simple component exposing a {@link MongoOperations} instance as CDI bean.
33+
*
34+
* @author Oliver Gierke
35+
*/
36+
class MongoTemplateProducer {
37+
38+
@Produces
39+
@ApplicationScoped
40+
public MongoOperations createMongoTemplate() throws UnknownHostException, MongoException {
41+
42+
MongoDbFactory factory = new SimpleMongoDbFactory(new Mongo(), "database");
43+
return new MongoTemplate(factory);
44+
}
45+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2012 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.springframework.data.mongodb.repository.cdi;
17+
18+
import org.springframework.data.mongodb.repository.Person;
19+
import org.springframework.data.repository.Repository;
20+
21+
public interface PersonRepository extends Repository<Person, String> {
22+
23+
void deleteAll();
24+
25+
Person save(Person person);
26+
27+
Person findOne(String id);
28+
}

0 commit comments

Comments
 (0)