parchen2008
parchen2008
2009-04-20 12:41

急:通過JNDI查找時返回的不是Bean實例對象,而是一個Null對象,該怎樣解決?

  • jboss
在Junit中测试Session Bean的业务方法时发现这样一种情况,通过JNDI查找Bean实例,并调用该Bean的某一业务方法时,抛出java.lang.NullPointerException异常,查找API文档,如下: 

public class NullPointerException extends RuntimeException
当应用程序试图在需要对象的地方使用 null 时,抛出该异常。这种情况包括:

调用 null 对象的实例方法。
访问或修改 null 对象的字段。
将 null 作为一个数组,获得其长度。
将 null 作为一个数组,访问或修改其时间片。
将 null 作为 Throwable 值抛出。
应用程序应该抛出该类的实例,指示其他对 null 对象的非法使用。

初步断定是第一种情况,调用了null对象的实例方法,也就是说通过JDNI查找时返回的不是Bean实例对象,而是一个null对象,请教一下,问题究竟出在什么地方,要怎样解决才好! 
我所使用的服务器是jboss-5.0.1.GA-jdk6,查找JNDI树发现该Session Bean已经绑定到全局命名空间,所使用的数据库是JBoss默認提供的數據庫,DefaultDS已經綁定在Java命名空間,下面是Junit測試中的部分代碼:

      @BeforeClass
public static void setUpBeforeClass() throws Exception {
    try {

        InitialContext ctx = new InitialContext();
        Object ref = ctx.lookup("MedicineManagerBean/remote");
        MedicineManager m = (MedicineManager) PortableRemoteObject.narrow(
                ref, MedicineManager.class);

    } catch (NamingException e) {
        System.out.println("命名异常");
        e.printStackTrace();
    }
}

測試的方法代碼:

      @Test
public void testSave() {
    m.save(new Medicine(11022, "黄莲上清片", "片剂", "片/板", "板", "2008-08-08",
            "2009-08-08"));
}

persistence.xml配置文件如下:

       <?xml version="1.0" encoding="UTF-8"?>
         <persistence xmlns="http://java.sun.com/xml/ns/persistence"
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      xsi:schemaLocation="http://java.sun.com/xml/ns/persistence                 
                      http://java.sun.com/xml/ns/persistence/persistence/persistence_1_0.xsd"
                      version="1.0">
                <persistence-unit name="medicine" transaction-type="JTA">
                      <jta-data-source>java:/DefaultDS</jta-data-source>
                      <properties>
                         <property name="hibernate.hbm2ddl.auto" value="update"/>
                         <property name="hibernate.show_sql" value="true"/>
                         <property name="hibernate.format_sql" value="true"/>
                      </properties>
                </persistence-unit>

          </persistence>

 該應用的目錄結構如下:
         +src
           +cn.gdpu.domain                     //包結構
               ---Medicine.java
           +cn.gdpu.profession                 //包結構
               ---MedicineManagerRemote.java
               ---MedicineManagerLocal.java
           +cn.gdpu.profession.impl            //包結構
               ---MedicineManagerBean.java
           +junit.test                         //測試包
               ---MedicineManagerTest.java
           +META-INF                            //META-INF目錄
               ---persistence.xml
           ---jndi.properties                   //JNDI配置文件
           +build                               //class文件所在目錄
               ---build.xml                     //ANT配置文件

我是一个EJB学习的新手,因为所学课程需要,我现在正尝试用EJB开发一个药品管理系统,但是却因为这个问题而阻碍了进展,在網上也找不到相關的有用信息,已經調試了一兩個星期了可是還是沒有解決,所以有点急,希望懂的朋友帮忙指定一下,谢谢!!!

[b]问题补充:[/b]
我所使用的開發工具是Eclipse,使用的JUnit工具也是Eclipse內嵌的,版本是JUnit4,下面是運行測試時給出的異常信息截圖:

[b]问题补充:[/b]
截圖中异常指向的位置就是testSave()方法中m.save(...)方法所在語句!
JNDI属性配置文件已经加入,内容如下:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.provider.url=localhost:1099
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.Interfaces

[b]问题补充:[/b]
很感谢lovewhzlq和hantsy的指点,在lovewhzlq的第二条回复中要求我给出更加详细的异常信息,由于我在使用Eclipse的JUnit进行测试的时候JUnit框架只给出了一条简单的信息,所以我就想通过一个简单的客户端来尝试捕获这个NullPointerException异常,并调用printStackTrace()方法,从而获得更加详细的异常信息,但是我却发现一个新的问题,我写了下面这样一个类来尝试获取详细的异常信息,但是却没有出现上面所说的异常,而是正确地运行了,查看数据库发现记录已经正确地插入了进去,但是重新运行Junit测试用例中的testSave()方法时却又出现了上面截图中所出现的情况,实际运行可以但是测试时却出异常,不知道这是不是因为Junit测试框架本身的问题!!

下面是我原本打算用来捕获异常的模拟客户端代码,这里的代码基本上都是从上面提到过的测试用例中直接Copy过来的:
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import cn.gdpu.domain.Medicine;
import cn.gdpu.profession.MedicineManager;

public class client {
public static void main(String args[]) {
try {

        InitialContext ctx = new InitialContext();
        Object ref = ctx.lookup("MedicineManagerBean/remote");
        MedicineManager m = (MedicineManager) PortableRemoteObject.narrow(
                ref, MedicineManager.class);

        m.save(new Medicine(11022, "黄莲上清片", "片剂", "片/板", "板", "2008-08-08",
                "2009-08-08"));
        System.out.println("保存成功");

    } catch (NamingException e) {
        System.out.println("命名异常");
        e.printStackTrace();
    } catch (NullPointerException er) {
        System.out.println("空指针异常");
        er.printStackTrace();
    }

}

}

[b]问题补充:[/b]
@BeforeClass
public static void setUpBeforeClass() throws Exception {
try {

InitialContext ctx = new InitialContext();
Object ref = ctx.lookup("MedicineManagerBean/remote");
[color=red]//你这个地方是个局部变量啊,
MedicineManager m = (MedicineManager) PortableRemoteObject.narrow(
ref, MedicineManager.class);
//应该写成
m = (MedicineManager) PortableRemoteObject.narrow(
ref, MedicineManager.class); [/color]
} catch (NamingException e) {
System.out.println("命名异常");
e.printStackTrace();
}
}

天哪?我怎么这么白痴啊,犯这种低级的错误这么久还没能够发现,晕!!真是太谢谢了!!问题已经解决!!

  • 点赞
  • 回答
  • 收藏
  • 复制链接分享

9条回答