Существует множество разочаровывающе некорректной (лучшее описание — «близко, но не сигара») информации, касающейся удаленного доступа к компонентам JBoss EJB из автономного приложения. Я уже больше суток бьюсь головой об эту стену, но безрезультатно.
Я пытаюсь перенести EJB из WebLogic в JBoss, который вызывается автономным приложением, работающим на другом сервере.
Я был здесь, здесь и в нескольких других местах безуспешно ищу различные "решения" моей проблемы. Я попытался прочитать официальная документация, которая требует, чтобы я установил "быстрый запуск" на основе Maven, который может соответствовать или не соответствовать моей ситуации, и который я пока решил не использовать. (Мой проект не построен с помощью Maven, он использует Gradle, но я достаточно уверен, что мне удалось развернуть все нужные зависимости).
У меня есть EJB с отслеживанием состояния, развернутый в WAR внутри EAR (предыдущая реализация развертывания его просто в WAR не помогла).
Я настраиваю клиента таким образом:
public InitialContext createInitialContext() throws NamingException {
Properties prop = new Properties();
prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
prop.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jboss.naming.remote.client.InitialContextFactory");
prop.put(Context.PROVIDER_URL, purl);
prop.put(Context.SECURITY_PRINCIPAL, "myusername");
prop.put(Context.SECURITY_CREDENTIALS, "mypassword");
prop.put("jboss.naming.client.ejb.context", false);
return new InitialContext(prop);
}
public void closeContext(Context context) throws NamingException {
if (context != null) {
context.close();
}
}
private String getJndiName(
String prefix,
String appName,
String moduleName,
String distinctName,
String beanName,
Class viewClass,
boolean stateful)
{
StringBuilder builder = new StringBuilder();
if (prefix != null && prefix.length() > 0) {
builder.append(prefix).append(':');
}
builder.append(appName)
.append('/')
.append(moduleName)
.append('/')
.append(distinctName)
.append('/')
.append(beanName).append('!')
.append(viewClass.getName());
if (stateful) {
builder.append("?stateful");
}
return builder.toString();
}
public Object lookup(Context context) throws NamingException {
final String prefix = "ejb";
final String appName = "myearname";
final String moduleName = "mywarname";
final String distinctName = "";
final String beanName = "MyBean";
final Class viewClass = MyBeanInterface.class;
String jndi = getJndiName(prefix, appName, moduleName, distinctName, beanName, viewClass, true);
return context.lookup(jndi);
}
Обратите внимание, что «отличное имя» не указано, поскольку оно не требуется. "различное имя" предполагается быть необязательным: все это вызывается:
MyBeanInterface sstatus = null;
try {
ctx = createInitialContext();
sstatus = (MyBeanInterface) lookup(ctx);
} catch (Exception ex) {
...
}
При вызове этого кода выдается следующее сообщение об ошибке:
Caused by: java.lang.IllegalStateException: EJBCLIENT000024: No EJB receiver available for handling [appName:SockTransport, moduleName:SockTransport, distinctName:] combination
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:873) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBClient.createSessionWithPossibleRetries(EJBClient.java:222) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBClient.createSession(EJBClient.java:202) ~[ttjd.jar:?]
at org.jboss.ejb.client.naming.ejb.EjbNamingContext.doCreateProxy(EjbNamingContext.java:227) ~[ttjd.jar:?]
at org.jboss.ejb.client.naming.ejb.EjbNamingContext.createEjbProxy(EjbNamingContext.java:204) ~[ttjd.jar:?]
Используя приведенный выше код, имя JNDI, которое я предоставляю, — ejb:myearname/mywarname//MyBean!com.whatever.my.package.MyBeanInterface
. Обратите внимание на двойную косую черту, вызванную отсутствием отдельного имени. Я могу и переделал этот код, чтобы он производил вместо ejb:myearname/mywarname/MyBean!com.whatever.my.package.MyBeanInterface
, и это не имеет значения.
Честно говоря, я думаю, что это сообщение об ошибке является отвлекающим маневром. Я подозреваю, что есть какая-то другая проблема с моей настройкой, которая не обнаруживается и не ломается в этом интерфейсе. Я не думаю, что отдельное имя или его отсутствие имеют какое-либо отношение к проблеме. Я думаю, что это просто то, как они регистрируют объект, который нельзя найти.
Прежде чем я пойду по пути выяснения того, как добавить бесполезное «отличное имя» в, возможно, тщетной попытке сделать JBOSS счастливым, может кто-нибудь рискнуть предположить, в чем может быть реальная проблема?
ОБНОВЛЕНИЕ:
Предложения @Steve_C весьма показательны, но я до сих пор не заставил их работать. Он упустил несколько моментов из первоначального создания контекста:
- Context.URL_PKG_PREFIXES
- Контекст.INITIAL_CONTEXT_FACTORY
- "jboss.именование.клиент.ejb.контекст"
но они были упомянуты в ресурс, который он цитировал - кстати, очень кстати.
Итак, я добавил их, и мой метод createInitialContext теперь выглядит так:
public InitialContext createInitialContext() throws NamingException {
Properties prop = new Properties();
prop.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
prop.put(Context.INITIAL_CONTEXT_FACTORY,
"org.jboss.naming.remote.client.InitialContextFactory");
prop.put(Context.PROVIDER_URL, "http-remoting://{server-ip}:{server-port});
prop.put("jboss.naming.client.ejb.context", true);
return new InitialContext(prop);
}
Почему PROVIDER_URL необходим, если я уже указал server-ip и server-port в файле jboss-ejb-client.properties, остается загадкой, но это имеет значение.
После добавления этих трех элементов в исходную контекстную среду я получаю другое сообщение об ошибке (EJBCLIENT000025 вместо EJBCLIENT000024):
java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling [appName:SockTransport, moduleName:SockTransport, distinctName:] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@67f639d3
at org.jboss.ejb.client.EJBClientContext.requireEJBReceiver(EJBClientContext.java:798) ~[ttjd.jar:?]
at org.jboss.ejb.client.ReceiverInterceptor.handleInvocation(ReceiverInterceptor.java:128) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBClientInvocationContext.sendRequest(EJBClientInvocationContext.java:186) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBInvocationHandler.sendRequestWithPossibleRetries(EJBInvocationHandler.java:255) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:200) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBInvocationHandler.doInvoke(EJBInvocationHandler.java:183) ~[ttjd.jar:?]
at org.jboss.ejb.client.EJBInvocationHandler.invoke(EJBInvocationHandler.java:146) ~[ttjd.jar:?]
at com.sun.proxy.$Proxy20.create(Unknown Source) ~[?:?]
Я полагаю, это считается прогрессом, но я нахожу это более сложным, чем должно быть. Интересно, должны ли эти новые свойства быть в файле свойств, но в официальной документации довольно четко сказано, что это не так.