Learn EJB (1)

初学EJB Session Bean理解的一些概念和一些低级的问题。IDE是RAD6。记性不好,记录下来备忘。

一些概念

觉得下面网址上这段话不错,先用一下:

http://www-128.ibm.com/developerworks/cn/java/j-namespace/index.html#resources

名称空间上下文初始上下文子上下文这些术语都是有关位置的 ―― 是从客户机的角度看时 EJB 组件所在的概念性的位置。将一个名称空间想像为一个城镇,城镇中的商店由 EJB home接口(我们将在稍后讨论它)表示。上下文是城镇中的一个位置。初始上下文是您开始时所在的位置 ―― 就像它是到城镇的道路。而子上下文是街道名。
home接口(home interface)和远程接口(remote interface企业 JavaBean 组件有三个部分。首先是 bean 代码本身。然后是home接口,它定义了创建您自己的 EJB bean 的方法。home接口是在名称空间中发布的。当您有了home接口后,就可以调用 Create() 以从应用服务器获得远程接口。获得了远程接口后,就可以调用构成实际的 EJB 代码的方法了。
如何将这些术语应用到您的城镇模拟中去呢?到达正确的城镇并找到正确的地址后,您需要走进商店或者按铃(调用Create())。这个过程对于您要去的所有商店都是一样的,不过,您所收到的响应取决于是由谁来提供服务 ―― 比如是一位屠夫、一位面包师还是一位烛台制作者。这个响应代表了远程接口。每个人都是不同的并且可以要求他提供不同的东西。您必须知道与您交谈的人(即 bean)的职业才能提出正确的问题(即调用正确的方法) ―― 向一位屠夫要一条面包可不妥当。
CosNamingLDAP JNDI Java 命名和目录接口(Java Naming and Directory Interface JNDI)提供了一个标准接口,它指明您需要如何与名称空间交互。我们所提到的LDAPCosNaming就是 JDNI 名称空间类型。现在扩展我们的比喻:JNDI 是城镇的模板,而 CosNaming 和 LDAP 是特定的城镇。它们以相似的方式操作,但是有不同的布局。

EJB的各种stub/tie java代码都是在布署的时候生成的, 所以如果是提示什么stub/tie找不到或出错什么的, 不妨把这些stub文件删掉, 重新编译布署试试. 因为自动生成的是stub/tie java代码, 所以用project clean是无法clean的.

新建EJB项目时,有一个选项 Create an EJB Client JAR Project to hold the client interfaces and classes ,如下:

对这个选项的描述如下:

What is a EJB client project? It is a plain Java project that holds the remote/local home and component interfaces, and generated stub classes. The project contains minimal classes and interface for a EJB client application to compile and execute.
How does the EJB project refer to the home and component interfaces in the EJB client project? The EJB client project is setup in the enterprise application project (Test Application) as a utility JAR project. The EJB project - Test EJB - has a Java JAR dependency on the client project. (The concept of a utility JAR project is fairly old and a discussion of this is beyond the scope of this tutorial).
The EJB client layer (i.e. the Web project) should build a dependency on the client JAR file only and never to the actual EJB JAR file. The EJB JAR file is installed only in the application server machine where the EJB module is deployed. The client JAR file can be freely distributed anywhere.

这样有一个好处, EJB和使用EJB的客户端都用到的类比如VO, 就可以定义在EJB client project中. 这在小型软件中是很方便实用的做法。

使用EJB的客户端想要远程调用EJB的方法,比如是普通的Java Application,它必须包含EJB Client的jar包(或整个EJB的jar包), j2ee.jar(因为用到javax.ejb, javax.naming, javax.rmi等包里的类), namingclient.jar(jndi的一些东西), implfactory.properties和jndi.properties (两个都放在代码目录src下编译后自动会拷贝到bin下或class路径下, 只要程序运行时能找到, implfactory.properties位于RAD6/runtimes/base_v51/bin/wsinstance/propdefaults, jndi.properties位于RAD6/rwd/eclipse/plugins/com.ibm.etools.utc_6.0.0/IBMUTC/IBMUTC.ear/UTC.war/WEB-INF/jndi.properties ).

不包含namingclient.jar可能出现如下错误:

Exception in thread "main" javax.naming.ConfigurationException: The property com.ibm.ws.naming.wsn.factory.initial is not set. The most likely cause is that the jar which contains the file com/ibm/websphere/naming/jndiprovider.properties cannot be found by the class loader.
      at com.ibm.websphere.naming.WsnInitialContextFactory.init_implClassCtor(WsnInitialContextFactory.java:192)
      at com.ibm.websphere.naming.WsnInitialContextFactory.getInitialContext(WsnInitialContextFactory.java:110)
      at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:675)
      at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:257)
      at javax.naming.InitialContext.init(InitialContext.java:233)
      at javax.naming.InitialContext.<init>(InitialContext.java:209)
      at Main.getContext(Main.java:22)
      at Main.main(Main.java:28)

