WildFly:来自远程客户端的EJB调用

时间:2013-12-28 17:17:21

标签: java jboss java-ee-7 wildfly ejb-3.2

我试图在WildFly中查找并调用部署为EAR的EJB。我试过不同的方法。

Properties properties = new Properties();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.naming.remote.client.InitialContextFactory");        
properties.put(Context.PROVIDER_URL, "remote://localhost:4447");
properties.put(Context.SECURITY_PRINCIPAL, myUser);
properties.put(Context.SECURITY_CREDENTIALS, myPassword);    
properties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

InitialContext context = new InitialContext(properties);
Object object = context.lookup(jndi);
MyService service = (MyService)object;
System.out.println(service.echo("JYM"));

抛出:

javax.naming.NamingException: Failed to connect to any server. Servers tried: [remote://localhost:4447]
    at org.jboss.naming.remote.client.HaRemoteNamingStore.failOverSequence(HaRemoteNamingStore.java:213)
    at org.jboss.naming.remote.client.HaRemoteNamingStore.namingStore(HaRemoteNamingStore.java:144)
    at org.jboss.naming.remote.client.HaRemoteNamingStore.namingOperation(HaRemoteNamingStore.java:125)
    at org.jboss.naming.remote.client.HaRemoteNamingStore.lookup(HaRemoteNamingStore.java:241)
    at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:79)
    at org.jboss.naming.remote.client.RemoteContext.lookup(RemoteContext.java:83)
    at javax.naming.InitialContext.lookup(InitialContext.java:417)
    at com.app.test.service.MyServiceTest.echo(MyServiceTest.java:60)

如果我添加以下属性:

properties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
properties.put("jboss.ejb.client.scoped.context", "true");

我收到了:

java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:roolafic, moduleName:usermanagement, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@3c0f93f1
    at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:749)
    at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:116)
    at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:183)
    at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:253)
    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:198)
    at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:181)
    at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:144)
    at com.sun.proxy.$Proxy4.echo(Unknown Source)
    at com.app.test.service.MyServiceTest.echo(MyServiceTest.java:62)

然后我看到Jboss forum post表示要使用http-remoting代替remote。但那也行不通。甚至使用端口8080。

我尝试过here提到的方式。但它似乎对我的情况不起作用。虽然我已将jboss-ejb-client.properties放在我从Eclipse运行客户端方法的同一目录中。

2 个答案:

答案 0 :(得分:3)

花了差不多半天后,我找到了解决方案。这是:

public static <T> T connectEJB(String jndi) throws NamingException {
    Properties clientProperties = new Properties();
    clientProperties.put("remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED", "false");
    clientProperties.put("remote.connections", "default");
    clientProperties.put("remote.connection.default.port", myPort);
    clientProperties.put("remote.connection.default.host", myHost);
    clientProperties.put("remote.connection.default.username", myUser);
    clientProperties.put("remote.connection.default.password", myPassword);
    clientProperties.put("remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS", "false");

    EJBClientConfiguration ejbClientConfiguration = new PropertiesBasedEJBClientConfiguration(clientProperties);
    ContextSelector<EJBClientContext> contextSelector = new ConfigBasedEJBClientContextSelector(ejbClientConfiguration);
    EJBClientContext.setSelector(contextSelector);

    Properties properties = new Properties();
    properties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
    Context context = new InitialContext(properties);
    return (T) context.lookup(jndi);
}

有关详细信息,请参阅here。 希望它对其他人有所帮助。

答案 1 :(得分:0)

我在Wildfly 10上遇到了同样的例外。

在遵循一些重要的参考资料时:

有关在以下位置建立远程EJB连接的文档: https://docs.jboss.org/author/display/WFLY10/EJB+invocations+from+a+remote+client+using+JNDI

  

java.lang.IllegalStateException:EJBCLIENT000025:

     

没有EJB接收器可用于处理[appName:,   moduleName:wildfly10-test-client-remote-ejb,distinctName:]   调用上下文的组合   org.jboss.ejb.client.EJBClientInvocationContext@1b26f7b2 at   org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:798)     在   org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:128)     在   org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186)     在   org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255)     在   org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200)     在   org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183)     在   org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)     在com.sun.proxy。$ Proxy6.doWork(未知来源)at   ejb.InvokeRemoteEjbTest.testThatFailsWithEJBCLIENT000025(InvokeRemoteEjbTest.java:90)

  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  at
     

sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:498)at   org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:50)     在   org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)     在   org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)     在   org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)     在   org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)     在org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)at   org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)     在   org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)     在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290)at at   org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:71)at at   org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at at   org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:58)at at   org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:268)at at   org.junit.runners.ParentRunner.run(ParentRunner.java:363)at at   org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)     在   org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)     在   org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)     在   org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)     在   org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)     在   org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

但是这个测试异常并不孤单,我在控制台上也遇到了以下异常:

  

NFO:XNIO版本3.3.4.Final 2017年2月13日下午12:42:28   org.xnio.nio.NioXnio信息:XNIO NIO实施版   3.3.4.Final 2017年2月13日下午12:42:28 org.jboss.remoting3.EndpointImpl INFO:JBoss Remoting版本4.0.18.Final 2017年2月13日   12:42:28 PM org.jboss.ejb.client.EJBClient INFO:JBoss EJB   客户端版本2.1.4.Final 2017年2月13日下午12:42:28   org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector   setupEJBReceivers WARN:无法注册EJB接收器   与localhost的连接:4447 java.io.EOFException:XNIO000812:   连接意外关闭了   org.xnio.http.HttpUpgrade $ HttpUpgradeState $ UpgradeResultListener.handleEvent(HttpUpgrade.java:416)     在   org.xnio.http.HttpUpgrade $ HttpUpgradeState $ UpgradeResultListener.handleEvent(HttpUpgrade.java:400)     在   org.xnio.ChannelListeners.invokeChannelListener(ChannelListeners.java:92)     在   org.xnio.conduits.ReadReadyHandler $ ChannelListenerHandler.readReady(ReadReadyHandler.java:66)     在   org.xnio.nio.NioSocketConduit.handleReady(NioSocketConduit.java:88)     在org.xnio.nio.WorkerThread.run(WorkerThread.java:559)at   ...异步调用...(未知来源)at   org.jboss.remoting3.EndpointImpl.doConnect(EndpointImpl.java:294)at at   org.jboss.remoting3.EndpointImpl.connect(EndpointImpl.java:416)at at   org.jboss.ejb.client.remoting.EndpointPool $ PooledEndpoint.connect(EndpointPool.java:192)     在   org.jboss.ejb.client.remoting.NetworkUtil.connect(NetworkUtil.java:153)     在   org.jboss.ejb.client.remoting.NetworkUtil.connect(NetworkUtil.java:133)     在   org.jboss.ejb.client.remoting.ConnectionPool.getConnection(ConnectionPool.java:78)     在   org.jboss.ejb.client.remoting.RemotingConnectionManager.getConnection(RemotingConnectionManager.java:51)

at org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector.setupEJBReceivers(ConfigBasedEJBClientContextSelector.java:161)
     

在   org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector.getCurrent(ConfigBasedEJBClientContextSelector.java:118)     在   org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector.getCurrent(ConfigBasedEJBClientContextSelector.java:47)     在   org.jboss.ejb.client.EJBClientContext.getCurrent(EJBClientContext.java:281)     在   org.jboss.ejb.client.EJBClientContext.requireCurrent(EJBClientContext.java:291)         在org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:178)     在   org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146)     在com.sun.proxy。$ Proxy6.doWork(未知来源)at   ejb.InvokeRemoteEjbTest.testThatFailsWithEJBCLIENT000025(InvokeRemoteEjbTest.java:90)

  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)  at
     

sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)     在   sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)     在java.lang.reflect.Method.invoke(Method.java:498)at   org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall(FrameworkMethod.java:50)     在   org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)     在   org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)     在   org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)     在   org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)     在org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)at   org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)     在   org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)     在org.junit.runners.ParentRunner $ 3.run(ParentRunner.java:290)at at   org.junit.runners.ParentRunner $ 1.schedule(ParentRunner.java:71)at at   org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)at at   org.junit.runners.ParentRunner.access $ 000(ParentRunner.java:58)at at   org.junit.runners.ParentRunner $ 2.evaluate(ParentRunner.java:268)at at   org.junit.runners.ParentRunner.run(ParentRunner.java:363)at at   org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)     在   org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)     在   org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)     在   org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)     在   org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)     在   org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

