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;
+
+@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
-(a)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
-(a)Local(PomeranianInterface.class)
+@TransactionManagement(BEAN)
@Tame
@Named("Teddy")
-@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;
+
+@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();