[webbeans-commits] Webbeans SVN: r1752 - ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bootstrap and 8 other directories.

webbeans-commits at lists.jboss.org webbeans-commits at lists.jboss.org
Tue Mar 3 13:04:56 EST 2009


Author: dallen6
Date: 2009-03-03 13:04:55 -0500 (Tue, 03 Mar 2009)
New Revision: 1752

Added:
   ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/transaction/
   ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/transaction/spi/
   ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/transaction/spi/TransactionServices.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/ObserverFactory.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/TransactionalObserverImpl.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/mock/MockTransactionServices.java
Modified:
   ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/bootstrap/api/Bootstrap.java
   ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/bootstrap/api/helpers/AbstractBootstrap.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ManagerImpl.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bootstrap/BeanDeployer.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bootstrap/WebBeansBootstrap.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/DeferredEventNotification.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/ObserverImpl.java
   ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/mock/MockLifecycle.java
   tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/Agent.java
   tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/DogAgent.java
   tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/EventTest.java
   tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/Pomeranian.java
   tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/PomeranianInterface.java
Log:
Changes to support transactional observers; new RI SPI class added; refactored observer method implicit objects.

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ManagerImpl.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ManagerImpl.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/ManagerImpl.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -73,6 +73,7 @@
 import org.jboss.webbeans.metadata.MetaDataCache;
 import org.jboss.webbeans.resources.spi.NamingContext;
 import org.jboss.webbeans.resources.spi.ResourceLoader;
+import org.jboss.webbeans.transaction.spi.TransactionServices;
 import org.jboss.webbeans.util.Beans;
 import org.jboss.webbeans.util.Reflections;
 
@@ -126,6 +127,9 @@
    private transient final EjbDescriptorCache ejbDescriptorCache;
 
    private transient final ResourceLoader resourceLoader;
+   
+   // The transaction management related services provided by the container
+   private transient final TransactionServices transactionServices;
 
    // The Naming (JNDI) access
    private transient final NamingContext namingContext;
@@ -137,11 +141,12 @@
     * 
     * @param ejbResolver the ejbResolver to use
     */
-   public ManagerImpl(NamingContext namingContext, EjbResolver ejbResolver, ResourceLoader resourceLoader)
+   public ManagerImpl(NamingContext namingContext, EjbResolver ejbResolver, ResourceLoader resourceLoader, TransactionServices transactionServices)
    {
       this.ejbResolver = ejbResolver;
       this.namingContext = namingContext;
       this.resourceLoader = resourceLoader;
+      this.transactionServices = transactionServices;
       this.beans = new CopyOnWriteArrayList<Bean<?>>();
       this.newEnterpriseBeanMap = new ConcurrentHashMap<Class<?>, EnterpriseBean<?>>();
       this.enterpriseBeanMap = new ConcurrentHashMap<Class<?>, EnterpriseBean<?>>();
@@ -884,6 +889,11 @@
       return resourceLoader;
    }
 
+   public TransactionServices getTransactionServices()
+   {
+      return transactionServices;
+   }
+
    /**
     * Accesses the factory used to create each instance of InjectionPoint that
     * is injected into web beans.

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bootstrap/BeanDeployer.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bootstrap/BeanDeployer.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bootstrap/BeanDeployer.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -26,6 +26,7 @@
 import org.jboss.webbeans.bean.RIBean;
 import org.jboss.webbeans.bean.SimpleBean;
 import org.jboss.webbeans.ejb.EJBApiAbstraction;
+import org.jboss.webbeans.event.ObserverFactory;
 import org.jboss.webbeans.event.ObserverImpl;
 import org.jboss.webbeans.introspector.AnnotatedClass;
 import org.jboss.webbeans.introspector.AnnotatedField;
@@ -190,7 +191,7 @@
    
    private void createObserverMethod(AbstractClassBean<?> declaringBean, AnnotatedMethod<?> method)
    {
-      ObserverImpl<?> observer = ObserverImpl.of(method, declaringBean, manager);
+      ObserverImpl<?> observer = ObserverFactory.create(method, declaringBean, manager);
       manager.addObserver(observer);
    }
    

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bootstrap/WebBeansBootstrap.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bootstrap/WebBeansBootstrap.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/bootstrap/WebBeansBootstrap.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -81,7 +81,11 @@
       {
          throw new IllegalStateException("EjbResolver is not set");
       }
-      this.manager = new ManagerImpl(getNamingContext(), getEjbResolver(), getResourceLoader());
+      if (getTransactionServices() == null)
+      {
+         throw new IllegalStateException("TransactionServices is not set");
+      }
+      this.manager = new ManagerImpl(getNamingContext(), getEjbResolver(), getResourceLoader(), getTransactionServices());
       getManager().getNaming().bind(ManagerImpl.JNDI_KEY, getManager());
       CurrentManager.setRootManager(manager);
       initializeContexts();

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/DeferredEventNotification.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/DeferredEventNotification.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/DeferredEventNotification.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -17,26 +17,18 @@
 
 package org.jboss.webbeans.event;
 
-import static org.jboss.webbeans.event.ObserverImpl.TransactionObservationPhase.AFTER_COMPLETION;
-import static org.jboss.webbeans.event.ObserverImpl.TransactionObservationPhase.AFTER_FAILURE;
-import static org.jboss.webbeans.event.ObserverImpl.TransactionObservationPhase.AFTER_SUCCESS;
-import static org.jboss.webbeans.event.ObserverImpl.TransactionObservationPhase.BEFORE_COMPLETION;
-
 import javax.event.Observer;
-import javax.transaction.Status;
-import javax.transaction.Synchronization;
 
 /**
- * A synchronization object which will deliver the event to the observer after
- * the JTA transaction currently in effect is committed.
+ * A task that will notify the observer of a specific event at some
+ * future time.
  * 
  * @author David Allen
- * @see javax.transaction.Synchronization
  */
