当前位置: 首页 > 知识库问答 >
问题:

如何去除JNDI名称、Jboss EAP 6、EJB 3.1中的版本号

邢运良
2023-03-14

我在EJB3.1中有EJB,我试图在JBoss EAP 6中部署它,但当我启动服务器时。它在JNDI名称中附加版本号,如下所示。

18:27:57,068 INFO  [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-6) JNDI bindings for session bean named TestService in deployment unit subdeployment "TestGroup-war-3_0_0-SNAPSHOT.war" of deployment "TestGroup-ear-3_0_0-SNAPSHOT.ear" are as follows:

java:global/TestGroup-ear-3_0_0-SNAPSHOT/TestGroup-war-3_0_0-SNAPSHOT/TestService!org.pkg.ejb.local.CRMDataServiceLocal
java:app/TestGroup-war-3_0_0-SNAPSHOT/TestService!org.pkg.ejb.local.CRMDataServiceLocal
java:module/TestService!org.pkg.ejb.local.CRMDataServiceLocal
java:global/TestGroup-ear-3_0_0-SNAPSHOT/TestGroup-war-3_0_0-SNAPSHOT/TestService
java:app/TestGroup-war-3_0_0-SNAPSHOT/TestService
java:module/TestService

如何从JNDI名称中删除版本号“-3_0_0-SNAPSHOT”?我有ejb jar。部署ear时放在ejbjar文件中的xml。

共有3个答案

和飞翔
2023-03-14

您不必删除版本信息。您可以通过JNDI自助获取正确的应用程序和模块名称!请参见这里的答案:https://stackoverflow.com/a/7066600/1465758

如果您已经在EJB容器中,您可以使用< code>@Resource注释:

@Resource(lookup = "java:app/AppName")
private String appName;

@Resource(lookup = "java:module/ModuleName")
private String moduleName;

如果您在EJB容器之外,则必须使用JNDI查找,如:

Context jndiCtxt = new InitialContext();
String appName = (String) jndiCtxt.lookup("java:app/AppName");
String moduleName = (String) jndiCtxt.lookup("java:module/ModuleName");

然后,您可以通过以下方式访问您的测试服务:

Context jndiCtxt = new InitialContext();
TestService testSvc = (TestService) jndiCtxt.lookup(
                          "java:global/" + appName + "/" + moduleName + "/TestService");

编辑:

如果您有多个作为一个模块的模块,那么在java:module/ModuleName上的JNDI查找可能会返回错误的模块名称。您还可以通过调用

NamingEnumeration<NameClassPair> list = 
     jndiCtxt.list("java:global/" + appName + "/");

或者更好:在启动应用程序时,可以在静态映射中加载所有已知的实体/类和相应的JNDI URI。例如:

public final class EJBUtil<T> {
  private static final Logger log = PSLogger.getLogger(EJBUtil.class);

  /** list of all known JNDI entities sort by the class: {Class; JNDI URI} */
  private final static Map<Class<?>, String> jndiEntities = new HashMap<>();
  /** synchronisation object for filling jndiEntities */
  private final static ReentrantLock jndiEntitiesLock = new ReentrantLock();

  /** the initial context */
  private static Context jndiCtxt = null;

  /**
   * class of the bean to get
   */
  private final Class<T> beanClass;

  /**
   * Constructs a new EJBUtil for the specified simple bean class name.
   * @param beanClass bean class for which this EJBUtil is
   */
  public EJBUtil(Class<T> beanClass) {
    this.beanClass = beanClass;
  }

  /**
   * Creates and returns a bean object from the EJB container.
   * @return the bean instance or null
   */
  @SuppressWarnings("unchecked")
  public final T getBean() {
    String jndiURI = null;

    try {
      if (jndiEntities.isEmpty()) {
        try {
          loadEntityMap();
        } catch (NamingException exc) {
          exc.printStackTrace();

          log.error(null, "! ! ! ! !   C A N N O T   L O A D   T H E   J N D I   E N T I T I E S  ! ! ! ! !",
              exc);

          return null;
        }
      }

      jndiURI = jndiEntities.get(beanClass);

      if (jndiURI == null) {
        log.error(null, "! ! ! ! !   C A N N O T   L O A D   T H E   \"" + beanClass.getSimpleName()
                + "\"   B E A N  (Entity not found in Naming Directory  ! ! ! ! !");
        return null;
      }

      Object obj = jndiLookup(jndiURI);
      return (T) obj;

    } catch (NamingException exc) {
      exc.printStackTrace();

      log.error(null, "! ! ! ! !   C A N N O T   L O A D   T H E   \"" + beanClass.getSimpleName()
              + "\"   B E A N  (JNDI URI: \"" + jndiURI + "\")  ! ! ! ! !",
          exc);

      return null;
    }
  }

