Author: gk
Date: Wed Apr 13 12:54:05 2016
New Revision: 1738932
URL: http://svn.apache.org/viewvc?rev=1738932&view=rev
Log:
- fix to allow java 6 for Json mapper
- check custom mapper context and add concurrent test
- make service more consistent
Added:
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/concurrent/
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/concurrent/JSONConcurrentTest.java
(with props)
Modified:
turbine/fulcrum/trunk/json/jackson2/pom.xml
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/DefaultServiceTest.java
Modified: turbine/fulcrum/trunk/json/jackson2/pom.xml
URL:
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/pom.xml?rev=1738932&r1=1738931&r2=1738932&view=diff
==============================================================================
--- turbine/fulcrum/trunk/json/jackson2/pom.xml (original)
+++ turbine/fulcrum/trunk/json/jackson2/pom.xml Wed Apr 13 12:54:05 2016
@@ -100,11 +100,14 @@
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-json-org</artifactId>
- <version>${jackson2.version}</version>
+ <!-- 2.7.3 is not compiled/compatible with Java 6 support, version
51 error, bug? -->
+ <!--version>${jackson2.version}</version-->
+ <version>2.6.6</version>
<optional>true</optional>
</dependency>
</dependencies>
<properties>
+ <!-- 2.7.x hase Java 7 baseline, but copmiled with Java 6 support,
cft. https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.7 -->
<jackson2.version>2.7.3</jackson2.version>
</properties>
</project>
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=1738932&r1=1738931&r2=1738932&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
Wed Apr 13 12:54:05 2016
@@ -137,7 +137,13 @@ public class Jackson2MapperService exten
if (filter == null) {
getLogger().debug("ser class::" + src.getClass() + " without
filter.");
return ser(src);
- }
+ } else {
+ getLogger().debug("add filter for cache filter Class " +
src.getClass().getName());
+ setCustomIntrospectorWithExternalFilterId(src.getClass(), null);
// filter class
+ if (filter != null) {
+ cacheService.getFilters().put(src.getClass().getName(),
filter);
+ }
+ }
getLogger().debug("ser class::" + src.getClass() + " with filter " +
filter);
mapper.setFilterProvider(filter);
String res = mapper.writer(filter).writeValueAsString(src);
@@ -286,14 +292,26 @@ public class Jackson2MapperService exten
return serializeAllExceptFilter(src, new Class[] {filterClass},
cleanFilter, filterAttr);
}
+ /**
+ *
+ * @param src the object to be serailized, may be a list
+ * @param filterClasses the same object class or a detail class, which
should be filtered
+ * @param clean cleaning the cache after serialization
+ * @param filterAttr attributes to be filtered for filtered class
+ * @return the serailized string
+ * @throws Exception
+ */
public synchronized <T> String serializeAllExceptFilter(Object src,
Class<T>[] filterClasses, Boolean clean, String... filterAttr)
throws Exception {
PropertyFilter pf = null;
if (filterAttr != null)
pf = SimpleBeanPropertyFilter.serializeAllExcept(filterAttr);
- else if (filterClasses == null) //no filter
- return ser(src, clean);
- return filter(src, new Class<?>[] { src.getClass() }, filterClasses,
pf, clean);
+ else if (filterClasses == null) { //no filter
+ return ser(src, clean);
+ // should be better:
+ //return filter(src, new Class<?>[] { src.getClass() },
filterClasses, pf, clean);
+ }
+ return filter(src, new Class<?>[] { filterClasses[0] }, filterClasses,
pf, clean);
}
@Override
@@ -347,6 +365,8 @@ public class Jackson2MapperService exten
SimpleFilterProvider filter = (SimpleFilterProvider)
cacheService.getFilters().get(src.getClass()
.getName());
return ser(src, filter,
cleanCache);//mapper.writerWithView(src.getClass()).writeValueAsString(src);
+ } else {
+
}
String res =
mapper.writerWithView(Object.class).writeValueAsString(src);
if (cleanCache != null && cleanCache) {
@@ -383,7 +403,7 @@ public class Jackson2MapperService exten
* @param src The source Object to be filtered.
* @param filterClass This Class array contains at least one element. If
no class is provided it is the class type of the source object.
* The filterClass is to become the key of the filter object cache.
- * @param excludeClasses The classes to be excluded, optionally used onlz
for methods like {@link #serializeAllExceptFilter(Object, Class[], String...)}.
+ * @param excludeClasses The classes to be excluded, optionally used only
for methods like {@link #serializeAllExceptFilter(Object, Class[], String...)}.
* @param pf Expecting a property filter from e.g @link {@link
SimpleBeanPropertyFilter}.
* @param clean if <code>true</code> does not reuse the filter object (no
cashing).
* @return The serialized Object as String
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=1738932&r1=1738931&r2=1738932&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
Wed Apr 13 12:54:05 2016
@@ -51,6 +51,7 @@ public class SimpleNameIntrospector exte
private List<Class<?>> filteredClasses = new
CopyOnWriteArrayList<Class<?>>();
private List<String> externalFilterExcludeClasses = new
CopyOnWriteArrayList<String>();
private List<String> externalFilterIncludeClasses = new
CopyOnWriteArrayList<String>();
+ // is used only for filtering by class
private AtomicBoolean isExludeType = new AtomicBoolean(false);
private static Logger logger;
Modified:
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/DefaultServiceTest.java
URL:
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/DefaultServiceTest.java?rev=1738932&r1=1738931&r2=1738932&view=diff
==============================================================================
---
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/DefaultServiceTest.java
(original)
+++
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/DefaultServiceTest.java
Wed Apr 13 12:54:05 2016
@@ -40,10 +40,17 @@ import org.junit.Before;
import org.junit.Test;
import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.AnnotationIntrospector;
import com.fasterxml.jackson.databind.MappingJsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
+import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
+import com.fasterxml.jackson.databind.ser.PropertyFilter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
/**
* Jackson 2 JSON Test
@@ -67,16 +74,82 @@ public class DefaultServiceTest extends
assertEquals("Serialization failed ", preDefinedOutput, serJson);
}
-// @Test
-// public void testCustomMapperSerialize() throws Exception {
-// ObjectMapper objectMapper = new ObjectMapper(
-// new MappingJsonFactory(((Jackson2MapperService)
sc).getMapper()));
-// objectMapper.enableDefaultTypingAsProperty(
-// DefaultTyping.NON_FINAL, "type");
-// ((Jackson2MapperService) sc).setMapper(objectMapper);
-// String serJson = sc.ser(new TestClass("mytest"));
-// assertEquals("Serialization with custom mapper failed ",
JacksonMapperEnabledDefaultTypingTest.preDefinedOutput, serJson);
-// }
+ @Test
+ public void testCustomSerializeWithoutServiceMapper() throws Exception {
+ ObjectMapper objectMapper = customMapper(true);
+ String expected =
"{\"type\":\"org.apache.fulcrum.json.TestClass\",\"container\":{\"type\":\"java.util.HashMap\",\"cf\":\"Config.xml\"},\"configurationName\":\"Config.xml\"}";
+ String serJson = customAllExceptFilter(objectMapper, new
TestClass("mytest"), TestClass.class,"name");
+ System.out.println("serJson:"+ serJson);
+ assertEquals("Serialization with custom mapper failed ",expected,
serJson);
+ }
+
+ private ObjectMapper customMapper(boolean withType) {
+ // inheriting Jackson2MapperService mapper does not get the configs,
+ // but has e.g. JsonFactory.Feature fields
+ ObjectMapper objectMapper = new ObjectMapper(
+ new MappingJsonFactory(((Jackson2MapperService)
sc).getMapper()));
+ // use other configuration
+ if (withType) objectMapper.enableDefaultTypingAsProperty(
+ DefaultTyping.NON_FINAL, "type");
+ AnnotationIntrospector ai =
objectMapper.getSerializationConfig().getAnnotationIntrospector();
+ // AnnotationIntrospector is by default JacksonAnnotationIntrospector
+ assertTrue("Expected Default JacksonAnnotationIntrospector", "ai:"+ ai
!= null && ai instanceof JacksonAnnotationIntrospector);
+ // add to allow filtering properties for non annotated class
+ AnnotationIntrospector siai = new SimpleNameIntrospector();
+ AnnotationIntrospector pair = new AnnotationIntrospectorPair(siai,ai);
+ objectMapper.setAnnotationIntrospector(pair);
+ return objectMapper;
+ }
+
+ private String customAllExceptFilter(ObjectMapper objectMapper, Object
target, Class<?> filterClass, String... props) throws JsonProcessingException {
+ PropertyFilter pf =
SimpleBeanPropertyFilter.SerializeExceptFilter.serializeAllExcept(props);
+ SimpleFilterProvider filter = new SimpleFilterProvider();
+ filter.setDefaultFilter(pf);
+ // we know thats a pair, and the second is our simple
+ Collection<AnnotationIntrospector> ais =
((AnnotationIntrospectorPair)objectMapper.getSerializationConfig().getAnnotationIntrospector()).allIntrospectors();
+ for (AnnotationIntrospector ai : ais) {
+ if (ai instanceof SimpleNameIntrospector) {
+ //activate filtering
+ ((SimpleNameIntrospector) ai).setFilteredClasses(filterClass);
+ }
+ }
+ // alternatively we could have set it here, if ref is still available
+ // ((SimpleNameIntrospector) siai).setFilteredClasses(filterClass);
+ String serJson =
objectMapper.writer(filter).writeValueAsString(target);
+ // alternatively
+ //String serJson2 =
objectMapper.setFilterProvider(filter).writeValueAsString(new
TestClass("mytest"));;
+ //assertEquals(serJson, serJson2);
+ return serJson;
+ }
+
+ @Test
+ public void testCustomSerializeListWithoutServiceMapper() throws Exception
{
+ String expected = "[{\"age\":0},{\"age\":1},{\"age\":2}]";
+ List<Bean> beanList = new ArrayList<Bean>();
+ for (int i = 0; i < 3; i++) {
+ Bean bean = new Bean();
+ bean.setAge(i);bean.setName("bean"+i);
+ beanList.add(bean);
+ }
+ ObjectMapper objectMapper = customMapper(false);
+ String serJson = customAllExceptFilter(objectMapper, beanList,
Bean.class,"name","profession");
+ System.out.println("serJson:"+ serJson);
+ assertEquals("Serialization with custom mapper failed ",expected,
serJson);
+ }
+
+ @Test
+ public void testSerializeList() throws Exception {
+ String expected = "[{\"age\":0},{\"age\":1},{\"age\":2}]";
+ List<Bean> beanList = new ArrayList<Bean>();
+ for (int i = 0; i < 3; i++) {
+ Bean bean = new Bean();
+ bean.setAge(i);bean.setName("bean"+i);
+ beanList.add(bean);
+ }
+ String serJson = sc.serializeAllExceptFilter(beanList, Bean.class,
"name","profession");
+ System.out.println("serJsonByService:"+ serJson);
+ assertEquals("Serialization with service mapper failed",expected,
serJson);
+ }
@Test
// the default test class: one String field, one Map
Added:
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/concurrent/JSONConcurrentTest.java
URL:
http://svn.apache.org/viewvc/turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/concurrent/JSONConcurrentTest.java?rev=1738932&view=auto
==============================================================================
---
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/concurrent/JSONConcurrentTest.java
(added)
+++
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/concurrent/JSONConcurrentTest.java
Wed Apr 13 12:54:05 2016
@@ -0,0 +1,243 @@
+package org.apache.fulcrum.json.jackson.concurrent;
+
+import static org.hamcrest.core.Is.is;
+import static org.hamcrest.core.IsNot.not;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.avalon.framework.component.ComponentException;
+import org.apache.fulcrum.json.JsonService;
+import org.apache.fulcrum.json.jackson.Bean;
+import org.apache.fulcrum.json.jackson.Jackson2MapperService;
+import org.apache.fulcrum.json.jackson.SimpleNameIntrospector;
+import org.apache.fulcrum.testcontainer.BaseUnit4Test;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.ParallelComputer;
+import org.junit.runner.JUnitCore;
+import org.junit.runner.Result;
+import org.junit.runner.notification.Failure;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.AnnotationIntrospector;
+import com.fasterxml.jackson.databind.MappingJsonFactory;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping;
+import com.fasterxml.jackson.databind.introspect.AnnotationIntrospectorPair;
+import com.fasterxml.jackson.databind.ser.PropertyFilter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
+import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;
+
+public class JSONConcurrentTest extends BaseUnit4Test
+{
+
+ private static final long TIMEOUT = 15;
+ private static volatile Thread fOne = null;
+ private static volatile Thread fTwo = null;
+ private static volatile Thread fThree = null;
+ private static JsonService jsonService = null;
+
+
+//
+ public JSONConcurrentTest( )
+ throws Exception {}
+
+
+ @BeforeClass
+ public static void setUp() throws Exception
+ {
+
+ }
+
+ @Before
+ public void init() throws ComponentException {
+ fOne = null;
+ fTwo = null;
+ fThree = null;
+ jsonService = (JsonService) this.lookup(JsonService.ROLE);
+ }
+
+ public static class JSONBeansTests extends BaseUnit4Test {
+
+ private static volatile CountDownLatch fSynchronizer;
+ static int N = 3;// number of concurrent test methods = methods
+
+
+ @Before
+ public void init() throws ComponentException {
+
+ fSynchronizer = new CountDownLatch(N);
+ }
+ @Test
+ public void one() throws InterruptedException {
+ String result = doJob("name");
+ assertTrue("Result does contain type", !result.contains(
"org.apache.fulcrum.json.jackson.Bean" ) );
+ assertTrue("Result does contain type", !result.contains(
"java.util.ArrayList" ) );
+ fSynchronizer.countDown();
+ assertTrue("waiting failed", fSynchronizer.await(TIMEOUT,
TimeUnit.SECONDS));
+ fOne = Thread.currentThread();
+ }
+
+ @Test
+ public void two() throws InterruptedException {
+ String result = doJob( "name", "age");
+
+ assertTrue("Result does contain type", !result.contains(
"org.apache.fulcrum.json.jackson.Bean" ) );
+ assertTrue("Result does contain type", !result.contains(
"java.util.ArrayList" ) );
+ fSynchronizer.countDown();
+ assertTrue("waiting failed", fSynchronizer.await(TIMEOUT,
TimeUnit.SECONDS));
+ fTwo = Thread.currentThread();
+ }
+
+ @Test
+ public void three() throws InterruptedException,
JsonProcessingException {
+ ObjectMapper mapper = customMapper(true);
+ //((Jackson2MapperService) jsonService).setMapper(mapper);
+ fThree = Thread.currentThread();
+ //String result = doTaskJob("name", "age","profession");
+ String result = doFilteredJob(mapper, new
String[]{"age","profession"});
+ assertTrue("Result does not contain type, which it should",
result.contains( "org.apache.fulcrum.json.jackson.Bean" ) );
+ assertTrue("Result does not contain type, which it should",
result.contains( "java.util.ArrayList" ) );
+ assertTrue("Result should not contain attribute name",
!result.contains( "\"name\"" ) );
+ fSynchronizer.countDown();
+ assertTrue("waiting failed", fSynchronizer.await(TIMEOUT,
TimeUnit.SECONDS));
+ }
+
+ private String doJob(String... filtereIds) {
+ final int randInt = randInt(999, 1001);
+ List<Bean> tasks = getBeans(randInt);
+ String result = getJson(tasks, Bean.class, true,
+ filtereIds);
+ System.out.println("ser result
(id="+Thread.currentThread()+"):"+ result);
+ for ( int i = 0; i < filtereIds.length; i++ )
+ {
+ assertTrue("Result does not contain ("+ filtereIds[i]
+")", result.contains( "\""+filtereIds[i]+"\"" ) );
+ }
+ return result;
+ }
+
+ private String doFilteredJob(ObjectMapper mapper, String...
filtereIds) throws JsonProcessingException {
+ final int randInt = randInt(999, 1001);
+ List<Bean> tasks = getBeans(randInt);
+ String result = serFiltered(tasks,Bean.class, mapper,
+ filtereIds);
+ System.out.println("ser result
(id="+Thread.currentThread()+"):"+ result);
+ for ( int i = 0; i < filtereIds.length; i++ )
+ {
+ assertTrue("Result does not contain ("+ filtereIds[i] +")",
result.contains( "\""+filtereIds[i]+"\"" ) );
+ }
+ return result;
+ }
+
+ private String serFiltered(List<?> list, Class<?> filterClass,
+ ObjectMapper mapper, String[] filterAttr)
+ throws JsonProcessingException {
+ Collection<AnnotationIntrospector> ais =
((AnnotationIntrospectorPair)mapper.getSerializationConfig().getAnnotationIntrospector()).allIntrospectors();
+ for (AnnotationIntrospector ai : ais) {
+ if (ai instanceof SimpleNameIntrospector) {
+ //activate filtering
+ ((SimpleNameIntrospector)
ai).setFilteredClasses(filterClass);
+ }
+ }
+ PropertyFilter pf =
SimpleBeanPropertyFilter.filterOutAllExcept(filterAttr);
+ SimpleFilterProvider filter = new SimpleFilterProvider();
+ filter.setDefaultFilter(pf);
+ return mapper.writer(filter).writeValueAsString(list);
+ }
+
+ private ObjectMapper customMapper(boolean withType) {
+ ObjectMapper objectMapper = new ObjectMapper(
+ new MappingJsonFactory(((Jackson2MapperService)
jsonService).getMapper()));
+ if (withType) objectMapper.enableDefaultTypingAsProperty(
+ DefaultTyping.NON_FINAL, "type");
+ AnnotationIntrospector ai =
objectMapper.getSerializationConfig().getAnnotationIntrospector();
+ AnnotationIntrospector siai = new SimpleNameIntrospector();
+ AnnotationIntrospector pair = new
AnnotationIntrospectorPair(siai,ai);
+ objectMapper.setAnnotationIntrospector(pair);
+ return objectMapper;
+ }
+
+ private List<Bean> getBeans(int randNum) {
+ List<Bean> beans = new ArrayList<Bean>();
+ for ( int i = 0; i < 50; i++ )
+ {
+ Bean dct = new Bean();
+ dct.setName( "title" +i );
+ dct.setAge(randNum + i);
+ dct.profession = "prof" +i;
+ beans.add( dct );
+ }
+ return beans;
+ }
+
+ private String getJson( List<?> list , Class clazz, Boolean refresh,
String... props)
+ {
+ String result ="";
+ try
+ {
+ result = jsonService.serializeOnlyFilter(list, clazz,
refresh, props);
+ }
+ catch ( Exception e )
+ {
+ System.out.println(e.getMessage());
+ fail();
+ }
+ return result;
+ }
+ }
+
+ @Test
+ public void testsRunInParallel() {
+ //Parallel among methods in a class in one thread pool
+ Result result = JUnitCore.runClasses(ParallelComputer.methods(),
JSONBeansTests.class);
+
+ assertNotNull("Parallel Init exist"+getFailures(result) ,
result.getFailureCount() ==0);
+ assertTrue("Parallel Init"+getTrace(result), result.wasSuccessful());
+ assertNotNull(fOne);
+ assertNotNull(fTwo);
+ assertNotNull(fThree);
+ assertThat(fOne, is(not(fTwo)));
+ assertThat(fTwo, is(not(fThree)));
+ assertThat(fOne, is(not(fThree)));
+ }
+
+ public static String getFailures(Result result) {
+ List<Failure> failures = result.getFailures() ;
+ StringBuffer sb = new StringBuffer();
+ for (Failure failure : failures) {
+ sb.append(failure.getMessage());
+ //System.out.println(failure.getMessage());
+ }
+ return sb.toString();
+ }
+
+
+ public static String getTrace(Result result) {
+ List<Failure> failures = result.getFailures() ;
+ StringBuffer sb = new StringBuffer();
+ for (Failure failure : failures) {
+ failure.getException().printStackTrace();
+ if (failure.getException().getCause() != null)
+ failure.getException().getCause().printStackTrace();
+ sb.append(failure.getTrace());
+ }
+ return sb.toString();
+ }
+
+ public static int randInt(int min, int max) {
+ Random rand = new Random();
+ return rand.nextInt((max - min) + 1) + min;
+ }
+
+
+}
Propchange:
turbine/fulcrum/trunk/json/jackson2/src/test/org/apache/fulcrum/json/jackson/concurrent/JSONConcurrentTest.java
------------------------------------------------------------------------------
svn:eol-style = native