[seam-commits] Seam SVN: r12333 - in modules/faces/trunk/src: main/java/org/jboss/seam/faces/context/conversation and 5 other directories.

seam-commits at lists.jboss.org seam-commits at lists.jboss.org
Tue Mar 30 18:44:08 EDT 2010


Author: lincolnthree
Date: 2010-03-30 18:44:07 -0400 (Tue, 30 Mar 2010)
New Revision: 12333

Added:
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FacesAnnotationsAdapterExtension.java
   modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/FacesAnnotationsAdapterExtensionTest.java
   modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/ImproperlyAnnotatedBean.java
Removed:
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/RetainsConversation.java
Modified:
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/Begin.java
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/ConversationBoundary.java
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/ConversationBoundaryInterceptor.java
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/End.java
   modules/faces/trunk/src/main/java/org/jboss/seam/faces/util/Annotations.java
   modules/faces/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
   modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/conversation/ConversationBoundaryInterceptorTest.java
   modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/conversation/ConversationalBean.java
   modules/faces/trunk/src/test/java/org/jboss/seam/faces/util/AnnotationTestObject.java
   modules/faces/trunk/src/test/java/org/jboss/seam/faces/util/AnnotationsTest.java
Log:
* Major updates for @Begin(permit={...}) and @End(permit={...})
* Added the FacesAnnotationAdapterExtension to help ease migration from legacy (DOA) JSF2 bean annotations.
* Added the Annotations utility class and Tests
* Tests tests tests!

