在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();
}
}
天哪?我怎么这么白痴啊,犯这种低级的错误这么久还没能够发现,晕!!真是太谢谢了!!问题已经解决!!