You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tomee.apache.org by ma...@apache.org on 2008/07/23 10:55:52 UTC
svn commit: r679032 - in /openejb/trunk/openejb3/container/openejb-core/src:
main/java/org/apache/openejb/core/stateless/
test/java/org/apache/openejb/core/stateless/
Author: manugeorge
Date: Wed Jul 23 01:55:51 2008
New Revision: 679032
URL: http://svn.apache.org/viewvc?rev=679032&view=rev
Log:
OPENEJB-865 Timeout ignored for stateless session beans
Solution
Use a Semaphore without a timeout when the timeout property is 0 or -ve. Use a semaphore with the timeout when the timeout property is given in milliseconds.
Added:
openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/StatelessInstanceManagerPoolingTest.java
Modified:
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java?rev=679032&r1=679031&r2=679032&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessContainer.java Wed Jul 23 01:55:51 2008
@@ -21,6 +21,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
import javax.ejb.EJBAccessException;
import javax.ejb.EJBHome;
@@ -32,13 +33,13 @@
import org.apache.openejb.ContainerType;
import org.apache.openejb.DeploymentInfo;
+import org.apache.openejb.InterfaceType;
import org.apache.openejb.OpenEJBException;
import org.apache.openejb.ProxyInfo;
-import org.apache.openejb.InterfaceType;
import org.apache.openejb.core.CoreDeploymentInfo;
+import org.apache.openejb.core.ExceptionType;
import org.apache.openejb.core.Operation;
import org.apache.openejb.core.ThreadContext;
-import org.apache.openejb.core.ExceptionType;
import org.apache.openejb.core.interceptor.InterceptorData;
import org.apache.openejb.core.interceptor.InterceptorStack;
import org.apache.openejb.core.timer.EjbTimerService;
@@ -46,6 +47,7 @@
import org.apache.openejb.core.transaction.TransactionContext;
import org.apache.openejb.core.transaction.TransactionPolicy;
import org.apache.openejb.spi.SecurityService;
+import org.apache.openejb.util.Duration;
import org.apache.xbean.finder.ClassFinder;
/**
@@ -66,7 +68,7 @@
this.transactionManager = transactionManager;
this.securityService = securityService;
- instanceManager = new StatelessInstanceManager(transactionManager, securityService, timeOut, poolSize, strictPooling);
+ instanceManager = new StatelessInstanceManager(transactionManager, securityService, new Duration(timeOut,TimeUnit.MILLISECONDS), poolSize, strictPooling);
for (DeploymentInfo deploymentInfo : deploymentRegistry.values()) {
org.apache.openejb.core.CoreDeploymentInfo di = (org.apache.openejb.core.CoreDeploymentInfo) deploymentInfo;
Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java?rev=679032&r1=679031&r2=679032&view=diff
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java Wed Jul 23 01:55:51 2008
@@ -41,6 +41,7 @@
import org.apache.openejb.core.interceptor.InterceptorData;
import org.apache.openejb.core.interceptor.InterceptorStack;
import org.apache.openejb.spi.SecurityService;
+import org.apache.openejb.util.Duration;
import org.apache.openejb.util.LinkedListStack;
import org.apache.openejb.util.LogCategory;
import org.apache.openejb.util.Logger;
@@ -55,28 +56,25 @@
private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources");
protected int poolLimit = 0;
+ protected Duration timeout;
protected int beanCount = 0;
protected boolean strictPooling = false;
- protected HashMap<Object,Semaphore> semaphores;
-
protected final SafeToolkit toolkit = SafeToolkit.getToolkit("StatefulInstanceManager");
private TransactionManager transactionManager;
private SecurityService securityService;
- public StatelessInstanceManager(TransactionManager transactionManager, SecurityService securityService, int timeout, int poolSize, boolean strictPooling) {
+ public StatelessInstanceManager(TransactionManager transactionManager, SecurityService securityService, Duration timeout, int poolSize, boolean strictPooling) {
this.transactionManager = transactionManager;
this.securityService = securityService;
this.poolLimit = poolSize;
this.strictPooling = strictPooling;
-
+ this.timeout = timeout;
+
if (strictPooling && poolSize < 1) {
throw new IllegalArgumentException("Cannot use strict pooling with a pool size less than one. Strict pooling blocks threads till an instance in the pool is available. Please increase the pool size or set strict pooling to false");
}
- if (this.strictPooling) {
- this.semaphores = new HashMap();
- }
}
/**
@@ -99,12 +97,22 @@
CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
Data data = (Data) deploymentInfo.getContainerData();
Stack pool = data.getPool();
+
if(strictPooling){
+ boolean acquired = false;
try {
- semaphores.get(deploymentInfo.getDeploymentID()).acquire();
+ if(timeout.getTime() <= 0L){
+ data.getSemaphore().acquire();
+ acquired = true;
+ } else {
+ acquired = data.getSemaphore().tryAcquire(timeout.getTime(),timeout.getUnit());
+ }
} catch (InterruptedException e2) {
throw new OpenEJBException("Unexpected Interruption of current thread: ",e2);
}
+ if(!acquired){
+ throw new IllegalStateException("An invocation of the Stateless Session Bean "+deploymentInfo.getEjbName()+" has timed-out");
+ }
}
Object bean = pool.pop();
@@ -300,7 +308,7 @@
if (strictPooling) {
pool.push(bean);
- semaphores.get(deploymentInfo.getDeploymentID()).release();
+ data.getSemaphore().release();
} else {
if (pool.size() >= poolLimit) {
freeInstance(callContext, (Instance)bean);
@@ -341,19 +349,12 @@
}
public void deploy(CoreDeploymentInfo deploymentInfo) {
- Data data = new Data(poolLimit);
+ Data data = new Data(poolLimit, this.strictPooling);
deploymentInfo.setContainerData(data);
- if (this.strictPooling) {
- this.semaphores.put(deploymentInfo.getDeploymentID(), new Semaphore(poolLimit));
- }
-
}
public void undeploy(CoreDeploymentInfo deploymentInfo) {
Data data = (Data) deploymentInfo.getContainerData();
- if (this.strictPooling) {
- semaphores.remove(deploymentInfo.getDeploymentID());
- }
if (data == null) return;
Stack pool = data.getPool();
//TODO ejbRemove on each bean in pool.
@@ -363,14 +364,23 @@
private static final class Data {
private final Stack pool;
-
- public Data(int poolLimit) {
+ private Semaphore semaphore;
+
+ public Data(int poolLimit, boolean strictPooling) {
pool = new LinkedListStack(poolLimit);
+ if (strictPooling) {
+ semaphore = new Semaphore(poolLimit);
+ }
}
public Stack getPool() {
return pool;
}
+
+ public Semaphore getSemaphore(){
+ return semaphore;
+ }
+
}
}
Added: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/StatelessInstanceManagerPoolingTest.java
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/StatelessInstanceManagerPoolingTest.java?rev=679032&view=auto
==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/StatelessInstanceManagerPoolingTest.java (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/core/stateless/StatelessInstanceManagerPoolingTest.java Wed Jul 23 01:55:51 2008
@@ -0,0 +1,176 @@
+/**
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.apache.openejb.core.stateless;
+
+import java.util.List;
+
+import javax.ejb.Remote;
+import javax.ejb.Stateless;
+import javax.naming.InitialContext;
+
+import junit.framework.TestCase;
+
+import org.apache.openejb.assembler.classic.Assembler;
+import org.apache.openejb.assembler.classic.ProxyFactoryInfo;
+import org.apache.openejb.assembler.classic.SecurityServiceInfo;
+import org.apache.openejb.assembler.classic.StatelessSessionContainerInfo;
+import org.apache.openejb.assembler.classic.TransactionServiceInfo;
+import org.apache.openejb.config.ConfigurationFactory;
+import org.apache.openejb.core.ivm.naming.InitContextFactory;
+import org.apache.openejb.jee.EjbJar;
+import org.apache.openejb.jee.StatelessBean;
+
+/**
+ * @version $Revision: 581127 $ $Date: 2007-10-02 07:43:16 +0530 (Tue, 02 Oct 2007) $
+ */
+public class StatelessInstanceManagerPoolingTest extends TestCase {
+
+ public void testStatelessBeanPooling() throws Exception {
+
+ InitialContext ctx = new InitialContext();
+ Object object = ctx.lookup("CounterBeanLocal");
+ assertTrue("instanceof counter", object instanceof Counter);
+
+ final Counter counter = (Counter) object;
+ // Do a business method...
+ Runnable r = new Runnable(){
+ public void run(){
+ counter.waitFor(10);
+ }
+ };
+
+ // How much ever the no of client invocations the count should be 10 as only 10 instances will be created.
+ for(int i=0;i<=30;i++){
+ Thread t = new Thread(r);
+ t.start();
+ if(i==30) t.join();
+ }
+
+ assertEquals(10,CounterBean.counter);
+
+ }
+
+ public void testStatelessBeanTimeout() throws Exception {
+ InitialContext ctx = new InitialContext();
+ Object object = ctx.lookup("CounterBeanLocal");
+ assertTrue("instanceof counter", object instanceof Counter);
+
+ final Counter counter = (Counter) object;
+ // Do a business method...
+ Runnable r = new Runnable(){
+ public void run(){
+ try{
+ counter.waitFor(30);
+ assertFalse(true);
+ }catch (Exception ex){
+ ex.printStackTrace();
+ assertEquals("An invocation of the Stateless Session Bean CounterBean has timed-out",ex.getMessage());
+ }
+ }
+ };
+
+ // How much ever the no of client invocations the count should be 10 as only 10 instances will be created.
+ for(int i=0;i<=30;i++){
+ Thread t = new Thread(r);
+ t.start();
+ }
+
+
+
+ }
+
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ System.setProperty(javax.naming.Context.INITIAL_CONTEXT_FACTORY, InitContextFactory.class.getName());
+
+ ConfigurationFactory config = new ConfigurationFactory();
+ Assembler assembler = new Assembler();
+
+ assembler.createProxyFactory(config.configureService(ProxyFactoryInfo.class));
+ assembler.createTransactionManager(config.configureService(TransactionServiceInfo.class));
+ assembler.createSecurityService(config.configureService(SecurityServiceInfo.class));
+
+ // containers
+ StatelessSessionContainerInfo statelessContainerInfo = config.configureService(StatelessSessionContainerInfo.class);
+ statelessContainerInfo.properties.setProperty("TimeOut", "100");
+ statelessContainerInfo.properties.setProperty("PoolSize", "10");
+ statelessContainerInfo.properties.setProperty("StrictPooling", "true");
+ assembler.createContainer(statelessContainerInfo);
+
+ // Setup the descriptor information
+
+ StatelessBean bean = new StatelessBean(CounterBean.class);
+ bean.addBusinessLocal(Counter.class.getName());
+ bean.addBusinessRemote(RemoteCounter.class.getName());
+ bean.addPostConstruct("init");
+ bean.addPreDestroy("destroy");
+
+ EjbJar ejbJar = new EjbJar();
+ ejbJar.addEnterpriseBean(bean);
+
+ assembler.createApplication(config.configureApplication(ejbJar));
+
+ }
+
+
+ public static interface Counter {
+ int count();
+ void waitFor(int i);
+ }
+
+ @Remote
+ public static interface RemoteCounter extends Counter {
+
+ }
+
+ public static enum Lifecycle {
+ CONSTRUCTOR, INJECTION, POST_CONSTRUCT, BUSINESS_METHOD, PRE_DESTROY
+ }
+
+ @Stateless
+ public static class CounterBean implements Counter, RemoteCounter {
+
+ public static int counter = 0;
+
+ public CounterBean() {
+ counter++;
+ }
+
+ public int count(){
+ return counter;
+ }
+
+ public void waitFor(int i){
+ try {
+ Thread.sleep(i);
+ } catch (InterruptedException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ public void init(){
+
+ }
+
+ public void destroy(){
+
+ }
+ }
+}