Added: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FacesAnnotationsAdapterExtension.java
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FacesAnnotationsAdapterExtension.java	                        (rev 0)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/FacesAnnotationsAdapterExtension.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -0,0 +1,152 @@
+package org.jboss.seam.faces.context;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.enterprise.event.Observes;
+import javax.enterprise.inject.spi.AnnotatedConstructor;
+import javax.enterprise.inject.spi.AnnotatedField;
+import javax.enterprise.inject.spi.AnnotatedMethod;
+import javax.enterprise.inject.spi.AnnotatedType;
+import javax.enterprise.inject.spi.Extension;
+import javax.enterprise.inject.spi.ProcessAnnotatedType;
+import javax.enterprise.inject.spi.ProcessBean;
+
+/**
+ * Alias the JSF scope annotations to the CDI scope annotations. If a JSF scope
+ * annotation is detected, advise the developer to update the code to use the
+ * equivalent CDI scope annotation. Forbid the developer from using the JSF
+ * managed bean annotation.
+ * 
+ * @author Dan Allen
+ */
+public class FacesAnnotationsAdapterExtension implements Extension
+{
+   private final Map<Class<? extends Annotation>, Class<? extends Annotation>> scopeAliasMapping;
+
+   /*
+    * For unit testing
+    */
+   static final Map<Class<?>, Class<? extends Annotation>> aliasedBeans = new HashMap<Class<?>, Class<? extends Annotation>>();
+
+   public FacesAnnotationsAdapterExtension()
+   {
+      scopeAliasMapping = new HashMap<Class<? extends Annotation>, Class<? extends Annotation>>(3);
+      scopeAliasMapping.put(javax.faces.bean.RequestScoped.class, javax.enterprise.context.RequestScoped.class);
+      scopeAliasMapping.put(javax.faces.bean.SessionScoped.class, javax.enterprise.context.SessionScoped.class);
+      scopeAliasMapping.put(javax.faces.bean.ApplicationScoped.class, javax.enterprise.context.ApplicationScoped.class);
+   }
+
+   public void aliasJsfScopeIfDetected(@Observes final ProcessAnnotatedType<Object> annotatedType)
+   {
+      for (Class<? extends Annotation> scope : scopeAliasMapping.keySet())
+      {
+         if (annotatedType.getAnnotatedType().isAnnotationPresent(scope))
+         {
+            System.out.println("WARNING: Please annotate class " + annotatedType.getAnnotatedType().getJavaClass() + " with @" + scopeAliasMapping.get(scope).getName() + " instead of @" + scope.getName());
+            aliasedBeans.put(annotatedType.getAnnotatedType().getJavaClass(), scope);
+            annotatedType.setAnnotatedType(decorateType(annotatedType.getAnnotatedType(), scope));
+            break;
+         }
+      }
+   }
+
+   public void failIfJsfManagedBeanAnnotationPresent(@Observes final ProcessBean<?> bean)
+   {
+      if (bean.getAnnotated().isAnnotationPresent(javax.faces.bean.ManagedBean.class))
+      {
+         bean.addDefinitionError(new RuntimeException("Use of @javax.faces.bean.ManagedBean is forbidden. Please use @javax.inject.Named instead."));
+      }
+   }
+
+   private Class<? extends Annotation> getCdiScopeFor(final Class<? extends Annotation> jsfScope)
+   {
+      return scopeAliasMapping.get(jsfScope);
+   }
+
+   private AnnotatedType<Object> decorateType(final AnnotatedType<Object> type, final Class<? extends Annotation> jsfScope)
+   {
+      final Class<? extends Annotation> cdiScope = getCdiScopeFor(jsfScope);
+      final Annotation cdiScopeAnnotation = new Annotation()
+      {
+         public Class<? extends Annotation> annotationType()
+         {
+            return cdiScope;
+         }
+      };
+
+      final Set<Annotation> maskedAnnotations = new HashSet<Annotation>(type.getAnnotations());
+      maskedAnnotations.remove(type.getAnnotation(jsfScope));
+      maskedAnnotations.add(cdiScopeAnnotation);
+
+      return new AnnotatedType<Object>()
+      {
+         public Class<Object> getJavaClass()
+         {
+            return type.getJavaClass();
+         }
+
+         public Set<AnnotatedConstructor<Object>> getConstructors()
+         {
+            return type.getConstructors();
+         }
+
+         public Set<AnnotatedMethod<? super Object>> getMethods()
+         {
+            return type.getMethods();
+         }
+
+         public Set<AnnotatedField<? super Object>> getFields()
+         {
+            return type.getFields();
+         }
+
+         public Type getBaseType()
+         {
+            return type.getBaseType();
+         }
+
+         public Set<Type> getTypeClosure()
+         {
+            return type.getTypeClosure();
+         }
+
+         @SuppressWarnings("unchecked")
+         public <T extends Annotation> T getAnnotation(final Class<T> annotationType)
+         {
+            if (annotationType == jsfScope)
+            {
+               return null;
+            }
+            else if (annotationType == cdiScope)
+            {
+               return (T) cdiScopeAnnotation;
+            }
+
+            return type.getAnnotation(annotationType);
+         }
+
+         public Set<Annotation> getAnnotations()
+         {
+            return maskedAnnotations;
+         }
+
+         public boolean isAnnotationPresent(final Class<? extends Annotation> annotationType)
+         {
+            if (annotationType == jsfScope)
+            {
+               return false;
+            }
+            else if (annotationType == cdiScope)
+            {
+               return true;
+            }
+            return type.isAnnotationPresent(annotationType);
+         }
+      };
+   }
+}
\ No newline at end of file

Modified: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/Begin.java
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/Begin.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/Begin.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -8,15 +8,15 @@
 import java.lang.annotation.Target;
 
 import javax.enterprise.context.Conversation;
+import javax.enterprise.util.Nonbinding;
 import javax.interceptor.InterceptorBinding;
 
 /**
- * Marks the beginning of a persistent {@link Conversation}.
+ * Begins a persistent {@link Conversation}.
  * 
  *<p>
- * <b>Note:</b> If this method throws an exception, the conversation will be
- * discarded, unless the exception is annotated with @
- * {@link RetainsConversation}
+ * <b>Note:</b> Unless the exception is of a permitted type, if this method
+ * throws an exception, the conversation will not begin.
  * 
  * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
  */
