You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/04/03 14:36:19 UTC

incubator-juneau git commit: Add support for overriding _type property name at class level.

Repository: incubator-juneau
Updated Branches:
  refs/heads/master ce5b9e810 -> 4d73a6368


Add support for overriding _type property name at class level.

Project: http://git-wip-us.apache.org/repos/asf/incubator-juneau/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-juneau/commit/4d73a636
Tree: http://git-wip-us.apache.org/repos/asf/incubator-juneau/tree/4d73a636
Diff: http://git-wip-us.apache.org/repos/asf/incubator-juneau/diff/4d73a636

Branch: refs/heads/master
Commit: 4d73a63680fbb6f624ca2d5f4fb078435cbf774e
Parents: ce5b9e8
Author: JamesBognar <ja...@apache.org>
Authored: Mon Apr 3 10:36:20 2017 -0400
Committer: JamesBognar <ja...@apache.org>
Committed: Mon Apr 3 10:36:20 2017 -0400

----------------------------------------------------------------------
 .../java/org/apache/juneau/jena/RdfParser.java  |  2 +-
 .../java/org/apache/juneau/BeanMapTest.java     | 28 ++++-----
 .../main/java/org/apache/juneau/BeanMap.java    |  4 +-
 .../main/java/org/apache/juneau/BeanMeta.java   | 12 +++-
 .../java/org/apache/juneau/BeanSession.java     |  9 ++-
 .../main/java/org/apache/juneau/ClassMeta.java  | 22 ++++++-
 .../main/java/org/apache/juneau/ObjectMap.java  | 50 ++++-----------
 .../java/org/apache/juneau/annotation/Bean.java | 32 +++++++++-
 .../java/org/apache/juneau/html/HtmlParser.java | 10 +--
 .../org/apache/juneau/html/HtmlSerializer.java  |  6 +-
 .../java/org/apache/juneau/json/JsonParser.java |  4 +-
 .../apache/juneau/msgpack/MsgPackParser.java    |  4 +-
 .../java/org/apache/juneau/parser/Parser.java   |  2 +-
 .../org/apache/juneau/parser/ParserSession.java |  2 +-
 .../java/org/apache/juneau/uon/UonParser.java   | 10 +--
 .../juneau/urlencoding/UrlEncodingParser.java   |  6 +-
 .../java/org/apache/juneau/xml/XmlParser.java   |  6 +-
 .../apache/juneau/xml/XmlSchemaSerializer.java  |  4 +-
 .../org/apache/juneau/xml/XmlSerializer.java    |  4 +-
 juneau-core/src/main/javadoc/overview.html      | 66 ++++++++++----------
 20 files changed, 160 insertions(+), 123 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