-public class DeferredEventNotification<T> implements Synchronization
+public class DeferredEventNotification<T> implements Runnable
 {
    // The observer
-   private ObserverImpl<T> observer;
+   private Observer<T> observer;
    // The event object
    private T event;
 
@@ -48,53 +40,13 @@
     */
    public DeferredEventNotification(T event, Observer<T> observer)
    {
-      this.observer = (ObserverImpl<T>) observer;
+      this.observer = observer;
       this.event = event;
    }
 
-   /**
-    * Called after completion of a transaction
-    * 
-    * Checks if the observer is interested in this particular transaction phase
-    * and if so, notifies the observer.
-    * 
-    * @param status The status of the transaction
-    * @see javax.transaction.Status
-    */
-   public void afterCompletion(int status)
+   @Override
+   public void run()
    {
-      if (observer.isInterestedInTransactionPhase(AFTER_COMPLETION))
-      {
-         observer.notify(event);
-      }
-      switch (status)
-      {
-      case Status.STATUS_COMMITTED:
-         if (observer.isInterestedInTransactionPhase(AFTER_SUCCESS))
-         {
-            observer.notify();
-         }
-         break;
-      case Status.STATUS_ROLLEDBACK:
-         if (observer.isInterestedInTransactionPhase(AFTER_FAILURE))
-         {
-            observer.notify();
-         }
-         break;
-      }
+      observer.notify(event);
    }
-
-   /**
-    * Called before completion of a transaction
-    * 
-    * Checks if the observer is interested in this particular transaction phase
-    * and if so, notifies the observer.
-    */
-   public void beforeCompletion()
-   {
-      if (observer.isInterestedInTransactionPhase(BEFORE_COMPLETION))
-      {
-         observer.notify(event);
-      }
-   }
 }

Added: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/ObserverFactory.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/ObserverFactory.java	                        (rev 0)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/ObserverFactory.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jboss.webbeans.event;
+
+import org.jboss.webbeans.ManagerImpl;
+import org.jboss.webbeans.bean.AbstractClassBean;
+import org.jboss.webbeans.introspector.AnnotatedMethod;
+
+/**
+ * Basic factory class that produces implicit observers for observer methods.
+ * 
+ * @author David Allen
+ * 
+ */
+public class ObserverFactory
+{
+   /**
+    * Creates an observer
+    * 
+    * @param method The observer method abstraction
+    * @param declaringBean The declaring bean
+    * @param manager The Web Beans manager
+    * @return An observer implementation built from the method abstraction
+    */
+   public static <T> ObserverImpl<T> create(AnnotatedMethod<?> method, AbstractClassBean<?> declaringBean, ManagerImpl manager)
+   {
+      ObserverImpl<T> result = null;
+      if (TransactionalObserverImpl.isObserverMethodTransactional(method))
+      {
+         result = new TransactionalObserverImpl<T>(method, declaringBean, manager);
+      }
+      else
+      {
+         result = new ObserverImpl<T>(method, declaringBean, manager);
+      }
+      return result;
+   }
+}


Property changes on: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/ObserverFactory.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/ObserverImpl.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/ObserverImpl.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/ObserverImpl.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -48,6 +48,7 @@
 import org.jboss.webbeans.introspector.AnnotatedMethod;
 import org.jboss.webbeans.introspector.AnnotatedParameter;
 import org.jboss.webbeans.transaction.UserTransaction;
