【问题标题】:EJB remote client migration from JBoss AS 7.1 to Wildfly 8.1EJB 远程客户端从 JBoss AS 7.1 迁移到 Wildfly 8.1
【发布时间】:2015-05-21 09:53:45
【问题描述】:

我们开发了一个培训应用程序,其中包含一个与 EJB 通信的独立 Java 客户端。工作设置包括 Windows 7 上的 JBoss AS 7.1 和通过 /bin/add-user.bat 创建的应用程序用户。

客户端是这样编码的:

Properties jndiProps = new Properties();
jndiProps.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
jndiProps.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
jndiProps.put("jboss.naming.client.ejb.context", true);
jndiProps.put(Context.PROVIDER_URL, "remote://localhost:4447");
jndiProps.put(Context.SECURITY_PRINCIPAL, "user");
jndiProps.put(Context.SECURITY_CREDENTIALS, "xxx");
Context ctx = new InitialContext(jndiProps);
MyBeanRemote myBean = (MyBeanRemote) ctx.lookup("ejb:/training//MyBean!mypackage.MyBeanRemote");
String result = myBean.greet("John");

客户端是用类路径中的 jboss-client.jar 启动的。

现在我们尝试使用成功部署的 WildFly 8.1,但客户端失败

Exception in thread "main" java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:, moduleName:syjeews, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@6e7d3146

将 JNDI 查找名称更改为在部署期间打印出来的名称(例如 java:global/training/MyBean!mypackage.MyBeanRemote)导致

Exception in thread "main" javax.naming.CommunicationException: Failed to connect to any server. Servers tried: [remote://localhost:4447 (java.net.ConnectException: Connection refused: no further information)]

在谷歌上搜索了一段时间后,我们偶然发现了几篇关于 SO(例如 thisthat)或 samplesWildfly Developer Guide 的文章,但所有替代方案,可能是最小的 JNDI 属性或扩展的通过 ClientContext 配置并没有使其工作。

所以我的问题是,需要做些什么来迁移上面的代码/配置以在 WildFly 下运行它?

注意:这不是生产代码,因此安全性不是问题 - 如果我可以简化整个配置,那很好 - 它应该只演示如何从独立的 Java 程序使用 EJB 远程接口。

【问题讨论】:

    标签: java jakarta-ee ejb jboss7.x wildfly


    【解决方案1】:

    你需要做两处改变

    不要使用“remote://localhost:4447”,而是使用“http-remoting://localhost:8080”

    jndiProps.put(Context.PROVIDER_URL, "http-remoting://localhost:8080");
    

    在代码中配置 jndi 属性时,查找名称不应包含ejb:

    MyBeanRemote myBean = (MyBeanRemote) ctx.lookup("/training//MyBean!mypackage.MyBeanRemote");
    

    这个解决方案已经过测试并且可以工作

    【讨论】:

    • 嘿,非常感谢您迟到但仍然非常感谢的答案 - 我立即尝试了它并且它有效!不过,我仍然想知道,为什么不能使用 WildFly 在部署期间输出的确切字符串来完成查找。
    【解决方案2】:

    提供者 URL 应该是 http-remoting://localhost:8080 而不是 remote://localhost:4447

    【讨论】:

    • 好的,我试过了,但它告诉我它找不到 JNDI 名称。除了上面带有ejb:/ 的原始版本之外,我还尝试了带有java:/ 的那些以及在部署EJB 时在控制台中列出的其他内容。知道还缺少什么吗?
    • @Geziefer 尝试在日志中作为查找字符串找到的关于您的 ejb 的 java:global/... 条目。
    • @Francesco:以防万一:您的建议是正确的,但是必须省略命名空间(尽管我不知道为什么)。
    【解决方案3】:

    我正在使用:

    • wildfly-10.0.0.Final(JBoss 应用服务器)。

    这对我有用:

    Properties jndiProperties = new Properties();
               jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
               jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
               jndiProperties.put("jboss.naming.client.ejb.context", true);
               jndiProperties.put(Context.PROVIDER_URL, "http-remoting://localhost:8080");   //System.getProperty(Context.PROVIDER_URL, "http-remoting://localhost:8080"));
    
            /* jndiProperties.put(Context.SECURITY_PRINCIPAL, "user");
               jndiProperties.put(Context.SECURITY_CREDENTIALS, "xxx");*/
    
            InitialContext context = new InitialContext(jndiProperties);
    
            MyFirstEJBRemote ejb = (MyFirstEJBRemote) context.lookup("/EJBProjectName/MyFirstEJB!src.MyFirstEJBRemote");
    

    希望对你有帮助!

    【讨论】:

    • Hallo Davijr,我也得到了和你上面提到的相同的配置,但我仍然得到错误:线程“main”中的异常 javax.naming.CommunicationException:无法连接到任何服务器。服务器尝试:[http-remoting://localhost:8080 (java.io.IOException: JBREM000202: Abrupt close on Remoting connection 329100e4 to localhost/127.0.0.1:8080 of endpoint "config-based-naming-client-endpoint" )]。你有什么想法吗?
    • 我尝试在不启动服务器的情况下运行该项目,但收到了类似的错误。所以我认为你忘记启动服务器了。
    • 我不得不“添加另一个答案”并且它上升了。
    【解决方案4】:

    这是我的名为“MyFirstEJBProject”的项目。 代码内部有一些注释可以提供帮助。

    package src.ejb;
    
    import javax.ejb.Stateless;
    
    /**
     * Session Bean implementation class MyFirstEJB
     */
    @Stateless
    public class MyFirstEJB implements MyFirstEJBRemote {
    
        public MyFirstEJB() {
        }
    
        @Override
        public String helloWorld() {
            return "Hello World EJB";
        }
    
    }
    
    
    package src.ejb;
    
    import javax.ejb.Remote;
    
    @Remote
    public interface MyFirstEJBRemote {
        public String helloWorld();
    }
    
    
    package src.clientTest;
    
    import java.util.Properties;
    
    import javax.naming.Context;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    import src.ejb.MyFirstEJB;
    import src.ejb.MyFirstEJBRemote;
    
    public class EJBClient {
    
        public static void main(String[] args) throws NamingException {
    
            /**JNDI or Java Naming and Directory Interface.
             * When JNDI constructs an initial context, the context's environment
             * is initialized with properties defined in the environment parameter
             * passed to the constructor, the system properties, the applet parameters,
             * and the application resource files.
             * 
             * JNDI applications need a way to communicate various preferences
             * and properties that define the environment in which naming and
             * directory services are accessed.
             * */
    
            Properties jndiProperties = new Properties();
            jndiProperties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");
            jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
            jndiProperties.put("jboss.naming.client.ejb.context", true);
            jndiProperties.put(Context.PROVIDER_URL, "http-remoting://localhost:8080");
    
            /* jndiProperties.put(Context.SECURITY_PRINCIPAL, "user");
               jndiProperties.put(Context.SECURITY_CREDENTIALS, "xxx");*/
    
            /**Context For JNDI**/
            InitialContext context = new InitialContext(jndiProperties);
    
            /**The nameOfEJB appears on the console when the server is starting up.**/
            String nameOfEJB = "/MyFirstEJBProject/MyFirstEJB!src.ejb.MyFirstEJBRemote";
    
                                                      /**The Method .lookup("") search for EJB by name**/
            MyFirstEJBRemote ejb = (MyFirstEJBRemote) context.lookup(nameOfEJB);
            System.out.println(ejb.helloWorld());
    
    
            System.out.println("/** =============== 2º TEST ===============**/"); 
    
            /**getting a EJB name by a private Method.**/
            String nameOfEJB_2 = getEJBName("", "MyFirstEJBProject", "", 
                    MyFirstEJB.class.getSimpleName(), MyFirstEJBRemote.class.getName());
    
            MyFirstEJBRemote ejb_2 = (MyFirstEJBRemote) context.lookup(nameOfEJB_2);
            System.out.println(ejb_2.helloWorld());
        }
    
        private static String getEJBName(String nameofAppEAR, String nameOfProjectModulo, 
                String distinctNameOfProject, String classBeanSimpleName, String classInterfaceName){
            /**Return a object name for search on JNDI */
    
            String finalNameOfEJB = nameofAppEAR + "/" + nameOfProjectModulo + "/" + distinctNameOfProject + 
                    "/" + classBeanSimpleName + "!" + classInterfaceName;  
    
            return finalNameOfEJB; 
    
            /**Ex:                 
               String nameofAppEAR= "";                            // EAR  (if there is)
               String nameOfProjectModulo= "MyFirstEJBProject";
               String distinctNameOfProject= "";                   // Alias (if there is)
               String classBeanSimpleName= MyFirstEJB.class.getSimpleName(); 
               String classInterfaceName=  MyFirstEJBRemote.class.getName();
    
               String finalNameOfEJB = "" + "/" + "MyFirstEJBProject" + "/" + "" + 
                    "/" + MyFirstEJB.class.getSimpleName() + "!" + MyFirstEJBRemote.class.getName();
    
               The nameOfEJB appears on the console when the server is starting up:
               String nameOfEJB = "/MyFirstEJBProject/MyFirstEJB!src.ejb.MyFirstEJBRemote";   
             */
        }
    }
    

    注意:我使用的是Wildfly(JBoss),所以需要在wildfly-10.0.0.Final\bin\client\文件夹下导入jboss-client.jar。

    【讨论】:

      猜你喜欢
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 2016-07-29
      • 2015-10-17
      • 1970-01-01
      • 2014-07-16
      • 1970-01-01
      • 2013-07-13
      相关资源
      最近更新 更多