名称 [services] 在此上下文中未绑定。无法找到 [服务]

Name [services] is not bound in this Context. Unable to find [services]

我试图将 jboss 中部署的 war 迁移到 tomcat 8。加载我的应用程序上下文 xml 时,我遇到以下异常。这在 jboss 中有效。 (与数据源有同样的问题,但当我在 context.xml 中配置 <GlobalNamingResources/> 设置时它得到修复。)

应用上下文有

..
<jee:jndi-lookup id="txnService" jndi-name="services/TxnService"
        lazy-init="true" />

<jee:jndi-lookup id="mailService" jndi-name="services/MailService"
        lazy-init="true" expected-type="com.tone.mailservice.MailService" />
..

错误:

Caused by: javax.naming.NameNotFoundException: Name [services/MailService] is not bound in this Context. Unable to find [services].

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txnService': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name [services/TxnService] is not bound in this Context. Unable to find [services].      

我可以看到 TxnService class 有以下代码。

public abstract interface TxnService
{
  public static final String JNDI_NAME = "services/TxnService";
  ..
}

这个 class 在一个罐子里,我把那个罐子放在 lib 文件夹里。 我试过用 java:/comp/env/services/TxnService 和 java:/comp/env/services/MailService 代替。但还是一样的问题。

完整跟踪:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mailService': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name [services/MailService] is not bound in this Context. Unable to find [services].
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1482)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireByName(AbstractAutowireCapableBeanFactory.java:1146)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1096)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:519)
    ... 45 more
Caused by: javax.naming.NameNotFoundException: Name [services/MailService] is not bound in this Context. Unable to find [services].
    at org.apache.naming.NamingContext.lookup(NamingContext.java:816)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:173)
    at org.apache.naming.SelectorContext.lookup(SelectorContext.java:163)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at org.springframework.jndi.JndiTemplate.doInContext(JndiTemplate.java:154)
    at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
    at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
    at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
    at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:104)
    at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
    at org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:201)
    at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:187)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1541)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1479)
    ... 54 more
Related cause:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'txnService': Invocation of init method failed; nested exception is javax.naming.NameNotFoundException: Name [services/TxnService] is not bound in this Context. Unable to find [services].
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1482)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:521)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getTypeForFactoryBean(AbstractBeanFactory.java:1368)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.getTypeForFactoryBean(AbstractAutowireCapableBeanFactory.java:720)
    at org.springframework.beans.factory.support.AbstractBeanFactory.isTypeMatch(AbstractBeanFactory.java:523)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doGetBeanNamesForType(DefaultListableBeanFactory.java:356)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanNamesForType(DefaultListableBeanFactory.java:334)
    at org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors(BeanFactoryUtils.java:187)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:897)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:855)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:770)
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:795)
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:723)
    at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:196)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1045)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:949)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:487)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:458)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getObject(AbstractBeanFactory.java:295)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:223)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:292)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:628)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:932)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:479)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:651)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:599)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:665)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:518)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:459)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1183)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1099)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:989)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4940)
    at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5250)
    at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:752)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:728)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:734)
    at org.apache.catalina.startup.HostConfig.deployWAR(HostConfig.java:952)
    at org.apache.catalina.startup.HostConfig$DeployWar.run(HostConfig.java:1823)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javax.naming.NameNotFoundException: Name [services/TxnService] is not bound in this Context. Unable to find [services].
    at org.apache.naming.NamingContext.lookup(NamingContext.java:816)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:159)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:827)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:159)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:827)
    at org.apache.naming.NamingContext.lookup(NamingContext.java:173)
    at org.apache.naming.SelectorContext.lookup(SelectorContext.java:163)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at org.springframework.jndi.JndiTemplate.doInContext(JndiTemplate.java:154)
    at org.springframework.jndi.JndiTemplate.execute(JndiTemplate.java:87)
    at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:152)
    at org.springframework.jndi.JndiTemplate.lookup(JndiTemplate.java:178)
    at org.springframework.jndi.JndiLocatorSupport.lookup(JndiLocatorSupport.java:95)
    at org.springframework.jndi.JndiObjectLocator.lookup(JndiObjectLocator.java:105)
    at org.springframework.jndi.JndiObjectFactoryBean.lookupWithFallback(JndiObjectFactoryBean.java:201)
    at org.springframework.jndi.JndiObjectFactoryBean.afterPropertiesSet(JndiObjectFactoryBean.java:187)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1541)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1479)
    ... 51 more

您的问题似乎是与 JNDI 查找相关的问题。