+import org.jboss.webbeans.transaction.spi.TransactionServices;
 import org.jboss.webbeans.util.Reflections;
 
 /**
@@ -63,37 +64,14 @@
  */
 public class ObserverImpl<T> implements Observer<T>
 {
-   /**
-    * The known transactional phases a transactional event observer can be
-    * interested in
-    */
-   protected enum TransactionObservationPhase
-   {
-      NONE, BEFORE_COMPLETION, AFTER_COMPLETION, AFTER_FAILURE, AFTER_SUCCESS
-   }
-
-   private final Bean<?> observerBean;
-   private final MethodInjectionPoint<?> observerMethod;
-   private TransactionObservationPhase transactionObservationPhase;
+   protected final Bean<?> observerBean;
+   protected final MethodInjectionPoint<?> observerMethod;
    private final boolean conditional;
-   private ManagerImpl manager;
+   protected ManagerImpl manager;
    private final Class<T> eventType;
    private final Annotation[] bindings;
 
    /**
-    * Creates an observer
-    * 
-    * @param method The observer method abstraction
-    * @param declaringBean The declaring bean
-    * @param manager The Web Beans manager
-    * @return An observer implementation built from the method abstraction
-    */
-   public static <T> ObserverImpl<T> of(AnnotatedMethod<?> method, AbstractClassBean<?> declaringBean, ManagerImpl manager)
-   {
-      return new ObserverImpl<T>(method, declaringBean, manager);
-   }
-
-   /**
     * Creates an Observer which describes and encapsulates an observer method
     * (8.5).
     * 
@@ -113,41 +91,17 @@
       this.eventType = c;
 
       this.bindings = observerMethod.getAnnotatedParameters(Observes.class).get(0).getBindingsAsArray();
-      initTransactionObservationPhase();
       this.conditional = !observerMethod.getAnnotatedParameters(IfExists.class).isEmpty();
+      init();
    }
 
-   private void initTransactionObservationPhase()
+   /**
+    * Completes initialization of the observer and allows derived types to
+    * override behavior.
+    */
+   protected void init()
    {
-      List<TransactionObservationPhase> observationPhases = new ArrayList<TransactionObservationPhase>();
-      if (!observerMethod.getAnnotatedParameters(BeforeTransactionCompletion.class).isEmpty())
-      {
-         observationPhases.add(TransactionObservationPhase.BEFORE_COMPLETION);
-      }
-      if (!observerMethod.getAnnotatedParameters(AfterTransactionCompletion.class).isEmpty())
-      {
-         observationPhases.add(TransactionObservationPhase.AFTER_COMPLETION);
-      }
-      if (!observerMethod.getAnnotatedParameters(AfterTransactionFailure.class).isEmpty())
-      {
-         observationPhases.add(TransactionObservationPhase.AFTER_FAILURE);
-      }
-      if (!observerMethod.getAnnotatedParameters(AfterTransactionSuccess.class).isEmpty())
-      {
-         observationPhases.add(TransactionObservationPhase.AFTER_SUCCESS);
-      }
-      if (observationPhases.size() > 1)
-      {
-         throw new DefinitionException("Transactional observers can only observe on a single phase");
-      }
-      else if (observationPhases.size() == 1)
-      {
-         transactionObservationPhase = observationPhases.iterator().next();
-      }
-      else
-      {
-         transactionObservationPhase = TransactionObservationPhase.NONE;
-      }
+
    }
 
    /**
@@ -192,6 +146,16 @@
 
    public void notify(final T event)
    {
+      sendEvent(event);
+   }
+
+   /**
+    * Invokes the observer method immediately passing the event.
+    * 
+    * @param event The event to notify observer with
+    */
+   protected void sendEvent(final T event)
+   {
       Object instance = null;
       DependentStorageRequest dependentStorageRequest = DependentStorageRequest.of(new DependentInstancesStore(), new Object());
       try
@@ -206,14 +170,7 @@
          {
             return;
          }
-         if (isTransactional() && isTransactionActive())
-         {
-            deferEvent(event);
-         }
-         else
-         {
-            observerMethod.invokeWithSpecialValue(instance, Observes.class, event, manager, null, ObserverException.class);
-         }
+         observerMethod.invokeWithSpecialValue(instance, Observes.class, event, manager, null, ObserverException.class);
       }
       finally
       {
@@ -224,57 +181,13 @@
          }
       }
    }