@@ -27,9 +27,34 @@
 public @interface Begin
 {
    /**
-    * The new conversation ID. Seam will Generate a conversation ID if left
-    * blank. If a conversation with the ID already exists, TODO what should we
-    * do?
+    * Sets the new {@link Conversation} ID. Seam will Generate a conversation ID
+    * if left blank.
+    * <p>
+    * If a conversation with the ID already exists... TODO what should we do?
+    * <p>
+    * TODO test default conversation ID functionality
     */
+   @Nonbinding
    String id() default "";
+
+   /**
+    * Sets the {@link Conversation} timeout period, in milliseconds (E.g.: 5000
+    * = 5 seconds.)
+    * <p>
+    * TODO implement timeout support on @Begin
+    */
+   @Nonbinding
+   long timeout() default -1;
+
+   /**
+    * Sets the exception types for which, when encountered during a method
+    * invocation, the {@link Conversation} will still begin. (In other words:
+    * Permitted exceptions do not abort @{@link Begin})
+    * <p>
+    * <b>By default:</b> { empty array } - all encountered exceptions will
+    * prevent the {@link Conversation} from beginning.
+    */
+   @Nonbinding
+   Class<? extends Exception>[] permit() default {};
+
 }
\ No newline at end of file

Modified: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/ConversationBoundary.java
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/ConversationBoundary.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/ConversationBoundary.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -12,6 +12,11 @@
 
 /**
  * Parent annotation for @{@link Begin} and @{@link End}
+ * <p>
+ * <b>Note:</b> This should never be used.
+ * <p>
+ * TODO: Should we warn at startup if @{@link Begin} and @{@link End} are used
+ * together on the same method?
  * 
  * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
  */

Modified: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/ConversationBoundaryInterceptor.java
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/ConversationBoundaryInterceptor.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/ConversationBoundaryInterceptor.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -4,8 +4,9 @@
 package org.jboss.seam.faces.context.conversation;
 
 import java.io.Serializable;
-import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
 
 import javax.enterprise.context.Conversation;
 import javax.inject.Inject;
@@ -17,10 +18,10 @@
 import org.slf4j.Logger;
 
 /**
- * Intercepts methods annotated as Conversational entry points.
+ * Intercepts methods annotated as Conversational entry points: @{@link Begin}
+ * and @{@link End}
  * 
  * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
- * 
  */
 @ConversationBoundary
 @Interceptor
@@ -35,26 +36,76 @@
    Conversation conversation;
 
    @AroundInvoke
-   public Object before(final InvocationContext ctx) throws Exception
+   public Object around(final InvocationContext ctx) throws Exception
    {
       Object result = null;
+
+      try
+      {
+         if (Annotations.hasAnnotation(ctx.getMethod(), Begin.class))
+         {
+            beginConversation(ctx);
+         }
+
+         result = ctx.proceed();
+
+         if (Annotations.hasAnnotation(ctx.getMethod(), End.class))
+         {
+            endConversation(ctx);
+         }
+      }
+      catch (Exception e)
+      {
+         handleExceptionBegin(ctx, e);
+         handleExceptionEnd(ctx, e);
+         throw e;
+      }
+
+      return result;
+   }
+
+   private void handleExceptionBegin(final InvocationContext ctx, final Exception e)
+   {
       if (Annotations.hasAnnotation(ctx.getMethod(), Begin.class))
       {
-         result = beginConversation(ctx);
+         List<? extends Class<? extends Exception>> typesPermittedByBegin = getPermittedExceptionTypesBegin(ctx.getMethod());
+         for (Class<? extends Exception> type : typesPermittedByBegin)
+         {
+            if (type.isInstance(e) == false)
+            {
+               log.debug("Aborting conversation: (#0) for method: (#1.#2(...)) - Encountered Exception of type (#4), which is not in the list of exceptions permitted by @Begin.", new Object[] { conversation.getId(), ctx.getMethod().getDeclaringClass().getName(), ctx.getMethod().getName(), e.getClass().getName() });
+               conversation.end();
+            }
+         }
       }
 
+   }
+
+   private void handleExceptionEnd(final InvocationContext ctx, final Exception e)
+   {
       if (Annotations.hasAnnotation(ctx.getMethod(), End.class))
       {
-         endConversation(ctx);
+         List<? extends Class<? extends Exception>> typesPermittedByEnd = getPermittedExceptionTypesEnd(ctx.getMethod());
+         boolean permitted = false;
+         for (Class<? extends Exception> type : typesPermittedByEnd)
+         {
+            if (type.isInstance(e))
+            {
+               permitted = true;
+               conversation.end();
+            }
+         }
+         if (!permitted)
+         {
+            log.debug("Conversation will remain open: (#0) for method: (#1.#2(...)) - Encountered Exception of type (#4), which is not in the list of exceptions permitted by @End.", new Object[] { conversation.getId(), ctx.getMethod().getDeclaringClass().getName(), ctx.getMethod().getName(), e.getClass().getName() });
+         }
       }
-
-      return result;
    }
 
