LINUX.ORG.RU

Помогите с EJB под WildFly

 


0

2

Собрал и задеплоил war на WildFly, но в клиенте выдает ошибку No EJB receiver available for handling [appName:EJBCalc, moduleName:EJBCalc, distinctName: ] combination for invocation context org.jboss.ejb.client.EJBClientInvocationContext@1057305

Код сервера:

package ru.dvach.calculator;
 
import javax.ejb.Remote;
 
@Remote
public interface CalculatorBeanRemote {
	public int summ(int x, int y);
}

package ru.dvach.calculator;
 
import javax.ejb.Stateless;
 
/**
 * Session Bean implementation class CalculatorBean
 */
@Stateless
public class CalculatorBean implements CalculatorBeanRemote {
 
    /**
     * Default constructor. 
     */
    public CalculatorBean() {
        // TODO Auto-generated constructor stub
    }
    
    @Override
    public int summ(int x, int y) {
    	return x + y;
    }
 
}

Код клиента:

package ru.dvach.calculator;
 
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
 
public class Program {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			System.err.println("Init EJB context...");
			Context context = new InitialContext();
			System.err.println("Create CalculatorBean...");
			final String appName = "EJBCalc";
			final String moduleName = "EJBCalc";
			final String distinctName = "";
			final String beanName = CalculatorBean.class.getSimpleName();
			final String viewClassName = CalculatorBeanRemote.class.getName();
			final String contextString = String.format(
					"ejb:%1s/%2s/%3s/%4s!%5s",
					appName, moduleName, distinctName,
					beanName, viewClassName);
			CalculatorBeanRemote helloBean = (CalculatorBeanRemote)
					context.lookup(contextString);
			System.err.println("Call summ method...");
			System.out.println(helloBean.summ(2, 3));
			System.err.println("Done.");
		} catch (NamingException ex) {
			System.err.println("Exception: " + ex.getClass().getName());
			System.err.println(ex.getMessage());
		}
	}
 
}

Файл jndi.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
remote.connection.default.username=admin
remote.connection.default.password=123
java.naming.factory.url.pkgs=org.jboss.ejb.client.naming
jboss.naming.client.ejb.context=true

Почему и что делать? Вроде все писал по манам.



Последнее исправление: Den_Zurin (всего исправлений: 1)

У тебя неправильный contextString, во-первых, должно быть что-то вроде java:/ear_name/ejb_jar_name/ejb_class, во-вторых, я не уверен, что бины из war-ников доступны по remote, в третьих - а security у тебя в wildfly готова к тому, что бы remote бины отдавать?

DiKeert ★★
()
Последнее исправление: DiKeert (всего исправлений: 1)
Ответ на: комментарий от DiKeert

Я только пользователя создавал, не знал, что еще и WildFly нужно настраивать (с сервлетами и REST он и так работал). Вот на другом форуме подсказали, как нужно изменить standalone.xml:

<subsystem xmlns="urn:jboss:domain:remoting:3.0">
 	<!-- . . .-->
 	<connector name="remoting-connector" socket-binding="remoting" security-realm="ApplicationRealm"/>
 </subsystem>
 
<interfaces>
 	<!-- . . . -->
 	<interface name="remote">
            <inet-address value="127.0.0.1"/>
    </interface>
</interfaces>
 
<socket-binding-group name="standard-sockets" default-interface="public" port-offset="${jboss.socket.binding.port-offset:0}">
    <!-- . . . -->
    <socket-binding name="remoting" interface="remote" port="4447"/>
</socket-binding-group>

Переписал код клиента (файл jndi.properties из него выкинул):

package ru.dvach.calculator;
 
import java.util.Properties;
 
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
 
public class Program {
 
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			System.err.println("Init EJB context...");
			Properties jndiProp = new Properties();
			jndiProp.put(Context.INITIAL_CONTEXT_FACTORY,
				"org.jboss.naming.remote.client.InitialContextFactory");
			jndiProp.put(Context.PROVIDER_URL,"remote://localhost:4447");
			jndiProp.put(Context.SECURITY_PRINCIPAL, "admin");
			jndiProp.put(Context.SECURITY_CREDENTIALS, "123");
			jndiProp.put("jboss.naming.client.ejb.context", true);
			Context context = new InitialContext(jndiProp);
			System.err.println("Create CalculatorBean...");
			final String moduleName = "EJBCalc";
			final String beanName = CalculatorBean.class.getSimpleName();
			final String viewClassName = CalculatorBeanRemote.class.getName();
			final String contextString = String.format(
					"java:jboss/exported/%1s/%2s!%3s",
					moduleName, beanName, viewClassName);
			System.err.println("Lookup for: " + contextString);
			CalculatorBeanRemote helloBean = (CalculatorBeanRemote)
					context.lookup(contextString);
			System.err.println("Call summ method...");
			System.out.println(helloBean.summ(2, 3));
			System.err.println("Done.");
		} catch (NamingException ex) {
			System.err.println("Exception: " + ex.getClass().getName());
			System.err.println(ex.getMessage());
		}
	}
 
}

Теперь выбрасывает исключение NameNotFoundException с сообщением:

jboss/exported/EJBCalc/CalculatorBean!ru.dvach.calculator.CalculatorBeanRemote -- service jboss.naming.context.java.jboss.exported.jboss.exported.EJBCalc."CalculatorBean!ru.dvach.calculator.CalculatorBeanRemote"

Строку подключения JNDI взял из терминала WildFly, там при запуске отображаются такие варианты:

