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.

2 2

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

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

Я столкнулся с таким же исключением на Wildfly 10.

Следуя некоторым важным ссылкам:

А именно документация по установлению удаленного EJB соединения на: https://docs.jboss.org/author/display/WFLY10/EJB+invocations+from+a+remote+client+using+JNDI

Java.яз..IllegalStateException: EJBCLIENT000025:

Нет приемника EJB, доступного для обработки [appName:, moduleName: wildfly10-test-client-remote-ejb, distinctName:] комбинация для контекста вызова орг..с JBoss.EJB-компонента.клиент.EJBClientInvocationContext@1b26f7b2 в орг..с JBoss.EJB-компонента.клиент.EJBClientContext.requireEJBReceiver(EJBClientContext.java: 798) около орг..с JBoss.EJB-компонента.клиент.ReceiverInterceptor.handleInvocation (ReceiverInterceptor.java: 128) около орг..с JBoss.EJB-компонента.клиент.EJBClientInvocationContext.sendrequest сценарию(EJBClientInvocationContext.java: 186) около орг..с JBoss.EJB-компонента.клиент.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java: 255) около орг..с JBoss.EJB-компонента.клиент.EJBInvocationHandler.doInvoke (EJBInvocationHandler.java: 200) около орг..с JBoss.EJB-компонента.клиент.EJBInvocationHandler.doInvoke (EJBInvocationHandler.java: 183) около орг..с JBoss.EJB-компонента.клиент.EJBInvocationHandler.invoke(EJBInvocationHandler.java: 146) на ком.солнце.полномочие.$ Proxy6.doWork (неизвестный источник) at EJB-компонента.InvokeRemoteEjbTest.testThatFailsWithEJBCLIENT000025 (InvokeRemoteEjbTest.java: 90)

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

Солнце.отражать.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.Ява: 62) около солнце.отражать.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java: 43) на Яве.яз..отражать.Метод.метод Invoke.java: 498) на орг..тесты JUnit.бегуны.модель.FrameworkMethod$1.runReflectiveCall (FrameworkMethod.java: 50) около орг..тесты JUnit.внутренний.бегуны.модель.ReflectiveCallable.run(ReflectiveCallable.java: 12) около орг..тесты JUnit.бегуны.модель.Фреймворкметод.invokeExplosively (FrameworkMethod.Ява: 47) около орг..тесты JUnit.внутренний.бегуны.заявления.Предназначен.оценить (InvokeMethod.java: 17) около орг..тесты JUnit.внутренний.бегуны.заявления.Ранбефоры.оценить (RunBefores.Ява: 26) в орг.тесты JUnit.бегуны.Парентраннер.ранлиф(ParentRunner.java:325) на орг..тесты JUnit.бегуны.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.Ява: 78) около орг..тесты JUnit.бегуны.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.Ява: 57) в орг.тесты JUnit.бегуны.ParentRunner$3.беги (ParentRunner.java: 290) на орг..тесты JUnit.бегуны.ParentRunner$1.расписание (ParentRunner.Ява: 71) на орг..тесты JUnit.бегуны.Парентраннер.runChildren(ParentRunner.java: 288) на орг..тесты JUnit.бегуны.Парентраннер.доступ $ 000(ParentRunner.Ява: 58) на орг..тесты JUnit.бегуны.ParentRunner$2.оцените (ParentRunner.java: 268) на орг..тесты JUnit.бегуны.Парентраннер.беги (ParentRunner.java: 363) на орг..затмение.JDT, предназначенным.внутренний.junit4.бегун.JUnit4TestReference.run (JUnit4TestReference.Ява: 86) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.Тестексекция.бег (TestExecution.java: 38) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.runTests (RemoteTestRunner.java: 459) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.runTests (RemoteTestRunner.java: 675) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.run (RemoteTestRunner.java: 382) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.main (RemoteTestRunner.java: 192)

Но это тестовое исключение было не единственным, у меня также было на консоли следующее исключение:

NFO: XNIO версия 3.3.4.Финал февраль 13, 2017 12: 42: 28 PM орг..хнио.НИО.NioXnio информация: Версия реализации XNIO NIO 3.3.4.Финал 13 февраля 2017 года 12:42: 28 орг.с JBoss.remoting3.EndpointImpl INFO: JBoss Remoting версия 4.0.18.Финал 13 Февраля 2017 Года 12:42: 28 вечера орг.с JBoss.EJB-компонента.клиент.EJBCLIENT INFO: JBoss EJB Клиентская версия 2.1.4.Финал февраль 13, 2017 12: 42: 28 PM орг..с JBoss.EJB-компонента.клиент.удаленное взаимодействие.ConfigBasedEJBClientContextSelector setupEJBReceivers предупреждает: не удалось зарегистрировать приемник EJB для подключение к localhost: 4447 Java.io. EOFException: XNIO000812: Соединение закрыто неожиданно на орг..хнио.http.HttpUpgrade$HttpUpgradeState$UpgradeResultListener.handleEvent (HttpUpgrade.java: 416) около орг..хнио.http.HttpUpgrade$HttpUpgradeState$UpgradeResultListener.handleEvent (HttpUpgrade.java: 400) около орг..хнио.Ченнеллистеры.invokeChannelListener (ChannelListeners.Ява: 92) около орг..хнио.каналы.ReadReadyHandler$ChannelListenerHandler.readReady(ReadReadyHandler.Ява: 66) около орг..хнио.НИО.Ниосокеткондуит.handleReady (NioSocketConduit.java: 88) около орг..хнио.НИО.WorkerThread.run (WorkerThread.java: 559) на ...асинхронный вызов...(Неизвестный источник) на орг..с JBoss.remoting3.Эндпоинтимпл.doConnect (EndpointImpl.Ява: 294) на орг..с JBoss.remoting3.Эндпоинтимпл.connect (EndpointImpl.java:416) на орг..с JBoss.EJB-компонента.клиент.удаленное взаимодействие.EndpointPool$PooledEndpoint.connect (EndpointPool.java: 192) около орг..с JBoss.EJB-компонента.клиент.удаленное взаимодействие.NetworkUtil.connect(NetworkUtil.java: 153) около орг..с JBoss.EJB-компонента.клиент.удаленное взаимодействие.NetworkUtil.connect(NetworkUtil.java: 133) около орг..с JBoss.EJB-компонента.клиент.удаленное взаимодействие.ConnectionPool.getConnection (ConnectionPool.Ява: 78) около орг..с JBoss.EJB-компонента.клиент.удаленное взаимодействие.RemotingConnectionManager.метод getconnection(RemotingConnectionManager.java: 51)

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

На орг..с JBoss.EJB-компонента.клиент.удаленное взаимодействие.ConfigBasedEJBClientContextSelector.getCurrent(ConfigBasedEJBClientContextSelector.java: 118) около орг..с JBoss.EJB-компонента.клиент.удаленное взаимодействие.ConfigBasedEJBClientContextSelector.getCurrent(ConfigBasedEJBClientContextSelector.Ява: 47) около орг..с JBoss.EJB-компонента.клиент.EJBClientContext.getCurrent (EJBClientContext.java: 281) около орг..с JBoss.EJB-компонента.клиент.EJBClientContext.requirerecurrent(EJBClientContext.java: 291) в орг.с JBoss.EJB-компонента.клиент.EJBInvocationHandler.doInvoke (EJBInvocationHandler.java: 178) около орг..с JBoss.EJB-компонента.клиент.EJBInvocationHandler.invoke(EJBInvocationHandler.java: 146) около ком.солнце.полномочие.$ Proxy6.doWork (неизвестный источник) at EJB-компонента.InvokeRemoteEjbTest.testThatFailsWithEJBCLIENT000025 (InvokeRemoteEjbTest.java: 90)

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

Солнце.отражать.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.Ява: 62) около солнце.отражать.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java: 43) на Яве.яз..отражать.Метод.метод Invoke.java: 498) на орг..тесты JUnit.бегуны.модель.FrameworkMethod$1.runReflectiveCall (FrameworkMethod.java: 50) около орг..тесты JUnit.внутренний.бегуны.модель.ReflectiveCallable.run(ReflectiveCallable.java: 12) около орг..тесты JUnit.бегуны.модель.Фреймворкметод.invokeExplosively (FrameworkMethod.Ява: 47) около орг..тесты JUnit.внутренний.бегуны.заявления.Предназначен.оценить (InvokeMethod.java: 17) около орг..тесты JUnit.внутренний.бегуны.заявления.Ранбефоры.оценить (RunBefores.Ява: 26) в орг.тесты JUnit.бегуны.Парентраннер.ранлиф(ParentRunner.java: 325) на орг..тесты JUnit.бегуны.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.Ява: 78) около орг..тесты JUnit.бегуны.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.Ява: 57) в орг.тесты JUnit.бегуны.ParentRunner$3.беги (ParentRunner.java: 290) на орг..тесты JUnit.бегуны.ParentRunner$1.расписание (ParentRunner.Ява: 71) на орг..тесты JUnit.бегуны.Парентраннер.runChildren(ParentRunner.java: 288) на орг..тесты JUnit.бегуны.Парентраннер.доступ $ 000(ParentRunner.Ява: 58) на орг..тесты JUnit.бегуны.ParentRunner$2.оцените (ParentRunner.java: 268) на орг..тесты JUnit.бегуны.Парентраннер.беги (ParentRunner.java: 363) на орг..затмение.JDT, предназначенным.внутренний.junit4.бегун.JUnit4TestReference.run (JUnit4TestReference.Ява: 86) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.Тестексекция.run (TestExecution.java: 38) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.runTests (RemoteTestRunner.java: 459) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.runTests (RemoteTestRunner.java: 675) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.RemoteTestRunner.run (RemoteTestRunner.java: 382) около орг..затмение.JDT, предназначенным.внутренний.тесты JUnit.бегун.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 из сервера, у вас есть прокси-сервер в руках. Где все действительно идет не так, это когда вы берете proxu и делаете что-то вроде:

remoteEJB.doWorkg();

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

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

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

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

Теперь, когда вы идете к этому: jboss-ejb-клиент.свойства

Вы можете попытаться сконфигурировать свой" удаленный " порт 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.

Наконец, просто для справки. Ваш объект-клиент.файл 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, для более старых версий я не уверен.

Удачи.