-   
+
    private <B> B getInstance(Bean<B> observerBean)
    {
       return manager.getInstance(observerBean, !isConditional());
    }
 
    /**
-    * Checks if there is currently a transaction active
-    * 
-    * @return True if there is one, false otherwise
-    */
-   private boolean isTransactionActive()
-   {
-      UserTransaction userTransaction = manager.getInstanceByType(UserTransaction.class);
-      try
-      {
-         return userTransaction != null && userTransaction.getStatus() == Status.STATUS_ACTIVE;
-      }
-      catch (SystemException e)
-      {
-         return false;
-      }
-   }
-
-   /**
-    * Defers an event for processing in a later phase of the current
-    * transaction.
-    * 
-    * Gets the transaction listener, creates a deferred event representation and
-    * registers the deferred event.
-    * 
-    * @param event The event type
-    */
-   private void deferEvent(T event)
-   {
-      UserTransaction userTransaction = manager.getInstanceByType(UserTransaction.class);
-      DeferredEventNotification<T> deferredEvent = new DeferredEventNotification<T>(event, this);
-      userTransaction.registerSynchronization(deferredEvent);
-   }
-
-   /**
-    * Indicates if the observer is transactional
-    * 
-    * @return True if transactional, false otherwise
-    */
-   public boolean isTransactional()
-   {
-      return !TransactionObservationPhase.NONE.equals(transactionObservationPhase);
-   }
-
-   /**
     * Indicates if the observer is conditional
     * 
     * @return True if conditional, false otherwise
@@ -284,22 +197,11 @@
       return conditional;
    }
 
-   /**
-    * Checks if the observer is interested in a particular transactional phase
-    * 
-    * @param currentPhase The phase to check
-    * @return True if interested, false otherwise
-    */
-   public boolean isInterestedInTransactionPhase(TransactionObservationPhase currentPhase)
-   {
-      return transactionObservationPhase.equals(currentPhase);
-   }
-
    @Override
    public String toString()
    {
       StringBuilder builder = new StringBuilder();
-      builder.append("Observer Implentation: \n");
+      builder.append("Observer Implementation: \n");
       builder.append("  Observer (Declaring) bean: " + observerBean);
       builder.append("  Observer method: " + observerMethod);
       return builder.toString();

Added: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/TransactionalObserverImpl.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/TransactionalObserverImpl.java	                        (rev 0)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/TransactionalObserverImpl.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -0,0 +1,174 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jboss.webbeans.event;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.event.AfterTransactionCompletion;
+import javax.event.AfterTransactionFailure;
+import javax.event.AfterTransactionSuccess;
+import javax.event.BeforeTransactionCompletion;
+import javax.inject.DefinitionException;
+import javax.inject.manager.Bean;
+
+import org.jboss.webbeans.ManagerImpl;
+import org.jboss.webbeans.introspector.AnnotatedMethod;
+import org.jboss.webbeans.transaction.spi.TransactionServices;
+
+/**
+ * @author David Allen
+ * 
+ */
+public class TransactionalObserverImpl<T> extends ObserverImpl<T>
+{
+   /**
+    * The known transactional phases a transactional event observer can be
+    * interested in
+    */
+   protected enum TransactionObservationPhase
+   {
+      BEFORE_COMPLETION
+      {
+         void registerTask(TransactionServices transactionServices, Runnable task)
+         {
+            transactionServices.executeBeforeTransactionCompletion(task);
+         }
+      },
+      AFTER_COMPLETION
+      {
+         void registerTask(TransactionServices transactionServices, Runnable task)
+         {
+            transactionServices.executeAfterTransactionCompletion(task);
+         }
+      },
+      AFTER_FAILURE
+      {
+         void registerTask(TransactionServices transactionServices, Runnable task)
+         {
+            transactionServices.executeAfterTransactionCompletion(task, TransactionServices.Status.SUCCESS);
+         }
+      },
+      AFTER_SUCCESS
+      {
+         void registerTask(TransactionServices transactionServices, Runnable task)
+         {
+            transactionServices.executeAfterTransactionCompletion(task, TransactionServices.Status.FAILURE);
+         }
+      };
+
+      abstract void registerTask(TransactionServices transactionServices, Runnable task);
+   }
+
+   private TransactionObservationPhase transactionObservationPhase;
+   private boolean deferred = false;
+
+   /**
+    * Tests an observer method to see if it is transactional.
+    * 
+    * @param observer The observer method
+    * @return true if the observer method is annotated as transactional
+    */
+   public static boolean isObserverMethodTransactional(AnnotatedMethod<?> observer)
+   {
+      boolean transactional = false;
+      if ((!observer.getAnnotatedParameters(BeforeTransactionCompletion.class).isEmpty()) || (!observer.getAnnotatedParameters(AfterTransactionCompletion.class).isEmpty()) || (!observer.getAnnotatedParameters(AfterTransactionSuccess.class).isEmpty()) || (!observer.getAnnotatedParameters(AfterTransactionFailure.class).isEmpty()))
+      {
+         transactional = true;
+      }
+      return transactional;
+   }
+
+   /**
+    * Creates a new instance of a transactional observer method implicit object.
+    * 
+    * @param observer The observer method
+    * @param observerBean The bean declaring the observer method
+    * @param manager The JCDI manager in use
+    */
+   protected TransactionalObserverImpl(AnnotatedMethod<?> observer, Bean<?> observerBean, ManagerImpl manager)
+   {
+      super(observer, observerBean, manager);
+   }
+
+   @Override
+   protected void init()
+   {
+      initTransactionObservationPhase();
+   }
+
+   @Override
+   public void notify(T event)
+   {
+      if (!deferred && manager.getTransactionServices().isTransactionActive())
+      {
+         deferEvent(event);
+      }
+      else
+      {
+         sendEvent(event);
+      }
+   }
+
+   private void initTransactionObservationPhase()
+   {
+      List<TransactionObservationPhase> observationPhases = new ArrayList<TransactionObservationPhase>();
+      if (!observerMethod.getAnnotatedParameters(BeforeTransactionCompletion.class).isEmpty())
+      {
+         observationPhases.add(TransactionObservationPhase.BEFORE_COMPLETION);
+      }
+      if (!observerMethod.getAnnotatedParameters(AfterTransactionCompletion.class).isEmpty())
+      {
+         observationPhases.add(TransactionObservationPhase.AFTER_COMPLETION);
+      }
+      if (!observerMethod.getAnnotatedParameters(AfterTransactionFailure.class).isEmpty())
+      {
+         observationPhases.add(TransactionObservationPhase.AFTER_FAILURE);
+      }
+      if (!observerMethod.getAnnotatedParameters(AfterTransactionSuccess.class).isEmpty())
+      {
+         observationPhases.add(TransactionObservationPhase.AFTER_SUCCESS);
+      }
+      if (observationPhases.size() > 1)
+      {
+         throw new DefinitionException("Transactional observers can only observe on a single phase: " + observerMethod);
+      }
+      else if (observationPhases.size() == 1)
+      {
+         transactionObservationPhase = observationPhases.iterator().next();
+      }
+      else
+      {
+         throw new IllegalStateException("This observer method is not transactional: " + observerMethod);
+      }
+   }
+
+   /**
+    * Defers an event for processing in a later phase of the current
+    * transaction.
+    * 
+    * @param event The event object
+    */
+   private void deferEvent(T event)
+   {
+      DeferredEventNotification<T> deferredEvent = new DeferredEventNotification<T>(event, this);
+      transactionObservationPhase.registerTask(manager.getTransactionServices(), deferredEvent);
+      deferred = true;
+   }
+
+}


Property changes on: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/event/TransactionalObserverImpl.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/mock/MockLifecycle.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/mock/MockLifecycle.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/mock/MockLifecycle.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -24,12 +24,14 @@
 import org.jboss.webbeans.ejb.spi.EjbResolver;
 import org.jboss.webbeans.resources.spi.ResourceLoader;
 import org.jboss.webbeans.servlet.AbstractLifecycle;
+import org.jboss.webbeans.transaction.spi.TransactionServices;
 
 public class MockLifecycle extends AbstractLifecycle
 { 
    
    private static final EjbResolver MOCK_EJB_RESOLVER = new MockEjBResolver();
    private static final ResourceLoader MOCK_RESOURCE_LOADER = new MockResourceLoader();
+   private static final TransactionServices MOCK_TRANSACTION_SERVICES = new MockTransactionServices();
    
    private final WebBeansBootstrap bootstrap;
    private final MockWebBeanDiscovery webBeanDiscovery;
@@ -55,6 +57,7 @@
       bootstrap.setResourceLoader(MOCK_RESOURCE_LOADER);
       bootstrap.setWebBeanDiscovery(webBeanDiscovery);
       bootstrap.setApplicationContext(applicationBeanStore);
+      bootstrap.setTransactionServices(MOCK_TRANSACTION_SERVICES);
       bootstrap.initialize();
    }
    

Added: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/mock/MockTransactionServices.java
===================================================================
--- ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/mock/MockTransactionServices.java	                        (rev 0)
+++ ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/mock/MockTransactionServices.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,  
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.jboss.webbeans.mock;
+
+import org.jboss.webbeans.transaction.spi.TransactionServices;
+
+/**
+ * A mock version of TransactionServices for RI unit tests.  Since
+ * no JTA transaction can be active for these unit tests, all
+ * methods here are empty.
+ * 
+ * @author David Allen
+ *
+ */
+public class MockTransactionServices implements TransactionServices
+{
+
+   /* (non-Javadoc)
+    * @see org.jboss.webbeans.transaction.spi.TransactionServices#executeAfterTransactionCompletion(java.lang.Runnable)
+    */
+   @Override
+   public void executeAfterTransactionCompletion(Runnable task)
+   {
+   }
+
+   /* (non-Javadoc)
+    * @see org.jboss.webbeans.transaction.spi.TransactionServices#executeAfterTransactionCompletion(java.lang.Runnable, org.jboss.webbeans.transaction.spi.TransactionServices.Status)
+    */
+   @Override
+   public void executeAfterTransactionCompletion(Runnable task, Status desiredStatus)
+   {
+   }
+
+   /* (non-Javadoc)
+    * @see org.jboss.webbeans.transaction.spi.TransactionServices#executeBeforeTransactionCompletion(java.lang.Runnable)
+    */
+   @Override
+   public void executeBeforeTransactionCompletion(Runnable task)
+   {
+   }
+
+   /* (non-Javadoc)
+    * @see org.jboss.webbeans.transaction.spi.TransactionServices#isTransactionActive()
+    */
+   @Override
+   public boolean isTransactionActive()
+   {
+      return false;
+   }
+
+}


Property changes on: ri/trunk/webbeans-ri/src/main/java/org/jboss/webbeans/mock/MockTransactionServices.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/bootstrap/api/Bootstrap.java
===================================================================
--- ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/bootstrap/api/Bootstrap.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/bootstrap/api/Bootstrap.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -8,6 +8,7 @@
 import org.jboss.webbeans.ejb.spi.EjbResolver;
 import org.jboss.webbeans.resources.spi.NamingContext;
 import org.jboss.webbeans.resources.spi.ResourceLoader;
+import org.jboss.webbeans.transaction.spi.TransactionServices;
 
 /**
  * Bootstrap API for Web Beans.
@@ -60,6 +61,13 @@
    public void setApplicationContext(BeanStore beanStore);
    
    /**
+    * Set the transaction services provider to use.
+    * 
+    * @param transactionServices An implementation of TransactionService
+    */
+   public void setTransactionServices(TransactionServices transactionServices);
+   
+   /**
     * Initialize the bootstrap:
     * <ul>
     *   <li>Create the manager and bind it to JNDI</li>

Modified: ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/bootstrap/api/helpers/AbstractBootstrap.java
===================================================================
--- ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/bootstrap/api/helpers/AbstractBootstrap.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/bootstrap/api/helpers/AbstractBootstrap.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -7,6 +7,7 @@
 import org.jboss.webbeans.ejb.spi.EjbResolver;
 import org.jboss.webbeans.resources.spi.NamingContext;
 import org.jboss.webbeans.resources.spi.ResourceLoader;
+import org.jboss.webbeans.transaction.spi.TransactionServices;
 
 public abstract class AbstractBootstrap implements Bootstrap
 {
@@ -17,6 +18,7 @@
    private EjbResolver ejbResolver;
    private EjbDiscovery ejbDiscovery;
    private BeanStore applicationContext;
+   private TransactionServices transactionServices;
 
    public void setEjbDiscovery(EjbDiscovery ejbDiscovery)
    {
@@ -42,6 +44,11 @@
    {
       this.webBeanDiscovery = webBeanDiscovery;
    }
+   
+   public void setTransactionServices(TransactionServices transactionServices)
+   {
+      this.transactionServices = transactionServices;
+   }
 
    public WebBeanDiscovery getWebBeanDiscovery()
    {
@@ -68,6 +75,11 @@
       return ejbDiscovery;
    }
    
+   public TransactionServices getTransactionServices()
+   {
+      return transactionServices;
+   }
+   
    public BeanStore getApplicationContext()
    {
       return applicationContext;

Added: ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/transaction/spi/TransactionServices.java
===================================================================
--- ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/transaction/spi/TransactionServices.java	                        (rev 0)
+++ ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/transaction/spi/TransactionServices.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -0,0 +1,62 @@
+package org.jboss.webbeans.transaction.spi;
+
+/**
+ * <p>
+ * The container must implement the services related to transactional behavior
+ * used in JSR-299, if that behavior is going to be used.
+ * </p>
+ * 
+ * <p>
+ * The event framework specified by JSR-299 includes the ability to create
+ * observer methods which are activated based on the phase and status of a
+ * currently active transaction. In order to use these abilities, the container
+ * must provide these intermediary services which in turn may interact with an
+ * application server and JTA or any other type of transaction service provider.
+ * </p>
+ * 
+ * @author David Allen
+ * 
+ */
+public interface TransactionServices
+{
+   /**
+    * Possible status conditions for a transaction.
+    */
+   public static enum Status
+   {
+      ALL, SUCCESS, FAILURE
+   }
+
+   /**
+    * Registers a task to be executed immediately before the current transaction
+    * is committed or rolled back.
+    * 
+    * @param task The Runnable that will be executed
+    */
+   public void executeBeforeTransactionCompletion(Runnable task);
+
+   /**
+    * Registers a task to be executed immediately after the current transaction
+    * is committed or rolled back.
+    * 
+    * @param task The Runnable that will be executed
+    */
+   public void executeAfterTransactionCompletion(Runnable task);
+
+   /**
+    * Registers a task to be executed immediately after the current transaction
+    * is committed or rolled back, but only one depending on the status
+    * provided.
+    * 
+    * @param task The Runnable that will be executed
+    */
+   public void executeAfterTransactionCompletion(Runnable task, Status desiredStatus);
+   
+   /**
+    * Queries the status of the current execution to see if a transaction is
+    * currently active.
+    * 
+    * @return true if a transaction is active
+    */
+   public boolean isTransactionActive();
+}


Property changes on: ri/trunk/webbeans-ri-spi/src/main/java/org/jboss/webbeans/transaction/spi/TransactionServices.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Modified: tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/Agent.java
===================================================================
--- tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/Agent.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/Agent.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -1,5 +1,8 @@
 package org.jboss.jsr299.tck.tests.event.transactionalObservers;
 
+import javax.ejb.Local;
+
+ at Local
 public interface Agent
 {
 

Modified: tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/DogAgent.java
===================================================================
--- tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/DogAgent.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/DogAgent.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -14,7 +14,6 @@
 import static javax.ejb.TransactionManagementType.BEAN;
 
 @Stateless
- at Local(Agent.class)
 @TransactionManagement(BEAN)
 @RunAs("Bubba")
 @Named

Modified: tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/EventTest.java
===================================================================
--- tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/EventTest.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/EventTest.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -21,11 +21,8 @@
 
 import java.lang.annotation.Annotation;
 import java.math.BigInteger;
-import java.util.Set;
 
-import javax.event.Observer;
 import javax.inject.AnnotationLiteral;
-import javax.inject.manager.Bean;
 
 import org.hibernate.tck.annotations.SpecAssertion;
 import org.hibernate.tck.annotations.SpecAssertions;
@@ -89,9 +86,10 @@
       dog.setCorrectContext(false);
       dog.setCorrectTransactionState(false);
       Agent dogAgent = getCurrentManager().getInstanceByType(Agent.class);
+      assert dogAgent != null;
       dogAgent.sendOutsideTransaction(BigInteger.TEN);
-      assert dog.isCorrectContext();
       assert dog.isCorrectTransactionState();
+      assert dog.isCorrectContext();
    }
 
    @Test(groups = { "events", "integration", "broken" })
@@ -104,7 +102,6 @@
       assert !getCurrentManager().resolveObservers("event").isEmpty();
       Agent dogAgent = getCurrentManager().getInstanceByType(Agent.class);
       dogAgent.sendInTransaction("event");
-      assert dog.isCorrectContext();
       assert dog.isCorrectTransactionState();
    }
 