-   private Object beginConversation(final InvocationContext ctx) throws Exception
+   private void beginConversation(final InvocationContext ctx) throws Exception
    {
       String cid = getConversationId(ctx.getMethod());
-      if (cid != null)
+      if ((cid != null) && !"".equals(cid))
       {
          conversation.begin(cid);
       }
@@ -62,47 +113,27 @@
       {
          conversation.begin();
       }
-
-      log.debug("Began conversation: (#0) on method: (#1.#2(...))", new Object[] { conversation.getId(), ctx.getMethod().getDeclaringClass().getName(), ctx.getMethod().getName() });
-
-      try
-      {
-         Object result = ctx.proceed();
-         return result;
-      }
-      catch (Exception e)
-      {
-         conversation.end();
-         throw e;
-      }
+      log.debug("Began conversation: (#0) before method: (#1.#2(...))", new Object[] { conversation.getId(), ctx.getMethod().getDeclaringClass().getName(), ctx.getMethod().getName() });
    }
 
    private void endConversation(final InvocationContext ctx)
    {
+      log.debug("Ending conversation: (#0) after method: (#1.#2(...))", new Object[] { conversation.getId(), ctx.getMethod().getDeclaringClass().getName(), ctx.getMethod().getName() });
       conversation.end();
    }
 
    private String getConversationId(final Method m)
    {
-      String result = null;
-      for (Annotation a : m.getAnnotations())
-      {
-         if (a.annotationType().isAnnotationPresent(Begin.class))
-         {
-            result = a.annotationType().getAnnotation(Begin.class).id();
-         }
-      }
+      return Annotations.getAnnotation(m, Begin.class).id();
+   }
 
-      if (result == null)
-      {
-         for (Annotation a : m.getDeclaringClass().getAnnotations())
-         {
-            if (a.annotationType().isAnnotationPresent(Begin.class))
-            {
-               result = a.annotationType().getAnnotation(Begin.class).id();
-            }
-         }
-      }
-      return result;
+   private List<? extends Class<? extends Exception>> getPermittedExceptionTypesBegin(final Method m)
+   {
+      return Arrays.asList(Annotations.getAnnotation(m, Begin.class).permit());
    }
+
+   private List<? extends Class<? extends Exception>> getPermittedExceptionTypesEnd(final Method m)
+   {
+      return Arrays.asList(Annotations.getAnnotation(m, End.class).permit());
+   }
 }

Modified: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/End.java
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/End.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/End.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -8,15 +8,15 @@
 import java.lang.annotation.Target;
 
 import javax.enterprise.context.Conversation;