  /**
   * Creates and returns a bean object from the EJB container.
   * @param name JNDI name of the resource to return
   * @return the resource object or null
   * @throws NamingException if the bean could not be created
   */
  public static final Object jndiLookup(String name) throws NamingException {
    try {
      if (jndiCtxt == null) {
        jndiCtxt = new InitialContext();
      }

      return jndiCtxt.lookup(name);
    } catch (NamingException exc) {
      exc.printStackTrace();

      log.error(null, "! ! ! ! !   C A N N O T   L O A D   T H E   J N D I   R E S O U R C E   \"" + name +
          "\"  (JNDI: \"" + name + "\")  ! ! ! ! !", exc);

      throw exc;
    }
  }

  private void loadEntityMap() throws NamingException {
    jndiEntitiesLock.lock();

    try {
      if (!jndiEntities.isEmpty()) {
        // map already filled
        return;
      }

      loadEntityMap("java:global/");
    } finally {
      jndiEntitiesLock.unlock();
    }

  }

  private void loadEntityMap(String jndiBaseURI) throws NamingException {
    if (jndiCtxt == null) {
      jndiCtxt = new InitialContext();
    }

    NamingEnumeration<NameClassPair> list = jndiCtxt.list(jndiBaseURI);

    while (list.hasMore()) {
      NameClassPair nameClassPair = list.next();

      if (nameClassPair.getClassName() != null &&
          !nameClassPair.getClassName().equals(Context.class.getName())) {

        try {
          jndiEntities.put(
              Class.forName(nameClassPair.getClassName()), jndiBaseURI + "/" + nameClassPair.getName());
        } catch (ClassNotFoundException e) {
          log.error(null, "Cannot load JNDI entity class " + nameClassPair.getClassName(), e);
        }
      }

      if (nameClassPair.getClassName() == null ||
          nameClassPair.getClassName().equals(Context.class.getName())) {

        loadEntityMap(jndiBaseURI + nameClassPair.getName() + "/");
      }
    }
  }
}

然后可以通过调用以下命令加载EJB测试服务:

TestService testSvc = new EJBUtil<TestService>(TestService.class).getBean();

侯焱
2023-03-14

上面的答案对我不起作用。在我的例子中,我将maven-ear-plugin升级到了版本2.10,并提供了“文件名映射”属性作为“无版本”:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-ear-plugin</artifactId>
    <version>2.10</version>
    <configuration>
        <!-- Tell Maven we are using Java EE 7 -->
        <version>7</version>
        <fileNameMapping>no-version</fileNameMapping>    
        <generateApplicationXml>true</generateApplicationXml>
        <defaultLibBundleDir>/lib</defaultLibBundleDir>
        <modules>
            <ejbModule>
                <groupId>${project.groupId}</groupId>
                <artifactId>dpc-ejb</artifactId>
                <bundleDir>/</bundleDir>
            </ejbModule>
            <webModule>
                <groupId>${project.groupId}</groupId>
                <artifactId>dpc-war</artifactId>
                <bundleDir>/</bundleDir>
                <contextRoot>dpc</contextRoot>
            </webModule>
        </modules>
    </configuration>
</plugin>
淳于哲
2023-03-14

根据EJB JNDI命名参考,会话bean的JNDI查找名称具有以下语法:

ejb:<appName>/<moduleName>/<distinctName>/<beanName>!<viewClassName>?stateful 

因此,你想要的可以通过两种方式实现:

  1. 修改可交付文件的名称(WAR和EAR)

为了从WAR中删除该版本,您可以在WAR的POM中执行以下操作:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <configuration>
                <warName>${project.artifactId}</warName>
            </configuration>
        </plugin>
    </plugins>
</build>