@@ -117,6 +114,7 @@
       dog.setCorrectTransactionState(false);
       Agent dogAgent = getCurrentManager().getInstanceByType(Agent.class);
       dogAgent.sendInTransaction(new Integer(4));
+      assert dog.isCorrectTransactionState();
    }
 
    @Test(groups = { "events", "integration", "broken" })
@@ -126,14 +124,21 @@
       PomeranianInterface dog = (PomeranianInterface) getCurrentManager().getInstanceByName("Teddy");
       dog.setCorrectContext(false);
       dog.setCorrectTransactionState(false);
-      getCurrentManager().fireEvent(new Float(4.0));
+      Agent dogAgent = getCurrentManager().getInstanceByType(Agent.class);
+      dogAgent.sendInTransaction(new Float(4.0));
+      assert dog.isCorrectTransactionState();
    }
 
-   @Test(groups = { "stub", "events", "integration" })
+   @Test(groups = { "stub", "events", "integration", "broken" })
    @SpecAssertions( { @SpecAssertion(section = "7.5.6", id = "b"), @SpecAssertion(section = "7.5.6", id = "h") })
    public void testBeforeTransactionCompletionObserver()
    {
-      assert false;
+      PomeranianInterface dog = (PomeranianInterface) getCurrentManager().getInstanceByName("Teddy");
+      dog.setCorrectContext(false);
+      dog.setCorrectTransactionState(false);
+      Agent dogAgent = getCurrentManager().getInstanceByType(Agent.class);
+      dogAgent.sendInTransaction(new Double(4.0));
+      assert dog.isCorrectTransactionState();
    }
 
    @Test(groups = { "stub", "events", "integration" })
