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 ответа:
Потратив почти полдня, я нашел решение проблемы. Вот ОНО:
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)
Критическая точка заключается в следующем. (1) Jboss, по-видимому, имеет два разных уровня кода, которые ведут себя по-разному. Первый-это исходный контекст JNDI, который работает правильно при подключении к" удаленному " порту, такому как старый традиционный порт 4447.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)
Поэтому, когда вы делаете в своем коде для контекста 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, для более старых версий я не уверен.
Удачи.