实际上,我正在尝试为 JBoss 到 Tomcat 迁移提供一个完成过程。这里我没有给出具体的答案。请按照程序进行。之后,如果出现任何问题,我们将开始进一步讨论。

在jboss和tomcat8之间迁移主要需要考虑3个方面。

  1. 常用库,
  2. 数据源配置,
  3. JNDI 绑定和基本服务器配置

常用库:

对于Tomcat:

Apache Tomcat 将常用库存储到 CATALINE_HOME/lib 文件夹中。

对于JBoss:

JBoss AS release ==== Path for common libs
4.x ================= JBOSS_HOME/server/[server-name]/lib
5.x - 6.x============ JBOSS_HOME/common/lib
7.x ================= JBOSS_HOME/modules

资源Link:

http://www.mastertheboss.com/jboss-as-7/how-to-install-a-module-on-jboss-as-7


数据源配置

如果您使用 Oracle 作为数据库,那么

对于Tomcat

在 Tomcat 的 context.xml 文件中配置了一个数据源:

<Resource name="jdbc/oracledb"
    auth="Container"
    type="javax.sql.DataSource"
    username="scott"
    password="tiger"
    driverClassName="oracle.jdbc.driver.OracleDriver"
    url="jdbc:oracle:thin:@localhost:1521:XE"
    maxActive="10"
    maxIdle="2"
    removeAbandoned="true"
    removeAbandonedTimeout="30"
    maxWait="5000"
    logAbandoned="true"
    accessToUnderlyingConnectionAllowed="true"/>

然后,您应该将 JDBC 驱动程序添加到 CATALINA_HOME/lib 文件夹

对于JBoss:

JBoss AS release ======== Path for data source
4.x - 5.x - 6.x  ======== datasource-ds.xml file into JBOSS_HOME/server/[server-name]/deploy
7.x ===================== datasource-ds.xml file into JBOSS_HOME/standalone/deployments or as a module into JBOSS_HOME/modules

JNDI 绑定和基本服务器配置

在 JNDI 绑定中,tomcat 中需要进行代码相关的更改。 JNDI 绑定可以通过两种方式完成。

  1. 使用查找代码
  2. 使用@Resource 注释 (javax.annotation.Resource) 而不是查找代码

使用查找代码 我们可以使用 Java 代码查找配置的 JNDI 数据源,如下所示:

Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:comp/env");
DataSource ds = (DataSource) envContext.lookup("jdbc/UsersDB");
Connection conn = ds.getConnection();

获取到连接后,我们就可以像普通的JDBC代码一样使用了:

然后

Statement statement = conn.createStatement();
String sql = "select username, email from users";
ResultSet rs = statement.executeQuery(sql);
// iterates over the result set...

使用@Resource注解(javax.annotation.Resource)代替查找代码

需要在servlet中声明一个名为dataSource的字段,如下所示:

@Resource(name = "jdbc/UsersDB")
private DataSource dataSource;

Tomcat 将查找指定的资源名称并在发现此注释时注入实际实现。

如需完整源代码和示例,您可以阅读本教程:Configuring JNDI DataSource for Database Connection Pooling in Tomcat

对于JBoss:

当使用 JBoss AS 7 时,您必须为数据源选择一个 JNDI 位置,例如 java:/ 或 java:/jboss 才能被接受.定义数据源的可移植方法是使用资源引用。

在我们的示例中,我们需要为您的连接池定义web.xml:

数据库连接 jdbc/oracledb javax.sql.DataSource 容器

或者,从 Java EE 5 (Servlet 2.5) 开始,可以使用 @Resource 注释在您的代码中更轻松地完成此操作。

public class MyServlet extends HttpServlet {

    @Resource(name = "jdbc/oracledb")
    private DataSource dataSource;

然后在JBoss端定义你的jboss-web.xml

<jboss-web>
 <resource-ref>
 <res-ref-name>jdbc/oracledb</res-ref-name>
 <jndi-name>java:jboss/datasources/jdbc/oracledb</jndi-name>
 </resource-ref>
</jboss-web>

很好,现在您的 JNDI 查找将在任一环境中工作,无需更改一行代码!


服务器配置

默认情况下,Tomcat 和 JBoss 都在端口 8080 上传送 http 应用程序,您可能需要配置 http 端口。这是 tomcat 的 server.xml

<Connector port="32080" protocol="HTTP/1.1"
           connectionTimeout="20000"
           redirectPort="8443" />

资源Link:

  1. Tomcat DataSource JNDI Example in Java
  2. Tomcat to JBoss migration