关于您的EAR,为了从中删除版本,您可以将以下内容放在EAR的POM中:

<build>
    <plugins>
        <plugin>
            <artifactId>maven-ear-plugin</artifactId>
            <configuration>
                (...)

                <finalName>${project.artifactId}</finalName>

                (...)

            </configuration>
        </plugin>
    </plugins>
</build>

使用上面的配置,您将拥有如下内容:

.../TestGroup-ear/TestGroup-war/...

创建一个包含以下内容的 ejb-jar.xml,并将其放在 WAR 的 src/主/网络应用/WEB-INF 文件夹下:

<ejb-jar xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/ejb-jar_3_2.xsd"
    version="3.2">
    <module-name>someModuleName</module-name>
</ejb-jar>

然后,在EAR的src/main/resources/META-INF文件夹下放置一个application.xml文件,其内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                                 http://xmlns.jcp.org/xml/ns/javaee/application_7.xsd"
    version="7">

    <application-name>someApplicationName</application-name>

    </<module>
        <web>
            <web-uri>TestGroup-war-${project.version}.war</web-uri>
            <context-root>testGroup</context-root>
        </web>
    </module>
</application>

然后,在您的 JNDI 上,您将获得如下内容:

java:global/someApplicationName/someModuleName/TestService!org.pkg.ejb.local.CRMDataServiceLocal
java:app/someModuleName/TestService!org.pkg.ejb.local.CRMDataServiceLocal
java:module/TestService!org.pkg.ejb.local.CRMDataServiceLocal
java:global/someApplicationName/someModuleName/TestService
java:app/someModuleName/TestService
java:module/TestService

从2.5版开始,Maven EAR插件具有选项no-version,可以设置为属性fileNameMap,以便从您的工件中省略该版本:

<plugin>
    <artifactId>maven-ear-plugin</artifactId>
    <configuration>
        (...)

        <fileNameMapping>no-version</fileNameMapping>

        (...)

    </configuration>
</plugin>
 类似资料:
  • 我试图在JBoss7上运行这个EJB示例,但它总是抛出NameNotFoundException。 我尝试测试的EJB是:计算器。在JBoss 7上部署时,在服务器控制台中显示以下几行: 计算器bean代码如下所示: 远程接口代码为: 必须通过JNDI连接EJB的主代码是: 第一个错误是:身份验证失败。因此,我在服务器:usr: test,pwd: test123中创建了一个用于“应用领域”的“管

  • 当我将mvn项目导入Intellij时,它生成的jar文件不包括版本。但是mvn生成的jar具有格式。所以我最终得到了两个jar文件,一个有版本,另一个没有版本。当然,我可以在Intellij设置中更改模块名称以包括版本。但当我更改pom文件时,它将被重置。 也许其他人有更好的主意?

  • 我有一个遗留的 EJB 2 应用程序,我将其部署到 Websphere 8.5 中。该应用程序具有依赖关系,这些依赖关系定义了与数据源的 JNDI 绑定.xml和 /元.xml数据源.xml 我不允许更改这些依赖项中的代码,也不能更改Websphere的配置。但我可以更改jar文件中的配置文件。 我想在我的应用程序中覆盖有效的JNDI绑定。是否可以定义一个将添加到Ear的文件来覆盖这些绑定? ej

  • 我的Web应用程序包含几个2. x有状态和无状态会话ejbs.但与以前的jboss版本(以及其他主要的应用程序服务器)不同,我无法在jboss 7.1.1中指定ejb jndi名称。/>有利于jboss-ejb3.xml,以及在完整配置文件模式下启动应用服务器。 然而,jboss-ejb3.xml中的jndi-name没有站稳脚跟,阻止我设置自己的自定义ejb jndi名称。

  • 我正在JBoss7.1上部署一个JavaEE应用程序。1,当部署会话bean时,JBoss会打印一条消息,说明它已经创建了多个JNDI绑定。大概是这样的: EJB和EJB之间有一点不同,但这是一般的想法。 我对这里发生的事情感到困惑。为什么有这么多?这些JNDI绑定之间有区别吗?如果有,应该在什么时候使用它们?

  • 我编写了这样的代码来查找Android版本 通过使用这段代码,我得到的是版本号,但我想要的是版本名。如何获取版本名?