+import javax.enterprise.util.Nonbinding;
 import javax.interceptor.InterceptorBinding;
 
 /**
- * Marks the beginning of a persistent {@link Conversation}.
+ * Ends a persistent {@link Conversation}.
  * 
  *<p>
- * <b>Note:</b> If this method throws an exception, the conversation will be
- * discarded, unless the exception is annotated with @
- * {@link RetainsConversation}
+ * <b>Note:</b> Unless the exception is of a permitted type, if this method
+ * throws an exception, the conversation will not be ended.
  * 
  * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
  */
@@ -27,9 +27,14 @@
 public @interface End
 {
    /**
-    * The new conversation ID. Seam will Generate a conversation ID if left
-    * blank. If a conversation with the ID already exists, TODO what should we
-    * do?
+    * Sets the exception types for which, when encountered during a method
+    * invocation, the {@link Conversation} will still end. (In other words:
+    * These exceptions do not abort @{@link End})
+    * <p>
+    * <b>By default:</b> { empty array } - all encountered exceptions will cause
+    * the {@link Conversation} to remain open.
     */
-   String id() default "";
+   @Nonbinding
+   Class<? extends Exception>[] permit() default {};
+
 }
\ No newline at end of file

Deleted: modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/RetainsConversation.java
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/RetainsConversation.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/context/conversation/RetainsConversation.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -1,35 +0,0 @@
-package org.jboss.seam.faces.context.conversation;
-
-import static java.lang.annotation.ElementType.FIELD;
-import static java.lang.annotation.ElementType.PARAMETER;
-import static java.lang.annotation.RetentionPolicy.RUNTIME;
-
-import java.lang.annotation.Documented;
-import java.lang.annotation.Retention;
-import java.lang.annotation.Target;
-
-import javax.enterprise.context.Conversation;
-import javax.inject.Qualifier;
-
-/**
- * Marks the beginning of a persistent {@link Conversation}.
- * 
- *<p>
- * <b>Note:</b> If this method throws an exception, the conversation will be
- * discarded, unless the exception is annotated with {@link RetainsConversation}
- * 
- * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
- */
- at Qualifier
- at Target( { FIELD, PARAMETER })
- at Retention(RUNTIME)
- at Documented
-public @interface RetainsConversation
-{
-   /**
-    * The new conversation ID. Seam will Generate a conversation ID if left
-    * blank. If a conversation with the ID already exists, TODO what should we
-    * do?
-    */
-   String id() default "";
-}
\ No newline at end of file

Modified: modules/faces/trunk/src/main/java/org/jboss/seam/faces/util/Annotations.java
===================================================================
--- modules/faces/trunk/src/main/java/org/jboss/seam/faces/util/Annotations.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/main/java/org/jboss/seam/faces/util/Annotations.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -20,6 +20,9 @@
     * Discover if a Method <b>m</b> has been annotated with <b>type</b>. This
     * also discovers annotations defined through a @{@link Stereotype}.
     * 
+    * @param m The method to inspect.
+    * @param type The targeted annotation class
+    * 
     * @return True if annotation is present either on the method itself, or on
     *         the declaring class of the method. Returns false if the annotation
     *         is not present.
@@ -53,6 +56,9 @@
     * Discover if a Class <b>c</b> has been annotated with <b>type</b>. This
     * also discovers annotations defined through a @{@link Stereotype}.
     * 
+    * @param c The class to inspect.
+    * @param type The targeted annotation class
+    * 
     * @return True if annotation is present either on class, false if the
     *         annotation is not present.
     */
@@ -75,4 +81,60 @@
       }
       return result;
    }
