-
Notifications
You must be signed in to change notification settings - Fork 94
/
BeanManagerInstanceCreator.java
127 lines (112 loc) · 4.8 KB
/
BeanManagerInstanceCreator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*******************************************************************************
* Copyright (c) 2016, 2018 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Roman Grigoriadi
******************************************************************************/
package org.eclipse.yasson.internal.components;
import org.eclipse.yasson.internal.JsonBinding;
import org.eclipse.yasson.internal.properties.MessageKeys;
import org.eclipse.yasson.internal.properties.Messages;
import org.eclipse.yasson.spi.JsonbComponentInstanceCreator;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.json.bind.JsonbException;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* CDI instance manager.
* Instances are created and stored per instance of {@link JsonBinding}.
* Calling close on JsonBinding, cleans up Jsonb CDI instances and in case of "dependant" scope its dependencies.
*
* CDI API dependency is optional, this class is never referenced / loaded if CDI API is not resolvable.
*
* @author Roman Grigoriadi
*/
public class BeanManagerInstanceCreator implements JsonbComponentInstanceCreator {
private final BeanManager beanManager;
private final ConcurrentMap<Class<?>, CDIManagedBean<?>> injectionTargets = new ConcurrentHashMap<>();
/**
* Creates a new instance.
*
* @param beanManager Bean manager.
*/
public BeanManagerInstanceCreator(Object beanManager) {
if (!(beanManager instanceof BeanManager)) {
throw new JsonbException(Messages.getMessage(MessageKeys.INTERNAL_ERROR,
"beanManager instance should be of type '" + BeanManager.class + "'"));
}
this.beanManager = (BeanManager) beanManager;
}
/**
* Creates an instance of the CDI managed bean.
* Calls CDI API to inject into the bean.
*
* @param componentClass bean class to be instantiated.
* @return New instance of bean class with injected content.
*/
@Override
@SuppressWarnings("unchecked")
public <T> T getOrCreateComponent(Class<T> componentClass) {
return (T) injectionTargets.computeIfAbsent(componentClass, clazz -> {
final AnnotatedType<T> aType = beanManager.createAnnotatedType(componentClass);
final InjectionTarget<T> injectionTarget = beanManager.createInjectionTarget(aType);
CreationalContext<T> creationalContext = beanManager.createCreationalContext(null);
final T beanInstance = injectionTarget.produce(creationalContext);
injectionTarget.inject(beanInstance, creationalContext);
injectionTarget.postConstruct(beanInstance);
return new CDIManagedBean(beanInstance, injectionTarget, creationalContext);
}).getInstance();
}
@Override
@SuppressWarnings("unchecked")
public void close() throws IOException {
injectionTargets.forEach((clazz,target)-> cleanupBean(target));
injectionTargets.clear();
}
private <T> void cleanupBean(CDIManagedBean<T> bean) {
bean.getInjectionTarget().preDestroy(bean.getInstance());
bean.getInjectionTarget().dispose(bean.getInstance());
bean.getCreationalContext().release();
}
/**
* Holder for bean instance and its injection target.
*/
private static final class CDIManagedBean<T> {
private final T instance;
private final InjectionTarget<T> injectionTarget;
private final CreationalContext<T> creationalContext;
public CDIManagedBean(T instance, InjectionTarget<T> injectionTarget, CreationalContext<T> creationalContext) {
this.instance = instance;
this.injectionTarget = injectionTarget;
this.creationalContext = creationalContext;
}
/**
* @return CDI InjectionTarget
*/
private InjectionTarget<T> getInjectionTarget() {
return injectionTarget;
}
/**
* @return managed instance of a bean
*/
private T getInstance() {
return instance;
}
/**
* @return creational context
*/
private CreationalContext<T> getCreationalContext() {
return creationalContext;
}
}
}