@@ -170,22 +175,15 @@
    }
 
    /**
-    * 
+    * Otherwise, the observer method is called in the same transaction context,
+    * client security context and lifecycle contexts as the invocation of
+    * Event.fire().
     */
-   @Test(groups = { "events", "integration", "broken" })
+   @Test(groups = { "events", "integration", "stub" })
    @SpecAssertion(section = "7.5.8", id = "unknown")
    public void testEnterpriseBeanObserverMethodCalledWithCallerContext()
    {
-      Set<Bean<PomeranianInterface>> beans = getCurrentManager().resolveByType(PomeranianInterface.class, TAME_LITERAL);
-      assert !beans.isEmpty();
-      String event = "A new event";
-      Set<Observer<String>> observers = getCurrentManager().resolveObservers(event);
-      assert observers.size() == 1;
-
-      getCurrentManager().fireEvent(event);
-      PomeranianInterface dog = (PomeranianInterface) getCurrentManager().getInstanceByName("Teddy");
-      dog.setCorrectContext(false);
-      dog.setCorrectTransactionState(false);
+      assert false;
    }
 
    @Test(groups = { "stub", "events", "integration" })

Modified: tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/Pomeranian.java
===================================================================
--- tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/Pomeranian.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/Pomeranian.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -2,31 +2,31 @@
 
 import static javax.ejb.TransactionManagementType.BEAN;
 import static javax.transaction.Status.STATUS_COMMITTED;