+
+   /**
+    * Inspect method <b>m</b> for a specific <b>type</b> of annotation. This
+    * also discovers annotations defined through a @ {@link Stereotype}.
+    * 
+    * @param m The method to inspect.
+    * @param type The targeted annotation class
+    * 
+    * @return The annotation instance found on this method or enclosing class,
+    *         or null if no matching annotation was found.
+    */
+   public static <A extends Annotation> A getAnnotation(final Method m, final Class<A> type)
+   {
+      A result = m.getAnnotation(type);
+      if (result == null)
+      {
+         for (Annotation a : m.getAnnotations())
+         {
+            if (a.annotationType().isAnnotationPresent(type))
+            {
+               result = a.annotationType().getAnnotation(type);
+            }
+         }
+      }
+      if (result == null)
+      {
+         result = getAnnotation(m.getDeclaringClass(), type);
+      }
+      return result;
+   }
+
+   /**
+    * Inspect class <b>c</b> for a specific <b>type</b> of annotation. This also
+    * discovers annotations defined through a @ {@link Stereotype}.
+    * 
+    * @param c The class to inspect.
+    * @param type The targeted annotation class
+    * 
+    * @return The annotation instance found on this class, or null if no
+    *         matching annotation was found.
+    */
+   public static <A extends Annotation> A getAnnotation(final Class<?> c, final Class<A> type)
+   {
+      A result = c.getAnnotation(type);
+      if (result == null)
+      {
+         for (Annotation a : c.getAnnotations())
+         {
+            if (a.annotationType().isAnnotationPresent(type))
+            {
+               result = a.annotationType().getAnnotation(type);
+            }
+         }
+      }
+      return result;
+   }
 }

Modified: modules/faces/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
===================================================================
--- modules/faces/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension	2010-03-30 22:44:07 UTC (rev 12333)
@@ -1,2 +1,3 @@
 org.jboss.seam.faces.context.ViewScopedExtension
-org.jboss.seam.faces.context.FlashScopedExtension
\ No newline at end of file
+org.jboss.seam.faces.context.FlashScopedExtension
+org.jboss.seam.faces.context.FacesAnnotationsAdapterExtension
\ No newline at end of file

Added: modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/FacesAnnotationsAdapterExtensionTest.java
===================================================================
--- modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/FacesAnnotationsAdapterExtensionTest.java	                        (rev 0)
+++ modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/FacesAnnotationsAdapterExtensionTest.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -0,0 +1,35 @@
+/**
+ * 
+ */
+package org.jboss.seam.faces.context;
+
+import static org.junit.Assert.assertTrue;
+
+import org.jboss.arquillian.api.Deployment;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.shrinkwrap.api.ArchivePaths;
+import org.jboss.shrinkwrap.api.Archives;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.impl.base.asset.ByteArrayAsset;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * @author <a href="mailto:lincolnbaxter at gmail.com>Lincoln Baxter, III</a>
+ */
+ at RunWith(Arquillian.class)
+public class FacesAnnotationsAdapterExtensionTest
+{
+
+   @Deployment
+   public static JavaArchive createTestArchive()
+   {
+      return Archives.create("test.jar", JavaArchive.class).addClasses(ImproperlyAnnotatedBean.class).addManifestResource(new ByteArrayAsset(new byte[0]), ArchivePaths.create("beans.xml"));
+   }
+
+   @Test
+   public void testImproperlyAnnotatedClassIsCaptured()
+   {
+      assertTrue(FacesAnnotationsAdapterExtension.aliasedBeans.containsKey(ImproperlyAnnotatedBean.class));
+   }
+}

Added: modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/ImproperlyAnnotatedBean.java
===================================================================
--- modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/ImproperlyAnnotatedBean.java	                        (rev 0)
+++ modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/ImproperlyAnnotatedBean.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -0,0 +1,15 @@
+/**
+ * 
+ */
+package org.jboss.seam.faces.context;
+
+import javax.faces.bean.RequestScoped;
+
+/**
+ * @author <a href="mailto:lincolnbaxter at gmail.com>Lincoln Baxter, III</a>
+ * 
+ */
+ at RequestScoped
+public class ImproperlyAnnotatedBean
+{
+}

Modified: modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/conversation/ConversationBoundaryInterceptorTest.java
===================================================================
--- modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/conversation/ConversationBoundaryInterceptorTest.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/conversation/ConversationBoundaryInterceptorTest.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -61,4 +61,82 @@
       assertTrue(conversation.isTransient());
       assertTrue(interceptedBean.isConversationLongRunningDuringInvocation2());
    }