lookup时只能引用EJB在server中的jndi name(iiop://localhost:2809/ejb/secondEJB/SecondHelloHome)来访问. java:comp/env前缀是j2ee上下文的标准前缀, 这个客户端并没有.

javax.rmi.PortableRemoteObject.narrow方法的作用只是为了检测, 只是出于安全上的考虑. 在不能构成所要对象时会抛出ClassCastException异常.

“Checks to ensure that an object of a remote or abstract interface type can be cast to a desired type.”

具体一份客户端讨问EJB的代码如下:

package  tony.firstEJBTest;

import  java.rmi.RemoteException;
import  java.util.Properties;

import  javax.ejb.CreateException;
import  javax.naming.InitialContext;
import  javax.naming.NamingException;
import  javax.rmi.PortableRemoteObject;

import  tony.firstEJB.HelloWorld;
import  tony.firstEJB.HelloWorldHome;

/**
 * 
@author p465890
 *
 * TODO To change the template for this generated type comment go to
 * Window - Preferences - Java - Code Style - Code Templates
 
*/

public   class  HelloWorldTest
{
    
// not used here, because the context has been set in jndi.properties
    private static InitialContext getContext() throws NamingException
    
{
        Properties props 
= new Properties();
        props.put(InitialContext.INITIAL_CONTEXT_FACTORY, 
"com.ibm.websphere.naming.WsnInitialContextFactory");
        props.put(InitialContext.PROVIDER_URL, 
"iiop://localhost:2809/");
        
return new InitialContext(props);
    }

    
    
public static void main(String[] args) throws NamingException, RemoteException, CreateException
    
{
        
// InitialContext initial = getContext();
        InitialContext initial = new InitialContext();
        Object objref 
= initial.lookup("iiop://localhost:2809/ejb/tony/firstEJB/HelloWorldHome");
        HelloWorldHome home 
= (HelloWorldHome)PortableRemoteObject.narrow(objref, HelloWorldHome.class);
        
//HelloWorldHome home = (HelloWorldHome)objref;
        if (objref == (HelloWorldHome) PortableRemoteObject.narrow(objref, HelloWorldHome.class))
        
{
            System.out.println(
"yes");
        }

        
else
        
{
            System.out.println(
"no");
        }

        HelloWorld hello 
= home.create();
        System.out.println(hello.getSomething());
    }

}

若客户端是J2EE Client Application或Web程序或什么垃圾容器中建的工程, 一般都包含了J2EE Context, 所以只要写客户端连接代码就可以了, 什么包啊, .properties配置文件都自动包含进来了.

EJB2.1的项目,除了重建,不知有没更好地办法改用EJB2.0。

在客户端要使用服务端EJB时,创建初始下下文时,如下语句:

InitialContext initial = new InitialContext();

错误提示:

javax.naming.ConfigurationException: Name space accessor for the java: name space has not been set. Possible cause is that the user is specifying a java: URL name in a JNDI Context method call but is not running in a J2EE client or server environment.
      at com.ibm.ws.naming.java.javaURLContextFactory.isNameSpaceAccessable(javaURLContextFactory.java:98)
      at com.ibm.ws.naming.urlbase.UrlContextFactory.getObjectInstance(UrlContextFactory.java:73)
      at javax.naming.spi.NamingManager.getURLObject(NamingManager.java:592)
      at javax.naming.spi.NamingManager.getURLContext(NamingManager.java:541)
      at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:289)
      at javax.naming.InitialContext.lookup(InitialContext.java:361)
      at helloWorldfEJB.HelloWorldClient.main(HelloWorldClient.java:57)

在默认情况下,InitialContext工厂是在jndi.properties中定义的,这个工厂类有默认的服务器 URL 和端口号默认值。这个文件在类路径中(这一般意味着在本地目录)或者在您的类路径中的任何 JAR 中。不同的应用服务器可能在不同的 JAR 文件中提供它们的默认值,WebSphere Application Server 在namingclient.jar中储存一个默认副本。

所以这个错误实际上是没有指定InitialContext工厂引起的,这可以在程序中指定,也可以通过其他方式,比如jndi.properties中指定, 具体看开头提到的那个网页:

http://www-128.ibm.com/developerworks/cn/java/j-namespace/index.html#resources

于是可以用下面的方法创建InitialContext实例:

Properties props  =   new  Properties();
props.put(InitialContext.INITIAL_CONTEXT_FACTORY,  
" com.ibm.websphere.naming.WsnInitialContextFactory " );
props.put(InitialContext.PROVIDER_URL, 
" iiop://localhost:2809/ " );
InitialContext initialContext 
=   new  InitialContext(props);

上面设的值com.ibm.websphere.naming.WsnInitialContextFactory和iiop://localhost:2809/在jndi.properties文件可以找到,也可以在Client Test(RAD有提供,直接布署EJB就会跳出)中JNDI Properties中查看,如下图:

在Test Client下还可以测试布署好的EJB,具体便不说了,图如下:

另外值得提下的是用开头引用页面上讲的方法,通过命令行配置InitialContext工厂,即运行tnameserv.exe方法,会出现错误提示大概如下:

Exception in thread "main" org.omg.CORBA.DATA_CONVERSION:   minor code: 5 4F4D0001  completed: No

网上查了下只知道跟字符的编码有关,没有细究。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值