+import static javax.transaction.Status.STATUS_NO_TRANSACTION;
+import static javax.transaction.Status.STATUS_PREPARED;
 import static javax.transaction.Status.STATUS_ROLLEDBACK;
-import static javax.transaction.Status.STATUS_NO_TRANSACTION;
 
 import java.math.BigInteger;
 
 import javax.annotation.Named;
 import javax.annotation.Resource;
 import javax.ejb.EJBException;
-import javax.ejb.Local;
 import javax.ejb.SessionContext;
 import javax.ejb.Stateful;
 import javax.ejb.TransactionManagement;
 import javax.event.AfterTransactionCompletion;
 import javax.event.AfterTransactionFailure;
 import javax.event.AfterTransactionSuccess;
+import javax.event.BeforeTransactionCompletion;
 import javax.event.Observes;
 import javax.transaction.SystemException;
 import javax.transaction.UserTransaction;
 
 
 @Stateful
- at Local(PomeranianInterface.class)
+ at TransactionManagement(BEAN)
 @Tame
 @Named("Teddy")
- at TransactionManagement(BEAN)
 public class Pomeranian implements PomeranianInterface
 {
    @Resource
@@ -53,7 +53,7 @@
          }
          else
          {
-            throw new EJBException("Transaction " + transaction + " is not in expected state");
+            throw new EJBException("Incorrect transaction state " + transaction.getStatus());
          }
          
          if (context.getCallerPrincipal().getName().equals("Bubba"))
