Миграция с JBoss 6 на JBoss 7 — почему из WAR не виден EJB?

Есть проект, состоящий из одного EJB и одного WAR, использующего методы EJB через локальный интерфейс. Под JBoss 6 они прекрасно работали вместе. Под JBoss 7 - не хотят.
EJB объявляет интерфейс с именем DBLocal (он используется для доступа к БД) и успешно разворачивается под Jboss7, в консоль пишет следующие JNDI bindings:
java:global/ru.test.ejb.orm/DBBean!ru.test.ecm.orm.bean.DBLocal
	java:app/ru.test.ejb.orm/DBBean!ru.test.ecm.orm.bean.DBLocal
	java:module/DBBean!ru.test.ecm.orm.bean.DBLocal
	java:global/ru.test.ejb.orm/DBBean
	java:app/ru.test.ejb.orm/DBBean
	java:module/DBBean

В серверном коде WAR-файла написано вот что:
//Это некий класс сервлета
public class LoginServiceImpl extends RemoteServiceServlet implements LoginService, ServletContextListener
{
        //Вот он, EJB-шник:
	@EJB(lookup="java:global/ru.test.ejb.orm/DBBean!ru.test.ecm.orm.bean.DBLocal")
	private DBLocal dbBean;
       ...
}


Не работает. Не может JBoss 7 обнаружить EJB, пишет в консоль такие ошибки:
Caused by: java.lang.NoClassDefFoundError: Lru/test/ecm/orm/bean/DBLocal;
	at java.lang.Class.getDeclaredFields0(Native Method) [rt.jar:1.7.0_25]
	at java.lang.Class.privateGetDeclaredFields(Unknown Source) [rt.jar:1.7.0_25]
	at java.lang.Class.getDeclaredFields(Unknown Source) [rt.jar:1.7.0_25]
	at org.jboss.as.server.deployment.reflect.ClassReflectionIndex.<init>(ClassReflectionIndex.java:57) [jboss-as-server-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	at org.jboss.as.server.deployment.reflect.DeploymentReflectionIndex.getClassIndex(DeploymentReflectionIndex.java:68) [jboss-as-server-7.3.0.Final-redhat-14.jar:7.3.0.Final-redhat-14]
	... 10 more
Caused by: java.lang.ClassNotFoundException: ru.test.ecm.orm.bean.DBLocal from [Module "deployment.ecm.war:main" from Service Module Loader]
	at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:197) [jboss-modules.jar:1.3.0.Final-redhat-2]
	at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:443) [jboss-modules.jar:1.3.0.Final-redhat-2]
	at org.jboss.modules.ConcurrentClassLoader.performLoadClassChecked(ConcurrentClassLoader.java:431) [jboss-modules.jar:1.3.0.Final-redhat-2]
	at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:373) [jboss-modules.jar:1.3.0.Final-redhat-2]
	at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:118) [jboss-modules.jar:1.3.0.Final-redhat-2]
	... 15 more


Т.е. он не может обратиться к классу, объявленному внутри EJB-модуля. Чтение документации мне сильно не помогло. Есть способ побороть NoClassDefFoundError, подключив EJB-модуль как библиотеку (путем помещения его в WEB-INF/lib папку в WAR), но тогда он, как я понимаю, используется как простая подключаемая библиотека. Если я разверну на сервере несколько WAR-ников, использующих этото же EJB, для каждого будет использоваться свой экземпляр EJB, что не есть здорово (строго говоря, это не EJB уже будет).
Как всё-таки заставить WAR увидеть EJB и работать с ним нормальным образом?
  • Вопрос задан
  • 3224 просмотра
Решения вопроса 1
@bobzer
Java EE Developer
проект, состоящий из одного EJB и одного WAR
В JBoss (и в терминологии серверов приложений JEE в целом) нет понятия "проект". Правильно ли я понимаю, что под "проектом" подразумевается Enterprise Archive (EAR)? Если у вас нет EAR, то я не вижу способов считать чем-то единым отдельный WAR и отдельный EJB-модуль.

Если есть EAR, попробуйте в папку META-INF добавить файл с именем jboss-deployment-structure.xml со следующим содержанием:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
    <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
</jboss-deployment-structure>


Создать EAR можно следующим образом. Создаете в папке deployments папку my.ear со следующей структурой:
my.ear
--META-INF
----application.xml
----jboss-deployment-structure.xml
--myWeb1.war
--myWeb2.war
--myEjb1.jar
--myEjb2.jar


Содержимое application.xml:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE application PUBLIC "-//Sun Microsystems, Inc.//DTD J2EE Application 1.3//EN" "http://java.sun.com/dtd/application_1_3.dtd">
<application>
    <display-name>myApp</display-name>
    <initialize-in-order>true</initialize-in-order>
    <module>
        <java>myEjb1.jar</java>
    </module>

    <module>
        <java>myEjb2.jar</java>
    </module>

    <module>
        <web>
            <web-uri>myWeb1.war</web-uri>
            <context-root>myWeb1</context-root>
        </web>
    </module>
    
    <module>
        <web>
            <web-uri>myWeb2.war</web-uri>
            <context-root>myWeb2</context-root>
        </web>
    </module>
</application>

Библиотеки, не содержащие EJB (просто "носители" нужных общих классов), можно поместить в папку my.ear/lib
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы