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,6 +36,7 @@ | ||
| 36 | */ | 36 | */ |
| 37 | package br.gov.frameworkdemoiselle.internal.context; | 37 | package br.gov.frameworkdemoiselle.internal.context; |
| 38 | 38 | ||
| 39 | +import java.io.Serializable; | ||
| 39 | import java.lang.annotation.Annotation; | 40 | import java.lang.annotation.Annotation; |
| 40 | import java.util.Collections; | 41 | import java.util.Collections; |
| 41 | import java.util.HashMap; | 42 | import java.util.HashMap; |
| @@ -156,8 +157,8 @@ public abstract class AbstractCustomContext implements CustomContext { | @@ -156,8 +157,8 @@ public abstract class AbstractCustomContext implements CustomContext { | ||
| 156 | return this.scope; | 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 | private ResourceBundle getBundle(){ | 164 | private ResourceBundle getBundle(){ |
| @@ -193,38 +194,47 @@ public abstract class AbstractCustomContext implements CustomContext { | @@ -193,38 +194,47 @@ public abstract class AbstractCustomContext implements CustomContext { | ||
| 193 | return true; | 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 | private boolean contains(final Class<?> type) { | 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 | private Object get(final Class<?> type) { | 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 | private void put(final Class<?> type, final Object instance) { | 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 | public void clear() { | 224 | public void clear() { |
| 217 | cache.clear(); | 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 | if (!cache.containsKey(classLoader)) { | 233 | if (!cache.containsKey(classLoader)) { |
| 224 | cache.put(classLoader, Collections.synchronizedMap(new HashMap<Class<?>, Object>())); | 234 | cache.put(classLoader, Collections.synchronizedMap(new HashMap<Class<?>, Object>())); |
| 225 | } | 235 | } |
| 226 | 236 | ||
| 227 | return cache.get(classLoader); | 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,6 +37,9 @@ | ||
| 37 | package br.gov.frameworkdemoiselle.internal.context; | 37 | package br.gov.frameworkdemoiselle.internal.context; |
| 38 | 38 | ||
| 39 | import java.lang.annotation.Annotation; | 39 | import java.lang.annotation.Annotation; |
| 40 | +import java.util.Collections; | ||
| 41 | +import java.util.HashMap; | ||
| 42 | +import java.util.Map; | ||
| 40 | 43 | ||
| 41 | import br.gov.frameworkdemoiselle.annotation.Priority; | 44 | import br.gov.frameworkdemoiselle.annotation.Priority; |
| 42 | import br.gov.frameworkdemoiselle.annotation.StaticScoped; | 45 | import br.gov.frameworkdemoiselle.annotation.StaticScoped; |
| @@ -58,7 +61,7 @@ import br.gov.frameworkdemoiselle.configuration.Configuration; | @@ -58,7 +61,7 @@ import br.gov.frameworkdemoiselle.configuration.Configuration; | ||
| 58 | @Priority(Priority.MIN_PRIORITY) | 61 | @Priority(Priority.MIN_PRIORITY) |
| 59 | public abstract class AbstractStaticContext extends AbstractCustomContext { | 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 | * Constructs this context to control the provided scope | 67 | * Constructs this context to control the provided scope |
| @@ -69,11 +72,16 @@ public abstract class AbstractStaticContext extends AbstractCustomContext { | @@ -69,11 +72,16 @@ public abstract class AbstractStaticContext extends AbstractCustomContext { | ||
| 69 | 72 | ||
| 70 | @Override | 73 | @Override |
| 71 | protected Store getStore() { | 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 | return store; | 80 | return store; |
| 73 | } | 81 | } |
| 74 | 82 | ||
| 75 | @Override | 83 | @Override |
| 76 | protected boolean isStoreInitialized() { | 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,7 +73,7 @@ public abstract class AbstractThreadLocalContext extends AbstractCustomContext { | ||
| 73 | @Override | 73 | @Override |
| 74 | protected Store getStore() { | 74 | protected Store getStore() { |
| 75 | if (this.threadLocal.get() == null) { | 75 | if (this.threadLocal.get() == null) { |
| 76 | - this.threadLocal.set(createStore()); | 76 | + this.threadLocal.set(createStore(getClass())); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | return this.threadLocal.get(); | 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,6 +60,7 @@ import javax.enterprise.inject.spi.InjectionPoint; | ||
| 60 | 60 | ||
| 61 | import org.slf4j.Logger; | 61 | import org.slf4j.Logger; |
| 62 | 62 | ||
| 63 | +import br.gov.frameworkdemoiselle.annotation.Priority; | ||
| 63 | import br.gov.frameworkdemoiselle.context.ConversationContext; | 64 | import br.gov.frameworkdemoiselle.context.ConversationContext; |
| 64 | import br.gov.frameworkdemoiselle.context.CustomContext; | 65 | import br.gov.frameworkdemoiselle.context.CustomContext; |
| 65 | import br.gov.frameworkdemoiselle.context.RequestContext; | 66 | import br.gov.frameworkdemoiselle.context.RequestContext; |
| @@ -133,7 +134,7 @@ public class CustomContextProducer { | @@ -133,7 +134,7 @@ public class CustomContextProducer { | ||
| 133 | /////////////PRODUCERS/////////////////// | 134 | /////////////PRODUCERS/////////////////// |
| 134 | 135 | ||
| 135 | @Produces | 136 | @Produces |
| 136 | - public RequestContext getRequestContext(InjectionPoint ip){ | 137 | + protected RequestContext getRequestContext(InjectionPoint ip){ |
| 137 | if (ip!=null){ | 138 | if (ip!=null){ |
| 138 | return getContext(ip); | 139 | return getContext(ip); |
| 139 | } | 140 | } |
| @@ -143,7 +144,7 @@ public class CustomContextProducer { | @@ -143,7 +144,7 @@ public class CustomContextProducer { | ||
| 143 | } | 144 | } |
| 144 | 145 | ||
| 145 | @Produces | 146 | @Produces |
| 146 | - public SessionContext getSessionContext(InjectionPoint ip){ | 147 | + protected SessionContext getSessionContext(InjectionPoint ip){ |
| 147 | if (ip!=null){ | 148 | if (ip!=null){ |
| 148 | return getContext(ip); | 149 | return getContext(ip); |
| 149 | } | 150 | } |
| @@ -153,7 +154,7 @@ public class CustomContextProducer { | @@ -153,7 +154,7 @@ public class CustomContextProducer { | ||
| 153 | } | 154 | } |
| 154 | 155 | ||
| 155 | @Produces | 156 | @Produces |
| 156 | - public ViewContext getViewContext(InjectionPoint ip){ | 157 | + protected ViewContext getViewContext(InjectionPoint ip){ |
| 157 | if (ip!=null){ | 158 | if (ip!=null){ |
| 158 | return getContext(ip); | 159 | return getContext(ip); |
| 159 | } | 160 | } |
| @@ -163,7 +164,7 @@ public class CustomContextProducer { | @@ -163,7 +164,7 @@ public class CustomContextProducer { | ||
| 163 | } | 164 | } |
| 164 | 165 | ||
| 165 | @Produces | 166 | @Produces |
| 166 | - public StaticContext getStaticContext(InjectionPoint ip){ | 167 | + protected StaticContext getStaticContext(InjectionPoint ip){ |
| 167 | if (ip!=null){ | 168 | if (ip!=null){ |
| 168 | return getContext(ip); | 169 | return getContext(ip); |
| 169 | } | 170 | } |
| @@ -173,7 +174,7 @@ public class CustomContextProducer { | @@ -173,7 +174,7 @@ public class CustomContextProducer { | ||
| 173 | } | 174 | } |
| 174 | 175 | ||
| 175 | @Produces | 176 | @Produces |
| 176 | - public ConversationContext getConversationContext(InjectionPoint ip){ | 177 | + protected ConversationContext getConversationContext(InjectionPoint ip){ |
| 177 | if (ip!=null){ | 178 | if (ip!=null){ |
| 178 | return getContext(ip); | 179 | return getContext(ip); |
| 179 | } | 180 | } |
| @@ -184,8 +185,17 @@ public class CustomContextProducer { | @@ -184,8 +185,17 @@ public class CustomContextProducer { | ||
| 184 | 185 | ||
| 185 | /////////////END OF PRODUCERS/////////////////// | 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 | @SuppressWarnings("unchecked") | 197 | @SuppressWarnings("unchecked") |
| 188 | - private <T extends CustomContext> T getContext(InjectionPoint ip){ | 198 | + public <T extends CustomContext> T getContext(InjectionPoint ip){ |
| 189 | T producedContext = null; | 199 | T producedContext = null; |
| 190 | 200 | ||
| 191 | if (ip!=null){ | 201 | if (ip!=null){ |
| @@ -200,8 +210,16 @@ public class CustomContextProducer { | @@ -200,8 +210,16 @@ public class CustomContextProducer { | ||
| 200 | return producedContext; | 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 | @SuppressWarnings("unchecked") | 221 | @SuppressWarnings("unchecked") |
| 204 | - private <T extends CustomContext> T getContext(Class<T> contextClass){ | 222 | + public <T extends CustomContext> T getContext(Class<T> contextClass){ |
| 205 | CustomContext producedContext = null; | 223 | CustomContext producedContext = null; |
| 206 | 224 | ||
| 207 | ArrayList<CustomContext> selectableContexts = new ArrayList<CustomContext>(); | 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,13 +41,11 @@ import java.util.HashMap; | ||
| 41 | import java.util.Map; | 41 | import java.util.Map; |
| 42 | 42 | ||
| 43 | import javax.enterprise.context.RequestScoped; | 43 | import javax.enterprise.context.RequestScoped; |
| 44 | -import javax.inject.Inject; | ||
| 45 | import javax.persistence.EntityManager; | 44 | import javax.persistence.EntityManager; |
| 46 | import javax.persistence.FlushModeType; | 45 | import javax.persistence.FlushModeType; |
| 47 | 46 | ||
| 48 | import org.slf4j.Logger; | 47 | import org.slf4j.Logger; |
| 49 | 48 | ||
| 50 | -import br.gov.frameworkdemoiselle.annotation.Name; | ||
| 51 | import br.gov.frameworkdemoiselle.internal.configuration.EntityManagerConfig; | 49 | import br.gov.frameworkdemoiselle.internal.configuration.EntityManagerConfig; |
| 52 | import br.gov.frameworkdemoiselle.internal.configuration.EntityManagerConfig.EntityManagerScope; | 50 | import br.gov.frameworkdemoiselle.internal.configuration.EntityManagerConfig.EntityManagerScope; |
| 53 | import br.gov.frameworkdemoiselle.util.Beans; | 51 | import br.gov.frameworkdemoiselle.util.Beans; |
| @@ -74,19 +72,6 @@ public abstract class AbstractEntityManagerStore implements EntityManagerStore { | @@ -74,19 +72,6 @@ public abstract class AbstractEntityManagerStore implements EntityManagerStore { | ||
| 74 | 72 | ||
| 75 | private final Map<String, EntityManager> cache = Collections.synchronizedMap(new HashMap<String, EntityManager>()); | 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 | public EntityManager getEntityManager(String persistenceUnit) { | 75 | public EntityManager getEntityManager(String persistenceUnit) { |
| 91 | EntityManager entityManager = null; | 76 | EntityManager entityManager = null; |
| 92 | 77 | ||
| @@ -114,6 +99,7 @@ public abstract class AbstractEntityManagerStore implements EntityManagerStore { | @@ -114,6 +99,7 @@ public abstract class AbstractEntityManagerStore implements EntityManagerStore { | ||
| 114 | //Se o produtor não possui escopo, então o ciclo de vida | 99 | //Se o produtor não possui escopo, então o ciclo de vida |
| 115 | //de EntityManager produzidos é responsabilidade do desenvolvedor. Não | 100 | //de EntityManager produzidos é responsabilidade do desenvolvedor. Não |
| 116 | //fechamos os EntityManagers aqui. | 101 | //fechamos os EntityManagers aqui. |
| 102 | + EntityManagerConfig configuration = getConfiguration(); | ||
| 117 | if (configuration.getEntityManagerScope() != EntityManagerScope.NOSCOPE){ | 103 | if (configuration.getEntityManagerScope() != EntityManagerScope.NOSCOPE){ |
| 118 | for (EntityManager entityManager : cache.values()) { | 104 | for (EntityManager entityManager : cache.values()) { |
| 119 | entityManager.close(); | 105 | entityManager.close(); |
| @@ -131,23 +117,18 @@ public abstract class AbstractEntityManagerStore implements EntityManagerStore { | @@ -131,23 +117,18 @@ public abstract class AbstractEntityManagerStore implements EntityManagerStore { | ||
| 131 | } | 117 | } |
| 132 | 118 | ||
| 133 | private EntityManagerFactoryProducer getFactory(){ | 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 | private Logger getLogger(){ | 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 | private ResourceBundle getBundle(){ | 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,8 +117,8 @@ public class EntityManagerProxy implements EntityManager, Serializable { | ||
| 117 | @Override | 117 | @Override |
| 118 | public void persist(Object entity) { | 118 | public void persist(Object entity) { |
| 119 | joinTransactionIfNecessary(); | 119 | joinTransactionIfNecessary(); |
| 120 | - checkEntityManagerScopePassivable(entity); | ||
| 121 | getEntityManagerDelegate().persist(entity); | 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,7 +75,7 @@ public class FacesViewContextImpl extends AbstractCustomContext implements ViewC | ||
| 75 | String key = Store.class.getName(); | 75 | String key = Store.class.getName(); |
| 76 | 76 | ||
| 77 | if (!viewMap.containsKey(key)) { | 77 | if (!viewMap.containsKey(key)) { |
| 78 | - viewMap.put(key, createStore()); | 78 | + viewMap.put(key, createStore( getClass() )); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | return (Store) viewMap.get(key); | 81 | return (Store) viewMap.get(key); |