TSS提出两种新的EJB调用模式

04-02-29 banq
1. 使用reflection 技术调用EJB :

http://www.theserverside.com/patterns/thread.jsp?thread_id=24019

目前JdonSD框架中的EJB调用框架实际就是这么做的,具体原理见我的书籍《Java实用系统开发指南》中“EJB方法调用框架”章节。

2.为所有的Session Bean 编写统一的Home Interface

http://www.theserverside.com/patterns/thread.jsp?thread_id=22817

这个办法是我在EJB方法调用框架之前使用的一个调用框架,《Java实用系统开发指南》书中也提及到了,也是最容易想到的,但是我发现它在JBuilder的EJB图形开发工具中无效,结果我在bean Imp中增加了新的方法,图形工具无法显示,而且,还需要在ejb-jar.xml配置两次,觉得麻烦,丢弃不用了。

                   

holykeeper
2004-07-03 21:35
banq,你好。

我想请教相关的几个问题:

1.你提到的第二个方法:“为所有的Session Bean 编写统一的Home Interface ”,是指什么?能说的详细一些吗?(链接有误,无法参考)

2.我也倾向于使用反射方法实现Session Bean的统一调用,但是我的同事提出一个疑问:在客户实现方法调用时难以确定方法的参数,就是说,在隐藏Session Bean调用的同时,丢失了一些必要的细节;同时,也无法进行编译时类型检查了。

究竟是该如何抉择?希望banq能给我指点。谢谢!

wwlhp@jdon
2004-07-04 11:19
第一种方法我已经使用过了,感觉挺好。我用这种方法写了一个无状态会话bean的通用代理,已经在我们的系统中使用,效果不错。

import java.lang.reflect.*;
import java.rmi.*;
import javax.ejb.*;
import javax.naming.*;

import com.gdpost.isp.lis.util.exception.*;
import com.gdpost.isp.lis.util.logging.*;
import com.gdpost.isp.lis.util.naming.*;

/**
 * <p>Title: stateless sessionBean的动态代理。这是一个单实例类,
 * 只能通过getInstance方法获得这个实例。</p>
 * <p>Description: </p>
 * <p>Copyright: Copyright (c) 2004</p>
 * <p>Company: </p>
 * @author wuwei
 * @version 1.0
 */
public class DynamicEJBProxy {

    // 私有构造函数,防止从外部创建实例
    private DynamicEJBProxy () {}

    private static DynamicEJBProxy singleton = new DynamicEJBProxy ();
    /**
     * 得到唯一的实例
     * @return  本类唯一的一个实例
     */
    public static DynamicEJBProxy getInstance () {
        return singleton;
    }

    /**
     * 此方法用来呼叫指定的stateless sessionBean的指定的业务方法。
     * 实现过程为:
     *   <br>&nbsp;&nbsp;1>  根据jndiName和homeInterface找到home接口
     *   <br>&nbsp;&nbsp;2>  呼叫home接口的create方法,返回remote接口
     *   <br>&nbsp;&nbsp;3>  呼叫remote接口的业务方法,保存调用结果
     *   <br>&nbsp;&nbsp;4>  呼叫remote接口的remove方法
     *   <br>&nbsp;&nbsp;5>  返回第3步的调用接过
     * @param jndiName  sessionBean的JNDI名字
     * @param homeInterface  sessionBean的home接口类型
     * @param methodName  sessionBean的业务方法名字
     * @param args  sessionBean的业务方法参数
     * @return  sessionBean的业务方法返回结果
     * @throws UserException  被呼叫的sessionBean的业务方法抛出的业务异常
     */
    public Object invoke (String jndiName,
                          Class homeInterface,
                          String methodName,
                          Object[] args)
        throws UserException {
        try {
            // 得到home stub
            EJBHome homestub =
                NamingLocator.getInstance().lookup (
                jndiName, homeInterface);

            // 调用home stub上的create方法,得到remote stub
            Object remotestub = homestub.getClass ().getMethod (
                "create", null).invoke (homestub, null);

            // 得到remote stub上的要调用的业务方法的参数类型
            Class[] paramTypes = new Class[args.length];
            for (int i = 0; i < args.length; ++i) {
                paramTypes[i] = args[i].getClass ();
            }

            // 调用remote stub上的业务方法
            Object returnValue = remotestub.getClass ().getMethod (
                methodName, paramTypes).invoke (remotestub, args);

            // 调用remote stub上的remove方法
            remotestub.getClass ().getMethod (
                "remove", null).invoke (remotestub, null);

            // 返回调用结果
            return returnValue;
        }
        catch (NamingException e) {
            LoggingUtil.loggingExceptionInLIS (e);
            throw new UserException ("399490000", 3, 6, "", "查询jndi出现异常");
        }
        catch (NoSuchMethodException e) {
            LoggingUtil.loggingExceptionInLIS (e);
            throw new UserException ("399490000", 3, 6, "", "ejb没有"+methodName+"方法");
        }
        catch (IllegalAccessException e) {
            LoggingUtil.loggingExceptionInLIS (e);
            throw new UserException ("399490000", 3, 6, "", e.getMessage());
        }
        catch (InvocationTargetException e) {
            // 得到sessionBean的create方法、业务方法以及remove方法抛出的异常
            Throwable cause = e.getTargetException();
            LoggingUtil.loggingExceptionInLIS (cause);
            // 判断异常的类型
            if (cause instanceof CreateException) {
                throw new UserException ("399490000", 3, 6, "",
                                         "ejb抛出CreateException");
            }
            else if (cause instanceof RemoveException) {
                throw new UserException ("399490000", 3, 6, "",
                                         "ejb抛出RemoveException");
            }
            else if (cause instanceof RemoteException) {
                throw new UserException ("399490000", 3, 6, "",
                                         "ejb抛出RemoteException");
            }
            else if (cause instanceof UserException) {
                // 真正的业务异常
                throw (UserException) cause;
            }
            else {
                // 未知类型的异常
                throw new UserException ("399490000", 3, 6, "",
                                         "ejb抛出未知类型的异常");
            }
        }
    }

}

zhuam
2004-07-05 08:49
采用反射不错,使得系统更加个灵活多变!

banq
2004-07-05 09:25
实际上这是两种模式的区别:

使用统一的接口,实际是使用Command模式,这种方式在PetStore中Web调用EJB层采用的方式,优点是Web层不需要知晓EJB的接口,通过XML文件配置。

使用反射机制,实际是一种动态代理,以方法拦截所有的调用,这种方式灵活,需要将EJB的接口方法通知Web层,EJB接口是Web开发小组和EJB开发小组所依赖,也体现了面向接口编程的OO方法吧。

猜你喜欢
4Go 1 2 3 4 下一页