02:43:28,351 INFO [org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor] (MSC service thread 1-1) JNDI bindings for session bean named CalculatorBean in deployment unit deployment "EJBCalc.jar" are as follows:

java:global/EJBCalc/CalculatorBean!ru.dvach.calculator.CalculatorBeanRemote
java:app/EJBCalc/CalculatorBean!ru.dvach.calculator.CalculatorBeanRemote
java:module/CalculatorBean!ru.dvach.calculator.CalculatorBeanRemote
java:jboss/exported/EJBCalc/CalculatorBean!ru.dvach.calculator.CalculatorBeanRemote
java:global/EJBCalc/CalculatorBean
java:app/EJBCalc/CalculatorBean
java:module/CalculatorBean

Что еще можно исправить?

Den_Zurin
() автор топика

war я не создаю, создаю jar (в Eclipse вариант EAR JAR), там внутри классы и стандартный файл манифеста на 2 строки в META-INF. Потом разворачиваю на странице администрирования WildFly в браузере.

Den_Zurin
() автор топика

Заработало с такой строкой подключения: «EJBCalc/CalculatorBean!ru.dvach.calculator.CalculatorBeanRemote»

Den_Zurin
() автор топика
Ответ на: комментарий от Den_Zurin

Третий снизу, который тоже global должен работать по идее. Если работает - то правильнее его использовать.

DiKeert ★★
()
Ответ на: комментарий от Den_Zurin

Я помню, что когда использовал WildFly и Jboss, что по сути одно и тоже, то для удаленного доступа приходилось использовать java:jboss/exported имена вместо обычных. Например JMS java:/ConnectionFactory не была видна из клиента, а java:jboss/exported/ConnectionFactoryRemote - была видна. Не знаю, исправляется ли это настройками, но такая особенность есть. Вообще вся эта херня с именами почти не стандартизирована, при смене application server-а всегда приходится трахаться, вкуривать доки для конкретного сервера и находить правильные имена ресурсов.

DiKeert ★★
()
Ответ на: комментарий от DiKeert

Вообще вся эта херня с именами почти не стандартизирована, при смене application server-а всегда приходится трахаться, вкуривать доки для конкретного сервера и находить правильные имена ресурсов.

Из тех вариантов, что отобразились (Помогите с EJB под WildFly (комментарий)) не подошел ни один.

Не понимаю, зачем тогда вообще нужны эти EJB, если нет стандарта? Я ведь вручную могу сериализовать и передать данные через сокеты и вызвать метод через рефлексию, в чем же профит?

Den_Zurin
() автор топика
Ответ на: комментарий от Den_Zurin

Ну типа у тебя есть объект и ты просто дергаешь его методы, а как этот объект к тебе доставлен - тебе не важно. Типа «упрощение». Именно потому что это так работает, этого никто не использует, из адекватных людей. Все давно сидят на SOAP, а самый адекватные на REST. Еще есть вариант, когда у тебя есть кластер серверов с remote EJB на них, и один из них в себя через CDI делает @Inject другого бина. Так вот ВНЕЗАПНО, вызовы методов могут обработаться на другой машине. Хорошо это или плохо - не мне судить. Но сообщество сказало свое веское слово дружно используя спринг, вместо этого переусложненного говна. А! Еще тебе это дает автоматическое управление транзакциями и потокобезопасность.

DiKeert ★★
()
Ответ на: комментарий от DiKeert

Вообще это нужно для тестового задания на вакансию Java Junior.

Такой тест: сделать war-приложение. В нём: один EJB-сервис отдаёт/сохраняет entity (человек: Фамилия, Имя, Отчество, дата рождения). Базу не надо, сохранение идёт в память. REST-контроллер, который выдаёт/принимает данные человека как JSON + 1 страничка html+jquery которая показывает и даёт редактировать эти четыре поля: Фамилия, Имя, Отчество, дата рождения. К дате рождения на страничке прицепить календарь. Желательно обойтись JAX-RS, но можно использовать и что-то другое. В таком случае - объясните свой выбор. web-приложение должно запускаться на jboss 7.x или на wildfly 8.x

Вот думаю, зачем здесь EJB? И как его объединять с JAX-RS - вообще непонятно. Без EJB все просто и ясно - нужно написать RESTful веб-приложение (RestEasy в JBoss/WildFly, Jersey в Glassfish), в нем сделать класс с аннотациями JPA, но без маппинга на БД, и читать/создавать/изменять/удалять объекты в REST-методах. Это я писал и не раз. А тут какой-то EJB сервис. Это что значит, делать на сервере сразу 2 приложения - сервлет с REST и EJB, который отдает JPA объекты? Ничего не понимаю.

Den_Zurin
() автор топика
Ответ на: комментарий от Den_Zurin

C EJB тоже все понятно. Никто не говорит, что они должны быть доступны через remoting. Используй локальные бины - просто пометь бин аннотацией Stateless, сделай для него интерфейс. В REST сервисе же своем, сделай поле с этим интерфейсом и пометь аннотацией @Inject. Остальное сделает контейнер - в том числе и упралевние транзакциями.

Задание просто проверяет твое владение J2EE технологиями, они в себя включают бины.

DiKeert ★★
()
Ответ на: комментарий от DiKeert

Понятно, просто «EJB-сервис» ввело в заблуждение. Для меня сервис - это что-то удаленное, к чему обращается клиент.

Den_Zurin
() автор топика
Ответ на: комментарий от Den_Zurin

Интересно, как начинающему, посмотреть на решение.

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.