关键点如下。 (1)Jboss似乎有两个不同的代码层。 第一个是JNDI初始上下文,当你连接到&#34;远程处理&#34;港口,如旧的传统港口4447。

因此,当您在代码中执行JNDI上下文时,例如:

final Properties env = new Properties();
        env.put(Context.INITIAL_CONTEXT_FACTORY, org.jboss.naming.remote.client.InitialContextFactory.class.getName());
        env.put(Context.PROVIDER_URL, "remote://localhost:4447");            

        // why is this needed?
        // This is an important property to set if you want to do EJB invocations via the remote-naming project
        env.put("jboss.naming.client.ejb.context", true);

        // Lookup optimization for @Stateless EJBs.
        // https://docs.jboss.org/author/display/AS71/Remote+EJB+invocations+via+JNDI+-+EJB+client+API+or+remote-naming+project
        // section: Why use the EJB client API approach then?
        env.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");

        // authenticate
        env.put(Context.SECURITY_PRINCIPAL, "adminUser");
        env.put(Context.SECURITY_CREDENTIALS, "adminPassword");
        initialContext = new InitialContext(env);

您可以将远程EJB从服务器中取出,您手头有代理。 事情真的出了问题,就是当你采取代理并做类似的事情时:

remoteEJB.doWorkg();

这是因为代理上的查找逻辑和执行逻辑不完全相同,即执行逻辑正在寻找这些:

&#34;没有可用于处理的EJB接收器&#34;

基于配置文件: &#34; jboss-ejb-client.properties&#34;

您应该在类路径中运行系统测试。或者您的客户申请。

现在,当你这样做时: jboss-ejb-client.properties

您可以尝试将您的&#34;远程处理&#34;端口4447,但这是非常错误的,因为您使用的是现代远程EJB客户端;

 <dependency>
        <groupId>org.wildfly</groupId>
        <artifactId>wildfly-ejb-client-bom</artifactId>
        <version>10.0.0.Final</version>
        <type>pom</type>
        <scope>test</scope>
    </dependency>

此客户端期望您的wildfly 10配置了今天的默认配置,其中远程处理可以从普通的HTTP套接字提供服务。 所以它想要对TCP进行HTTP套接字升级,就像使用Web套接字一样。 这不适用于你的:4447套接字,它从来没有从构思到http套接字。

所以当我最终看看如何配置远程子系统时,我需要使用以下内容来增加它:

  <subsystem xmlns="urn:jboss:domain:remoting:3.0">
            <endpoint/>
            <connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
            <http-connector name="http-remoting-connector" connector-ref="default" security-realm="ApplicationRealm"/>
        </subsystem>

http连接器是新增功能。 现在,就JNDI初始上下文设置而言,无论是否使用端口4447或8080都无关紧要。 为了保持一致,我不使用4447端口..它仍然是打开的,我使用的是8080端口。 但是,对于8080 pot,您的提供者URL必须按如下方式进行调整:

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

我的建议是:为远程ejb子系统配置端口4447和8080。 但是对于Client conneciton,使用端口8080,用于JNDI查找和EJB执行。

在这种情况下,野生蝇的例外情况是边缘无用的,开发人员弄清楚出了什么问题并没有多大帮助。

解决这个问题的关键是查看HTTP连接升级问题,并确定socket 4447的行为显然是错误的。

最后,仅供参考。 您的ejb-client.proeprties文件应该是以下形式:

#QUOTE:
#First the endpoint.name property. 
#We mentioned earlier that the EJB receivers will communicate with the server for EJB invocations.
#Internally, they use JBoss Remoting project to carry out the communication. 
#The endpoint.name property represents the name that will be used to create the client side of the enpdoint. 
# The endpoint.name property is optional and if not specified in the jboss-ejb-client.properties file, it will default to "config-based-ejb-client-endpoint" name.
# https://docs.jboss.org/author/display/WFLY10/EJB+invocations+from+a+remote+client+using+JNDI
endpoint.name=client-endpoint
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false

remote.connections=default

remote.connection.default.host=localhost
remote.connection.default.port=8080
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false

remote.connection.default.username=youAppServerAdmin
remote.connection.default.password=youAppServerAdminPass

要记住的关键是上面文件中的PORT应该是HTTP端口而不是&#34;远程处理&#34;像4447这样的港口。 至少在wildfly 10中,对于旧版本,我不确定。

祝你好运。