+
+   @Test
+   public void testConversationAbortsBeginOnFatalException()
+   {
+      assertTrue(conversation.isTransient());
+      assertFalse(interceptedBean.isConversationLongRunningDuringInvocation3());
+
+      try
+      {
+         interceptedBean.beginAndThrowFatalException();
+      }
+      catch (Exception e)
+      {
+         // expected
+      }
+
+      assertTrue(conversation.isTransient());
+      assertTrue(interceptedBean.isConversationLongRunningDuringInvocation3());
+   }
+
+   @Test
+   public void testConversationBeginsOnPermittedException()
+   {
+      assertTrue(conversation.isTransient());
+      assertFalse(interceptedBean.isConversationLongRunningDuringInvocation4());
+
+      try
+      {
+         interceptedBean.beginAndThrowPermittedException();
+      }
+      catch (Exception e)
+      {
+         // expected
+      }
+
+      assertFalse(conversation.isTransient());
+      assertTrue(interceptedBean.isConversationLongRunningDuringInvocation4());
+   }
+
+   @Test
+   public void testConversationAbortsEndOnFatalException()
+   {
+      assertTrue(conversation.isTransient());
+      assertFalse(interceptedBean.isConversationLongRunningDuringInvocation5());
+
+      try
+      {
+         interceptedBean.begin();
+         interceptedBean.endAndThrowFatalException();
+      }
+      catch (Exception e)
+      {
+         // expected
+      }
+
+      assertFalse(conversation.isTransient());
+      assertTrue(interceptedBean.isConversationLongRunningDuringInvocation5());
+   }
+
+   @Test
+   public void testConversationEndsOnPermittedException()
+   {
+      assertTrue(conversation.isTransient());
+      assertFalse(interceptedBean.isConversationLongRunningDuringInvocation6());
+
+      try
+      {
+         interceptedBean.begin();
+         interceptedBean.endAndThrowPermittedException();
+      }
+      catch (Exception e)
+      {
+         // expected
+      }
+
+      assertTrue(conversation.isTransient());
+      assertTrue(interceptedBean.isConversationLongRunningDuringInvocation6());
+   }
 }

Modified: modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/conversation/ConversationalBean.java
===================================================================
--- modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/conversation/ConversationalBean.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/test/java/org/jboss/seam/faces/context/conversation/ConversationalBean.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -7,6 +7,8 @@
 import javax.enterprise.context.RequestScoped;
 import javax.inject.Inject;
 
