Клиент EJB не может подключиться к компоненту EJB с отслеживанием состояния, развернутому на JBoss
Я использовал eclipse для создания EJB-проекта и создал 2 класса, как показано ниже.
package com.abhijit.ejbs;
import java.util.List;
import javax.ejb.Remote;
@Remote
public interface TestEJBRemote {
public void addElement(int a);
public void removeElement(int a);
public List getElements();
}
фактический EJB, как показано ниже -
package com.abhijit.ejbs;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.LocalBean;
import javax.ejb.Stateful;
/**
* Session Bean implementation class TesEJB
*/
@Stateful
@LocalBean
public class TestEJB implements TestEJBRemote {
List <Integer> myList = new ArrayList<>();
/**
* Default constructor.
*/
public TestEJB() {
// TODO Auto-generated constructor stub
}
@Override
public void addElement(int a) {
myList.add(a);
}
@Override
public void removeElement(int a) {
myList.remove(a);
}
@Override
public List getElements() {
return myList;
}
}
Этот EJB-компонент затем развертывается на JBoss AS 7 и работает без каких-либо ошибок. Я вижу это сообщение в консоли:
**java:global/EJB1/TestEJB!com.abhijit.ejbs.TestEJBRemote
java:app/EJB1/TestEJB!com.abhijit.ejbs.TestEJBRemote
java:module/TestEJB!com.abhijit.ejbs.TestEJBRemote
java:jboss/exported/EJB1/TestEJB!com.abhijit.ejbs.TestEJBRemote
java:global/EJB1/TestEJB!com.abhijit.ejbs.TestEJB
java:app/EJB1/TestEJB!com.abhijit.ejbs.TestEJB
java:module/TestEJB!com.abhijit.ejbs.TestEJB**
Сейчас я создаю второй Java-проект Eclipse и пишу простой код Java для удаленного клиента, как показано ниже:
package com;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import com.abhijit.ejbs.TestEJB;
import com.abhijit.ejbs.TestEJBRemote;
public class EJBClient {
public static void main(String[] args) {
TestEJBRemote values;
try {
System.out.println("----");
final Hashtable<String, String> jndiProperties = new Hashtable();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
//tried with rmi: also .. not working....
jndiProperties.put(Context.PROVIDER_URL, "ejb://localhost:1099");
InitialContext ic = new InitialContext(jndiProperties);
values = (TestEJBRemote)ic.lookup("java:global/EJB1/TestEJB!com.abhijit.ejbs.TestEJB");
System.out.println("---" + values.getElements());
}
catch(Exception e) {
e.printStackTrace();
}
}
Пробовал с различными комбинациями в lookup(), но когда я запускаю этот код Java-клиента, который будет работать в отдельной JVM, он не работает.. Я получаю эту ошибку -
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.getURLOrDefaultInitCtx(Unknown Source)
at javax.naming.InitialContext.lookup(Unknown Source)
at com.EJBClient.main(EJBClient.java:25)
Я уверен, что это должно быть что-то делать с параметрами jndi.. Но я не понимаю, что это такое...
2 ответа
То, как вы пытаетесь соединиться, неверно.
Ниже следует указать формат для подключения к удаленному ejb:
// Create a look up string name
String name = "ejb:" + appName + "/" + moduleName + "/" + distinctName
+ "/" + beanName + "!" + interfaceName;
Я внес следующее в документацию SO.
Настройка EJB с JBoss AS 7.1
1. Обзор
В этой статье мы собираемся обсудить, как начать работу с Enterprise JavaBeans (EJB). Мы будем использовать JBoss AS 7.1.1.Final, но вы можете использовать любой сервер по вашему выбору.
2. Maven зависимости для бобов
Чтобы использовать EJB, убедитесь, что вы добавили его последнюю версию в раздел зависимостей вашего файла pom.xml:
<dependency>
<groupId>org.jboss.spec.javax.ejb</groupId>
<artifactId>jboss-ejb-api_3.2_spec</artifactId>
<version>1.0.0.Final</version>
</dependency>
Убедитесь, что вы правильно добавили зависимости JBoss, так как мы будем использовать JBoss в качестве нашего сервера приложений в этом руководстве. В следующей части руководства мы подробно обсудим, как настроить сборку maven для проекта.
3. EJB Remote
Давайте сначала создадим Bean-интерфейс под названием HelloWorldRemote.
public interface HelloWorldRemote {
public String getHelloWorld();
}
Теперь мы реализуем вышеуказанный интерфейс и назовем его HelloWorldBean
,
@Stateless
public class HelloWorldBean implements HelloWorldRemote {
public HelloWorldBean() {
}
@Override
public String getHelloWorld(){
return ("Hello World");
}
}
Обратите внимание @Stateless
запись в верхней части объявления класса. Он обозначает сессионный компонент без сохранения состояния.
4. Настройка Maven для удаленного компонента
В этом разделе мы обсудим, как настроить maven для сборки и запуска приложения на сервере.
Давайте посмотрим на плагины один за другим.
4.1. Плагин компилятора
Maven-compiler-plugin используется для компиляции исходников нашего проекта.
Здесь мы использовали версию 2.3.1 плагина с исходным и целевым JDK, установленным на 1.7 в конфигурации.
Мы определили эти настройки как свойства внутри тега и ссылаемся на него через $ {property}.
<version.compiler.plugin>2.3.1</version.compiler.plugin>
<!-- maven-compiler-plugin -->
<maven.compiler.target>1.7</maven.compiler.target>
<maven.compiler.source>1.7</maven.compiler.source>
4.2 Плагин EJB
Этот плагин генерирует файл Bean, а также связанный с ним jar-файл клиента.
Мы указали версию ejb как 3.2, а для свойства generateClient установлено значение true, которое генерирует клиента.
4.3 Развертывание в JBoss
Плагин jboss-as-maven-plugin используется для развертывания, повторного развертывания, отмены развертывания или запуска приложения в JBoss AS 7.
В этой конфигурации мы указываем имя файла сборки, совпадающее с именем файла сборки проекта, которое в нашем случае по умолчанию имеет вид artifactid-version ejb-remote-1.0-SNAPSHOT
,
4.4 Требуемые зависимости Maven для EJB
jboss-javaee-6.0 определяет версию API Java EE 6 JBoss, которую мы хотим использовать.
JBoss распространяет полный набор API-интерфейсов Java EE 6, включая спецификацию.
Спецификация определяет версии стека (или коллекции) артефактов. Мы указываем это в теге, чтобы мы всегда получали правильные версии артефактов. Тип этой зависимости сам pom, который содержит необходимые зависимости.
<dependency>
<groupId>org.jboss.spec</groupId>
<artifactId>jboss-javaee-6.0</artifactId>
<version>${version.org.jboss.spec.jboss.javaee.6.0}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
4.5 Аннотации
Следующее получит зависимость от аннотаций:
<dependency>
<groupId>org.jboss.spec.javax.annotation</groupId>
<artifactId>jboss-annotations-api_1.1_spec</artifactId>
<scope>provided</scope>
</dependency>
4.6 EJB версия 3.2
В следующем фрагменте кода мы получаем последнюю версию спецификаций:
<dependency>
<groupId>org.jboss.spec.javax.ejb</groupId>
<artifactId>jboss-ejb-api_3.2_spec</artifactId>
<version>1.0.0.Final</version>
</dependency>
Для запуска вышеуказанного проекта на сервере JBoss нам нужно сначала запустить:
mvn clean install
Затем нам нужно развернуть его на работающем сервере JBoss, выполнив следующую команду maven:
jboss-as:deploy
Теперь вы должны увидеть файл jar, развернутый на сервере jboss.
В качестве альтернативы вы можете скопировать доступный файл JAR из целевой папки в проекте и вставить его в папку веб-приложения на сервере.
5. Настройка клиентского проекта
После создания удаленного компонента мы должны протестировать развернутый компонент, создав клиент.
Сначала давайте обсудим настройку maven для проекта.
5.1 Используемые плагины Maven
Maven-compiler-plugin используется для компиляции исходников вашего проекта.
Мы указали версию jdk 1.7 для исходного и целевого классов.
Наш клиент - это Java-программа, для ее запуска мы используем exec-maven-plugin
который помогает выполнять системные и Java-программы. Нам нужно указать исполняемый файл (т.е. java), classpath и класс java (com.baeldung.ejb.client.Client).
Путь к классам оставлен пустым, потому что плагин содержит необходимые аргументы пути к классам, основанные на предоставленных зависимостях.
5.2 Maven Dependencies для клиента EJB3
Чтобы запустить клиент EJB3, нам нужно включить следующие зависимости.
Мы зависим от удаленных бизнес-интерфейсов EJB этого приложения для запуска клиента. Поэтому нам нужно указать зависимость jar от ejb client. Тег со значением "ejb-client" используется для указания зависимости этого проекта от jar-файла EJB-клиента.
<dependency>
<groupId>com.theopentutorials.ejb3</groupId>
<artifactId>ejbmavendemo</artifactId>
<type>ejb-client</type>
<version>${project.version}</version>
</dependency>
Зависимости jboss-transaction-api_1.1_spec
, jboss-ejb-api_3.1_spec
, jboss-ejb-client
, xnio-api
, xnio-nio
, jboss-remoting
, jboss-sasl
, jboss-marshalling-river
имейте область действия как время выполнения, потому что они требуются во время выполнения, а не во время компиляции.
Зависимости jboss-javaee-6.0 и jboss-as-ejb-client-bom в dependencyManagement имеют область действия в качестве импорта. Это используется для включения информации управления зависимостями из удаленного POM в текущий проект. Эти удаленные POM предоставляются JBoss, который содержит необходимые зависимости для запуска клиента.
5.3 Свойства клиента JBoss EJB
Создайте файл в "src/main/resources" и назовите его как jboss-ejb-client.properties.
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=default
remote.connection.default.host=localhost
remote.connection.default.port = 4447
remote.connection.default.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
6. Создание класса клиента
Сначала мы создаем класс ClientUtility:
public class ClientUtility {
private static Context initialContext;
private static final String PKG_INTERFACES = "org.jboss.ejb.client.naming";
public static Context getInitialContext() throws NamingException {
if (initialContext == null) {
Properties properties = new Properties();
properties.put(Context.URL_PKG_PREFIXES, PKG_INTERFACES);
initialContext = new InitialContext(properties);
}
return initialContext;
}
}
Теперь давайте создадим фактический класс Client, который будет использовать компонент, который мы развернули на сервере:
public class Client {
//The lookup method to get the EJB name
private static HelloWorldRemote doLookup() {
Context context = null;
HelloWorldRemote bean = null;
try {
// 1. Obtaining Context
context = ClientUtility.getInitialContext();
// 2. Generate JNDI Lookup name
String lookupName = getLookupName();
// 3. Lookup and cast
bean = (HelloWorldRemote) context.lookup(lookupName);
} catch (NamingException e) {
e.printStackTrace();
}
return bean;
}
private static String getLookupName() {
// The app name is the EAR name of the deployed EJB without .ear suffix.
// Since we haven't deployed the application as a .ear, the app name for
// us will be an empty string
String appName = "";
// The module name is the JAR name of the deployed EJB without the .jar
// suffix.
String moduleName = "ejb-remote-0.0.1-SNAPSHOT";
// AS7 allows each deployment to have an (optional) distinct name. This
// can be an empty string if distinct name is not specified.
String distinctName = "";
// The EJB bean implementation class name
String beanName = "HelloWorldBean";
// Fully qualified remote interface name
final String interfaceName = "com.baeldung.ejb.tutorial.HelloWorldRemote";
// Create a look up string name
String name = "ejb:" + appName + "/" + moduleName + "/" + distinctName
+ "/" + beanName + "!" + interfaceName;
return name;
}
}
Класс Client потребляет компонент и выводит результат.
7. Заключение
Итак, мы создали EJB-сервер и клиент, который использует сервис. Проект можно запустить на любом сервере приложений.
Это решение работает для Wildfly 8, 9 и 10.
1. Добавьте необходимую зависимость wildfly-ejb-client-bom
Вам нужно добавить зависимость wildfly-ejb-client-bom
к вашему проекту.
Если вы используете Maven, вы можете добавить следующую зависимость к вашему pom
,
<dependency>
<groupId>org.wildfly</groupId>
<artifactId>wildfly-ejb-client-bom</artifactId>
<version>10.1.0.Final</version>
<type>pom</type>
<scope>runtime</scope>
</dependency>
Информация использовать другие версии для Wildfly 8 (8.2.1.Final
) или 9 (9.0.2.Final
).
2. Создать jboss-ejb-client.properties
Добавьте к вашему resources
папка а jboss-ejb-client.properties
и добавьте следующий контент.
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
3. Создайте свой начальный контекст
Вам необходимо создать начальный контекст следующим образом.
final Hashtable<String, String> jndiProperties = new Hashtable<>();
jndiProperties.put(Context.URL_PKG_PREFIXES, "org.jboss.ejb.client.naming");
final Context context = new InitialContext(jndiProperties);
4. Поиск удаленного бизнес-интерфейса
Наконец, вы можете выполнить поиск вашего сессионного компонента.
TestEJBRemote remote = (TestEJBRemote) context.lookup("ejb:/EJB1/TestEJB!" + TestEJBRemote.class.getName() + "?stateful");
Если вы хотите найти bean-компонент без состояния, вы должны удалить ?stateful
,
К сожалению, последние документы о полевых мухах - беспорядок, и они не обеспечивают работающего решения. Но вы можете найти работающий пример hello world в ejb-remote: Remote EJB Client Example.