@@ -84,6 +84,10 @@
          {
             setCorrectTransactionState(true);
          }
+         else
+         {
+            throw new EJBException("Incorrect transaction state " + transaction.getStatus());
+         }
       }
       catch (SystemException e)
       {
@@ -104,6 +108,10 @@
          {
             setCorrectTransactionState(true);
          }
+         else
+         {
+            throw new EJBException("Incorrect transaction state " + transaction.getStatus());
+         }
       }
       catch (SystemException e)
       {
@@ -121,13 +129,17 @@
          }
          else
          {
-            throw new EJBException("Transaction " + transaction + " is not in expected state");
+            throw new EJBException("Incorrect transaction state " + transaction.getStatus());
          }
          
          if (context.getCallerPrincipal().getName().equals("Bubba"))
          {
             setCorrectContext(true);
          }
+         else
+         {
+            throw new EJBException("Wrong principal: " + context.getCallerPrincipal().getName());
+         }
       }
       catch (SystemException e)
       {
@@ -135,6 +147,30 @@
       }
    }
 
+   public void observeDoubleEvent(@Observes @BeforeTransactionCompletion Double event)
+   {
+      try
+      {
+         if (transaction.getStatus() == STATUS_NO_TRANSACTION)
+         {
+            setCorrectTransactionState(true);
+         }
+         else
+         {
+            throw new EJBException("Incorrect transaction state " + transaction.getStatus());
+         }
+         
+         if (context.getCallerPrincipal().getName().equals("Bubba"))
+         {
+            setCorrectContext(true);
+         }
+      }
+      catch (SystemException e)
+      {
+         throw new EJBException("Failed to detect transaction status", e);
+      }      
+   }
+   
    public boolean isCorrectContext()
    {
       return correctContext;

Modified: tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/PomeranianInterface.java
===================================================================
--- tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/PomeranianInterface.java	2009-03-02 21:47:11 UTC (rev 1751)
+++ tck/trunk/impl/src/main/java/org/jboss/jsr299/tck/tests/event/transactionalObservers/PomeranianInterface.java	2009-03-03 18:04:55 UTC (rev 1752)
@@ -2,6 +2,9 @@
 
 import java.math.BigInteger;
 
+import javax.ejb.Local;
+
+ at Local
 public interface PomeranianInterface
 {
    /**
@@ -26,6 +29,8 @@
    public void observeFloatEvent(Float event);
 
    public void observeBigIntegerEvent(BigInteger event);
+   
+   public void observeDoubleEvent(Double event);
 
    public boolean isCorrectContext();
 




More information about the weld-commits mailing list