Return-Path: Delivered-To: apmail-incubator-geronimo-dev-archive@www.apache.org Received: (qmail 34957 invoked from network); 16 Feb 2004 19:57:25 -0000 Received: from daedalus.apache.org (HELO mail.apache.org) (208.185.179.12) by minotaur-2.apache.org with SMTP; 16 Feb 2004 19:57:25 -0000 Received: (qmail 32128 invoked by uid 500); 16 Feb 2004 19:57:07 -0000 Delivered-To: apmail-incubator-geronimo-dev-archive@incubator.apache.org Received: (qmail 32020 invoked by uid 500); 16 Feb 2004 19:57:07 -0000 Mailing-List: contact geronimo-dev-help@incubator.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: list-post: Reply-To: geronimo-dev@incubator.apache.org Delivered-To: mailing list geronimo-dev@incubator.apache.org Delivered-To: moderator for geronimo-dev@incubator.apache.org Received: (qmail 41616 invoked from network); 16 Feb 2004 19:14:22 -0000 From: Giampaolo Tomassoni To: geronimo-dev@incubator.apache.org, openejb-user@lists.sourceforge.net Subject: Re: Limitations in EJBs Home interface handling by OpenENB Date: Mon, 16 Feb 2004 20:12:47 +0100 User-Agent: KMail/1.5.1 References: <200402152044.28278.g.tomassoni@libero.it> <20040216005556.GA6028@sweetums.ce1.client2.attbi.com> In-Reply-To: <20040216005556.GA6028@sweetums.ce1.client2.attbi.com> MIME-Version: 1.0 Content-Type: Multipart/Mixed; boundary="Boundary-00=_vYRMA29SUrTK50C" Message-Id: <200402162012.47306.g.tomassoni@eurosoft-italia.com> X-Spam-Rating: daedalus.apache.org 1.6.2 0/1000/N X-Spam-Rating: minotaur-2.apache.org 1.6.2 0/1000/N --Boundary-00=_vYRMA29SUrTK50C Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline On Monday 16 February 2004 01:55, david.blevins@visi.com wrote: >...omissis... If you ever have the urge to contribute > code, I'll be happy to check it over. Dear David and friends, I had the impression that the problem was limited to the org.openejb.core.ivm.EjbHomeProxyHandler class only, so I tried to modify it to support the feature I need. At least, it should have been faster than downloading another EJB server, installing and configuring it, deploying my test app, ecc. ecc. In effect, it seems that I was right at first: the 'patched' version of the class seems to work to me. Whould you (and anybody else who may care) have a review at it? I'm attaching it as a unified diff format. In both the OpenEJB revision threads the class is the same, so the patch should be appliable to both. Regards, Giampaolo Tomassoni PS: I'm sending this patch to the openejb-user thread too. --Boundary-00=_vYRMA29SUrTK50C Content-Type: text/x-diff; charset="iso-8859-1"; name="HomeBusinessMethodsSupport.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="HomeBusinessMethodsSupport.patch" --- src/main/org/openejb/core/ivm/EjbHomeProxyHandler.java- 2002-10-04 00:09:34.000000000 +0200 +++ src/main/org/openejb/core/ivm/EjbHomeProxyHandler.java 2004-02-16 19:51:48.000000000 +0100 @@ -80,21 +80,68 @@ * * @author David Blevins * @author Richard Monson-Haefel + * @author Giampaolo Tomassoni * @see org.openejb.core.ivm.EjbObjectProxyHandler * @see org.openejb.core.stateful.StatefulContainer */ public abstract class EjbHomeProxyHandler extends BaseEjbProxyHandler { protected final static org.apache.log4j.Category logger = org.apache.log4j.Category.getInstance("OpenEJB"); - static final java.util.HashMap dispatchTable; + // This interface is an invoker helper, which helps method dispatching + // in costant time. + private interface InvokeHelper { + public Object invoke(Method method, Object[] args, Object proxy) + throws Throwable; + } + + private final InvokeHelper ihFind = new InvokeHelper() { + public Object invoke(Method method, Object[] args, Object proxy) + throws Throwable + { return(findX(method, args, proxy)); } + }; + + private final InvokeHelper ihBusiness = new InvokeHelper() { + public Object invoke(Method method, Object[] args, Object proxy) + throws Throwable + { return(businessMethod(method, args, proxy)); } + }; // this table helps dispatching in constant time, instead of many expensive equals() calls - static { + private java.util.HashMap dispatchTable; + { dispatchTable = new java.util.HashMap(); - dispatchTable.put("create", new Integer(1)); - dispatchTable.put("getEJBMetaData", new Integer(2)); - dispatchTable.put("getHomeHandle", new Integer(3)); - dispatchTable.put("remove", new Integer(4)); + dispatchTable.put( + "create", + new InvokeHelper() { + public Object invoke(Method method, Object[] args, Object proxy) + throws Throwable + { return(create(method, args, proxy)); } + } + ); + dispatchTable.put( + "getEJBMetaData", + new InvokeHelper() { + public Object invoke(Method method, Object[] args, Object proxy) + throws Throwable + { return(getEJBMetaData(method, args, proxy)); } + } + ); + dispatchTable.put( + "getHomeHandle", + new InvokeHelper() { + public Object invoke(Method method, Object[] args, Object proxy) + throws Throwable + { return(getHomeHandle(method, args, proxy)); } + } + ); + dispatchTable.put( + "remove", + new InvokeHelper() { + public Object invoke(Method method, Object[] args, Object proxy) + throws Throwable + { return(removeMethod(method, args, proxy)); } + } + ); } /** @@ -113,7 +160,6 @@ } protected Object createProxy(ProxyInfo proxyInfo){ - if (proxyInfo instanceof SpecialProxyInfo) { Object proxy = ((SpecialProxyInfo)proxyInfo).getProxy(); if (proxy == null) throw new RuntimeException("Could not create IVM proxy for "+proxyInfo.getInterface()+" interface"); @@ -135,50 +181,41 @@ protected abstract EjbObjectProxyHandler newEjbObjectHandler(RpcContainer container, Object pk, Object depID); + /** + *

