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 2016/08/30 20:12:05 UTC

incubator-juneau git commit: Simplify @Bean(subTypes) annotation.

Repository: incubator-juneau
Updated Branches:
  refs/heads/master 4b2719c0d -> 4fb5136f8


Simplify @Bean(subTypes) annotation.

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

Branch: refs/heads/master
Commit: 4fb5136f8fe6fa806c86a5779d52c37185e2c3ea
Parents: 4b2719c
Author: jamesbognar <ja...@gmail.com>
Authored: Tue Aug 30 16:11:57 2016 -0400
Committer: jamesbognar <ja...@gmail.com>
Committed: Tue Aug 30 16:11:57 2016 -0400

----------------------------------------------------------------------
 .../java/org/apache/juneau/BeanContext.java     | 11 +++
 .../main/java/org/apache/juneau/ClassMeta.java  | 12 +++-
 .../main/java/org/apache/juneau/ObjectMap.java  | 13 +++-
 .../java/org/apache/juneau/annotation/Bean.java | 73 +++++++++++++++++++-
 .../java/org/apache/juneau/annotation/Pojo.java | 72 +++++++++++++++++++
 .../apache/juneau/internal/ReflectionUtils.java | 13 ++++
 .../juneau/transform/AnnotationBeanFilter.java  | 14 +++-
 .../java/org/apache/juneau/BeanFilterTest.java  | 14 ++--
 .../juneau/a/rttests/RoundTripBeanMapsTest.java | 16 ++---
 .../a/rttests/RoundTripTransformBeansTest.java  |  5 +-
 10 files changed, 217 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
