Java ejb 查找因 NamingException 而失败
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1473939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ejb lookup failing with NamingException
提问by Drake
I've added the following in my web.xml:
我在 web.xml 中添加了以下内容:
<ejb-ref>
<ejb-ref-name>ejb/userManagerBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>gha.ywk.name.entry.ejb.usermanager.UserManagerHome</home>
<remote>what should go here??</remote>
</ejb-ref>
The following java code is giving me NamingException:
以下 java 代码给了我 NamingException:
public UserManager getUserManager () throws HUDException {
String ROLE_JNDI_NAME = "ejb/userManagerBean";
try {
Properties props = System.getProperties();
Context ctx = new InitialContext(props);
UserManagerHome userHome = (UserManagerHome) ctx.lookup(ROLE_JNDI_NAME);
UserManager userManager = userHome.create();
WASSSecurity user = userManager.getUserProfile("user101", null);
return userManager;
} catch (NamingException e) {
log.error("Error Occured while getting EJB UserManager" + e);
return null;
} catch (RemoteException ex) {
log.error("Error Occured while getting EJB UserManager" + ex);
return null;
} catch (CreateException ex) {
log.error("Error Occured while getting EJB UserManager" + ex);
return null;
}
}
The code is used inside the container. By that I mean that the .WAR is deployed on the server (Sun Application Server).
代码在容器内部使用。我的意思是 .WAR 部署在服务器(Sun Application Server)上。
StackTrace (after jsight's suggestion):
StackTrace(根据 jsight 的建议):
>Exception occurred in target VM: com.sun.enterprise.naming.java.javaURLContext.<init>(Ljava/util/Hashtable;Lcom/sun/enterprise/naming/NamingManagerImpl;)V
java.lang.NoSuchMethodError: com.sun.enterprise.naming.java.javaURLContext.<init>(Ljava/util/Hashtable;Lcom/sun/enterprise/naming/NamingManagerImpl;)V
at com.sun.enterprise.naming.java.javaURLContextFactory.getObjectInstance(javaURLContextFactory.java:32)
at javax.naming.spi.NamingManager.getURLObject(NamingManager.java:584)
at javax.naming.spi.NamingManager.getURLContext(NamingManager.java:533)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:279)
at javax.naming.InitialContext.lookup(InitialContext.java:351)
at gov.hud.pih.eiv.web.EjbClient.EjbClient.getUserManager(EjbClient.java:34)
回答by Pascal Thivent
First, fix your web.xml and add the Remote Interface in it:
首先,修复您的 web.xml 并在其中添加远程接口:
<ejb-ref>
<description>Sample EJB</description>
<ejb-ref-name>SampleBean</ejb-ref-name>
<ejb-ref-type>Session</ejb-ref-type>
<home>com.SampleHome</home>
<remote>com.Sample</remote> <!-- the remote interface goes here -->
</ejb-ref>
Then, regarding the java.lang.NoSuchMethodError
, Sean is right, you have a mismatch between the version of the app server "client library" you are using inside NetBeans and the app server version (server-side). I can't tell you exactly which JARs you need to align though, refer to the Sun Application Server documentation.
然后,关于java.lang.NoSuchMethodError
,Sean 是对的,您在 NetBeans 中使用的应用服务器“客户端库”版本与应用服务器版本(服务器端)不匹配。我不能确切地告诉您需要对齐哪些 JAR,请参阅 Sun Application Server 文档。
PS: This is not a direct answer to the problem but I don't think you're currently passing any useful properties when creating your initial context with the results of the call to System.getProperties()
, there is nothing helpful in these properties to define the environment of a context (e.g. the initial context factory). Refer to the InitialContextjavadocs for more details.
PS:这不是问题的直接答案,但我认为在使用调用结果创建初始上下文时,您目前没有传递任何有用的属性System.getProperties()
,这些属性中没有任何帮助来定义环境上下文(例如初始上下文工厂)。有关更多详细信息,请参阅InitialContextjavadocs。
回答by Sean Owen
Last two answers are both correct in that they are things you need to change/fix. But the NoSuchMethodError you see is not from your code, nor from things trying to find your code (would produce some kind of NoClassDefFoundException, I think, were this the case). This looks more like incompatible versions of the JNDI provider provided by the container, and what the JNDI implementation in the Java library wants. That's a pretty vague answer, but, would imagine it is solvable by perhaps upgrading your application server, and, ensuring you aren't deploying possibly-stale copies of infrastructure classes related to JNDI with your app, that might interfere.
最后两个答案都是正确的,因为它们是您需要更改/修复的东西。但是你看到的 NoSuchMethodError 不是来自你的代码,也不是来自试图找到你的代码的东西(我认为会产生某种 NoClassDefFoundException ,如果是这种情况)。这看起来更像是容器提供的 JNDI 提供程序的不兼容版本,以及 Java 库中的 JNDI 实现需要什么。这是一个非常模糊的答案,但是,可以想象它可以通过升级您的应用程序服务器来解决,并且确保您不会在您的应用程序中部署与 JNDI 相关的基础设施类的可能过时的副本,这可能会产生干扰。
回答by Arthur Ronald
I think you want to access an EJB application (known as EJB module) from a web application in Sun Application Server, right ?
我想您想从 Sun Application Server 中的 Web 应用程序访问 EJB 应用程序(称为 EJB 模块),对吗?
ok, let's go.
好了,走吧。
When you deploy an EJB into an application server, the application server gives it an address - known as global JNDI address - as a way you can access it (something like your address). It changes from an application server to another.
当您将 EJB 部署到应用程序服务器中时,应用程序服务器会为其提供一个地址——称为全局 JNDI 地址——作为您访问它的一种方式(类似于您的地址)。它从一个应用程序服务器更改为另一个应用程序服务器。
In JBoss Application Server, you can see global JNDI address (after starting it up) in the following address
在JBoss应用服务器中,可以在如下地址看到全局JNDI地址(启动后)
http://127.0.0.1:8080/jmx-console/HtmlAdaptor
In Sun Application Server, if you want to see global JNDI address (after starting it up), do the following
在 Sun Application Server 中,如果要查看全局 JNDI 地址(启动后),请执行以下操作
Access the admin console in the following address
在以下地址访问管理控制台
http://127.0.0.1:4848/asadmin
And click JNDI browsing
然后点击JNDI 浏览
If your EJB IS NOT registered right there, there is something wrong
如果您的 EJB 未在那里注册,则说明有问题
EJB comes in two flavors: EJB 2.1 and EJB 3.0. So what is the difference ?
EJB 有两种版本:EJB 2.1 和 EJB 3.0。那么区别是什么呢 ?
Well, well, well...
嗯,嗯,嗯……
Let's start with EJB 2.1
让我们从 EJB 2.1 开始
- Create a Home interface
- 创建主页界面
It defines methods for CREATING, destroying, and finding local or remote EJB objects. It acts as life cycle interfaces for the EJB objects. All home interfaces have to extend standard interface javax.ejb.EJBHome - if you a using a remote ejb object - or javax.ejb.EJBLocalHome - if you are using a local EJB object.
它定义了用于创建、销毁和查找本地或远程 EJB 对象的方法。它充当 EJB 对象的生命周期接口。所有本地接口都必须扩展标准接口 javax.ejb.EJBHome - 如果您使用远程 ejb 对象 - 或 javax.ejb.EJBLocalHome - 如果您使用本地 EJB 对象。
// a remote EJB object - extends javax.ejb.EJBHome
// a local EJB object - extends javax.ejb.EJBLocalHome
public interface MyBeanRemoteHome extends javax.ejb.EJBHome {
MyBeanRemote create() throws javax.ejb.CreateException, java.rmi.RemoteException;
}
Application Server will create Home objects as a way you can obtain an EJB object, nothing else.
Application Server 将创建 Home 对象作为获取 EJB 对象的一种方式,仅此而已。
Take care of the following
请注意以下事项
A session bean's remote home interface MUST DEFINE ONE OR MORE create<METHOD> methods. A stateless session bean MUST DEFINE exactly one <METHOD> method with no arguments.
会话 bean 的远程 home 接口必须定义一个或多个 create<METHOD> 方法。无状态会话 bean 必须准确定义一个没有参数的 <METHOD> 方法。
...
...
throws clause MUST INCLUDE javax.ejb.CreateException
throws 子句必须包含 javax.ejb.CreateException
...
...
If your Home interface extends javax.ejb.EJBHome, throws clauses MUST INCLUDE the java.rmi.RemoteException. If it extends javax.ejb.EJBLocalHome, MUST NOT INCLUDE the java.rmi.RemoteException.
如果 Home 接口扩展 javax.ejb.EJBHome,则 throws 子句必须包含 java.rmi.RemoteException。如果它扩展了 javax.ejb.EJBLocalHome,则不得包含 java.rmi.RemoteException。
...
...
Each create method of a stateful session bean MUST BE NAMED create<METHOD>, and it must match one of the Init methods or ejbCreate<METHOD> methods defined in the session bean class. The matching ejbCreate<METHOD> method MUST HAVE THE SAME NUMBER AND TYPES OF ARGUMENTS. The create method for a stateless session bean MUST BE NAMED createbut need not have a matching “ejbCreate” method.
有状态会话 bean 的每个 create 方法都必须命名为 create<METHOD>,并且它必须匹配会话 bean 类中定义的 Init 方法或 ejbCreate<METHOD> 方法之一。匹配的 ejbCreate<METHOD> 方法必须具有相同数量和类型的参数。无状态会话 bean 的 create 方法必须命名为create但不需要匹配的“ejbCreate”方法。
Now create an business interface in order to define business logic in our EJB object
现在创建一个业务接口,以便在我们的 EJB 对象中定义业务逻辑
// a remote EJB object - extends javax.ejb.EJBObject
// a local EJB object - extends javax.ejb.EJBLocalObject
public interface MyBeanRemote extends javax.ejb.EJBObject {
void doSomething() throws java.rmi.RemoteException;
}
Now take care of the following
现在注意以下几点
If you are using a remote EJB object, remote interface methods MUST NOT EXPOSE local interface types or local home interface types.
如果您使用远程 EJB 对象,远程接口方法不得公开本地接口类型或本地本地接口类型。
...
...
If your Home interface extends javax.ejb.EJBObject, throws clauses MUST INCLUDE the java.rmi.RemoteException. If it extends javax.ejb.EJBLocalObject, MUST NOT INCLUDE the java.rmi.RemoteException.
如果 Home 接口扩展 javax.ejb.EJBObject,则 throws 子句必须包含 java.rmi.RemoteException。如果它扩展了 javax.ejb.EJBLocalObject,则不得包含 java.rmi.RemoteException。
Now our EJB
现在我们的 EJB
public class MyBean implements javax.ejb.SessionBean {
// why create method ? Take a special look at EJB Home details (above)
public void create() {
System.out.println("create");
}
public void doSomething() throws java.rmi.RemoteException {
// some code
};
}
Now take care of the following
现在注意以下几点
It MUST IMPLEMENTS javax.ejb.SessionBean. It defines four methods - not shown above: setSessionContext, ejbRemove, ejbPassivate, and ejbActivate.
它必须实现 javax.ejb.SessionBean。它定义了四种方法——上面没有显示:setSessionContext、ejbRemove、ejbPassivate 和 ejbActivate。
Notice our bean DOES NOT IMPLEMENTour business interface because of EJB specification says:
注意我们的 bean没有实现我们的业务接口,因为 EJB 规范说:
For each method defined in the interface, there must be a matching methodin the session bean's class. The matching method must have:
对于接口中定义的每个方法,会话 bean 的类中必须有一个匹配的方法。匹配方法必须具有:
- The same name
- The same number and types of arguments, and the same return type.
- All the exceptions defined in the throws clause of the matching method of the session bean class must be defined in the throws clause of the method of the local interface.
- 同名
- 相同数量和类型的参数,以及相同的返回类型。
- 会话bean类的匹配方法的throws子句中定义的所有异常都必须在本地接口的方法的throws子句中定义。
And YOU HAVE TO DECLARE a ejb-jar.xml file according to
你必须根据
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd" version="2.1">
<enterprise-beans>
<session>
<ejb-name>HelloWorldEJB</ejb-name>
<home>br.com.MyBeanRemoteHome</home>
<remote>br.com.MyBeanRemote</remote>
<local-home>br.com.MyBeanLocalHome</local-home>
<local>br.com.MyBeanLocal</local>
<ejb-class>br.com.MyBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
If you do not have a local EJB object remove from the deployment descriptor above
如果您没有从上面的部署描述符中删除本地 EJB 对象
<local-home>br.com.MyBeanLocalHome</local-home>
<local>br.com.MyBeanLocal</local>
If you do not have a remote EJB object remove from the deployment descriptor above
如果您没有从上面的部署描述符中删除远程 EJB 对象
<home>br.com.MyBeanRemoteHome</home>
<remote>br.com.MyBeanRemote</remote>
And put in META-INF directory
并放入 META-INF 目录
Our jar file will contain the following
我们的 jar 文件将包含以下内容
/META-INF/ejb-jar.xml
br.com.MyBean.class
br.com.MyBeanRemote.class
br.com.MyBeanRemoteHome.class
Now our EJB 3.0
现在我们的 EJB 3.0
// or @Local
// You can not put @Remote and @Local at the same time
@Remote
public interface MyBean {
void doSomething();
}
@Stateless
public class MyBeanStateless implements MyBean {
public void doSomething() {
}
}
Nothing else,
没有其他的,
In JBoss put jar file in
在 JBoss 中放入 jar 文件
<JBOSS_HOME>/server/default/deploy
In Sun Application Server access (after starting it up) admin console
在 Sun Application Server 访问(启动后)管理控制台
http://127.0.0.1:4848/asadmin
And access EJB Modules in order to deploy your ejb-jar file
并访问 EJB 模块以部署您的 ejb-jar 文件
As you have some problems when deploying your application in NetBeans, i suggest the following
由于您在 NetBeans 中部署应用程序时遇到一些问题,我建议如下
- Create a simple Java library PROJECT (a simple jar without a main method)
- Add /server/default/lib (contains jar files in order you retrieve your EJB's) jar files to your Java application whether you are using JBoss (I do not know which directory in Sun Application Server)
- Implement code above
- 创建一个简单的Java库PROJECT(一个没有main方法的简单jar)
- 将 /server/default/lib(包含 jar 文件,以便您检索 EJB 的)jar 文件添加到您的 Java 应用程序,无论您使用的是 JBoss(我不知道 Sun Application Server 中的哪个目录)
- 实现上面的代码
Now create another war PROJECT
现在创建另一个战争项目
- Add our project created just above and add <JBOSS_HOME>/client (contains jar files in order to access our EJB's). Again i do not know which directory in Sun Application Server. Ckeck out its documentation.
- See its global mapping address as shown in the top of the answer
- 添加我们刚刚在上面创建的项目并添加 <JBOSS_HOME>/client(包含 jar 文件以便访问我们的 EJB)。我再次不知道 Sun Application Server 中的哪个目录。看看它的文档。
- 查看其全局映射地址,如答案顶部所示
And implement the following code in your Servlet or something else whether you are using JBoss
并在您的 Servlet 或其他内容中实现以下代码,无论您使用的是 JBoss
public static Context getInitialContext() throws javax.naming.NamingException {
Properties p = new Properties();
p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
p.put(Context.URL_PKG_PREFIXES, " org.jboss.naming:org.jnp.interfaces");
p.put(Context.PROVIDER_URL, "jnp://127.0.0.1:1099");
return new javax.naming.InitialContext(p);
}
Or the following whether you are using Sun Application Server - put the file appserv-rt.jar (I do not know which past contain appserv-rt.jar in Sun Application Server) in your classpath
或者以下是否使用 Sun Application Server - 将文件 appserv-rt.jar(我不知道 Sun Application Server 中哪个过去包含 appserv-rt.jar)在您的类路径中
public static Context getInitialContext() throws javax.naming.NamingException {
return new javax.naming.InitialContext();
}
In order to access your EJB in our Servlet or something else
为了在我们的 Servlet 或其他东西中访问您的 EJB
MyBeanRemote myBean = (MyBeanRemote) getInitialContext().lookup(<PUT_EJB_GLOBAL_ADDRESS_RIGHT_HERE>);
myBean.doSomething();
regards,
问候,