----------------------------------------------------------------------
diff --git a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
index c3138dc..d3e7abe 100644
--- a/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
+++ b/juneau-core-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
@@ -374,7 +374,7 @@ public class RdfParser extends ReaderParser {
 			Resource r = n.asResource();
 			Map m = new ObjectMap(session);
 			parseIntoMap(session, r, m, sType.getKeyType(), sType.getValueType(), pMeta);
-			if (m.containsKey(session.getBeanTypePropertyName()))
+			if (m.containsKey(session.getBeanTypePropertyName(eType)))
 				o = session.cast((ObjectMap)m, pMeta, eType);
 			else
 				throw new ParseException(session, "Class ''{0}'' could not be instantiated.  Reason: ''{1}''", sType.getInnerClass().getName(), sType.getNotABeanReason());

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core-test/src/test/java/org/apache/juneau/BeanMapTest.java
----------------------------------------------------------------------
diff --git a/juneau-core-test/src/test/java/org/apache/juneau/BeanMapTest.java b/juneau-core-test/src/test/java/org/apache/juneau/BeanMapTest.java
index a254525..5dd13b0 100755
--- a/juneau-core-test/src/test/java/org/apache/juneau/BeanMapTest.java
+++ b/juneau-core-test/src/test/java/org/apache/juneau/BeanMapTest.java
@@ -1144,7 +1144,7 @@ public class BeanMapTest {
 		m.put("f1", 1);
 		m.put("f2", "2");
 
-		R2 t = (R2)m.cast();
+		R2 t = (R2)m.cast(Object.class);
 		assertEquals(1, t.f1);
 
 		t = (R2)m.cast(R1.class);
@@ -1160,7 +1160,7 @@ public class BeanMapTest {
 		m.put("f1", 1);
 		m.put("f2", "2");
 
-		m = (ObjectMap)m.cast();
+		m = (ObjectMap)m.cast(Object.class);
 		assertEquals(1, t.f1);
 		assertEquals(2, t.f2);
 
@@ -1193,7 +1193,7 @@ public class BeanMapTest {
 		m.put("_type", "S");
 		m.put("f1", new ObjectMap(session).append("_type", "R1").append("f1", 1));
 
-		S t = (S)m.cast();
+		S t = (S)m.cast(Object.class);
 		assertEquals(1, t.f1.f1);
 
 		t = m.cast(S.class);
@@ -1206,7 +1206,7 @@ public class BeanMapTest {
 		m = new ObjectMap(session);
 		m.put("f1", new ObjectMap(session).append("_type", R1.class.getName()).append("f1", 1));
 
-		m = (ObjectMap)m.cast();
+		m = (ObjectMap)m.cast(Object.class);
 		assertEquals(1, t.f1.f1);
 
 		t = m.cast(S.class);
@@ -1232,7 +1232,7 @@ public class BeanMapTest {
 		m.put("_type", "TreeMap");
 		m.put("1", "ONE");
 
-		m2 = (Map)m.cast();
+		m2 = (Map)m.cast(Object.class);
 		assertTrue(m2 instanceof TreeMap);
 		assertEquals("ONE", m2.get("1"));
 
@@ -1269,7 +1269,7 @@ public class BeanMapTest {
 		m = new ObjectMap();
 		m.put("1", "ONE");
 
-		m2 = (ObjectMap)m.cast();
+		m2 = (ObjectMap)m.cast(Object.class);
 		assertTrue(m2 instanceof ObjectMap);
 		assertEquals("ONE", m2.get("1"));
 
@@ -1311,7 +1311,7 @@ public class BeanMapTest {
 		m.put("_type", "LinkedList");
 		m.put("items", new ObjectList().append("1").append("2"));
 
-		List l = (List)m.cast();
+		List l = (List)m.cast(Object.class);
 		assertTrue(l instanceof LinkedList);
 		assertEquals("1", l.get(0));
 
@@ -1364,7 +1364,7 @@ public class BeanMapTest {
 		m.put("_type", "LinkedListOfInts");
 		m.put("items", new ObjectList().append("1").append("2"));
 
-		List l = (List)m.cast();
+		List l = (List)m.cast(Object.class);
 		assertTrue(l instanceof LinkedList);
 		assertEquals(1, l.get(0));
 
@@ -1426,7 +1426,7 @@ public class BeanMapTest {
 		m.put("_type", "LinkedListOfR1");
 		m.put("items", new ObjectList(session).append("{f1:1}"));
 
-		List l = (List)m.cast();
+		List l = (List)m.cast(Object.class);
 		assertTrue(l instanceof LinkedList);
 		assertTrue(l.get(0) instanceof R1);
 		assertEquals(1, ((R1)l.get(0)).f1);
@@ -1507,7 +1507,7 @@ public class BeanMapTest {
 		m.put("_type", "LinkedListOfCalendar");
 		m.put("items", new ObjectList().append("2001-07-04T15:30:45Z"));
 
-		List l = (List)m.cast();
+		List l = (List)m.cast(Object.class);
 		assertTrue(l instanceof LinkedList);
 		assertEquals(2001, ((Calendar)l.get(0)).get(Calendar.YEAR));
 
@@ -1569,7 +1569,7 @@ public class BeanMapTest {
 		m.put("_type", "StringArray");
 		m.put("items", new ObjectList().append("1").append("2"));
 
-		String[] l = (String[])m.cast();
+		String[] l = (String[])m.cast(Object.class);
 		assertEquals("1", l[0]);
 
 		l = m.cast(String[].class);
@@ -1615,7 +1615,7 @@ public class BeanMapTest {
 		m.put("_type", "IntArray");
 		m.put("items", new ObjectList().append("1").append("2"));
 
-		int[] l = (int[])m.cast();
+		int[] l = (int[])m.cast(Object.class);
 		assertEquals(1, l[0]);
 
 		l = m.cast(int[].class);
@@ -1660,7 +1660,7 @@ public class BeanMapTest {
 		m.put("_type", "String2dArray");
 		m.put("items", new ObjectList().append(new ObjectList().append("1")).append(new ObjectList().append("2")));
 
-		String[][] l = (String[][])m.cast();
+		String[][] l = (String[][])m.cast(Object.class);
 		assertEquals("1", l[0][0]);
 		assertEquals("2", l[1][0]);
 
@@ -1692,7 +1692,7 @@ public class BeanMapTest {
 		m.put("_type", "Int2dArray");
 		m.put("items", new ObjectList().append(new ObjectList().append("1")).append(new ObjectList().append("2")));
 
-		int[][] l = (int[][])m.cast();
+		int[][] l = (int[][])m.cast(Object.class);
 		assertEquals(1, l[0][0]);
 		assertEquals(2, l[1][0]);
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/BeanMap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanMap.java b/juneau-core/src/main/java/org/apache/juneau/BeanMap.java
index ed57429..6318255 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanMap.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanMap.java
@@ -65,6 +65,7 @@ public class BeanMap<T> extends AbstractMap<String,Object> implements Delegate<T
 	protected BeanMeta<T> meta;
 
 	private final BeanSession session;
+	private final String beanTypePropertyName;
 
 	/**
 	 * Instance of this class are instantiated through the BeanContext class.
@@ -79,6 +80,7 @@ public class BeanMap<T> extends AbstractMap<String,Object> implements Delegate<T
 		this.meta = meta;
 		if (meta.constructorArgs.length > 0)
 			propertyCache = new TreeMap<String,Object>();
+		this.beanTypePropertyName = session.getBeanTypePropertyName(meta.classMeta);
 	}
 
 	/**
@@ -203,7 +205,7 @@ public class BeanMap<T> extends AbstractMap<String,Object> implements Delegate<T
 			if (meta.ctx.ignoreUnknownBeanProperties)
 				return null;
 
-			if (property.equals(session.getBeanTypePropertyName()))
+			if (property.equals(beanTypePropertyName))
 				return null;
 
 			throw new BeanRuntimeException(meta.c, "Bean property ''{0}'' not found.", property);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java b/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java
index e327a75..e1edb43 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanMeta.java
@@ -87,6 +87,7 @@ public class BeanMeta<T> {
 	private final MetadataMap extMeta;  // Extended metadata
 
 	// Other fields
+	final String typePropertyName;                                      // "_type" property actual name.
 	private final BeanPropertyMeta typeProperty;                        // "_type" mock bean property.
 	private final String dictionaryName;                                // The @Bean.typeName() annotation defined on this bean class.
 	final String notABeanReason;                                        // Readable string explaining why this class wasn't a bean.
@@ -118,7 +119,8 @@ public class BeanMeta<T> {
 		this.constructorArgs = b.constructorArgs;
 		this.extMeta = b.extMeta;
 		this.beanRegistry = b.beanRegistry;
-		this.typeProperty = new BeanPropertyMeta.Builder(this, ctx.getBeanTypePropertyName(), ctx.string(), beanRegistry).build();
+		this.typePropertyName = b.typePropertyName;
+		this.typeProperty = new BeanPropertyMeta.Builder(this, typePropertyName, ctx.string(), beanRegistry).build();
 	}
 
 	private static final class Builder<T> {
@@ -135,7 +137,7 @@ public class BeanMeta<T> {
 		MetadataMap extMeta = new MetadataMap();
 		PropertyNamer propertyNamer;
 		BeanRegistry beanRegistry;
-		String dictionaryName;
+		String dictionaryName, typePropertyName;
 
 		private Builder(ClassMeta<T> classMeta, BeanContext ctx, BeanFilter beanFilter, String[] pNames) {
 			this.classMeta = classMeta;
@@ -165,6 +167,12 @@ public class BeanMeta<T> {
 				}
 				this.beanRegistry = new BeanRegistry(ctx, null, bdClasses.toArray(new Class<?>[bdClasses.size()]));
 
+				for (Bean b : ReflectionUtils.findAnnotationsParentFirst(Bean.class, classMeta.innerClass))
+					if (! b.typePropertyName().isEmpty())
+						typePropertyName = b.typePropertyName();
+				if (typePropertyName == null)
+					typePropertyName = ctx.getBeanTypePropertyName();
+
 				// If @Bean.interfaceClass is specified on the parent class, then we want
 				// to use the properties defined on that class, not the subclass.
 				Class<?> c2 = (beanFilter != null && beanFilter.getInterfaceClass() != null ? beanFilter.getInterfaceClass() : c);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanSession.java b/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
index 0f9e79b..ad1cee6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanSession.java
@@ -554,7 +554,7 @@ public class BeanSession extends Session {
 			if (type.isBean() && value instanceof Map) {
 				if (value instanceof ObjectMap) {
 					ObjectMap m2 = (ObjectMap)value;
-					String typeName = m2.getString(getBeanTypePropertyName());
+					String typeName = m2.getString(getBeanTypePropertyName(type));
 					if (typeName != null) {
 						ClassMeta cm = type.getBeanRegistry().getClassMeta(typeName);
 						if (cm != null && ClassUtils.isParentClass(type.innerClass, cm.innerClass))
@@ -873,10 +873,13 @@ public class BeanSession extends Session {
 	/**
 	 * Returns the type property name as defined by {@link BeanContext#BEAN_beanTypePropertyName}.
 	 *
+	 * @param cm The class meta of the type we're trying to resolve the type name for.
+	 * Can be <jk>null</jk>.
 	 * @return The type property name.  Never <jk>null</jk>.
 	 */
-	public final String getBeanTypePropertyName() {
-		return ctx.beanTypePropertyName;
+	public final String getBeanTypePropertyName(ClassMeta cm) {
+		String s = cm == null ? null : cm.getBeanTypePropertyName();
+		return s == null ? ctx.beanTypePropertyName : s;
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
index 397e4e0..9614408 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@ -100,6 +100,7 @@ public final class ClassMeta<T> implements Type {
 		valueType;                                           // If MAP, the value class type.
 	private final BeanMeta<T> beanMeta;                     // The bean meta for this bean class (if it's a bean).
 	private final String
+		typePropertyName,                                    // The property name of the _type property for this class and subclasses.
 		notABeanReason,                                      // If this isn't a bean, the reason why.
 		dictionaryName,                                      // The dictionary name of this class if it has one.
 		resolvedDictionaryName;                              // The name if this is an array type (e.g. "X^^").
@@ -171,6 +172,7 @@ public final class ClassMeta<T> implements Type {
 		this.notABeanReason = builder.notABeanReason;
 		this.beanMeta = builder.beanMeta;
 		this.initException = builder.initException;
+		this.typePropertyName = builder.typePropertyName;
 		this.dictionaryName = builder.dictionaryName;
 		this.resolvedDictionaryName = builder.resolvedDictionaryName;
 		this.serializedClassMeta = builder.serializedClassMeta;
@@ -221,6 +223,7 @@ public final class ClassMeta<T> implements Type {
 		this.valueType = valueType;
 		this.invocationHandler = mainType.invocationHandler;
 		this.beanMeta = mainType.beanMeta;
+		this.typePropertyName = mainType.typePropertyName;
 		this.dictionaryName = mainType.dictionaryName;
 		this.resolvedDictionaryName = mainType.resolvedDictionaryName;
 		this.notABeanReason = mainType.notABeanReason;
@@ -269,6 +272,7 @@ public final class ClassMeta<T> implements Type {
 		this.valueType = null;
 		this.invocationHandler = null;
 		this.beanMeta = null;
+		this.typePropertyName = null;
 		this.dictionaryName = null;
 		this.resolvedDictionaryName = null;
 		this.notABeanReason = null;
@@ -314,6 +318,7 @@ public final class ClassMeta<T> implements Type {
 			elementType = null,
 			serializedClassMeta = null;
 		String
+			typePropertyName = null,
 			notABeanReason = null,
 			dictionaryName = null,
 			resolvedDictionaryName = null;
@@ -622,7 +627,11 @@ public final class ClassMeta<T> implements Type {
 					try {
 						newMeta = new BeanMeta(ClassMeta.this, beanContext, beanFilter, null);
 						notABeanReason = newMeta.notABeanReason;
-						beanRegistry = newMeta.beanRegistry;  // Always get the bean registry even if it's not a bean.
+						
+						// Always get these even if it's not a bean:
+						beanRegistry = newMeta.beanRegistry;  
+						typePropertyName = newMeta.typePropertyName; 
+						
 					} catch (RuntimeException e) {
 						notABeanReason = e.getMessage();
 						throw e;
@@ -698,6 +707,17 @@ public final class ClassMeta<T> implements Type {
 
 
 	/**
+	 * Returns the type property name associated with this class and subclasses.
+	 * <p>
+	 * If <jk>null</jk>, <js>"_type"</js> should be assumed.
+	 *
+	 * @return The type property name associated with this bean class, or <jk>null</jk> if there is no explicit type property name defined or this isn't a bean.
+	 */
+	public String getBeanTypePropertyName() {
+		return typePropertyName;
+	}
+
+	/**
 	 * Returns the bean dictionary name associated with this class.
 	 * <p>
 	 * The lexical name is defined by {@link Bean#typeName()}.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
index c146b25..0bb3491 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
@@ -1069,39 +1069,8 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	}
 
 	/**
-	 * Converts this map into the class type specified by the <js>"_type"</js> entry value.
-	 * <p>
-	 * TODO - Needs better description.
-	 *
-	 * @return This object map cast as another object.
-	 */
-	public Object cast() {
-		return cast(session.getBeanRegistry());
-	}
-
-	/**
-	 * Same as {@link #cast()}, but first do a lookup for the name in the specified dictionary.
-	 *
-	 * @param beanRegistry
-	 * The class lexicon to resolve the name.  Can be <jk>null</jk>.
-	 * @return The new Java object of type specified by the <js>"_type"</js> entry value, or this
-	 * 	same object if entry does not exist.
-	 */
-	public Object cast(BeanRegistry beanRegistry) {
-		String c = (String)get(session.getBeanTypePropertyName());
-		if (c == null || beanRegistry == null)
-			return this;
-		ClassMeta<?> cm = beanRegistry.getClassMeta(c);
-		if (cm == null)
-			return this;
-		return cast2(cm);
-	}
-
-	/**
 	 * Converts this map into an object of the specified type.
 	 * <p>
-	 * The rules are the same as those specified in {@link #cast()}.
-	 * <p>
 	 * If this map contains a <js>"_type"</js> entry, it must be the same as or a subclass
 	 * 	of the <code>type</code>.
 	 *
@@ -1113,9 +1082,12 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	 */
 	@SuppressWarnings("unchecked")
 	public <T> T cast(Class<T> type) {
-		ClassMeta<?> c1 = session.getBeanRegistry().getClassMeta((String)get(session.getBeanTypePropertyName()));
 		ClassMeta<?> c2 = session.getClassMeta(type);
-		ClassMeta<?> c = narrowClassMeta(c1, c2);
+		String typePropertyName = session.getBeanTypePropertyName(c2);
+		ClassMeta<?> c1 = session.getBeanRegistry().getClassMeta((String)get(typePropertyName));
+		ClassMeta<?> c = c1 == null ? c2 : narrowClassMeta(c1, c2);
+		if (c.isObject())
+			return (T)this;
 		return (T)cast2(c);
 	}
 
@@ -1130,7 +1102,7 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	 */
 	@SuppressWarnings({"unchecked"})
 	public <T> T cast(ClassMeta<T> cm) {
-		ClassMeta<?> c1 = session.getBeanRegistry().getClassMeta((String)get(session.getBeanTypePropertyName()));
+		ClassMeta<?> c1 = session.getBeanRegistry().getClassMeta((String)get(session.getBeanTypePropertyName(cm)));
 		ClassMeta<?> c = narrowClassMeta(c1, cm);
 		return (T)cast2(c);
 	}
@@ -1162,7 +1134,7 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	 * Otherwise, returns c2.
 	 */
 	private static ClassMeta<?> getNarrowedClassMeta(ClassMeta<?> c1, ClassMeta<?> c2) {
-		if (isParentClass(c2.getInnerClass(), c1.getInnerClass()))
+		if (c2 == null || isParentClass(c2.getInnerClass(), c1.getInnerClass()))
 			return c1;
 		return c2;
 	}
@@ -1182,11 +1154,11 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 				for (Map.Entry<String,Object> e : entrySet()) {
 					Object k = e.getKey();
 					Object v = e.getValue();
-					if (! k.equals(session.getBeanTypePropertyName())) {
+					if (! k.equals(session.getBeanTypePropertyName(cm))) {
 
 						// Attempt to recursively cast child maps.
 						if (v instanceof ObjectMap)
-							v = ((ObjectMap)v).cast(session.getBeanRegistry());
+							v = ((ObjectMap)v).cast(vType);
 
 						k = (kType.isString() ? k : session.convertToType(k, kType));
 						v = (vType.isObject() ? v : session.convertToType(v, vType));
@@ -1203,11 +1175,11 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 				for (Map.Entry<String,Object> e : entrySet()) {
 					String k = e.getKey();
 					Object v = e.getValue();
-					if (! k.equals(session.getBeanTypePropertyName())) {
+					if (! k.equals(session.getBeanTypePropertyName(cm))) {
 
 						// Attempt to recursively cast child maps.
 						if (v instanceof ObjectMap)
-							v = ((ObjectMap)v).cast(session.getBeanRegistry());
+							v = ((ObjectMap)v).cast(bm.getProperty(k).getMeta().getClassMeta());
 
 						bm.put(k, v);
 					}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/annotation/Bean.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/annotation/Bean.java b/juneau-core/src/main/java/org/apache/juneau/annotation/Bean.java
index d4abba2..5b7bf93 100644
--- a/juneau-core/src/main/java/org/apache/juneau/annotation/Bean.java
+++ b/juneau-core/src/main/java/org/apache/juneau/annotation/Bean.java
@@ -84,13 +84,43 @@ public @interface Bean {
 	 * 	{
 	 * 		x: [
 	 * 			{_type:<js>'bar'</js>},
-	 * 			{_type>:<js>'baz'</js>}
+	 * 			{_type:<js>'baz'</js>}
 	 * 		]
 	 * 	}
 	 * </p>
 	 */
 	String typeName() default "";
 
+
+	/**
+	 * The property name to use for representing the type name.
+	 * <p>
+	 * This can be used to override the name used for the <js>"_type"</js> property designated above.
+	 * Typically, you'll define this on an interface class so that it can apply to all subclasses.
+	 * <p class='bcode'>
+	 * 	<ja>@Bean</ja>(typePropertyName=<js>"mytype"</js>, beanDictionary={MyClass1.<jk>class</jk>,MyClass2.<jk>class</jk>})
+	 * 	<jk>public interface</jk> MyInterface {...}
+	 *
+	 * 	<ja>@Bean</ja>(typeName=<js>"C1"</js>)
+	 * 	<jk>public class</jk> MyClass1 <jk>implements</jk> MyInterface {...}
+	 *
+	 * 	<ja>@Bean</ja>(typeName=<js>"C2"</js>)
+	 * 	<jk>public class</jk> MyClass2 <jk>implements</jk> MyInterface {...}
+	 *
+	 * 	MyInterface[] x = <jk>new</jk> MyInterface[]{ <jk>new</jk> MyClass1(), <jk>new</jk> MyClass2() };
+	 *
+	 *	<jc>// Produces "[{mytype:'C1',...},{mytype:'C2',...}]"</jc>
+	 * 	String json = JsonSerializer.<jsf>DEFAULT_LAX</jsf>.serialize(x);
+	 * </p>
+	 * <p>
+	 * This is similar in concept to the {@link BeanContext#BEAN_beanTypePropertyName} setting except this annotation
+	 * applies only to the annotated class and subclasses whereas the bean context property applies globally on
+	 * serializers and parsers.
+	 * <p>
+	 * The default value if not specified is <js>"_type"</js> unless overridden by the {@link BeanContext#BEAN_beanTypePropertyName} setting.
+	 */
+	String typePropertyName() default "";
+
 	/**
 	 * The set and order of names of properties associated with a bean class.
 	 * <p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
index 9e53303..5e65356 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlParser.java
@@ -183,7 +183,7 @@ public class HtmlParser extends XmlParser {
 
 		} else if (tag == TABLE) {
 
-			String typeName = getAttribute(r, session.getBeanTypePropertyName(), "object");
+			String typeName = getAttribute(r, session.getBeanTypePropertyName(eType), "object");
 			ClassMeta cm = session.getClassMeta(typeName, pMeta, eType);
 
 			if (cm != null) {
@@ -225,7 +225,7 @@ public class HtmlParser extends XmlParser {
 			}
 
 		} else if (tag == UL) {
-			String typeName = getAttribute(r, session.getBeanTypePropertyName(), "array");
+			String typeName = getAttribute(r, session.getBeanTypePropertyName(eType), "array");
 			ClassMeta cm = session.getClassMeta(typeName, pMeta, eType);
 			if (cm != null)
 				sType = eType = cm;
@@ -377,7 +377,7 @@ public class HtmlParser extends XmlParser {
 				break;
 
 			ClassMeta elementType = null;
-			String beanType = getAttribute(r, session.getBeanTypePropertyName(), null);
+			String beanType = getAttribute(r, session.getBeanTypePropertyName(type), null);
 			if (beanType != null)
 				elementType = session.getClassMeta(beanType, pMeta, null);
 			if (elementType == null)
@@ -409,7 +409,7 @@ public class HtmlParser extends XmlParser {
 				}
 				l.add(m == null ? null : (E)m.getBean());
 			} else {
-				String c = getAttributes(r).get(session.getBeanTypePropertyName());
+				String c = getAttributes(r).get(session.getBeanTypePropertyName(type));
 				Map m = (Map)(elementType.isMap() && elementType.canCreateNewInstance(l) ? elementType.newInstance(l) : new ObjectMap(session));
 				for (int i = 0; i < keys.size(); i++) {
 					tag = nextTag(r, TD, NULL);
@@ -428,7 +428,7 @@ public class HtmlParser extends XmlParser {
 				}
 				if (m != null && c != null) {
 					ObjectMap m2 = (m instanceof ObjectMap ? (ObjectMap)m : new ObjectMap(m).setBeanSession(session));
-					m2.put(session.getBeanTypePropertyName(), c);
+					m2.put(session.getBeanTypePropertyName(type), c);
 					l.add((E)session.cast(m2, pMeta, elementType));
 				} else {
 					l.add((E)m);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index a4d8c7d..28b31c0 100644
--- a/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -362,7 +362,7 @@ public class HtmlSerializer extends XmlSerializer {
 		out.oTag(i, "table");
 
 		if (typeName != null && ppMeta != null && ppMeta.getClassMeta() != aType)
-			out.attr(session.getBeanTypePropertyName(), typeName);
+			out.attr(session.getBeanTypePropertyName(sType), typeName);
 
 		out.appendln(">");
 		if (session.isAddKeyValueTableHeaders() && ! (aType.getExtendedMeta(HtmlClassMeta.class).isNoTableHeaders() || (ppMeta != null && ppMeta.getExtendedMeta(HtmlBeanPropertyMeta.class).isNoTableHeaders()))) {
@@ -406,7 +406,7 @@ public class HtmlSerializer extends XmlSerializer {
 
 		String typeName = m.getMeta().getDictionaryName();
 		if (typeName != null && eType != m.getClassMeta())
-			out.attr(session.getBeanTypePropertyName(), typeName);
+			out.attr(session.getBeanTypePropertyName(m.getClassMeta()), typeName);
 
 		out.append('>').nl();
 		if (session.isAddKeyValueTableHeaders() && ! (m.getClassMeta().getExtendedMeta(HtmlClassMeta.class).isNoTableHeaders() || (ppMeta != null && ppMeta.getExtendedMeta(HtmlBeanPropertyMeta.class).isNoTableHeaders()))) {
@@ -474,7 +474,7 @@ public class HtmlSerializer extends XmlSerializer {
 		c = session.sort(c);
 
 		HtmlBeanPropertyMeta hbpMeta = (ppMeta == null ? null : ppMeta.getExtendedMeta(HtmlBeanPropertyMeta.class));
-		String btpn = session.getBeanTypePropertyName();
+		String btpn = session.getBeanTypePropertyName(eType);
 
 		// Look at the objects to see how we're going to handle them.  Check the first object to see how we're going to handle this.
 		// If it's a map or bean, then we'll create a table.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
index 5a09de5..bd79451 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
@@ -215,7 +215,7 @@ public class JsonParser extends ReaderParser {
 		} else if (c == '{') {
 			Map m = new ObjectMap(session);
 			parseIntoMap2(session, r, m, sType.getKeyType(), sType.getValueType(), pMeta);
-			if (m.containsKey(session.getBeanTypePropertyName()))
+			if (m.containsKey(session.getBeanTypePropertyName(eType)))
 				o = session.cast((ObjectMap)m, pMeta, eType);
 			else
 				throw new ParseException(session, "Class ''{0}'' could not be instantiated.  Reason: ''{1}''", sType.getInnerClass().getName(), sType.getNotABeanReason());
@@ -493,7 +493,7 @@ public class JsonParser extends ReaderParser {
 				if (session.isCommentOrWhitespace(c)) {
 					skipCommentsAndSpace(session, r.unread());
 				} else {
-					if (! currAttr.equals(session.getBeanTypePropertyName())) {
+					if (! currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
 						BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 						session.setCurrentProperty(pMeta);
 						if (pMeta == null) {

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
index fc18351..8895f33 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -127,7 +127,7 @@ public class MsgPackParser extends InputStreamParser {
 						String pName = parseAnything(session, string(), is, m.getBean(false), null);
 						BeanPropertyMeta bpm = m.getPropertyMeta(pName);
 						if (bpm == null) {
-							if (pName.equals(session.getBeanTypePropertyName()))
+							if (pName.equals(session.getBeanTypePropertyName(eType)))
 								parseAnything(session, session.string(), is, null, null);
 							else
 								onUnknownProperty(session, pName, m, 0, is.getPosition());
@@ -178,7 +178,7 @@ public class MsgPackParser extends InputStreamParser {
 				ObjectMap m = new ObjectMap(session);
 				for (int i = 0; i < length; i++)
 					m.put(parseAnything(session, string(), is, outer, pMeta), parseAnything(session, object(), is, m, pMeta));
-				if (m.containsKey(session.getBeanTypePropertyName()))
+				if (m.containsKey(session.getBeanTypePropertyName(eType)))
 					o = session.cast(m, pMeta, eType);
 				else
 					throw new ParseException(session, "Class ''{0}'' could not be instantiated.  Reason: ''{1}''", sType.getInnerClass().getName(), sType.getNotABeanReason());

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
index 389e224..25b3840 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/Parser.java
@@ -611,7 +611,7 @@ public abstract class Parser extends CoreObject {
 	 * @param <T> The class type of the bean map that doesn't have the expected property.
 	 */
 	protected <T> void onUnknownProperty(ParserSession session, String propertyName, BeanMap<T> beanMap, int line, int col) throws ParseException {
-		if (propertyName.equals("type") || propertyName.equals(session.getBeanTypePropertyName()))
+		if (propertyName.equals(session.getBeanTypePropertyName(beanMap.getClassMeta())))
 			return;
 		if (! session.isIgnoreUnknownBeanProperties())
 			throw new ParseException(session, "Unknown property ''{0}'' encountered while trying to parse into class ''{1}''", propertyName, beanMap.getClassMeta());

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
index c84e6e2..ea20042 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
@@ -283,7 +283,7 @@ public class ParserSession extends BeanSession {
 	 */
 	public final Object cast(ObjectMap m, BeanPropertyMeta pMeta, ClassMeta<?> eType) {
 
-		String btpn = getBeanTypePropertyName();
+		String btpn = getBeanTypePropertyName(eType);
 
 		Object o = m.get(btpn);
 		if (o == null)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java b/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
index 52ff871..b53f5b7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/uon/UonParser.java
@@ -169,7 +169,7 @@ public class UonParser extends ReaderParser {
 				ObjectMap m = new ObjectMap(session);
 				parseIntoMap(session, r, m, string(), object(), pMeta);
 				// Handle case where it's a collection, but serialized as a map with a _type or _value key.
-				if (m.containsKey(session.getBeanTypePropertyName()))
+				if (m.containsKey(session.getBeanTypePropertyName(sType)))
 					o = session.cast(m, pMeta, eType);
 				// Handle case where it's a collection, but only a single value was specified.
 				else {
@@ -196,7 +196,7 @@ public class UonParser extends ReaderParser {
 				ObjectMap m = new ObjectMap(session);
 				parseIntoMap(session, r, m, string(), object(), pMeta);
 				// Handle case where it's an array, but serialized as a map with a _type or _value key.
-				if (m.containsKey(session.getBeanTypePropertyName()))
+				if (m.containsKey(session.getBeanTypePropertyName(sType)))
 					o = session.cast(m, pMeta, eType);
 				// Handle case where it's an array, but only a single value was specified.
 				else {
@@ -212,7 +212,7 @@ public class UonParser extends ReaderParser {
 			// It could be a non-bean with _type attribute.
 			ObjectMap m = new ObjectMap(session);
 			parseIntoMap(session, r, m, string(), object(), pMeta);
-			if (m.containsKey(session.getBeanTypePropertyName()))
+			if (m.containsKey(session.getBeanTypePropertyName(sType)))
 				o = session.cast(m, pMeta, eType);
 			else
 				throw new ParseException(session, "Class ''{0}'' could not be instantiated.  Reason: ''{1}''", sType.getInnerClass().getName(), sType.getNotABeanReason());
@@ -454,7 +454,7 @@ public class UonParser extends ReaderParser {
 					}
 				} else if (state == S3) {
 					if (c == -1 || c == ',' || c == ')' || c == AMP) {
-						if (! currAttr.equals(session.getBeanTypePropertyName())) {
+						if (! currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
 							BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 							if (pMeta == null) {
 								onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);
@@ -467,7 +467,7 @@ public class UonParser extends ReaderParser {
 							return m;
 						state = S1;
 					} else {
-						if (! currAttr.equals(session.getBeanTypePropertyName())) {
+						if (! currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
 							BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 							if (pMeta == null) {
 								onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
index 5fd9647..6ecf88d 100644
--- a/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
@@ -119,7 +119,7 @@ public class UrlEncodingParser extends UonParser {
 			// It could be a non-bean with _type attribute.
 			ObjectMap m = new ObjectMap(session);
 			parseIntoMap(session, r, m, session.getClassMeta(Map.class, String.class, Object.class), outer);
-			if (m.containsKey(session.getBeanTypePropertyName()))
+			if (m.containsKey(session.getBeanTypePropertyName(eType)))
 				o = session.cast(m, null, eType);
 			else if (m.containsKey("_value")) {
 				o = session.convertToType(m.get("_value"), sType);
@@ -265,7 +265,7 @@ public class UrlEncodingParser extends UonParser {
 					}
 				} else if (state == S3) {
 					if (c == -1 || c == '\u0001') {
-						if (! currAttr.equals(session.getBeanTypePropertyName())) {
+						if (! currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
 							BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 							if (pMeta == null) {
 								onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);
@@ -283,7 +283,7 @@ public class UrlEncodingParser extends UonParser {
 							return m;
 						state = S1;
 					} else {
-						if (! currAttr.equals(session.getBeanTypePropertyName())) {
+						if (! currAttr.equals(session.getBeanTypePropertyName(m.getClassMeta()))) {
 							BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 							if (pMeta == null) {
 								onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
index d0e592f..7830163 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlParser.java
@@ -94,7 +94,7 @@ public class XmlParser extends ReaderParser {
 		session.setCurrentClass(sType);
 
 		String wrapperAttr = (isRoot && session.isPreserveRootElement()) ? r.getName().getLocalPart() : null;
-		String typeAttr = r.getAttributeValue(null, session.getBeanTypePropertyName());
+		String typeAttr = r.getAttributeValue(null, session.getBeanTypePropertyName(eType));
 		int jsonType = getJsonType(typeAttr);
 		String elementName = session.getElementName(r);
 		if (jsonType == 0) {
@@ -195,7 +195,7 @@ public class XmlParser extends ReaderParser {
 		for (int i = 0; i < r.getAttributeCount(); i++) {
 			String a = r.getAttributeLocalName(i);
 			// TODO - Need better handling of namespaces here.
-			if (! (a.equals(session.getBeanTypePropertyName()))) {
+			if (! (a.equals(session.getBeanTypePropertyName(null)))) {
 				K key = session.trim(convertAttrToType(session, m, a, keyType));
 				V value = session.trim(convertAttrToType(session, m, r.getAttributeValue(i), valueType));
 				setName(valueType, value, key);
@@ -429,7 +429,7 @@ public class XmlParser extends ReaderParser {
 			for (int i = 0; i < r.getAttributeCount(); i++) {
 				String key = session.getAttributeName(r, i);
 				String val = r.getAttributeValue(i);
-				if (! key.equals(session.getBeanTypePropertyName()))
+				if (! key.equals(session.getBeanTypePropertyName(null)))
 					m.put(key, val);
 			}
 		}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
index 740ff3a..68031de 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSchemaSerializer.java
@@ -346,7 +346,7 @@ public class XmlSchemaSerializer extends XmlSerializer {
 			w.cTag().nl();
 
 			if (! (cm.isMapOrBean() || cm.isCollectionOrArray() || (cm.isAbstract() && ! cm.isNumber()) || cm.isObject())) {
-				w.oTag(i+1, "attribute").attr("name", session.getBeanTypePropertyName()).attr("type", "string").ceTag().nl();
+				w.oTag(i+1, "attribute").attr("name", session.getBeanTypePropertyName(cm)).attr("type", "string").ceTag().nl();
 
 			} else {
 
@@ -494,7 +494,7 @@ public class XmlSchemaSerializer extends XmlSerializer {
 				}
 
 				w.oTag(i+1, "attribute")
-					.attr("name", session.getBeanTypePropertyName())
+					.attr("name", session.getBeanTypePropertyName(null))
 					.attr("type", "string")
 					.ceTag().nl();
 			}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
index da39582..3db721c 100644
--- a/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/xml/XmlSerializer.java
@@ -498,9 +498,9 @@ public class XmlSerializer extends WriterSerializer {
 			}
 			if (! isExpectedType) {
 				if (resolvedDictionaryName != null)
-					out.attr(dns, session.getBeanTypePropertyName(), resolvedDictionaryName);
+					out.attr(dns, session.getBeanTypePropertyName(eType), resolvedDictionaryName);
 				else if (type != null && type != STRING)
-					out.attr(dns, session.getBeanTypePropertyName(), type);
+					out.attr(dns, session.getBeanTypePropertyName(eType), type);
 			}
 			if (o == null) {
 				if ((sType.isBoolean() || sType.isNumber()) && ! sType.isNullable())

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4d73a636/juneau-core/src/main/javadoc/overview.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/javadoc/overview.html b/juneau-core/src/main/javadoc/overview.html
index 3b23b5c..171b7c3 100644
--- a/juneau-core/src/main/javadoc/overview.html
+++ b/juneau-core/src/main/javadoc/overview.html
@@ -5704,51 +5704,53 @@
 	WriterSerializer s = JsonSerializer.<jsf>DEFAULT_LAX</jsf>.builder().ws().pojoSwaps(BSwap.<jk>class</jk>).build();
 				</p>	
 			<li>Also introduced the following builder classes and related architecture changes to make the built objects unmodifiable:
-			<ul>
-				<li>{@link org.apache.juneau.serializer.SerializerGroupBuilder}
-				<li>{@link org.apache.juneau.parser.ParserGroupBuilder}
-				<li>{@link org.apache.juneau.encoders.EncoderGroupBuilder}
-			</ul>
+				<ul>
+					<li>{@link org.apache.juneau.serializer.SerializerGroupBuilder}
+					<li>{@link org.apache.juneau.parser.ParserGroupBuilder}
+					<li>{@link org.apache.juneau.encoders.EncoderGroupBuilder}
+				</ul>
 			<li>Revamped the config file API to use a build:  {@link org.apache.juneau.ini.ConfigFileBuilder}.
 			<li>Removed the <code><del>Lockable</del></code> interface.
 			<li>New <code>addBeanTypeProperties</code> setting added to serializers to override the 
 				{@link org.apache.juneau.serializer.SerializerContext#SERIALIZER_addBeanTypeProperties} setting
 				for individual serializers in a serializer group:
-			<ul>
-				<li>{@link org.apache.juneau.html.HtmlSerializerContext#HTML_addBeanTypeProperties}
-				<li>{@link org.apache.juneau.json.JsonSerializerContext#JSON_addBeanTypeProperties}
-				<li>{@link org.apache.juneau.msgpack.MsgPackSerializerContext#MSGPACK_addBeanTypeProperties}
-				<li>{@link org.apache.juneau.uon.UonSerializerContext#UON_addBeanTypeProperties}
-				<li>{@link org.apache.juneau.xml.XmlSerializerContext#XML_addBeanTypeProperties}
-				<li>{@link org.apache.juneau.jena.RdfSerializerContext#RDF_addBeanTypeProperties}
-			</ul>
+				<ul>
+					<li>{@link org.apache.juneau.html.HtmlSerializerContext#HTML_addBeanTypeProperties}
+					<li>{@link org.apache.juneau.json.JsonSerializerContext#JSON_addBeanTypeProperties}
+					<li>{@link org.apache.juneau.msgpack.MsgPackSerializerContext#MSGPACK_addBeanTypeProperties}
+					<li>{@link org.apache.juneau.uon.UonSerializerContext#UON_addBeanTypeProperties}
+					<li>{@link org.apache.juneau.xml.XmlSerializerContext#XML_addBeanTypeProperties}
+					<li>{@link org.apache.juneau.jena.RdfSerializerContext#RDF_addBeanTypeProperties}
+				</ul>
 			<li>UON notation serializers and parsers moved into the new <code>org.apache.juneau.uon</code> package.
 			<li>New {@link org.apache.juneau.xml.annotation.XmlFormat#VOID} format to identify HTML void elements.
 			<li>Tweaks to HTML5 support.
-			<ul>
-				<li>Fixed handling of empty non-void elements in HTML serializer.
-				<li>Added <code>style()</code> override methods to all elements.
-			</ul>
+				<ul>
+					<li>Fixed handling of empty non-void elements in HTML serializer.
+					<li>Added <code>style()</code> override methods to all elements.
+				</ul>
 			<li>Improvements to Swagger support.
-			<ul>
-				<li>New {@link org.apache.juneau.dto.swagger.SwaggerBuilder} class.
-				<li>Fluent-style setters added to the Swagger beans.
-				<li>Added Swagger examples <a href="#DTOs.Swagger">here</a> and in the <a class='doclink' href='org/apache/juneau/dto/swagger/package-summary.html#TOC'>org.apache.juneau.dto.swagger</a> javadocs.
-			</ul>
+				<ul>
+					<li>New {@link org.apache.juneau.dto.swagger.SwaggerBuilder} class.
+					<li>Fluent-style setters added to the Swagger beans.
+					<li>Added Swagger examples <a href="#DTOs.Swagger">here</a> and in the <a class='doclink' href='org/apache/juneau/dto/swagger/package-summary.html#TOC'>org.apache.juneau.dto.swagger</a> javadocs.
+				</ul>
 			<li>Improvements to {@link org.apache.juneau.svl.VarResolver}.
-			<ul>
-				<li>New {@link org.apache.juneau.svl.vars.IfVar $IF} variable for if-else block logic.
-				<li>New {@link org.apache.juneau.svl.vars.SwitchVar $SWITCH} variable for switch block logic.
-				<li>Whitespace wasn't being ignored in some cases.
-			</ul>
+				<ul>
+					<li>New {@link org.apache.juneau.svl.vars.IfVar $IF} variable for if-else block logic.
+					<li>New {@link org.apache.juneau.svl.vars.SwitchVar $SWITCH} variable for switch block logic.
+					<li>Whitespace wasn't being ignored in some cases.
+				</ul>
 			<li>{@link org.apache.juneau.html.HtmlParser} can now parse full body contents generated by {@link org.apache.juneau.html.HtmlDocSerializer}. 
 			<li>Parse-args supported added to {@link org.apache.juneau.msgpack.MsgPackParser} to allow it to be used in remoteable proxies. 
 			<li>Added some convenience classes for constructing collections using a fluent interface:
-			<ul>
-				<li>{@link org.apache.juneau.utils.AList}
-				<li>{@link org.apache.juneau.utils.ASet}
-				<li>{@link org.apache.juneau.utils.AMap}
-			</ul>
+				<ul>
+					<li>{@link org.apache.juneau.utils.AList}
+					<li>{@link org.apache.juneau.utils.ASet}
+					<li>{@link org.apache.juneau.utils.AMap}
+				</ul>
+			<li>New {@link org.apache.juneau.annotation.Bean#typePropertyName @Bean.typePropertyName()} annotation allows you to 
+				specify the name of the <js>"_type"</js> property at the class level.
 		</ul>
 		
 		<h6 class='topic'>org.apache.juneau.rest</h6>