利用EjbProxy

利用EjbProxy

调用远程EJB的一个简单有效的class

摘要:

这个技巧告诉你如何利用EjbProxy,它提供了一些事例,调用远程EJB并不是直接与你的代码接合执行一个特殊的EJB

By Gorsen Huang

Translator Biggie

 

如果你经常采用EJB开发,你或许从客户机程序那里写代码访问EJB或者写代码访问其它EJB。通常情况下,执行这些代码仅需要一些很少的变化。一个好的程序员大多数情况下处理这个问题用拷贝和贴切。然而,拷贝和贴切几次后,它会变得让人烦燥。 那就是为什么我决定开发一个class让它帮我去做,我把它叫EjbProxy,用它使得代码保持干净和整洁,这个类在调用任何EJB都不需要知道EJBjndi name,并且可以在客户端或是EJB里使用它。

 

你必须遵循4种基本的措施来调用EJB

1.             创建一个jndi上下文(initial context

2.             在上下文中查找EJB name (look up the EJB name in context)

3.             取得EJB对像

4.             通过home对像的create()方法创建EJB实例对像

1-3步具体实施如下:

InitialContext ctx = new InitialContext (prop);
    Object home = ctx.lookup(beanName);
    EJBHome obHome =
      (EJBHome) PortableRemoteObject.narrow (home, EJBHome.class);

 

如你所见,你得到一个EJB name Object不需要知道具体的执行细节,除用jndi查找以外。

4步不是简单易懂的,当你试图用home对像去创建一个EJB 对像的时候,一旦EJBHome 接口没有定义create()方法时,你就不能通过home 对象调用create() 方法,只是实际上执行EJB实现这个方法。

 

作为一个可行的解决方法,你可以定义一个接口去继承EJB home并且声名create()方法,然后你可以简单的用home对像的这个接口并且访问create()方法。然而,这种方法有一个缺点:它需要所有的EJB实现这个接口,从任意的home接口中,调用你想调用的create()方法。

 

一个更好的解决方法是你可以使用java的反射能力(关于反射API的详细资料请参考Resources)利用reflection (反射)API你可以用Class.forname方法加载指定的class,然后访问getDeclaredMethod()方法重新声明class,你能用Method.invoke 执行这种方法。

 

以下代码是使用反射从home对像中获得EJB的实例对像:

Method m = obHome.getClass().getDeclaredMethod("create", new Class[0]);
Object objRemote = m.invoke (obHome, new Object[0]);
Object obj = PortableRemoteObject.narrow(objRemote, theClass);

 

即,这段程序片断是从home对像中得到class,并且通过访问getDeclaredMethod()create()方法名称获得create's Method对像。此外用invoke()方法执行create方法,返回EJB的实例对像。

The EjbProxy class

EjbProxy class,源代码EjbProxy.java,为你处理这些令人讨厌的细节。

 

EjbProxy相当简单,首先创建一个EjbProxy对像,你可以传递参数,例如用initial context 工厂 provider URL去创建initial context对像。然后访问getObj()方法用jndi查找EJB获得EJB实例对像。注意,当你从一个EJB调用另一个EJB涉及到名称时,你可能需要填加lookup name的一个环境字符串,例如java.comp/env/.

 

例子程序download 它将显示给你如何用EjbProxy去调用一个EJB。测试目的,我同样执行一个EJB,名字叫EjbProxyExample,它有一个pulbic 方法

 

public String hello (String name) throws RemoteException;

 

这个方法传入一个名称字符串并且返回一个hello组成的字符串变量,EjbProxy的jndi名称例子如下:com.javaworldtip.ejbproxyexample.EjbProxyExample,假设你用weblogic在本地的7001端口去构造和发布EJB, EjbProxyExample,客户端代码:

 

EjbProxy myproxy = new EjbProxy ("weblogic.jndi.WLInitialContextFactory",
                                 "t3://localhost:7001");
EjbProxyExample obj = (EjbProxyExample)myproxy.getObj
("com.javaworldtip.ejbproxyexample.EjbProxyExample");
//now get "Hello, World!" string and show it
String strHello = obj.hello("World");
System.out.println (strHello);

 

如果你用这个EJB调用同一服务器内部的另一个EJB的话,代码如下:

 

EjbProxy myproxy = new EbjProxy ();
EjbProxyExample obj = (EjbProxyExample)myproxy.getObj
("com.javaworldtip.ejbproxyexample.EjbProxyExample ");

 

如果你已经在部署文件中指定了EjbProxyExample,你就可以直接用getObj()方法:

EjbProxyExample obj =
      (EjbProxyExample) myproxy.getObj ("java:comp/env/EjbProxyExmaple");

How it works(它是如何工作的)

你可以扩展构造器或setContextProperties()方法;

public void setContextProperties (String initContextFactory,
                                  String providerUrl,
                                  String user,
                                  String password)
    {
        _prop = new Properties ();
        _prop.put (Context.INITIAL_CONTEXT_FACTORY, initContextFactory);
        _prop.put (Context.PROVIDER_URL, providerUrl);
        if (user != null)
        {
            _prop.put(Context.SECURITY_PRINCIPAL, user);
            if (password == null)
                        password = "";
            _prop.put(Context.SECURITY_CREDENTIALS, password);
        }
    }

所有的参数都是创建initContext的环境,包括initcontext工厂,provider URL,用户名,密码,如果你用这个类在同一容器中重新得到EJB,你可以简单的传入null或是干脆不用理睬他们。

 

现在,让我们看一看在我们的代理类中的重要方法,getObj()

public Object getObj (String beanJndiLookupName) throws EJBException
    {
        try
        {
            EJBHome obHome = getHome (beanJndiLookupName);
            //get the method of create
            Method m = obHome.getClass().getDeclaredMethod("create", new Class[0]);
            //invoke the create method
            Object obj = m.invoke (obHome, new Object[0]);
            return obj;
        }
        catch (NoSuchMethodException ne)
        {
            throw new EJBException (ne);
        }
        catch (InvocationTargetException ie)
        {
            throw new EJBException (ie);
        }
        catch (IllegalAccessException iae)
        {
            throw new EJBException (iae);
        }
    }

getObj()方法里,唯一需要的参数就是EJB查找的jndi name,这个方法首先调用了一个gethome()方法来获得EJBhome对像,然后调用getDeclaredMethod()方法获得create方法。一旦create被捕获,你就可以调用它并取得EJB的实例对像,如果发生意外的话,将抛出一个异常。

 

你必须处理一些可能发生的异常,例如:如果EJB没有声名create方法,方法getDeclaredMethod()将抛出NoSuchMethodException异常,在这段程序中,各种各样的捕捉将通过创建新的EJBException来处理这些可能发生的异常,这个方法,程序调用getObj()方法必须抛出EJBException并且适当的处理。

 

以下那些在getOjb()方法的getHome()方法代码如下:

public EJBHome getHome (String beanJndiLookupName) throws EJBException
    {
        try
        {
              InitialContext ctx = null;

              if (_prop != null)
                        ctx = new InitialContext (_prop);
                else
                        ctx = new InitialContext ();

            Object home = ctx.lookup(beanJndiLookupName);
            EJBHome obHome = (EJBHome)PortableRemoteObject.narrow (home, EJBHome.class);
            return obHome;
        }
        catch (NamingException ne)
        {
            throw new EJBException (ne);
        }
    }

这个方法简单的限制了第一步到第三步调用EJB方法,我用getHome()方法正确得到我想要的home对像。I.e你想得到EJB对像,并且迟些后调用它的方法(例如调用create方法创建一个session bean)

 

Extend EjbProxy

针对一些情况,你可能想继承EjbProxy,例如:假设EJB’s create()方法没有任何输入参数,你可以简单的通过继承这个类用getObj去处理大多数情况:

public Object getObj (String beanJNDILookupName, Class[] classes, Object[]
objects) throws EJBException;

在方法内部,当调用getDeclaredMethod() 和invoke()方法应用额外参数:

 

Method m = obHome.getClass().getDeclaredMethod("create", classes);
Object obj = m.invoke (obHome, objects);

 

你可以通过扩展这个类去执行任意EJB方法:

public Object executeMethod (String methodName, Class[] classes, Object[]
objects) throws EJBException;

methodName是执行方法名,在获得EJB对像之前,你可能需要在类中隐藏EJB对像。然后用类似过程修改getObj方法。

 

Simplify your everyday coding

利用java的反射机制,你可以用普通的柔韧性的EjbProxy,来调用本地的或是远程的或是另一个EJB,如你所见,你可以用EjbProxy 或是扩展它去实例化和调用EJB。

Resources

  • Obtain the source file for this tip:
    http://www.javaworld.com/javaworld/javatips/javatip118/EJBProxyTip.zip

  • Sun's Enterprise JavaBeans information:
    http://java.sun.com/products/ejb

  • Sun's Java Reflection API documentation:
    http://java.sun.com/products/jdk/1.1/docs/guide/reflection/

  • Also see "Make an EJB from Any Java Class with Java Reflection," Tony Loton (JavaWorld, December 2000):
    http://www.javaworld.com/jw-12-2000/jw-1215-anyclass.html

  • For more EJB articles, check out JavaWorld's Topical Index:
    http://www.javaworld.com/channel_content/jw-ejbs-index.shtml

  • For more articles on JNDI, visit our Topical Index:
    http://www.javaworld.com/channel_content/jw-jndi-index.shtml

  • View all previous Java Tips and submit your own:
    http://www.javaworld.com/javatips/jw-javatips.index.html

  • Learn Java from the ground up in JavaWorld's Java 101 column:
    http://www.javaworld.com/javaworld/topicalindex/jw-ti-java101.html

  • Java experts answer your toughest Java questions in JavaWorld's Java Q&A column:
    http://www.javaworld.com/javaworld/javaqa/javaqa-index.html

  • Sign up for JavaWorld's free weekly email newsletters:
    http://www.idg.net/jw-subscribe

  • You'll find a wealth of IT-related articles from our sister publications at IDG.net

 

你可能感兴趣的:(Java技术)