Skip to content

Commit 1118c52

Browse files
committed
Fixed CDI integration.
1 parent 5ae0af1 commit 1118c52

File tree

17 files changed

+349
-171
lines changed

17 files changed

+349
-171
lines changed

integration/javamoney-cdi/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
<dependency>
1717
<groupId>org.jboss.weld.se</groupId>
1818
<artifactId>weld-se</artifactId>
19-
<version>1.1.5.Final</version>
19+
<version>2.2.4.Final</version>
2020
<scope>provided</scope>
2121
</dependency>
2222
<dependency>
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
/*
2+
* Copyright (c) 2012, 2013, Werner Keil, Credit Suisse (Anatole Tresch).
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* 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, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*
16+
*
17+
* Contributors: Anatole Tresch - initial version.
18+
*/
19+
package org.javamoney.cdi.bootstrap;
20+
21+
import org.slf4j.Logger;
22+
import org.slf4j.LoggerFactory;
23+
24+
import java.lang.annotation.Annotation;
25+
import java.util.*;
26+
27+
import javax.enterprise.context.spi.CreationalContext;
28+
import javax.enterprise.inject.Instance;
29+
import javax.enterprise.inject.Vetoed;
30+
import javax.enterprise.inject.spi.Bean;
31+
import javax.enterprise.inject.spi.BeanManager;
32+
import javax.enterprise.inject.spi.CDI;
33+
import javax.enterprise.util.TypeLiteral;
34+
import javax.inject.Named;
35+
import javax.naming.InitialContext;
36+
37+
/**
38+
* Small utility class that glues together service loading and CDI, including support for different CDI version.
39+
*/
40+
final class CDIAccessor {
41+
42+
private static final Logger LOG = LoggerFactory.getLogger(CDIAccessor.class);
43+
44+
private static final Instance<?> EMPTY_INSTANCE = new EmptyInstance<>();
45+
46+
private CDIAccessor() {
47+
}
48+
49+
private static <T> Instance<T> emptyInstance() {
50+
return Instance.class.cast(EMPTY_INSTANCE);
51+
}
52+
53+
public static <T> Optional<T> getInstance(Class<T> instanceType,
54+
Annotation... qualifiers) {
55+
BeanManager man = getBeanManager();
56+
if (man != null) {
57+
return Optional.ofNullable(getInstanceByType(man, instanceType, qualifiers));
58+
}
59+
return Optional.empty();
60+
}
61+
62+
private static BeanManager getBeanManager() {
63+
// 1 try JNDI
64+
try {
65+
InitialContext ctx = new InitialContext();
66+
BeanManager man = (BeanManager) ctx.lookup("comp:/env/BeanManager");
67+
if (man != null) {
68+
return man;
69+
}
70+
} catch (Exception e) {
71+
LoggerFactory.getLogger(CDIAccessor.class).debug("Unable to locate BeanManager from JNDI...", e);
72+
}
73+
try {
74+
Class.forName("javax.enterprise.inject.spi.CDI");
75+
// OK CDI 1.1 is loaded
76+
return CDI.current().getBeanManager();
77+
} catch (ClassNotFoundException e) {
78+
LoggerFactory.getLogger(CDIAccessor.class).debug("CDI accessor not available (CDI 1.0).");
79+
} catch (Exception e) {
80+
LoggerFactory.getLogger(CDIAccessor.class).debug("Unable to locate BeanManager from CDI providers...", e);
81+
}
82+
// 3 error, CDI not loaded...
83+
throw new IllegalStateException("CDI is not available.");
84+
}
85+
86+
/**
87+
* Utility method allowing managed instances of beans to provide entry points
88+
* for non-managed beans (such as {@link org.jboss.weld.environment.se.WeldContainer}). Should only called
89+
* once Weld has finished booting.
90+
*
91+
* @param manager the BeanManager to use to access the managed instance
92+
* @param type the type of the Bean
93+
* @param bindings the bean's qualifiers
94+
* @return a managed instance of the bean
95+
* @throws IllegalArgumentException if the given type represents a type
96+
* variable
97+
* @throws IllegalArgumentException if two instances of the same qualifier
98+
* type are given
99+
* @throws IllegalArgumentException if an instance of an annotation that is
100+
* not a qualifier type is given
101+
* @throws javax.enterprise.inject.UnsatisfiedResolutionException if no beans can be resolved * @throws
102+
* AmbiguousResolutionException if the ambiguous dependency
103+
* resolution rules fail
104+
* @throws IllegalArgumentException if the given type is not a bean type of
105+
* the given bean
106+
*/
107+
private static <T> T getInstanceByType(BeanManager manager, Class<T> type, Annotation... bindings) {
108+
final Bean<?> bean = manager.resolve(manager.getBeans(type));
109+
if (bean == null) {
110+
return null;
111+
}
112+
CreationalContext<?> cc = manager.createCreationalContext(bean);
113+
return type.cast(manager.getReference(bean, type, cc));
114+
}
115+
116+
public static <T> Instance<T> getInstances(Class<T> instanceType,
117+
Annotation... qualifiers) {
118+
try {
119+
return getInstance(Instance.class).get().select(instanceType, qualifiers);
120+
} catch (Exception e) {
121+
LOG.info("Failed to load instances from CDI.", e);
122+
return emptyInstance();
123+
}
124+
}
125+
126+
public static Set<?> getInstances(String name) {
127+
try {
128+
return getBeanManager().getBeans(name);
129+
} catch (Exception e) {
130+
LOG.info("Failed to load instances from CDI.", e);
131+
return Collections.emptySet();
132+
}
133+
134+
}
135+
136+
public static void fireEvent(Object evt, Annotation... qualifiers) {
137+
try {
138+
getBeanManager().fireEvent(evt, qualifiers);
139+
} catch (Exception e) {
140+
LOG.info("Failed to fire event from CDI.", e);
141+
}
142+
}
143+
144+
@SuppressWarnings("unchecked")
145+
public static <T> T getNamedInstance(Class<T> type, String id) {
146+
try {
147+
Set<?> found = getBeanManager().getBeans(id);
148+
if (found.isEmpty()) {
149+
return null;
150+
}
151+
for (Object object : found) {
152+
if (type.isAssignableFrom(object.getClass())) {
153+
return (T) object;
154+
}
155+
}
156+
return null;
157+
} catch (Exception e) {
158+
LOG.info("Failed to load instances from CDI.", e);
159+
return null;
160+
}
161+
162+
}
163+
164+
public static String getName(Object o) {
165+
if (o == null) {
166+
return "<null>";
167+
}
168+
Named named = o.getClass().getAnnotation(Named.class);
169+
if (named != null) {
170+
return named.value();
171+
}
172+
return o.getClass().getSimpleName();
173+
}
174+
175+
@Vetoed
176+
private static final class EmptyInstance<T> implements Instance<T> {
177+
@Override
178+
public Instance<T> select(Annotation... annotations) {
179+
return this;
180+
}
181+
182+
@Override
183+
public <U extends T> Instance<U> select(Class<U> uClass, Annotation... annotations) {
184+
return new EmptyInstance<>();
185+
}
186+
187+
@Override
188+
public <U extends T> Instance<U> select(TypeLiteral<U> uTypeLiteral, Annotation... annotations) {
189+
return new EmptyInstance<>();
190+
}
191+
192+
@Override
193+
public boolean isUnsatisfied() {
194+
return true;
195+
}
196+
197+
@Override
198+
public boolean isAmbiguous() {
199+
return false;
200+
}
201+
202+
@Override
203+
public void destroy(T t) {
204+
}
205+
206+
@Override
207+
public Iterator<T> iterator() {
208+
return Collections.emptyIterator();
209+
}
210+
211+
@Override
212+
public T get() {
213+
throw new NoSuchElementException();
214+
}
215+
}
216+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.javamoney.cdi.bootstrap;
2+
3+
import java.util.*;
4+
import java.util.concurrent.ConcurrentHashMap;
5+
6+
import javax.enterprise.inject.Instance;
7+
import javax.money.spi.DefaultServiceProvider;
8+
import javax.money.spi.ServiceProvider;
9+
10+
import org.javamoney.moneta.spi.ServicePriority;
11+
import org.slf4j.LoggerFactory;
12+
13+
/**
14+
* Overriding ServiceProvider that actually tries to satisfy component requests from CDI,
15+
* where possible. Additionally ServiceLoader based service are loaded and are returned
16+
* ONLY, when not the same service is loaded as well in CDI.
17+
*/
18+
@ServicePriority(ServicePriority.NORM_PRIORITY + 1)
19+
public class CDISEServiceProvider implements ServiceProvider {
20+
/**
21+
* Default provider, using ServiceLoader.
22+
*/
23+
private ServiceProvider defaultServiceProvider = new DefaultServiceProvider();
24+
25+
@Override
26+
public <T> List<T> getServices(Class<T> serviceType) {
27+
List<T> instances = new ArrayList<T>();
28+
Set<String> types = new HashSet<>();
29+
for (T t : CDIAccessor
30+
.getInstances(serviceType)) {
31+
instances.add(t);
32+
types.add(t.getClass().getName());
33+
}
34+
for (T t : defaultServiceProvider.getServices(serviceType)) {
35+
if (!types.contains(t.getClass().getName())) {
36+
instances.add(t);
37+
}
38+
}
39+
return instances;
40+
}
41+
42+
@Override
43+
public <T> List<T> getServices(Class<T> serviceType,
44+
List<T> defaultList) {
45+
Instance<T> found = CDIAccessor
46+
.getInstances(serviceType);
47+
Set<String> types = new HashSet<>();
48+
List<T> instances = new ArrayList<T>();
49+
for (T t : found) {
50+
instances.add(t);
51+
types.add(t.getClass().getName());
52+
}
53+
for (T t : defaultServiceProvider.getServices(serviceType)) {
54+
if (!types.contains(t.getClass().getName())){
55+
instances.add(t);
56+
}
57+
}
58+
if (instances.isEmpty()) {
59+
return defaultList;
60+
}
61+
return instances;
62+
}
63+
64+
@Override
65+
public String toString() {
66+
return "CDISEServiceProvider{" +
67+
"defaultServiceProvider=" + defaultServiceProvider +
68+
'}';
69+
}
70+
}

integration/javamoney-cdi/src/main/java/org/javamoney/cdi/bootstrap/CDIServices.java

Lines changed: 0 additions & 51 deletions
This file was deleted.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
* Contains the bootstrap support for loading beans additionally from CDI, when available.
3+
*/
4+
package org.javamoney.cdi.bootstrap;

0 commit comments

Comments
 (0)