Commit 9f3eff34910cb89943b4ded1c5defb349a98e562
1 parent
1267e2a2
Exists in
master
Implementando fix para bug que impede a serialização de beans presentes
nos contextos personalizados, devido ao uso de ClassLoader como chave do mapa interno dos contextos.
Showing
7 changed files
with
69 additions
and
52 deletions
Show diff stats
impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/context/AbstractCustomContext.java
... | ... | @@ -36,6 +36,7 @@ |
36 | 36 | */ |
37 | 37 | package br.gov.frameworkdemoiselle.internal.context; |
38 | 38 | |
39 | +import java.io.Serializable; | |
39 | 40 | import java.lang.annotation.Annotation; |
40 | 41 | import java.util.Collections; |
41 | 42 | import java.util.HashMap; |
... | ... | @@ -156,8 +157,8 @@ public abstract class AbstractCustomContext implements CustomContext { |
156 | 157 | return this.scope; |
157 | 158 | } |
158 | 159 | |
159 | - protected static Store createStore() { | |
160 | - return new Store(); | |
160 | + protected static Store createStore(Class<?> owningClass) { | |
161 | + return new Store(owningClass); | |
161 | 162 | } |
162 | 163 | |
163 | 164 | private ResourceBundle getBundle(){ |
... | ... | @@ -193,38 +194,47 @@ public abstract class AbstractCustomContext implements CustomContext { |
193 | 194 | return true; |
194 | 195 | } |
195 | 196 | |
196 | - static class Store { | |
197 | + static class Store implements Serializable { | |
197 | 198 | |
198 | - private Map<ClassLoader, Map<Class<?>, Object>> cache = Collections | |
199 | - .synchronizedMap(new HashMap<ClassLoader, Map<Class<?>, Object>>()); | |
199 | + private static final long serialVersionUID = -8237464177510563034L; | |
200 | + | |
201 | + private final String SEPARATOR = "#"; | |
202 | + | |
203 | + private final String ID_PREFIX; | |
204 | + | |
205 | + private Map<String, Object> cache = Collections.synchronizedMap(new HashMap<String, Object>()); | |
200 | 206 | |
201 | - private Store() { | |
207 | + private Store(Class<?> owningClass) { | |
208 | + ID_PREFIX = Thread.currentThread().getContextClassLoader().toString() | |
209 | + + SEPARATOR + owningClass.getCanonicalName(); | |
202 | 210 | } |
203 | 211 | |
204 | 212 | private boolean contains(final Class<?> type) { |
205 | - return this.getMap().containsKey(type); | |
213 | + return cache.containsKey( prefixId(type.getCanonicalName()) ); | |
206 | 214 | } |
207 | 215 | |
208 | 216 | private Object get(final Class<?> type) { |
209 | - return this.getMap().get(type); | |
217 | + return cache.get( prefixId(type.getCanonicalName()) ); | |
210 | 218 | } |
211 | 219 | |
212 | 220 | private void put(final Class<?> type, final Object instance) { |
213 | - this.getMap().put(type, instance); | |
221 | + cache.put( prefixId(type.getCanonicalName()) , instance); | |
214 | 222 | } |
215 | 223 | |
216 | 224 | public void clear() { |
217 | 225 | cache.clear(); |
218 | 226 | } |
227 | + | |
228 | + private String prefixId(String id){ | |
229 | + return ID_PREFIX + SEPARATOR + id; | |
230 | + } | |
219 | 231 | |
220 | - private Map<Class<?>, Object> getMap() { | |
221 | - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); | |
222 | - | |
232 | + /*private Map<String, Object> getMap() { | |
223 | 233 | if (!cache.containsKey(classLoader)) { |
224 | 234 | cache.put(classLoader, Collections.synchronizedMap(new HashMap<Class<?>, Object>())); |
225 | 235 | } |
226 | 236 | |
227 | 237 | return cache.get(classLoader); |
228 | - } | |
238 | + }*/ | |
229 | 239 | } |
230 | 240 | } | ... | ... |
impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/context/AbstractStaticContext.java
... | ... | @@ -37,6 +37,9 @@ |
37 | 37 | package br.gov.frameworkdemoiselle.internal.context; |
38 | 38 | |
39 | 39 | import java.lang.annotation.Annotation; |
40 | +import java.util.Collections; | |
41 | +import java.util.HashMap; | |
42 | +import java.util.Map; | |
40 | 43 | |
41 | 44 | import br.gov.frameworkdemoiselle.annotation.Priority; |
42 | 45 | import br.gov.frameworkdemoiselle.annotation.StaticScoped; |
... | ... | @@ -58,7 +61,7 @@ import br.gov.frameworkdemoiselle.configuration.Configuration; |
58 | 61 | @Priority(Priority.MIN_PRIORITY) |
59 | 62 | public abstract class AbstractStaticContext extends AbstractCustomContext { |
60 | 63 | |
61 | - private final static Store store = createStore(); | |
64 | + private static Map<String, Store> cache = Collections.synchronizedMap( new HashMap<String, Store>() ); | |
62 | 65 | |
63 | 66 | /** |
64 | 67 | * Constructs this context to control the provided scope |
... | ... | @@ -69,11 +72,16 @@ public abstract class AbstractStaticContext extends AbstractCustomContext { |
69 | 72 | |
70 | 73 | @Override |
71 | 74 | protected Store getStore() { |
75 | + Store store = cache.get( this.getClass().getCanonicalName() ); | |
76 | + if ( store==null ){ | |
77 | + store = createStore(this.getClass()); | |
78 | + cache.put(this.getClass().getCanonicalName(), store); | |
79 | + } | |
72 | 80 | return store; |
73 | 81 | } |
74 | 82 | |
75 | 83 | @Override |
76 | 84 | protected boolean isStoreInitialized() { |
77 | - return store!=null; | |
85 | + return cache.get( this.getClass().getCanonicalName() )!=null; | |
78 | 86 | } |
79 | 87 | } | ... | ... |
impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/context/AbstractThreadLocalContext.java
... | ... | @@ -73,7 +73,7 @@ public abstract class AbstractThreadLocalContext extends AbstractCustomContext { |
73 | 73 | @Override |
74 | 74 | protected Store getStore() { |
75 | 75 | if (this.threadLocal.get() == null) { |
76 | - this.threadLocal.set(createStore()); | |
76 | + this.threadLocal.set(createStore(getClass())); | |
77 | 77 | } |
78 | 78 | |
79 | 79 | return this.threadLocal.get(); | ... | ... |
impl/core/src/main/java/br/gov/frameworkdemoiselle/internal/context/CustomContextProducer.java
... | ... | @@ -60,6 +60,7 @@ import javax.enterprise.inject.spi.InjectionPoint; |
60 | 60 | |
61 | 61 | import org.slf4j.Logger; |
62 | 62 | |
63 | +import br.gov.frameworkdemoiselle.annotation.Priority; | |
63 | 64 | import br.gov.frameworkdemoiselle.context.ConversationContext; |
64 | 65 | import br.gov.frameworkdemoiselle.context.CustomContext; |
65 | 66 | import br.gov.frameworkdemoiselle.context.RequestContext; |
... | ... | @@ -133,7 +134,7 @@ public class CustomContextProducer { |
133 | 134 | /////////////PRODUCERS/////////////////// |
134 | 135 | |
135 | 136 | @Produces |
136 | - public RequestContext getRequestContext(InjectionPoint ip){ | |
137 | + protected RequestContext getRequestContext(InjectionPoint ip){ | |
137 | 138 | if (ip!=null){ |
138 | 139 | return getContext(ip); |
139 | 140 | } |
... | ... | @@ -143,7 +144,7 @@ public class CustomContextProducer { |
143 | 144 | } |
144 | 145 | |
145 | 146 | @Produces |
146 | - public SessionContext getSessionContext(InjectionPoint ip){ | |
147 | + protected SessionContext getSessionContext(InjectionPoint ip){ | |
147 | 148 | if (ip!=null){ |
148 | 149 | return getContext(ip); |
149 | 150 | } |
... | ... | @@ -153,7 +154,7 @@ public class CustomContextProducer { |
153 | 154 | } |
154 | 155 | |
155 | 156 | @Produces |
156 | - public ViewContext getViewContext(InjectionPoint ip){ | |
157 | + protected ViewContext getViewContext(InjectionPoint ip){ | |
157 | 158 | if (ip!=null){ |
158 | 159 | return getContext(ip); |
159 | 160 | } |
... | ... | @@ -163,7 +164,7 @@ public class CustomContextProducer { |
163 | 164 | } |
164 | 165 | |
165 | 166 | @Produces |
166 | - public StaticContext getStaticContext(InjectionPoint ip){ | |
167 | + protected StaticContext getStaticContext(InjectionPoint ip){ | |
167 | 168 | if (ip!=null){ |
168 | 169 | return getContext(ip); |
169 | 170 | } |
... | ... | @@ -173,7 +174,7 @@ public class CustomContextProducer { |
173 | 174 | } |
174 | 175 | |
175 | 176 | @Produces |
176 | - public ConversationContext getConversationContext(InjectionPoint ip){ | |
177 | + protected ConversationContext getConversationContext(InjectionPoint ip){ | |
177 | 178 | if (ip!=null){ |
178 | 179 | return getContext(ip); |
179 | 180 | } |
... | ... | @@ -184,8 +185,17 @@ public class CustomContextProducer { |
184 | 185 | |
185 | 186 | /////////////END OF PRODUCERS/////////////////// |
186 | 187 | |
188 | + /** | |
189 | + * Obtain a custom context for the provided injection point. | |
190 | + * | |
191 | + * @param ip The object containing information about the injection point - most importantly | |
192 | + * the declared type of the injection point, to decide the context to return | |
193 | + * | |
194 | + * @return A context of a type compatible with the type of the injection point, or <code>null</code> if there is | |
195 | + * no such context. | |
196 | + */ | |
187 | 197 | @SuppressWarnings("unchecked") |
188 | - private <T extends CustomContext> T getContext(InjectionPoint ip){ | |
198 | + public <T extends CustomContext> T getContext(InjectionPoint ip){ | |
189 | 199 | T producedContext = null; |
190 | 200 | |
191 | 201 | if (ip!=null){ |
... | ... | @@ -200,8 +210,16 @@ public class CustomContextProducer { |
200 | 210 | return producedContext; |
201 | 211 | } |
202 | 212 | |
213 | + /** | |
214 | + * Obtain a context compatible with the provided type. | |
215 | + * | |
216 | + * @param contextClass The type of the desired context. The returned context will be compatible with this type, if there | |
217 | + * is more than one compatible type, this method will decide witch one to return based on the {@link Priority} annotation. | |
218 | + * | |
219 | + * @return A context of a type compatible with the informed type, or <code>null</code> if there is no such context. | |
220 | + */ | |
203 | 221 | @SuppressWarnings("unchecked") |
204 | - private <T extends CustomContext> T getContext(Class<T> contextClass){ | |
222 | + public <T extends CustomContext> T getContext(Class<T> contextClass){ | |
205 | 223 | CustomContext producedContext = null; |
206 | 224 | |
207 | 225 | ArrayList<CustomContext> selectableContexts = new ArrayList<CustomContext>(); | ... | ... |
impl/extension/jpa/src/main/java/br/gov/frameworkdemoiselle/internal/producer/AbstractEntityManagerStore.java
... | ... | @@ -41,13 +41,11 @@ import java.util.HashMap; |
41 | 41 | import java.util.Map; |
42 | 42 | |
43 | 43 | import javax.enterprise.context.RequestScoped; |
44 | -import javax.inject.Inject; | |
45 | 44 | import javax.persistence.EntityManager; |
46 | 45 | import javax.persistence.FlushModeType; |
47 | 46 | |
48 | 47 | import org.slf4j.Logger; |
49 | 48 | |
50 | -import br.gov.frameworkdemoiselle.annotation.Name; | |
51 | 49 | import br.gov.frameworkdemoiselle.internal.configuration.EntityManagerConfig; |
52 | 50 | import br.gov.frameworkdemoiselle.internal.configuration.EntityManagerConfig.EntityManagerScope; |
53 | 51 | import br.gov.frameworkdemoiselle.util.Beans; |
... | ... | @@ -74,19 +72,6 @@ public abstract class AbstractEntityManagerStore implements EntityManagerStore { |
74 | 72 | |
75 | 73 | private final Map<String, EntityManager> cache = Collections.synchronizedMap(new HashMap<String, EntityManager>()); |
76 | 74 | |
77 | - @Inject | |
78 | - private EntityManagerFactoryProducer factory; | |
79 | - | |
80 | - @Inject | |
81 | - private Logger logger; | |
82 | - | |
83 | - @Inject | |
84 | - @Name("demoiselle-jpa-bundle") | |
85 | - private ResourceBundle bundle; | |
86 | - | |
87 | - @Inject | |
88 | - private EntityManagerConfig configuration; | |
89 | - | |
90 | 75 | public EntityManager getEntityManager(String persistenceUnit) { |
91 | 76 | EntityManager entityManager = null; |
92 | 77 | |
... | ... | @@ -114,6 +99,7 @@ public abstract class AbstractEntityManagerStore implements EntityManagerStore { |
114 | 99 | //Se o produtor não possui escopo, então o ciclo de vida |
115 | 100 | //de EntityManager produzidos é responsabilidade do desenvolvedor. Não |
116 | 101 | //fechamos os EntityManagers aqui. |
102 | + EntityManagerConfig configuration = getConfiguration(); | |
117 | 103 | if (configuration.getEntityManagerScope() != EntityManagerScope.NOSCOPE){ |
118 | 104 | for (EntityManager entityManager : cache.values()) { |
119 | 105 | entityManager.close(); |
... | ... | @@ -131,23 +117,18 @@ public abstract class AbstractEntityManagerStore implements EntityManagerStore { |
131 | 117 | } |
132 | 118 | |
133 | 119 | private EntityManagerFactoryProducer getFactory(){ |
134 | - if (factory==null){ | |
135 | - factory = Beans.getReference(EntityManagerFactoryProducer.class); | |
136 | - } | |
137 | - return factory; | |
120 | + return Beans.getReference(EntityManagerFactoryProducer.class); | |
138 | 121 | } |
139 | 122 | |
140 | 123 | private Logger getLogger(){ |
141 | - if (logger==null){ | |
142 | - logger = Beans.getReference(Logger.class); | |
143 | - } | |
144 | - return logger; | |
124 | + return Beans.getReference(Logger.class); | |
145 | 125 | } |
146 | 126 | |
147 | 127 | private ResourceBundle getBundle(){ |
148 | - if (bundle==null){ | |
149 | - bundle = Beans.getReference(ResourceBundle.class , new NameQualifier("demoiselle-jpa-bundle")); | |
150 | - } | |
151 | - return bundle; | |
128 | + return Beans.getReference(ResourceBundle.class , new NameQualifier("demoiselle-jpa-bundle")); | |
129 | + } | |
130 | + | |
131 | + private EntityManagerConfig getConfiguration(){ | |
132 | + return Beans.getReference(EntityManagerConfig.class); | |
152 | 133 | } |
153 | 134 | } | ... | ... |
impl/extension/jpa/src/main/java/br/gov/frameworkdemoiselle/internal/proxy/EntityManagerProxy.java
... | ... | @@ -117,8 +117,8 @@ public class EntityManagerProxy implements EntityManager, Serializable { |
117 | 117 | @Override |
118 | 118 | public void persist(Object entity) { |
119 | 119 | joinTransactionIfNecessary(); |
120 | - checkEntityManagerScopePassivable(entity); | |
121 | 120 | getEntityManagerDelegate().persist(entity); |
121 | + checkEntityManagerScopePassivable(entity); | |
122 | 122 | } |
123 | 123 | |
124 | 124 | /* | ... | ... |
impl/extension/jsf/src/main/java/br/gov/frameworkdemoiselle/internal/context/FacesViewContextImpl.java
... | ... | @@ -75,7 +75,7 @@ public class FacesViewContextImpl extends AbstractCustomContext implements ViewC |
75 | 75 | String key = Store.class.getName(); |
76 | 76 | |
77 | 77 | if (!viewMap.containsKey(key)) { |
78 | - viewMap.put(key, createStore()); | |
78 | + viewMap.put(key, createStore( getClass() )); | |
79 | 79 | } |
80 | 80 | |
81 | 81 | return (Store) viewMap.get(key); | ... | ... |