+import org.jboss.seam.faces.SeamFacesException;
+
 /**
  * @author <a href="mailto:lincolnbaxter at gmail.com">Lincoln Baxter, III</a>
  * 
@@ -17,11 +19,20 @@
    @Inject
    Conversation conversation;
 
-   private boolean conversationLongRunningDuringInvocation = false;
-
+   private boolean conversationLongRunningDuringInvocation;
    private boolean conversationLongRunningDuringInvocation2;
+   private boolean conversationLongRunningDuringInvocation3;
+   private boolean conversationLongRunningDuringInvocation4;
+   private boolean conversationLongRunningDuringInvocation5;
 
+   private boolean conversationLongRunningDuringInvocation6;
+
    @Begin
+   public void begin()
+   {
+   }
+
+   @Begin
    public void beginConversation()
    {
       if (!conversation.isTransient())
@@ -34,22 +45,80 @@
    @End
    public void beginAndEndConversation()
    {
-      conversationLongRunningDuringInvocation2 = true;
+      if (!conversation.isTransient())
+      {
+         conversationLongRunningDuringInvocation2 = true;
+      }
    }
 
-   public boolean isConversationLongRunningDuringInvocation2()
+   @Begin(permit = { SeamFacesException.class })
+   public void beginAndThrowFatalException()
    {
-      return conversationLongRunningDuringInvocation2;
+      if (!conversation.isTransient())
+      {
+         conversationLongRunningDuringInvocation3 = true;
+      }
+      throw new RuntimeException("A vanilla exception.");
    }
 
-   public void setConversationLongRunningDuringInvocation2(final boolean conversationLongRunningDuringInvocation2)
+   @Begin(permit = { SeamFacesException.class })
+   public void beginAndThrowPermittedException()
    {
-      this.conversationLongRunningDuringInvocation2 = conversationLongRunningDuringInvocation2;
+      if (!conversation.isTransient())
+      {
+         conversationLongRunningDuringInvocation4 = true;
+      }
+      throw new SeamFacesException("Just so it's not a vanilla Exception.");
    }
 
+   @End(permit = { SeamFacesException.class })
+   public void endAndThrowFatalException()
+   {
+      if (!conversation.isTransient())
+      {
+         conversationLongRunningDuringInvocation5 = true;
+      }
+      throw new RuntimeException("A vanilla exception.");
+   }
+
+   @End(permit = { SeamFacesException.class })
+   public void endAndThrowPermittedException()
+   {
+      if (!conversation.isTransient())
+      {
+         conversationLongRunningDuringInvocation6 = true;
+      }
+      throw new SeamFacesException("A vanilla exception.");
+   }
+
    public boolean isConversationLongRunningInsideMethodCall()
    {
       return conversationLongRunningDuringInvocation;
    }
 
+   public boolean isConversationLongRunningDuringInvocation2()
+   {
+      return conversationLongRunningDuringInvocation2;
+   }
+
+   public boolean isConversationLongRunningDuringInvocation3()
+   {
+      return conversationLongRunningDuringInvocation3;
+   }
+
+   public boolean isConversationLongRunningDuringInvocation4()
+   {
+      return conversationLongRunningDuringInvocation4;
+   }
+
+   public boolean isConversationLongRunningDuringInvocation5()
+   {
+      return conversationLongRunningDuringInvocation5;
+   }
+
+   public boolean isConversationLongRunningDuringInvocation6()
+   {
+      return conversationLongRunningDuringInvocation6;
+   }
+
 }

Modified: modules/faces/trunk/src/test/java/org/jboss/seam/faces/util/AnnotationTestObject.java
===================================================================
--- modules/faces/trunk/src/test/java/org/jboss/seam/faces/util/AnnotationTestObject.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/test/java/org/jboss/seam/faces/util/AnnotationTestObject.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -16,4 +16,9 @@
    {
    }
 
+   @End(permit = { Exception.class })
+   public void endPermittingExceptions()
+   {
+
+   }
 }

Modified: modules/faces/trunk/src/test/java/org/jboss/seam/faces/util/AnnotationsTest.java
===================================================================
--- modules/faces/trunk/src/test/java/org/jboss/seam/faces/util/AnnotationsTest.java	2010-03-30 20:34:51 UTC (rev 12332)
+++ modules/faces/trunk/src/test/java/org/jboss/seam/faces/util/AnnotationsTest.java	2010-03-30 22:44:07 UTC (rev 12333)
@@ -43,4 +43,20 @@
       assertTrue(Annotations.hasAnnotation(end, Begin.class));
    }
 
+   public void testGetAnnotationOnMethodDirectly() throws Exception
+   {
+      Method end = AnnotationTestObject.class.getMethod("end", new Class[] {});
+      End anno = Annotations.getAnnotation(end, End.class);
+
+      assertTrue(anno instanceof End);
+   }
+
+   public void testGetAnnotationOnMethodIndirectlyFromClass() throws Exception
+   {
+      Method end = AnnotationTestObject.class.getMethod("begin", new Class[] {});
+      Begin anno = Annotations.getAnnotation(end, Begin.class);
+
+      assertTrue(anno instanceof Begin);
+   }
+
 }



More information about the seam-commits mailing list