WildFly: вызовы EJB от удаленного клиента

Я пытался найти и вызвать EJB, развернутый как EAR в WildFly. Я пробовал разные способы.

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, в котором говорится, что нужно использовать http-remoting вместо remote. Но это тоже не сработало. Даже используя порт 8080.

Я пробовал упомянутый способ здесь . Но, похоже, в моем случае это не сработает. Хотя я поместил jboss-ejb-client.properties в тот же каталог, из которого я запускаю свой клиентский метод из Eclipse.


person Tapas Bose    schedule 28.12.2013    source источник


Ответы (2)


Потратив почти полдня, я нашел решение. Вот:

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);
}

Дополнительную информацию см. здесь . Надеюсь, это будет полезно для других.

person Tapas Bose    schedule 28.12.2013
comment
какой порт по умолчанию для этого? - person Isuru Gunawardana; 19.02.2015
comment
@IsuruGunawardana По умолчанию Wildfly работает на порту 8080. - person Jon Onstott; 05.08.2015

Я столкнулся с таким же исключением на 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, DifferentName:] для контекста вызова org.jboss.ejb.client.EJBClientInvocationContext@1b26f7b2 в 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.doInvoke(EJBInvocationHandler.java:200) java:183) в org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146) в com.sun.proxy.$Proxy6.doWork(неизвестный источник) в ejb.InvokeRemoteEjbTest.testThatFailsWithEJBCLIENT000 025 (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) в 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) в org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) в org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) в org.junit.runners.ParentRunner$3.run(ParentRunner.java:29 0) в org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) в org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) в org.junit.runners.ParentRunner.access$000(ParentRunner .java:58) в org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) в org.junit.runners.ParentRunner.run(ParentRunner.java:363) в 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, 13 февраля 2017 г., 12:42:28 org.xnio.nio.NioXnio INFO: Версия XNIO NIO, версия 3.3.4.Final, 13 февраля 2017 г., 12:42:28 org.jboss .remoting3.EndpointImpl INFO: JBoss Remoting версии 4.0.18.Final 13 февраля 2017 г. 12:42:28 org.jboss.ejb.client.EJBClient INFO: JBoss EJB Client версии 2.1.4.Final 13 февраля 2017 г. 12: 42:28 PM org.jboss.ejb.client.remoting.ConfigBasedEJBClientContextSelector setupEJBReceivers ПРЕДУПРЕЖДЕНИЕ: не удалось зарегистрировать приемник EJB для подключения к локальному хосту: 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) в ...асинхронном вызове...(неизвестный источник) в org.jboss .remoting3.EndpointImpl.doConnect(EndpointImpl.java:294) в org.jboss.remoting3.EndpointImpl.connect(EndpointImpl.java:416) в 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.jbo.s. .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(неизвестный источник) в 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) в 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) в org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) в org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) в org.junit.runners.ParentRunner$3.run(ParentRunner.java:29 0) в org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) в org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) в org.junit.runners.ParentRunner.access$000(ParentRunner .java:58) в org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) в org.junit.runners.ParentRunner.run(ParentRunner.java:363) в 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, который работает правильно, когда вы подключаетесь к «удаленному» порту, такому как старый традиционный порт 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();

Это происходит потому, что логика поиска и логика выполнения на прокси-сервере не совсем совпадают, а именно логика выполнения ищет следующее:

"Нет приемника EJB, доступного для обработки"

на основе файла конфигурации: "jboss-ejb-client.properties"

Это вы должны иметь в своем пути к классам для запуска системного теста. Или ваше клиентское приложение.

Теперь, когда вы перейдете к этому: jboss-ejb-client.properties

Вы можете попытаться настроить свой «удаленный» порт 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-сокетов. Таким образом, он хочет обновить сокет HTTP до TCP почти так же, как это происходит с веб-сокетами. Это не будет работать на вашем сокете: 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 URL-адрес вашего провайдера должен быть изменен следующим образом:

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

Моя рекомендация: настройте оба порта 4447 и 8080 для вашей удаленной подсистемы ejb. Но для подключения клиента используйте порт 8080, как для поиска JNDI, так и для выполнения EJB.

Исключение wildfly в этом случае практически бесполезно, оно не очень помогает разработчику понять, что происходит не так.

Ключом к этой проблеме было обнаружение проблемы с обновлением HTTP-соединения и выяснение того, что такое поведение явно неправильно для сокета 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

Главное, о чем следует помнить, это то, что ПОРТ в приведенном выше файле должен быть портом HTTP, а не портом «удаления», например 4447. По крайней мере, в wildfly 10, для более старых версий я не уверен.

Удачи.

person 99Sono    schedule 13.02.2017