Author: gk Date: Thu Mar 13 14:28:14 2014 New Revision: 1577174 URL: http://svn.apache.org/r1577174 Log: Added clean cache parameter for serialization methods. This behaviour is only supported at the moment in Jackson 2 API.
Added: turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/TypeAdapterForRectangle.java (with props) Modified: turbine/fulcrum/trunk/json/api/src/java/org/apache/fulcrum/json/JsonService.java turbine/fulcrum/trunk/json/gson/src/java/org/apache/fulcrum/json/gson/GSONBuilderService.java turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/DefaultServiceTest.java turbine/fulcrum/trunk/json/jackson/src/java/org/apache/fulcrum/json/jackson/JacksonMapperService.java turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/SimpleNameIntrospector.java turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/JacksonMapperEnabledDefaultTypingTest.java Modified: turbine/fulcrum/trunk/json/api/src/java/org/apache/fulcrum/json/JsonService.java URL: http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/api/src/java/org/apache/fulcrum/json/JsonService.java?rev=1577174&r1=1577173&r2=1577174&view=diff ============================================================================== --- turbine/fulcrum/trunk/json/api/src/java/org/apache/fulcrum/json/JsonService.java (original) +++ turbine/fulcrum/trunk/json/api/src/java/org/apache/fulcrum/json/JsonService.java Thu Mar 13 14:28:14 2014 @@ -52,6 +52,17 @@ public interface JsonService { * if JSON serialization fails */ String ser(Object src) throws Exception; + + /** + * @param src + * The java object to be serialized. + * @param refreshCache + * If <code>true</code>, try to refresh cache after serialization + * + * For other attributes @see {@link #ser(Object)} + + */ + String ser(Object src, Boolean cleanCache) throws Exception; /** * Serializes a Java object @@ -64,9 +75,20 @@ public interface JsonService { * @return JSON string * * @throws Exception - * if JSON serialization fails + * If JSON serialization fails */ <T> String ser(Object src, Class<T> type) throws Exception; + + /** + * + * @param src + * @param type + * @param refreshCache + * If <code>true</code>, try to clean cache after serialization + * + * For other attributes @see {@link #ser(Object, Class)} + */ + <T> String ser(Object src, Class<T> type, Boolean cleanCache) throws Exception; /** * Deserializing a JSON string @@ -103,21 +125,21 @@ public interface JsonService { /** * @see #serializeOnlyFilter(Object, Class, Boolean, String...). * - * <code>refreshFilter</code> is <code>false</code>. + * <code>refreshFilter</code> is set to <code>false</code> for this method call. */ public <T> String serializeOnlyFilter(Object src, Class<T> filterClass, String... filterAttr) throws Exception; /** - * Serialize only object properties where filters attributes are provided + * Serialize only object properties where filter attributes are provided * * @param src * The Java object to serialize * @param filterClass * The class to which the filtering should be applied * - * @param refreshFilter - * refresh filter (clean cache for this filterClass) + * @param cleanFilter + * clean filter (clean cache for this filterClass) if <code>true</code>, after serialization. * * @param filterAttr * The class bean attributes which should be serialized @@ -127,7 +149,7 @@ public interface JsonService { * @throws Exception * if JSON serialization or filter registration fails */ - public <T> String serializeOnlyFilter(Object src, Class<T> filterClass, Boolean refreshFilter, + public <T> String serializeOnlyFilter(Object src, Class<T> filterClass, Boolean cleanFilter, String... filterAttr) throws Exception; /** @@ -139,8 +161,8 @@ public interface JsonService { * The class to which the filtering should be applied. If its the * same class, just the filterAttributes get applied. If not the * class is filtered out, if found as a property type. - * @param refreshFilter - * refresh filter (clean cache for this filterClass) + * @param cleanFilter + * refresh filter (clean cache for this filterClass) after serialization. * * @param filterAttr * The bean attributes which should not be serialized @@ -151,7 +173,7 @@ public interface JsonService { * if JSON serialization or filter registration fails */ public <T> String serializeAllExceptFilter(Object src, - Class<T> filterClass, Boolean refreshFilter, String... filterAttr) throws Exception; + Class<T> filterClass, Boolean cleanFilter, String... filterAttr) throws Exception; /** * @see #serializeAllExceptFilter(Object, Class, Boolean, String...) @@ -182,9 +204,9 @@ public interface JsonService { throws Exception; /** - * Adds an adapter (mixin, serializer,..) for the target class depending on + * Add an adapter (mixin, serializer,..) for the target class depending on * the JsonService implementation. Adapters could by default not deregistered. If you want - * to get rid of it, you have to (@see {@link #reInitService()} (or overwrite with the same target type, depending on + * to get rid of them, you have to (@see {@link #reInitService()} (or overwrite with the same target type, depending on * implementation) * * @param name Modified: turbine/fulcrum/trunk/json/gson/src/java/org/apache/fulcrum/json/gson/GSONBuilderService.java URL: http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/gson/src/java/org/apache/fulcrum/json/gson/GSONBuilderService.java?rev=1577174&r1=1577173&r2=1577174&view=diff ============================================================================== --- turbine/fulcrum/trunk/json/gson/src/java/org/apache/fulcrum/json/gson/GSONBuilderService.java (original) +++ turbine/fulcrum/trunk/json/gson/src/java/org/apache/fulcrum/json/gson/GSONBuilderService.java Thu Mar 13 14:28:14 2014 @@ -28,6 +28,7 @@ import java.util.Date; import java.util.Enumeration; import java.util.HashSet; import java.util.Hashtable; +import java.util.Iterator; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.configuration.Configurable; @@ -38,6 +39,7 @@ import org.apache.fulcrum.json.JsonServi import com.google.gson.ExclusionStrategy; import com.google.gson.FieldAttributes; +import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonElement; import com.google.gson.JsonPrimitive; @@ -104,7 +106,9 @@ public class GSONBuilderService extends @Override public <T> String serializeOnlyFilter(Object src, Class<T> filterClass, String... filterAttr) throws Exception { - throw new Exception("Not yet implemented!"); + return gson + .addSerializationExclusionStrategy( + include(filterClass, filterAttr)).create().toJson(src); } @Override @@ -141,15 +145,26 @@ public class GSONBuilderService extends @Override public <T> String serializeAllExceptFilter(Object src, Class<T> filterClass, String... filterAttr) throws Exception { - return serializeAllExceptFilter(src, filterClass, false, filterAttr); + return gson + .addSerializationExclusionStrategy( + exclude(filterClass, filterAttr)).create().toJson(src); } @Override public <T> String serializeAllExceptFilter(Object src, Class<T> filterClass, - Boolean arg2, String... filterAttr) throws Exception { - return gson - .addSerializationExclusionStrategy( - exclude(filterClass, filterAttr)).create().toJson(src); + Boolean clearCache, String... filterAttr) throws Exception { + throw new Exception("Not yet implemented!"); + } + + @Override + public String ser(Object src, Boolean refreshCache) throws Exception { + throw new Exception("Not implemented!"); + } + + @Override + public <T> String ser(Object src, Class<T> type, Boolean refreshCache) + throws Exception { + throw new Exception("Not implemented!"); } public JsonService registerTypeAdapter(JsonSerializer serdeser, Type type) { @@ -278,5 +293,51 @@ public class GSONBuilderService extends }.init(clazz, filterAttrs); } + private ExclusionStrategy include(Class clazz, String... filterAttrs) { + return new ExclusionStrategy() { + + private Class<?> includeThisClass; + private HashSet<String> includedAttributes; + + private ExclusionStrategy init(Class<?> includeThisClass, + String... filterAttrs) { + this.includeThisClass = includeThisClass; + if (filterAttrs != null) { + this.includedAttributes = new HashSet<String>( + filterAttrs.length); + getLogger().debug(" ... adding includedAttributes:" + filterAttrs.length); + Collections.addAll(this.includedAttributes, filterAttrs); + for (String includedAttribute : includedAttributes) { + getLogger().debug("includedAttribute:" +includedAttribute); + } + } else + this.includedAttributes = new HashSet<String>(); + + return this; + } + + /** + * skip is current class is not equal provided class + */ + @Override + public boolean shouldSkipClass(Class<?> clazz) { + getLogger().debug(includeThisClass+ ": comparing include class:" + clazz); + return (includeThisClass != null) ? !includeThisClass + .equals(clazz) : false; + } + + /** + * skip if current field attribute is not included are skip else + */ + @Override + public boolean shouldSkipField(FieldAttributes paramFieldAttributes) { + return (!includedAttributes.isEmpty()) ? !this.includedAttributes + .contains(paramFieldAttributes.getName()) : true; + + } + }.init(clazz, filterAttrs); + } + + } Modified: turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/DefaultServiceTest.java URL: http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/DefaultServiceTest.java?rev=1577174&r1=1577173&r2=1577174&view=diff ============================================================================== --- turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/DefaultServiceTest.java (original) +++ turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/DefaultServiceTest.java Thu Mar 13 14:28:14 2014 @@ -206,6 +206,45 @@ public class DefaultServiceTest extends .get(i).getSize()); } } + + public void testSerializeWithMixinAndFilter2() throws Exception { + Rectangle filteredRectangle = new Rectangle(5, 10); + filteredRectangle.setName("jim"); + // + sc.addAdapter("M4RMixin2", Rectangle.class, + TypeAdapterForRectangle.class); + + // as gson adds all kind, we could not easiy use multiple strategies + String rectangle = sc.ser(filteredRectangle); + assertEquals( + "Ser filtered Rectangle failed ", + "{\"name\":\"jim\",\"width\":5}", + rectangle); + } + + public void testSerializeWithMixinAndFilter3() throws Exception { + + // as gson adds we could not use multiple disjunct exclusion strategies + String serJson = sc.serializeOnlyFilter(new TestClass("mytest"), + (Class) null, "configurationName"); + assertEquals("Serialization failed ", + "{\"configurationName\":\"Config.xml\"}", + serJson); + } + + public void testSerializeWithMixinAndFilter4() throws Exception { + + // as gson adds we could not use multiple disjunct exclusion strategies + Rectangle filteredRectangle = new Rectangle(5, 10); + filteredRectangle.setName("jim"); + String rectangle = sc.serializeOnlyFilter(filteredRectangle, (Class) null, "w"); + assertEquals( + "Ser filtered Rectangle failed ", + "{\"w\":5}", + rectangle); + + } + } Added: turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/TypeAdapterForRectangle.java URL: http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/TypeAdapterForRectangle.java?rev=1577174&view=auto ============================================================================== --- turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/TypeAdapterForRectangle.java (added) +++ turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/TypeAdapterForRectangle.java Thu Mar 13 14:28:14 2014 @@ -0,0 +1,25 @@ +package org.apache.fulcrum.json.gson; + +import java.lang.reflect.Type; + +import org.apache.fulcrum.json.Rectangle; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +public class TypeAdapterForRectangle implements JsonSerializer<Rectangle> { + + @Override + public JsonElement serialize(Rectangle src, Type typeOfSrc, + JsonSerializationContext context) { + final JsonObject jsonObject = new JsonObject(); + jsonObject.addProperty("name", src.getName()); + jsonObject.addProperty("width", src.getW()); + // ignore rest + return jsonObject; + } + + +} Propchange: turbine/fulcrum/trunk/json/gson/src/test/org/apache/fulcrum/json/gson/TypeAdapterForRectangle.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: turbine/fulcrum/trunk/json/jackson/src/java/org/apache/fulcrum/json/jackson/JacksonMapperService.java URL: http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson/src/java/org/apache/fulcrum/json/jackson/JacksonMapperService.java?rev=1577174&r1=1577173&r2=1577174&view=diff ============================================================================== --- turbine/fulcrum/trunk/json/jackson/src/java/org/apache/fulcrum/json/jackson/JacksonMapperService.java (original) +++ turbine/fulcrum/trunk/json/jackson/src/java/org/apache/fulcrum/json/jackson/JacksonMapperService.java Thu Mar 13 14:28:14 2014 @@ -91,6 +91,23 @@ public class JacksonMapperService extend @Override public synchronized String ser(Object src) throws Exception { + return ser(src, false); + } + + @Override + public <T> String ser(Object src, Class<T> type) throws Exception { + return ser(src, type, false); + } + + public synchronized <T> String ser(Object src, FilterProvider filters) + throws Exception { + getLogger().debug("ser::" + src + " with filters " + filters); + String serResult = mapper.writer(filters).writeValueAsString(src); + return serResult; + } + + @Override + public String ser(Object src, Boolean cleanCache) throws Exception { if (filters.containsKey(src.getClass().getName())) { getLogger().warn( "Found registered filter - using instead of default view filter for class:" @@ -103,7 +120,8 @@ public class JacksonMapperService extend } @Override - public <T> String ser(Object src, Class<T> type) throws Exception { + public <T> String ser(Object src, Class<T> type, Boolean cleanCache) + throws Exception { getLogger().debug("ser::" + src + " with type" + type); if (filters.containsKey(src.getClass().getName())) { getLogger() @@ -116,13 +134,6 @@ public class JacksonMapperService extend return mapper.writerWithView(type).writeValueAsString(src); } - public synchronized <T> String ser(Object src, FilterProvider filters) - throws Exception { - getLogger().debug("ser::" + src + " with filters " + filters); - String serResult = mapper.writer(filters).writeValueAsString(src); - return serResult; - } - @Override public <T> T deSer(String src, Class<T> type) throws Exception { ObjectReader reader = mapper.reader(type); Modified: turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java URL: http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java?rev=1577174&r1=1577173&r2=1577174&view=diff ============================================================================== --- turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java (original) +++ turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/Jackson2MapperService.java Thu Mar 13 14:28:14 2014 @@ -23,12 +23,10 @@ import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Collection; -import java.util.Collections; import java.util.Enumeration; -import java.util.HashMap; import java.util.Hashtable; -import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import org.apache.avalon.framework.activity.Initializable; import org.apache.avalon.framework.configuration.Configurable; @@ -112,44 +110,34 @@ public class Jackson2MapperService exten @Override public String ser(Object src) throws Exception { - if (filters.containsKey(src.getClass().getName())) { - getLogger().warn( - "Found registered filter - using instead of default view filter for class:" - + src.getClass().getName()); - // throw new - // Exception("Found registered filter - could not use custom view and custom filter for class:"+ - // src.getClass().getName()); - } - return mapper.writerWithView(Object.class).writeValueAsString(src); - // return mapper.writer().writeValueAsString(src); + return ser(src, false); } @Override public <T> String ser(Object src, Class<T> type) throws Exception { - getLogger().info("serializing object:" + src + " for type "+ type); - if (src != null && filters.containsKey(src.getClass().getName())) { - getLogger() - .warn("Found registered filter - could not use custom view and custom filter for class:" - + src.getClass().getName()); - // throw new - // Exception("Found registered filter - could not use custom view and custom filter for class:"+ - // src.getClass().getName()); - } - return (type != null)? mapper.writerWithView(type).writeValueAsString(src): mapper.writeValueAsString(src); + return ser(src, type, false); } - public <T> String ser(Object src, FilterProvider filters) throws Exception { + public <T> String ser(Object src, FilterProvider filter) throws Exception { + return ser(src, filter, false); + } + + public <T> String ser(Object src, FilterProvider filter, Boolean cleanCache) throws Exception { String serResult= null; if (src == null) { getLogger().info("no serializable object:" + src); return serResult; } - if (filters == null) { - getLogger().debug("ser class::" + src.getClass() + " without filters" +filters); + if (filter == null) { + getLogger().debug("ser class::" + src.getClass() + " without filter " +filter); return ser(src); } - getLogger().debug("ser class::" + src.getClass() + " with filters " + filters); - return mapper.writer(filters).writeValueAsString(src); + getLogger().debug("ser class::" + src.getClass() + " with filter " + filter); + String res = mapper.writer(filter).writeValueAsString(src); + if (cleanCache) { + cleanSerializerCache(); + } + return res; } @Override @@ -174,20 +162,33 @@ public class Jackson2MapperService exten public void getJsonService() throws InstantiationException { } + /** + * @param name name of the module + * @param target target class + * @param mixin provide mixin as class. + * Deregistering module could be only done by setting this parameter to null. + * + * @see #addAdapter(String, Class, Object) + */ @Override public JsonService addAdapter(String name, Class target, Class mixin) throws Exception { Module mx = new MixinModule(name, target, mixin); - getLogger().debug("registering module " + mx + " for: " + mixin); + getLogger().debug("registering unversioned simple mixin module named " + name + " of type " + mixin + " for: " + target); mapper.registerModule(mx); return this; } /** + * Add a named module + * + * @param name name of the module + * + * @param target target class * * @param module * Either an Jackson Module @link {@link Module} or an custom - * wrapper @link CustomModuleWrapper. + * wrapper @link CustomModuleWrapper. * * @see JsonService#addAdapter(String, Class, Object) */ @@ -198,7 +199,7 @@ public class Jackson2MapperService exten CustomModuleWrapper cmw = (CustomModuleWrapper) module; Module cm = new CustomModule(name, target, cmw.getSer(), cmw.getDeSer()); - getLogger().debug("registering module " + cm + " for: " + target); + getLogger().debug("registering custom module " + cm + " for: " + target); mapper.registerModule(cm); } else if (module instanceof Module) { getLogger().debug( @@ -225,12 +226,12 @@ public class Jackson2MapperService exten } public synchronized <T> String serializeAllExceptFilter(Object src, - Class<T> filterClass, Boolean refresh, String... filterAttr) throws Exception { + Class<T> filterClass, Boolean clean, String... filterAttr) throws Exception { FilterContext fc = new FilterContext(); if (filterAttr != null) fc.setFilter(SimpleBeanPropertyFilter .serializeAllExcept(filterAttr)); - return filter(src, filterClass, fc, refresh, filterAttr); + return filter(src, filterClass, fc, clean, filterAttr); } @Override @@ -243,13 +244,58 @@ public class Jackson2MapperService exten public synchronized <T> String serializeOnlyFilter(Object src, Class<T> filterClass, Boolean refresh, String... filterAttr) throws Exception { FilterContext fc = new FilterContext(); - if (filterAttr != null && filterAttr.length > 0) + if (filterAttr != null && filterAttr.length > 0) { fc.setFilter(SimpleBeanPropertyFilter.filterOutAllExcept(filterAttr)); + getLogger().debug("setting filteroutAllexcept filter for size of filterAttr: " + filterAttr.length); + } return filter(src, filterClass, fc, refresh, filterAttr); } + + @Override + public String ser(Object src, Boolean cleanCache) throws Exception { + if (filters.containsKey(src.getClass().getName())) { + getLogger().warn( + "Found registered filter - using instead of default view filter for class:" + + src.getClass().getName()); + // throw new + // Exception("Found registered filter - could not use custom view and custom filter for class:"+ + // src.getClass().getName()); + SimpleFilterProvider filter = (SimpleFilterProvider) this.filters.get(src.getClass() + .getName()); + return ser(src, filter);//mapper.writerWithView(src.getClass()).writeValueAsString(src); + } + String res = mapper.writerWithView(Object.class).writeValueAsString(src); + if (cleanCache) { + cleanSerializerCache(); + } + return res; + } + + @Override + public <T> String ser(Object src, Class<T> type, Boolean cleanCache) + throws Exception { + getLogger().info("serializing object:" + src + " for type "+ type); + if (src != null && filters.containsKey(src.getClass().getName())) { + getLogger() + .warn("Found registered filter - could not use custom view and custom filter for class:" + + src.getClass().getName()); + // throw new + // Exception("Found registered filter - could not use custom view and custom filter for class:"+ + // src.getClass().getName()); + SimpleFilterProvider filter = (SimpleFilterProvider) this.filters.get(src.getClass() + .getName()); + return ser(src, filter); + } + + String res = (type != null)? mapper.writerWithView(type).writeValueAsString(src): mapper.writeValueAsString(src); + if (cleanCache) { + cleanSerializerCache(); + } + return res; + } private <T> String filter(Object src, Class<T> filterClass, - FilterContext fc, boolean refresh, String... filterAttr) throws Exception { + FilterContext fc, boolean clean, String... filterAttr) throws Exception { FilterProvider filter = null; if (src != null) { filter = checkFilter(fc, src.getClass(), filterClass, @@ -257,7 +303,7 @@ public class Jackson2MapperService exten } getLogger().info("filtering with filter "+ filter); String serialized = ser(src, filter); - if (!cacheFilters || refresh) { + if (!cacheFilters || clean) { removeFilter(filterClass); if (src != null) removeFilter(src.getClass()); } @@ -282,7 +328,7 @@ public class Jackson2MapperService exten private <T> SimpleFilterProvider retrieveFilter(SimpleFilterProvider filter, FilterContext fc, Class<T> filterClass, String... filterAttr) { if (!this.filters.containsKey(filterClass.getName())) { - getLogger().debug("add filter for class" + filterClass.getName()); + getLogger().debug("add filter for class " + filterClass.getName()); if (fc.getFilter() != null) { filter.addFilter(filterClass.getName(), fc.getFilter()); } @@ -308,22 +354,26 @@ public class Jackson2MapperService exten .get(filterClass.getName()); smpfilter.removeFilter(filterClass.getName()); this.filters.remove(filterClass.getName()); - if (mapper.getSerializerProvider() instanceof DefaultSerializerProvider) { - int cachedSerProvs = ((DefaultSerializerProvider) mapper - .getSerializerProvider()).cachedSerializersCount(); - if (cachedSerProvs > 0) { - getLogger() - .debug("flushing cachedSerializersCount:" - + cachedSerProvs); - ((DefaultSerializerProvider) mapper.getSerializerProvider()) - .flushCachedSerializers(); - } - } + cleanSerializerCache(); getLogger().debug( "removed from SimpleFilterProvider filters " + filterClass.getName()); } } + + private void cleanSerializerCache() { + if (mapper.getSerializerProvider() instanceof DefaultSerializerProvider) { + int cachedSerProvs = ((DefaultSerializerProvider) mapper + .getSerializerProvider()).cachedSerializersCount(); + if (cachedSerProvs > 0) { + getLogger() + .debug("flushing cachedSerializersCount:" + + cachedSerProvs); + ((DefaultSerializerProvider) mapper.getSerializerProvider()) + .flushCachedSerializers(); + } + } + } private <T> void setCustomIntrospectorWithExternalFilterId( Class<T> externalFilterId) { @@ -588,8 +638,7 @@ public class Jackson2MapperService exten mapper.setDateFormat(new SimpleDateFormat(dateFormat)); - filters = Collections - .synchronizedMap(new HashMap<String, FilterProvider>()); + filters = new ConcurrentHashMap<String, FilterProvider>(); getLogger().debug("initialized mapper:" + mapper); mapper.getSerializerProvider().setNullValueSerializer( @@ -665,6 +714,5 @@ public class Jackson2MapperService exten .constructCollectionType(((Collection<T>)collectionType).getClass(), elementType)); } - } - + } } Modified: turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/SimpleNameIntrospector.java URL: http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/SimpleNameIntrospector.java?rev=1577174&r1=1577173&r2=1577174&view=diff ============================================================================== --- turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/SimpleNameIntrospector.java (original) +++ turbine/fulcrum/trunk/json/jackson2/src/java/org/apache/fulcrum/json/jackson/SimpleNameIntrospector.java Thu Mar 13 14:28:14 2014 @@ -19,9 +19,8 @@ package org.apache.fulcrum.json.jackson; * under the License. */ -import java.util.ArrayList; -import java.util.Collections; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; import com.fasterxml.jackson.databind.introspect.AnnotatedClass; import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector; @@ -38,8 +37,7 @@ import com.fasterxml.jackson.databind.se * */ public class SimpleNameIntrospector extends JacksonAnnotationIntrospector { - public List<String> externalFilterClasses = Collections - .synchronizedList(new ArrayList()); + public List<String> externalFilterClasses = new CopyOnWriteArrayList<String>(); /** * Filtering on method types @@ -98,11 +96,9 @@ public class SimpleNameIntrospector exte } public void removeExternalFilterClass(Class externalFilterClass) { - synchronized(externalFilterClasses) { if (externalFilterClasses.contains(externalFilterClass.getName())) { externalFilterClasses.remove(externalFilterClass.getName()); } - } } } \ No newline at end of file Modified: turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/JacksonMapperEnabledDefaultTypingTest.java URL: http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/JacksonMapperEnabledDefaultTypingTest.java?rev=1577174&r1=1577173&r2=1577174&view=diff ============================================================================== --- turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/JacksonMapperEnabledDefaultTypingTest.java (original) +++ turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/JacksonMapperEnabledDefaultTypingTest.java Thu Mar 13 14:28:14 2014 @@ -200,16 +200,77 @@ public class JacksonMapperEnabledDefault Rectangle filteredRectangle = new Rectangle(5, 10); filteredRectangle.setName("jim"); - String serRect = sc.addAdapter("M4RMixin2", Rectangle.class, + String serRect = sc.addAdapter("M4RMixin2", Rectangle.class, Mixin2.class).ser(filteredRectangle); assertEquals("Ser failed ", "{\"name\":\"jim\",\"width\":5}", serRect); - String bean = sc.serializeOnlyFilter(filteredBean, Bean.class, "name"); + // + String bean = sc.addAdapter("M4RBeanMixin", Bean.class, + BeanMixin.class).ser(filteredBean);; + assertEquals( "Ser filtered Bean failed ", "{\"type\":\"org.apache.fulcrum.json.jackson.JacksonMapperEnabledDefaultTypingTest$Bean\",\"name\":\"joe\"}", bean); } + + public void testSerializeWithMixinAndFilter() throws Exception { + Bean filteredBean = new Bean(); + filteredBean.setName("joe"); + // + sc.addAdapter("M4RBeanMixin", Bean.class, + BeanMixin.class); + // profession was already set to ignore, does not change + String bean = sc.serializeOnlyFilter(filteredBean, Bean.class, "profession"); + assertEquals( + "Ser filtered Bean failed ", + "{\"type\":\"org.apache.fulcrum.json.jackson.JacksonMapperEnabledDefaultTypingTest$Bean\"}", + bean); + } + + public void testSerializeWithUnregisteredMixinAndFilter() throws Exception { + Bean filteredBean = new Bean(); + filteredBean.setName("joe"); + // + sc.addAdapter("M4RBeanMixin", Bean.class, + BeanMixin.class) + .addAdapter("M4RBeanMixin", Bean.class, + null); + // now profession is used after cleaning adapter + String bean = sc.serializeOnlyFilter(filteredBean, Bean.class, "profession"); + assertEquals( + "Ser filtered Bean failed ", + "{\"type\":\"org.apache.fulcrum.json.jackson.JacksonMapperEnabledDefaultTypingTest$Bean\",\"profession\":\"\"}", + bean); + } + + public void testSerializeWithMixinAndFilter2() throws Exception { + Rectangle filteredRectangle = new Rectangle(5, 10); + filteredRectangle.setName("jim"); + // + sc.addAdapter("M4RMixin2", Rectangle.class, + Mixin2.class); + + // if serialization is done this way, filtering has no effect. + // this is may be a bug in Jackson: as mixin modules may be cached..? + String rectangle0 = sc.ser(filteredRectangle,Rectangle.class,true); + assertEquals( + "Ser filtered Rectangle failed ", + "{\"name\":\"jim\",\"width\":5}", + rectangle0); + // filtering out name, using width from mixin2 as a second filter + String rectangle = sc.serializeOnlyFilter(filteredRectangle, Rectangle.class, true, "width"); + assertEquals( + "Ser filtered Rectangle failed ", + "{\"width\":5}", + rectangle); + // default for mixin + String rectangle1 = sc.ser(filteredRectangle); + assertEquals( + "Ser filtered Rectangle failed ", + "{\"name\":\"jim\",\"width\":5}", + rectangle1); + } public void testSerializationCollectionWithMixin() throws Exception {