+ * Invokes a method in the javax.ejb.EnterpiseBean + * by yielding control to the appropriate proxy method invoker. + *

+ *

+ * In order to keep a linear search time for the proxy method + * to call given an Home Interface method, an hashtable mapping + * the Home Interface method names to the related proxy method + * is maintained. + * Each time an H.I. method name not yet in the hashtable + * is invoked, this function attempts mapping to the corresponding + * proxy method and saves the mapping in the hashtable. + *

+ * + * @param proxy The Proxy object that represents this bean deployment's EJBObject or EJBHome. + * @param method The EJBHome method the caller is invoking. + * @param args The parameters to the method being invoked + * @return The result of invoking the appropriate method on the bean. + * @exception Throwable + */ protected Object _invoke(Object proxy, Method method, Object[] args) throws Throwable{ - if (logger.isInfoEnabled()) { logger.info("invoking method "+method.getName()+" on "+deploymentID); } String methodName = method.getName(); - - try{ - java.lang.Object retValue; - Integer operation = (Integer)dispatchTable.get(methodName); - - if(operation==null) { - if ( methodName.startsWith("find") ){ - retValue = findX(method, args, proxy); - } else { - // Cannot return null. Must throw and exception instead. - throw new UnsupportedOperationException("Unkown method: "+method); + InvokeHelper methodTarget = (InvokeHelper)dispatchTable.get(methodName); + if(methodTarget == null) { + methodTarget = (methodName.startsWith("find") ? ihFind : ihBusiness); + dispatchTable.put(methodName, methodTarget); } - }else { - switch(operation.intValue()) { - /*-- CREATE ------------- .create() ---*/ - case 1: retValue = create(method, args, proxy); break; - /*-- GET EJB METADATA ------ EJBHome.getEJBMetaData() ---*/ - case 2: retValue = getEJBMetaData(method, args, proxy); break; - /*-- GET HOME HANDLE -------- EJBHome.getHomeHandle() ---*/ - case 3: retValue = getHomeHandle(method, args, proxy); break; - /*-- REMOVE ------------------------ EJBHome.remove() ---*/ - case 4: { - Class type = method.getParameterTypes()[0]; - /*-- HANDLE ------- EJBHome.remove(Handle handle) ---*/ - if (javax.ejb.Handle.class.isAssignableFrom(type)) { - retValue = removeWithHandle(method, args, proxy); - } else { - /*-- PRIMARY KEY ----- EJBHome.remove(Object key) ---*/ - retValue = removeByPrimaryKey(method, args, proxy); - } - break; - } - default: - throw new RuntimeException("Inconsistent internal state: value "+operation.intValue()+" for operation "+methodName); - } - } + try{ + java.lang.Object retValue = methodTarget.invoke(method, args, proxy); if(logger.isDebugEnabled()) { logger.debug("finished invoking method "+method.getName()+". Return value:"+retValue); @@ -269,6 +306,44 @@ */ protected abstract Object findX(Method method, Object[] args, Object proxy) throws Throwable; + + /** + *

+ * Invokes a Home Business method, i.e.: a + * Business method which doesn't depend on + * a specific instance of the Bean. + *

+ *

+ * Home Business methods are declared in the + * Home interface. Their support is mandatory + * (see 9.5.4 of ejb-2_1-fr spec). + *

+ *

+ * Checks if the caller is authorized to invoke the + * javax.ejb.EJBHome.getHomeHandle on the EJBHome of the + * deployment. + *

+ * + * @param proxy The Proxy object that represents this bean deployment's EJBObject or EJBHome. + * @param method The EJBHome method the caller is invoking. + * @param args The parameters to the method being invoked + * @return Returns whatever the method declaration in the Home Interface dictates it shall return + * @exception Throwable + * @author Giampaolo Tomassoni + */ + protected Object businessMethod(Method method, Object[] args, Object proxy) + throws Throwable { + checkAuthorization(method); + return( + createProxy( + (ProxyInfo)container.invoke( + deploymentID, method, args, null, + getThreadSpecificSecurityIdentity() + ) + ) + ); + } + /*-------------------------------------------------*/ /* EJBHome methods */ /*-------------------------------------------------*/ @@ -468,4 +543,35 @@ * @see javax.ejb.EJBHome#remove */ protected abstract Object removeByPrimaryKey(Method method, Object[] args, Object proxy) throws Throwable; + + /** + *

+ * This is a 'generic' version of the remove method, + * implementing logic act to detect whether or not + * the method is invoked on an handle, thereby + * yielding control to a more specialized version + * of the method itself. + *

+ * + * @param method + * @param args + * @param proxy + * @return Whatever removeWithHandle or removeByPrimaryKey returns, that should be null + * @exception Throwable + * @see javax.ejb.EJBHome + * @see javax.ejb.EJBHome#remove + * @author Giampaolo Tomassoni + */ + private Object removeMethod(Method method, Object[] args, Object proxy) + throws Throwable { + return( + javax.ejb.Handle.class.isAssignableFrom(method.getParameterTypes()[0]) + ? + /*-- HANDLE ------- EJBHome.remove(Handle handle) ---*/ + removeWithHandle(method, args, proxy) + : + /*-- PRIMARY KEY ----- EJBHome.remove(Object key) ---*/ + removeByPrimaryKey(method, args, proxy) + ); + } } --Boundary-00=_vYRMA29SUrTK50C--