[seam-commits] Seam SVN: r9505 - in branches/enterprise/JBPAPP_4_3_FP01/src: test/unit/org/jboss/seam/test/unit and 1 other directory.
seam-commits at lists.jboss.org
seam-commits at lists.jboss.org
Wed Nov 5 05:01:54 EST 2008
Author: manaRH
Date: 2008-11-05 05:01:54 -0500 (Wed, 05 Nov 2008)
New Revision: 9505
Added:
branches/enterprise/JBPAPP_4_3_FP01/src/test/unit/org/jboss/seam/test/unit/FooBar.java
Modified:
branches/enterprise/JBPAPP_4_3_FP01/src/main/org/jboss/seam/core/BijectionInterceptor.java
branches/enterprise/JBPAPP_4_3_FP01/src/test/unit/org/jboss/seam/test/unit/InterceptorTest.java
Log:
JBPAPP-1122
Modified: branches/enterprise/JBPAPP_4_3_FP01/src/main/org/jboss/seam/core/BijectionInterceptor.java
===================================================================
--- branches/enterprise/JBPAPP_4_3_FP01/src/main/org/jboss/seam/core/BijectionInterceptor.java 2008-11-04 23:54:11 UTC (rev 9504)
+++ branches/enterprise/JBPAPP_4_3_FP01/src/main/org/jboss/seam/core/BijectionInterceptor.java 2008-11-05 10:01:54 UTC (rev 9505)
@@ -1,13 +1,13 @@
//$Id$
package org.jboss.seam.core;
+import java.util.concurrent.locks.ReentrantLock;
+
import org.jboss.seam.Component;
import org.jboss.seam.annotations.intercept.AroundInvoke;
import org.jboss.seam.annotations.intercept.Interceptor;
import org.jboss.seam.intercept.AbstractInterceptor;
import org.jboss.seam.intercept.InvocationContext;
-import org.jboss.seam.log.LogProvider;
-import org.jboss.seam.log.Logging;
/**
* Before invoking the component, inject all dependencies. After
@@ -20,40 +20,89 @@
{
private static final long serialVersionUID = 4686458105931528659L;
- private static final LogProvider log = Logging.getLogProvider(BijectionInterceptor.class);
+ private boolean injected;
- private boolean reentrant; //OK, since all Seam components are single-threaded
+ private int counter = 0;
+ private ReentrantLock lock = new ReentrantLock();
+
@AroundInvoke
public Object aroundInvoke(InvocationContext invocation) throws Exception
{
- if (reentrant)
+ Component component = getComponent();
+ boolean enforceRequired = !component.isLifecycleMethod( invocation.getMethod() );
+
+ try
{
- if ( log.isTraceEnabled() )
+ lock.lock();
+ try
{
- log.trace("reentrant call to component: " + getComponent().getName() );
+ if (!injected)
+ {
+ component.inject( invocation.getTarget(), enforceRequired );
+ injected = true;
+ }
+ counter++;
}
- return invocation.proceed();
- }
- else
- {
- reentrant = true;
+
+ finally
+ {
+ lock.unlock();
+ }
+
+ Object result = invocation.proceed();
+
+ lock.lock();
try
{
- Component component = getComponent();
- boolean enforceRequired = !component.isLifecycleMethod( invocation.getMethod() );
- component.inject( invocation.getTarget(), enforceRequired );
- Object result = invocation.proceed();
- component.outject( invocation.getTarget(), enforceRequired );
- component.disinject( invocation.getTarget() );
- return result;
+ counter--;
+ if (counter == 0)
+ {
+ try
+ {
+ component.outject( invocation.getTarget(), enforceRequired );
+ }
+ finally
+ {
+ // Avoid an extra lock by disinjecting here instead of the finally block
+ if (injected)
+ {
+ injected = false;
+ component.disinject( invocation.getTarget() );
+ }
+ }
+ }
}
finally
{
- reentrant = false;
+ lock.unlock();
}
+
+ return result;
}
+ finally
+ {
+ if (injected)
+ {
+ lock.lock();
+ try
+ {
+ component.disinject( invocation.getTarget() );
+ counter--;
+
+ if (counter == 0)
+ {
+ injected = false;
+ }
+ }
+ finally
+ {
+ lock.unlock();
+ }
+
+ }
+ }
}
}
Added: branches/enterprise/JBPAPP_4_3_FP01/src/test/unit/org/jboss/seam/test/unit/FooBar.java
===================================================================
--- branches/enterprise/JBPAPP_4_3_FP01/src/test/unit/org/jboss/seam/test/unit/FooBar.java (rev 0)
+++ branches/enterprise/JBPAPP_4_3_FP01/src/test/unit/org/jboss/seam/test/unit/FooBar.java 2008-11-05 10:01:54 UTC (rev 9505)
@@ -0,0 +1,23 @@
+ package org.jboss.seam.test.unit;
+import java.util.concurrent.CountDownLatch;
+import org.jboss.seam.ScopeType;
+import org.jboss.seam.annotations.In;
+import org.jboss.seam.annotations.Name;
+import org.jboss.seam.annotations.Scope;
+ at Name("fooBar")
+ at Scope(ScopeType.APPLICATION)
+public class FooBar
+{
+ @In Foo foo;
+
+ public Foo delayedGetFoo(CountDownLatch latch)
+ {
+ try
+ {
+ latch.await();
+ }
+ catch (InterruptedException ex) {}
+
+ return foo;
+ }
+}
\ No newline at end of file
Property changes on: branches/enterprise/JBPAPP_4_3_FP01/src/test/unit/org/jboss/seam/test/unit/FooBar.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Modified: branches/enterprise/JBPAPP_4_3_FP01/src/test/unit/org/jboss/seam/test/unit/InterceptorTest.java
===================================================================
--- branches/enterprise/JBPAPP_4_3_FP01/src/test/unit/org/jboss/seam/test/unit/InterceptorTest.java 2008-11-04 23:54:11 UTC (rev 9504)
+++ branches/enterprise/JBPAPP_4_3_FP01/src/test/unit/org/jboss/seam/test/unit/InterceptorTest.java 2008-11-05 10:01:54 UTC (rev 9505)
@@ -2,6 +2,7 @@
package org.jboss.seam.test.unit;
import java.lang.reflect.Method;
+import java.util.concurrent.CountDownLatch;
import javax.faces.context.ExternalContext;
import javax.faces.event.PhaseId;
@@ -25,6 +26,7 @@
import org.jboss.seam.core.Manager;
import org.jboss.seam.ejb.RemoveInterceptor;
import org.jboss.seam.faces.FacesMessages;
+import org.jboss.seam.intercept.InvocationContext;
import org.jboss.seam.mock.MockApplication;
import org.jboss.seam.mock.MockExternalContext;
import org.jboss.seam.mock.MockFacesContext;
@@ -235,6 +237,101 @@
}
@Test
+ public void testReentrantBijection() throws Exception
+ {
+ MockServletContext servletContext = new MockServletContext();
+ ServletLifecycle.beginApplication(servletContext);
+ MockExternalContext externalContext = new MockExternalContext(servletContext);
+ Context appContext = new ApplicationContext( externalContext.getApplicationMap() );
+ appContext.set( Seam.getComponentName(Init.class), new Init() );
+ appContext.set( Seam.getComponentName(ConversationEntries.class) + ".component",
+ new Component(ConversationEntries.class, appContext) );
+ appContext.set( Seam.getComponentName(Manager.class) + ".component",
+ new Component(Manager.class, appContext) );
+ appContext.set( Seam.getComponentName(Foo.class) + ".component",
+ new Component(Foo.class, appContext) );
+ appContext.set( Seam.getComponentName(FooBar.class) + ".component",
+ new Component(FooBar.class, appContext) );
+ FacesLifecycle.beginRequest(externalContext);
+ Manager.instance().setCurrentConversationId("1");
+ FacesLifecycle.resumeConversation(externalContext);
+ FacesLifecycle.setPhaseId(PhaseId.RENDER_RESPONSE);
+
+ final Foo foo = new Foo();
+ final FooBar fooBar = new FooBar();
+ Contexts.getSessionContext().set("foo", foo);
+
+ final BijectionInterceptor bi = new BijectionInterceptor();
+ bi.setComponent( new Component(FooBar.class, appContext) );
+
+ final Method m = FooBar.class.getMethod("delayedGetFoo", CountDownLatch.class);
+
+ final CountDownLatch latchA = new CountDownLatch(1);
+ final CountDownLatch latchB = new CountDownLatch(1);
+ final CountDownLatch latchC = new CountDownLatch(1);
+ final CountDownLatch latchD = new CountDownLatch(1);
+
+ final InvocationContext invocationA = new MockInvocationContext() {
+ @Override public Object getTarget() { return fooBar; }
+ @Override public Method getMethod() { return m; }
+ @Override public Object[] getParameters() { return new Object[] { latchA }; }
+ };
+ final InvocationContext invocationB = new MockInvocationContext() {
+ @Override public Object getTarget() { return fooBar; }
+ @Override public Method getMethod() { return m; }
+ @Override public Object[] getParameters() { return new Object[] { latchB }; }
+ };
+
+ new Thread(new Runnable() {
+ public void run() {
+ try
+ {
+ Foo result = (Foo) bi.aroundInvoke( invocationA );
+ assert result == foo;
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ finally
+ {
+ latchC.countDown();
+ }
+ }
+ }).start();
+
+ new Thread(new Runnable() {
+ public void run() {
+ try
+ {
+ Foo result = (Foo) bi.aroundInvoke( invocationB );
+ assert result == foo;
+ }
+ catch (Exception ex)
+ {
+ throw new RuntimeException(ex);
+ }
+ finally
+ {
+ latchD.countDown();
+ }
+ }
+ }).start();
+
+ // Allow invocationA to complete
+ latchA.countDown();
+
+ // Wait for invocationA to finalise
+ latchC.await();
+
+ // Allow invocationB to proceed
+ latchB.countDown();
+
+ // Wait for invocationB
+ latchD.await();
+ }
+
+ @Test
public void testConversationInterceptor() throws Exception
{
MockServletContext servletContext = new MockServletContext();
More information about the seam-commits
mailing list