javax.naming.NameNotFoundException: While trying to lookup 。。。

本文解决了一个在WebLogic环境下使用JNDI查找EJB时出现的NameNotFoundException问题,通过在EJB上添加@Stateless注解并设置mappedName属性,以及修改客户端的JNDI查找方式,成功解决了此异常。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

错误大致如下:


javax.naming.NameNotFoundException: While trying to lookup 'HelloWorldApp.HelloWorldBean/local' didn't find subcontext 'HelloWorldApp'. Resolved ''; remaining name 'HelloWorldApp/HelloWorldBean/local' at weblogic.jndi.internal.BasicNamingNode.newNameNotFoundException(BasicNamingNode.java:1138) at weblogic.jndi.internal.BasicNamingNode.lookupHere(BasicNamingNode.java:246) at weblogic.jndi.internal.ServerNamingNode.lookupHere(ServerNamingNode.java:171) at weblogic.jndi.internal.BasicNamingNode.lookup(BasicNamingNode.java:205) at weblogic.jndi.internal.WLEventContextImpl.lookup(WLEventContextImpl.java:254) at weblogic.jndi.internal.WLContextImpl.lookup(WLContextImpl.java:367) at javax.naming.InitialContext.lookup(InitialContext.java:351) at ejb.learning.Locator.getBean(Ljava.lang.String Ljava.lang.Object;(Unknown Source) at ejb.learning.web.HelloWorldServlet.processRequest(Ljavax.servlet.http.HttpServletRequest;Ljavax.servlet.http.HttpServletResponse V(Unknown Source) at ejb.learning.web.HelloWorldServlet.doGet(Ljavax.servlet.http.HttpServletRequest;Ljavax.servlet.http.HttpServletResponse V(Unknown Source) at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:226) at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:124) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:283) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:175) at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3370) at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) at weblogic.security.service.SecurityManager.runAs(Lweblogic.security.acl.internal.AuthenticatedSubject;Lweblogic.security.acl.internal.AuthenticatedSubject;Ljava.security.PrivilegedAction Ljava.lang.Object;(Unknown Source) at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2117) at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2023) at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1359) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:200) at weblogic.work.ExecuteThread.run(ExecuteThread.java:172)




解决办法:


在bean里面加上

@Stateless(mappedName="HelloWorldBean")



客户端访问的时候只需要


helloWorld = (HelloWorld) ctx.lookup("HelloWorldBean#"+ HelloWorld.class.getName());