index 8b260bc..9b9ce4a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/BeanContext.java
@@ -446,6 +446,10 @@ public class BeanContext extends Context {
 	 */
 	public static final String BEAN_implClasses_put = "BeanContext.implClasses.map.put";
 
+	public static final String BEAN_classLexicon = "BeanContext.pojoSwaps.list";
+	public static final String BEAN_classLexicon_add = "BeanContext.pojoSwaps.list.add";
+	public static final String BEAN_classLexicon_remove = "BeanContext.pojoSwaps.list.remove";
+
 	/**
 	 * Specifies the default parser to use when converting <code>Strings</code> to POJOs in the {@link BeanContext#convertToType(Object, Class)} method (<code>Class</code>).
 	 */
@@ -525,6 +529,7 @@ public class BeanContext extends Context {
 	final String[] notBeanPackageNames, notBeanPackagePrefixes;
 	final BeanFilter<?>[] beanFilters;
 	final PojoSwap<?,?>[] pojoSwaps;
+	final ClassLexicon classLexicon;
 	final Map<Class<?>,Class<?>> implClasses;
 	final Class<?>[] implKeyClasses, implValueClasses;
 	final ClassLoader classLoader;
@@ -615,6 +620,8 @@ public class BeanContext extends Context {
 		}
  		pojoSwaps = lpf.toArray(new PojoSwap[0]);
 
+ 		classLexicon = new ClassLexicon(pm.get(BEAN_pojoSwaps, Class[].class, new Class[0]));
+
  		implClasses = new TreeMap<Class<?>,Class<?>>(new ClassComparator());
  		Map<Class,Class> m = pm.getMap(BEAN_implClasses, Class.class, Class.class, null);
  		if (m != null)
@@ -1456,6 +1463,10 @@ public class BeanContext extends Context {
 		return null;
 	}
 
+	protected ClassLexicon getClassLexicon() {
+		return classLexicon;
+	}
+
 	/**
 	 * Gets the no-arg constructor for the specified class.
 	 *

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/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 eb60730..ba31b41 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ClassMeta.java
@@ -83,6 +83,7 @@ public final class ClassMeta<T> implements Type {
 		isMemberClass;                                // True if this is a non-static member class.
 
 	private MetadataMap extMeta = new MetadataMap();  // Extended metadata
+	private ClassLexicon classLexicon;
 
 	private Throwable initException;                   // Any exceptions thrown in the init() method.
 	private boolean hasChildPojoSwaps;                 // True if this class or any subclass of this class has a PojoSwap associated with it.
@@ -128,6 +129,15 @@ public final class ClassMeta<T> implements Type {
 		try {
 			beanFilter = findBeanFilter(beanContext);
 			pojoSwap = findPojoSwap(beanContext);
+
+			classLexicon = beanContext.getClassLexicon();
+			for (Pojo p : ReflectionUtils.findAnnotationsParentFirst(Pojo.class, innerClass))
+				if (p.lexicon().length > 0)
+					classLexicon = new ClassLexicon(classLexicon, p.lexicon());
+			for (Bean b : ReflectionUtils.findAnnotationsParentFirst(Bean.class, innerClass))
+				if (b.lexicon().length > 0)
+					classLexicon = new ClassLexicon(classLexicon, b.lexicon());
+
 			serializedClassMeta = (pojoSwap == null ? this : beanContext.getClassMeta(pojoSwap.getSwapClass()));
 			if (serializedClassMeta == null)
 				serializedClassMeta = this;
@@ -394,7 +404,7 @@ public final class ClassMeta<T> implements Type {
 	}
 
 	/**
-	 * Returns <jk>true</jk> if this class as subtypes defined through {@link Bean#subTypes} or {@link BeanFilter#getSubTypes()}.
+	 * Returns <jk>true</jk> if this class as subtypes defined through {@link Bean#subTypes}.
 	 *
 	 * @return <jk>true</jk> if this class has subtypes.
 	 */

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/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 93dad9d..6edebf5 100644
--- a/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
+++ b/juneau-core/src/main/java/org/apache/juneau/ObjectMap.java
@@ -1150,12 +1150,21 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 	 * 	same object if entry does not exist.
 	 */
 	public Object cast() {
+		return cast((ClassLexicon)null);
+	}
+
+	public Object cast(ClassLexicon classLexicon) {
 		String c = (String)get("_class");
 		if (c == null) {
 			if (containsKey("_value"))
 				return get("_value");
 			return this;
 		}
+		if (classLexicon != null) {
+			Class<?> c2 = classLexicon.getClassForName(c);
+			if (c2 != null)
+				return cast2(beanContext.getClassMeta(c2));
+		}
 		return cast2(beanContext.getClassMetaFromString(c));
 	}
 
@@ -1249,7 +1258,7 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 
 						// Attempt to recursively cast child maps.
 						if (v instanceof ObjectMap)
-							v = ((ObjectMap)v).cast();
+							v = ((ObjectMap)v).cast(beanContext.classLexicon);
 
 						k = (kType.isString() ? k : beanContext.convertToType(k, kType));
 						v = (vType.isObject() ? v : beanContext.convertToType(v, vType));
@@ -1270,7 +1279,7 @@ public class ObjectMap extends LinkedHashMap<String,Object> {
 
 						// Attempt to recursively cast child maps.
 						if (v instanceof ObjectMap)
-							v = ((ObjectMap)v).cast();
+							v = ((ObjectMap)v).cast(beanContext.classLexicon);
 
 						bm.put(k, v);
 					}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/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 dd436a2..34b6414 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
@@ -42,6 +42,77 @@ import org.apache.juneau.transform.*;
 public @interface Bean {
 
 	/**
+	 * An identifying name for this class.
+	 * <p>
+	 * The name is used to identify the class type during parsing when it cannot be inferred through reflection.
+	 * For example, if a bean property is of type <code>Object</code>, then the serializer will add the name to the
+	 * 	output so that the class can be determined during parsing.
+	 * It is also used to specify element names in XML.
+	 * <p>
+	 * The name is used in combination with the lexicon defined through {@link #lexicon()}.  Together, they make up
+	 * 	a simple name/value mapping of names to classes.
+	 * Names do not need to be universally unique.  However, they must be unique within a lexicon.
+	 *
+	 * <dl>
+	 * 	<dt>Example:</dt>
+	 * 	<dd>
+	 * 		<p class='bcode'>
+	 * 	<ja>@Bean</ja>(name=<js>"foo"</js>)
+	 * 	<jk>public class</jk> Foo {
+	 * 		<jc>// A bean property where the object types cannot be inferred since it's an Object[].</jc>
+	 * 	   <ja>@BeanProperty</ja>(lexicon={Bar.<jk>class</jk>,Baz.<jk>class</jk>})
+	 * 	   <jk>public</jk> Object[] x = <jk>new</jk> Object[]{<jk>new</jk> Bar(), <jk>new</jk> Baz()};
+	 * 	}
+	 *
+	 * 	<ja>@Bean</ja>(name=<js>"bar"</js>)
+	 * 	<jk>public class</jk> Bar {}
+	 *
+	 * 	<ja>@Bean</ja>(name=<js>"baz"</js>)
+	 * 	<jk>public class</jk> Baz {}
+	 * 		</p>
+	 * 		<p>
+	 * 			When serialized as XML, the bean is rendered as:
+	 * 		</p>
+	 * 		<p class='bcode'>
+	 * 	<xt>&lt;foo&gt;</xt>
+	 * 	   <xt>&lt;x&gt;</xt>
+	 * 	      <xt>&lt;bar/&gt;v
+	 * 	      <xt>&lt;baz/&gt;</xt>
+	 * 	   <xt>&lt;/x&gt;</xt>
+	 * 	<xt>&lt;/foo&gt;</xt>
+	 * 		</p>
+	 * 		<p>
+	 * 			When serialized as JSON, <js>'n'</js> attributes would be added when needed to infer the type during parsing:
+	 * 		</p>
+	 * 		<p class='bcode'>
+	 * 	{
+	 * 	   <jsa>x</jsa>: [
+	 * 	      {<jsa>n</jsa>:<jss>'bar'</jss>},
+	 * 	      {<jsa>n</jsa>:<jss>'baz'</jss>}
+	 * 	   ]
+	 * 	}	 *
+	 * 	</dd>
+	 * </dl>
+	 */
+	String name() default "";
+
+	/**
+	 * The list of classes that make up the class lexicon for this class.
+	 * <p>
+	 * The lexicon is a name/class mapping used to find class types during parsing when they cannot be inferred through reflection.
+	 * The names are defined through the {@link #name()} annotation defined on the bean or POJO classes.
+	 * <p>
+	 * This list can consist of the following class types:
+	 * <ul>
+	 * 	<li>Any bean class that specifies a value for {@link Bean#name() @Bean.name()};
+	 * 	<li>Any POJO class that specifies a value for {@link Pojo#name() @Pojo.name()};
+	 * 	<li>Any subclass of {@link ClassLexicon} that defines an entire set of mappings.
+	 * 		Note that the subclass MUST implement a no-arg constructor so that it can be instantiated.
+	 * </ul>
+	 */
+	Class<?>[] lexicon() default {};
+
+	/**
 	 * The set and order of names of properties associated with a bean class.
 	 * <p>
 	 * 	The order specified is the same order that the entries will be returned by the {@link BeanMap#entrySet()} and related methods.
@@ -177,7 +248,7 @@ public @interface Bean {
 	/**
 	 * Used in conjunction with {@link #subTypeProperty()} to set up bean subtypes.
 	 */
-	BeanSubType[] subTypes() default {};
+	Class<?>[] subTypes() default {};
 
 	/**
 	 * Identifies a class to be used as the interface class for this and all subclasses.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/juneau-core/src/main/java/org/apache/juneau/annotation/Pojo.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/annotation/Pojo.java b/juneau-core/src/main/java/org/apache/juneau/annotation/Pojo.java
index f200622..9d615c1 100644
--- a/juneau-core/src/main/java/org/apache/juneau/annotation/Pojo.java
+++ b/juneau-core/src/main/java/org/apache/juneau/annotation/Pojo.java
@@ -17,6 +17,7 @@ import static java.lang.annotation.RetentionPolicy.*;
 
 import java.lang.annotation.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.transform.*;
 
@@ -32,6 +33,77 @@ import org.apache.juneau.transform.*;
 public @interface Pojo {
 
 	/**
+	 * An identifying name for this class.
+	 * <p>
+	 * The name is used to identify the class type during parsing when it cannot be inferred through reflection.
+	 * For example, if a bean property is of type <code>Object</code>, then the serializer will add the name to the
+	 * 	output so that the class can be determined during parsing.
+	 * It is also used to specify element names in XML.
+	 * <p>
+	 * The name is used in combination with the lexicon defined through {@link #lexicon()}.  Together, they make up
+	 * 	a simple name/value mapping of names to classes.
+	 * Names do not need to be universally unique.  However, they must be unique within a lexicon.
+	 *
+	 * <dl>
+	 * 	<dt>Example:</dt>
+	 * 	<dd>
+	 * 		<p class='bcode'>
+	 * 	<ja>@Bean</ja>(name=<js>"foo"</js>)
+	 * 	<jk>public class</jk> Foo {
+	 * 		<jc>// A bean property where the object types cannot be inferred since it's an Object[].</jc>
+	 * 	   <ja>@BeanProperty</ja>(lexicon={Bar.<jk>class</jk>,Baz.<jk>class</jk>})
+	 * 	   <jk>public</jk> Object[] x = <jk>new</jk> Object[]{<jk>new</jk> Bar(), <jk>new</jk> Baz()};
+	 * 	}
+	 *
+	 * 	<ja>@Pojo</ja>(name=<js>"bar"</js>)
+	 * 	<jk>public class</jk> Bar <jk>extends</jk> HashMap {}
+	 *
+	 * 	<ja>@Pojo</ja>(name=<js>"baz"</js>)
+	 * 	<jk>public class</jk> Baz <jk>extends</jk> HashMap {}
+	 * 		</p>
+	 * 		<p>
+	 * 			When serialized as XML, the bean is rendered as:
+	 * 		</p>
+	 * 		<p class='bcode'>
+	 * 	<xt>&lt;foo&gt;</xt>
+	 * 	   <xt>&lt;x&gt;</xt>
+	 * 	      <xt>&lt;bar/&gt;v
+	 * 	      <xt>&lt;baz/&gt;</xt>
+	 * 	   <xt>&lt;/x&gt;</xt>
+	 * 	<xt>&lt;/foo&gt;</xt>
+	 * 		</p>
+	 * 		<p>
+	 * 			When serialized as JSON, <js>'n'</js> attributes would be added when needed to infer the type during parsing:
+	 * 		</p>
+	 * 		<p class='bcode'>
+	 * 	{
+	 * 	   <jsa>x</jsa>: [
+	 * 	      {<jsa>n</jsa>:<jss>'bar'</jss>},
+	 * 	      {<jsa>n</jsa>:<jss>'baz'</jss>}
+	 * 	   ]
+	 * 	}	 *
+	 * 	</dd>
+	 * </dl>
+	 */
+	String name() default "";
+
+	/**
+	 * The list of classes that make up the class lexicon for this class.
+	 * <p>
+	 * The lexicon is a name/class mapping used to find class types during parsing when they cannot be inferred through reflection.
+	 * The names are defined through the {@link #name()} annotation defined on the bean or POJO classes.
+	 * <p>
+	 * This list can consist of the following class types:
+	 * <ul>
+	 * 	<li>Any bean class that specifies a value for {@link Bean#name() @Bean.name()};
+	 * 	<li>Any POJO class that specifies a value for {@link Pojo#name() @Pojo.name()};
+	 * 	<li>Any subclass of {@link ClassLexicon} that defines an entire set of mappings.
+	 * 		Note that the subclass MUST implement a no-arg constructor so that it can be instantiated.
+	 * </ul>
+	 */
+	Class<?>[] lexicon() default {};
+
+	/**
 	 * Associate a {@link PojoSwap} or {@link SurrogateSwap} with this class type.
 	 *
 	 * <p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java b/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java
index 0936d91..c1686ab 100644
--- a/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java
+++ b/juneau-core/src/main/java/org/apache/juneau/internal/ReflectionUtils.java
@@ -91,6 +91,19 @@ public final class ReflectionUtils {
 	}
 
 	/**
+	 * Same as {@link #findAnnotations(Class, Class)} but returns the list in parent-to-child order.
+	 *
+	 * @param a The annotation class type.
+	 * @param c The class being searched.
+	 * @return The found matches, or an empty array if annotation was not found.
+	 */
+	public static <T extends Annotation> List<T> findAnnotationsParentFirst(Class<T> a, Class<?> c) {
+		List<T> l = findAnnotations(a, c);
+		Collections.reverse(l);
+		return l;
+	}
+
+	/**
 	 * Sames as {@link #findAnnotations(Class, Class)} except returns the annotations as a map
 	 * with the keys being the class on which the annotation was found.
 	 * <p>

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
index dd8cb4d..24c6d5a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilter.java
@@ -88,8 +88,18 @@ public final class AnnotationBeanFilter<T> extends BeanFilter<T> {
 				if (! b.subTypeProperty().isEmpty()) {
 					subTypeProperty = b.subTypeProperty();
 
-					for (BeanSubType bst : b.subTypes())
-						subTypes.put(bst.type(), bst.id());
+					for (Class<?> bst : b.subTypes()) {
+						Bean b2 = bst.getAnnotation(Bean.class);
+						Pojo p2 = bst.getAnnotation(Pojo.class);
+						String name = null;
+						if (! b2.name().isEmpty())
+							name = b2.name();
+						else if (! p2.name().isEmpty())
+							name = p2.name();
+						else
+							name = bst.getName();
+						subTypes.put(bst, name);
+					}
 				}
 			}
 		}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/juneau-core/src/test/java/org/apache/juneau/BeanFilterTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/test/java/org/apache/juneau/BeanFilterTest.java b/juneau-core/src/test/java/org/apache/juneau/BeanFilterTest.java
index 78fe620..c2da6ab 100755
--- a/juneau-core/src/test/java/org/apache/juneau/BeanFilterTest.java
+++ b/juneau-core/src/test/java/org/apache/juneau/BeanFilterTest.java
@@ -55,39 +55,37 @@ public class BeanFilterTest {
 
 	@Bean(
 		subTypeProperty="subType",
-		subTypes={
-			@BeanSubType(type=A1.class, id="A1"),
-			@BeanSubType(type=A2.class, id="A2")
-		}
+		subTypes={A1.class,A2.class}
 	)
 	public static abstract class A {
 		public String f0 = "f0";
 		public B fb;
 	}
 
+	@Bean(name="A1")
 	public static class A1 extends A {
 		public String f1;
 	}
 
+	@Bean(name="A2")
 	public static class A2 extends A {
 		public String f2;
 	}
 
 	@Bean(
 		subTypeProperty="subType",
-		subTypes={
-			@BeanSubType(type=B1.class, id="B1"),
-			@BeanSubType(type=B2.class, id="B2")
-		}
+		subTypes={B1.class,B2.class}
 	)
 	public static abstract class B {
 		public String f0b = "f0b";
 	}
 
+	@Bean(name="B1")
 	public static class B1 extends B {
 		public String f1;
 	}
 
+	@Bean(name="B2")
 	public static class B2 extends B {
 		public String f2;
 	}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
index 143c677..060f52a 100755
--- a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
+++ b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripBeanMapsTest.java
@@ -249,16 +249,13 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
 
 	@Bean(
 		subTypeProperty="subType",
-		subTypes={
-			@BeanSubType(type=B1.class, id="B1"),
-			@BeanSubType(type=B2.class, id="B2"),
-			@BeanSubType(type=B3.class, id="B3")
-		}
+		subTypes={B1.class,B2.class,B3.class}
 	)
 	public abstract static class B {
 		public String f0 = "f0";
 	}
 
+	@Bean(name="B1")
 	public static class B1 extends B {
 		public String f1;
 		public static B1 create() {
@@ -269,6 +266,7 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
 		}
 	}
 
+	@Bean(name="B2")
 	public static class B2 extends B {
 		public int f2;
 		public static B2 create() {
@@ -279,6 +277,7 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
 		}
 	}
 
+	@Bean(name="B3")
 	public static class B3 extends B {
 		public XMLGregorianCalendar f3;
 		public static B3 create() throws Exception {
@@ -387,15 +386,13 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
 
 	@Bean(
 		subTypeProperty="subType",
-		subTypes={
-			@BeanSubType(type=BA1.class, id="BA1"),
-			@BeanSubType(type=BA2.class, id="BA2")
-		}
+		subTypes={BA1.class,BA2.class}
 	)
 	public abstract static class BA {
 		public String f0a, subType, f0b;
 	}
 
+	@Bean(name="BA1")
 	public static class BA1 extends BA {
 		public String f1;
 		public static BA1 create() {
@@ -408,6 +405,7 @@ public class RoundTripBeanMapsTest extends RoundTripTest {
 		}
 	}
 
+	@Bean(name="BA2")
 	public static class BA2 extends BA {
 		public String f2;
 	}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/4fb5136f/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java
index 14414e8..4ac7270 100755
--- a/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java
+++ b/juneau-core/src/test/java/org/apache/juneau/a/rttests/RoundTripTransformBeansTest.java
@@ -281,9 +281,7 @@ public class RoundTripTransformBeansTest extends RoundTripTest {
 
 	@Bean(
 		subTypeProperty="type",
-		subTypes={
-			@BeanSubType(id="C3", type=C3.class)
-		}
+		subTypes={C3.class}
 	)
 	public static interface C1<T> extends Serializable {
 		void setF1(T f1);
@@ -304,6 +302,7 @@ public class RoundTripTransformBeansTest extends RoundTripTest {
 		}
 	}
 
+	@Bean(name="C3")
 	public static class C3<T> extends C2<T> {
 
 		public static C3 create() {