ok,问题解决
<think>我们遇到了一个EJB查找失败的错误。错误信息表明:在尝试查找名为`com.lkm.pmi.dept.service.DeptmentSerivce/deptInfoRemote`的bean时,没有找到。同时,嵌套异常是`javax.naming.NameNotFoundException`,指出在查找`deptInfoRemote#com.lkm.ejb.dept.remote.DeptInfoRemote`时,没有找到子上下文`deptInfoRemote#com`。 错误分析: 1. 错误发生在EJB注入或查找时。 2. 从错误信息看,可能是以下原因: - EJB的JNDI名称不正确。 - EJB未正确部署在应用服务器上。 - 客户端代码(这里是一个JSF管理的Bean)中引用的EJB名称错误。 具体错误信息分解: - `No bean named 'com.lkm.pmi.dept.service.DeptmentSerivce/deptInfoRemote' available`:说明Spring(可能是被包装的)在尝试按名称查找bean时失败。 - 嵌套异常是`javax.naming.NameNotFoundException`,并且指出在查找`deptInfoRemote#com.lkm.ejb.dept.remote.DeptInfoRemote`时出错,剩余名称为`deptInfoRemote#com/lkm/ejb/dept/remote/DeptInfoRemote`。 注意:错误信息中出现了两个不同的名称: 1. `com.lkm.pmi.dept.service.DeptmentSerivce/deptInfoRemote` 2. `deptInfoRemote#com.lkm.ejb.dept.remote.DeptInfoRemote` 这可能是由于不同的查找方式导致的。通常,在Java EE中,EJB的默认JNDI名称遵循一定的模式,但不同的应用服务器可能有所不同。 解决方案: 步骤1:确认EJB接口和实现 - 确保`DeptInfoRemote`是一个远程业务接口,并且有正确的注解。 - 确保EJB实现类实现了这个接口,并且使用了`@Stateless`或`@Stateful`注解。 示例EJB接口: ```java package com.lkm.ejb.dept.remote; import javax.ejb.Remote; @Remote public interface DeptInfoRemote { // 方法声明 } ``` 示例EJB实现: ```java package com.lkm.ejb.dept.impl; import javax.ejb.Stateless; import com.lkm.ejb.dept.remote.DeptInfoRemote; @Stateless(name = "DeptInfoRemote", mappedName = "DeptInfoRemote") public class DeptInfoRemoteBean implements DeptInfoRemote { // 实现方法 } ``` 步骤2:检查EJB的JNDI名称 - 不同的应用服务器(如WebLogic, WildFly, GlassFish等)有不同的JNDI命名规则。 - 在WebLogic中,默认的全局JNDI名称通常是:`<接口的完整类名>#<接口的完整类名>` 或 `<mappedName>#<接口的完整类名>`。 步骤3:在客户端代码中正确注入 - 在JSF管理的Bean中,我们使用`@EJB`注解注入EJB。需要确保指定的名称与服务器上的JNDI名称匹配。 错误中的注入点: `@EJB private DeptmentSerivce deptmentSerivce;` 但是,错误信息中提到了`DeptmentSerivce`(注意拼写,可能是`DeptmentService`?)和`deptInfoRemote`。这里可能存在混淆。 步骤4:可能的修正 - 情况1:如果`DeptmentSerivce`是一个EJB,那么应该检查它的JNDI名称。 - 情况2:如果`DeptmentSerivce`是一个本地接口,而`deptInfoRemote`是另一个EJB,那么可能是注入时使用了错误的名称。 修正建议: 1. 检查EJB注入的注解: 在`DeptmentBean`中,我们注入了`DeptmentSerivce`(注意拼写,可能是拼写错误?),但错误信息中提到了`deptInfoRemote`。这可能是两个不同的EJB。 如果`DeptmentSerivce`是一个EJB,那么应该这样注入: ```java @EJB private DeptmentSerivce deptmentSerivce; ``` 但是,如果`DeptmentSerivce`的实现依赖于另一个EJB(`DeptInfoRemote`),那么可能是`DeptmentSerivce`本身没有被正确部署。 2. 如果`DeptmentSerivce`是一个EJB,那么请检查它的JNDI名称。可以在服务器日志中查看部署的JNDI名称。 3. 尝试使用`mappedName`或`lookup`属性明确指定JNDI名称: ```java @EJB(mappedName = "DeptInfoRemote") // 或者使用具体的JNDI名称 private DeptmentSerivce deptmentSerivce; ``` 或者 ```java @EJB(lookup = "java:global/your-app-name/DeptInfoRemote!com.lkm.ejb.dept.remote.DeptInfoRemote") private DeptmentSerivce deptmentSerivce; ``` 4. 检查应用服务器中EJB的实际JNDI名称。例如,在WebLogic中,可以在管理控制台查看。 5. 确保EJB接口和实现在类路径中,并且部署正确。 6. 如果项目结构是EAR,包含EJB模块和Web模块,确保EJB模块已经正确部署,并且Web模块有对EJB模块的依赖。 7. 检查拼写错误:`DeptmentSerivce` 应该是 `DeptmentService`?另外,在错误信息中,`com.lkm.pmi.dept.service.DeptmentSerivce` 这个包名和类名是否确实存在? 8. 如果`DeptmentSerivce`是一个本地业务接口,那么不应该使用远程查找。确保在同一个应用中使用本地接口。 示例修正后的代码: 假设我们有一个EJB,它的远程接口是`DeptInfoRemote`,而我们的`DeptmentSerivce`是一个拼写错误的类,实际上应该是`DeptmentService`,并且它实现了`DeptInfoRemote`接口。 在客户端(Web模块)中,我们这样注入: ```java @EJB private DeptInfoRemote deptInfoRemote; ``` 或者,如果我们有一个本地接口: ```java @EJB private DeptInfoLocal deptInfoLocal; ``` 因此,在`DeptmentBean`中,应该注入正确的EJB接口。 修正`DeptmentBean`中的注入: ```java @EJB private DeptInfoRemote deptInfoRemote; // 或者使用本地接口 ``` 然后,在`save()`和`delete()`等方法中,使用这个注入的EJB。 如果问题仍然存在,请检查应用服务器日志,查看EJB部署时的JNDI名称,然后在注入时使用`lookup`属性指定该名称。 由于我们无法直接查看服务器环境,所以需要根据实际情况调整。 总结:这个错误是由于EJB注入时找不到对应的bean。需要检查EJB的部署名称和注入时使用的名称是否匹配,并确保EJB已经成功部署。 §§相关问题§§: 1.Java EE中,如何正确查找EJB的JNDI名称? 2. 如何解决WebLogic服务器上的EJB注入问题? 3. 在JSF中,如何注入远程EJB和本地EJB? 4. 如何调试Java EE应用中的JNDI查找失败问题?</think>### 错误分析:EJB 注入失败 这个错误表明应用服务器无法找到名为 `deptInfoRemote` 的 EJB 组件。错误信息包含几个关键点: 1. **NoSuchBeanDefinitionException**:Spring 容器找不到指定的 bean 2. **NameNotFoundException**:JNDI 查找失败,找不到 `deptInfoRemote#com.lkm.ejb.dept.remote.DeptInfoRemote` 3. **LinkException**:JNDI 名称解析失败,缺少子上下文 ### 错误原因分析 1. **EJB 名称不匹配**: - 代码中使用的名称:`DeptmentSerivce` - JNDI 查找的名称:`deptInfoRemote#com.lkm.ejb.dept.remote.DeptInfoRemote` 2. **部署问题**: - EJB 未正确部署到应用服务器 - JNDI 名称配置错误 - 接口与实现类不匹配 3. **依赖关系问题**: - 客户端模块缺少 EJB 依赖 - 类路径问题导致接口不可见 ### 解决方案 #### 步骤 1:修复 EJB 接口定义 ```java // DeptInfoRemote.java package com.lkm.ejb.dept.remote; import javax.ejb.Remote; @Remote public interface DeptInfoRemote { void saveEventData(DeptmentDm dept); void deleteDeptmentInfo(Long id); DeptmentDm getDeptmentInfo(Long id); List<DeptmentDm> getDeptmentInfoList(int page, int size, Map<String, Object> filters, Map<String, String> sortParams); } ``` #### 步骤 2:修复 EJB 实现类 ```java // DeptInfoRemoteBean.java package com.lkm.ejb.dept.impl; import javax.ejb.Stateless; import com.lkm.ejb.dept.remote.DeptInfoRemote; @Stateless(name = "deptInfoRemote", mappedName = "java:global/app-name/DeptInfoRemote") public class DeptInfoRemoteBean implements DeptInfoRemote { // 实现接口方法... @Override public void saveEventData(DeptmentDm dept) { // 持久化逻辑 } // 其他方法实现... } ``` #### 步骤 3:修复客户端注入 ```java // DeptmentBean.java @ManagedBean(name = "deptmentBean") @ViewScoped public class DeptmentBean { // 使用正确的接口类型和名称 @EJB(mappedName = "java:global/app-name/DeptInfoRemote") private DeptInfoRemote deptmentService; // 方法中使用 deptmentService 替代 deptmentSerivce public void save() { deptmentService.saveEventData(department); // ... } } ``` #### 步骤 4:添加 JNDI 查找后备方案 ```java // 添加手动查找方法 private DeptInfoRemote lookupDeptService() { try { Context ctx = new InitialContext(); return (DeptInfoRemote) ctx.lookup("java:global/app-name/DeptInfoRemote"); } catch (NamingException e) { throw new RuntimeException("EJB lookup failed", e); } } // 在方法中使用 public void save() { if (deptmentService == null) { deptmentService = lookupDeptService(); } deptmentService.saveEventData(department); } ``` ### 完整解决方案 #### 1. EJB 接口定义 ```java package com.lkm.ejb.dept.remote; import java.util.List; import java.util.Map; public interface DeptInfoRemote { void saveEventData(DeptmentDm dept); void deleteDeptmentInfo(Long id); DeptmentDm getDeptmentInfo(Long id); List<DeptmentDm> getDeptmentInfoList(int page, int size, Map<String, Object> filters, Map<String, String> sortParams); } ``` #### 2. EJB 实现类 ```java package com.lkm.ejb.dept.impl; import javax.ejb.Stateless; import com.lkm.ejb.dept.remote.DeptInfoRemote; @Stateless(name = "deptInfoRemote", mappedName = "java:global/DeptManagement/DeptInfoRemote") public class DeptInfoRemoteBean implements DeptInfoRemote { @Override public void saveEventData(DeptmentDm dept) { // 实际持久化逻辑 } @Override public void deleteDeptmentInfo(Long id) { // 删除逻辑 } @Override public DeptmentDm getDeptmentInfo(Long id) { // 查询单个部门 return null; } @Override public List<DeptmentDm> getDeptmentInfoList(int page, int size, Map<String, Object> filters, Map<String, String> sortParams) { // 分页查询部门列表 return null; } } ``` #### 3. 修复后的 JSF Managed Bean ```java import javax.annotation.PostConstruct; import javax.ejb.EJB; import javax.faces.bean.ManagedBean; import javax.faces.bean.ViewScoped; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import java.util.HashMap; import java.util.List; import java.util.Map; @ManagedBean(name = "deptmentBean") @ViewScoped public class DeptmentBean { private DeptmentQuery department = new DeptmentQuery(); private List<DeptmentQuery> departments; // 使用正确的接口类型 @EJB(mappedName = "java:global/DeptManagement/DeptInfoRemote") private DeptInfoRemote deptmentService; @PostConstruct public void init() { loadDepartments(); } // 手动查找后备方案 private DeptInfoRemote lookupDeptService() { try { Context ctx = new InitialContext(); return (DeptInfoRemote) ctx.lookup("java:global/DeptManagement/DeptInfoRemote"); } catch (NamingException e) { throw new RuntimeException("EJB lookup failed", e); } } public void save() { if (deptmentService == null) { deptmentService = lookupDeptService(); } // 修复:使用正确的属性值 DeptmentDm deptmentDm = new DeptmentDm(); deptmentDm.setAddr(department.getAddr()); deptmentDm.setName(department.getName()); deptmentService.saveEventData(deptmentDm); department = new DeptmentQuery(); departments = null; } // 其他方法保持不变... } ``` ### 关键修复点 1. **JNDI 名称标准化**: ```java @Stateless(name = "deptInfoRemote", mappedName = "java:global/DeptManagement/DeptInfoRemote") ``` 2. **接口-实现一致性**: - 确保 EJB 实现类正确实现接口 - 接口和实现类在正确的包结构中 3. **客户端注入修复**: ```java @EJB(mappedName = "java:global/DeptManagement/DeptInfoRemote") private DeptInfoRemote deptmentService; ``` 4. **添加后备查找机制**: - 当自动注入失败时,手动进行 JNDI 查找 5. **名称一致性**: - 统一使用 `deptInfoRemote` 作为 EJB 名称 - 避免拼写错误(如 `Serivce` → `Service`) ### 验证步骤 1. 部署 EJB 模块后,检查应用服务器的 JNDI 树: ``` java:global/DeptManagement/DeptInfoRemote ``` 2. 在客户端使用以下代码测试 JNDI 查找: ```java Context ctx = new InitialContext(); DeptInfoRemote service = (DeptInfoRemote) ctx.lookup("java:global/DeptManagement/DeptInfoRemote"); ``` 3. 确保客户端模块包含 EJB 接口的依赖: ```xml <!-- Maven 依赖示例 --> <dependency> <groupId>com.lkm</groupId> <artifactId>dept-ejb</artifactId> <version>1.0</version> <type>ejb</type> </dependency> ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值