3

У меня есть модуль EJB 3, развернутый на моем сервере Glassfish 2.1.Модули EJB не могут найти класс из другого модуля EJB на стеклянную рыбку

Я пытаюсь развернуть второй модуль EJB, который зависит от этого первого модуля, но развертывание не выполняется с помощью java.lang.NoClassDefFoundError о классе, который можно найти в первом модуле EJB.

Каков наилучший способ решить эту зависимость между 2 модулями EJB? Я хочу развернуть их отдельно и не иметь их в одном EAR.

Более конкретно, у меня есть зависимые пакеты инъекция EJB из моего первого модуля EJB в одном из моих EJBs моего второго модуля EJB:

@EJB (name="ejb/FirstEJB") 
private FirstEJBRemote ejb; 

Но во время развертывания я NoClassDefFoundError о классе FirstEJBRemote:

Error in annotation processing: java.lang.NoClassDefFoundError: FirstEJBRemote 
+0

Пожалуйста вывесить фрагмент кода, где вы объявляете зависимость между EJBs. –

+0

См. Редактирование. –

ответ

2

У Miljen Mikic есть точка вокруг всех загрузчиков классов, загружаемых обычно называемыми классами, если они не будут изолированы.

Но с помощью Glassfish, что вы должны сделать в своем случае, разместите свой первый модуль EJB в каталоге glassfish_home/domains/domain1/lib/applibs. Затем во время развертывания второго модуля EJB вы можете указать, что банку модуля первого EJB необходимо загрузить этот модуль EJB, который развертывается.

Это называется Application конкретного класса загрузкой, и вот об этом подробнее: http://docs.oracle.com/cd/E19798-01/821-1752/gatej/index.html

+0

Это плохая практика! Загрузка класса приложения предназначена для загрузки внешних библиотек, а не других EJB! Таким образом, EJB_1 не управляется контейнером вообще, что, например, реализует веб-службу, что веб-сервис не отображается за пределами сервера приложений. Что, если есть EJB_3, который вызывает EJB_2, вы также ставите EJB_2 в applibs? Вы можете найти EJB_1 в реестре JNDI? Как бы вы его ввели? В заключение - ставя EJB_1 только в каталог applibs и не развертывая его стандартным образом, он вообще не действует как EJB. –

+0

Я никогда не говорил, что ей не следует разворачивать модуль EJB. Конечно, EJB следует развернуть как EJB. –

+0

В этом случае достаточно указать интерфейс FirstEJBRemote в каталоге applibs, как я и предложил. Вы будете таким образом загружать все классы дважды без необходимости. Чтобы сделать аналогию, если вашему автономному приложению требуется java-e-api-6.jar, например, вы не будете упаковывать весь java-ee-6.jar с вашим приложением, а просто api. Это одна из основных целей разделения интерфейсов и реализаций. –

0

попробовать это вместо

@EJB (поиск = "JNDI_BEAN_NAME")

+0

Я не думаю, что это поможет, это ссылка на интерфейс EJB, который не может быть разрешен во время развертывания, а не на то, как он просматривается во время выполнения. –

3

Чтобы понять, почему это исключение произошло, есть две вещи, чтобы понять:

  1. Как работает одна ссылка EJB другой EJB
  2. EJB загрузки классов

первой сделки Давайте с номером один, так что давайте имя сначала EJB (содержащий FirstEJBRemote класс) EJB_A и второй EJB (кто пытается получить доступ к методу EJB_A) EJB_B. Не слишком глубоко вносятся аннотации и подобные материалы, единственный способ для EJB_B получить доступ к методам EJB_A - через интерфейс. Другими словами, EJB_A реализует некоторый интерфейс (в вашем случае это FirstEJBRemote), который EJB_B объявляет и через инъекцию извлекает экземпляр EJB_A. Все идет нормально.

Далее мы должны понимать загрузчики классов EJB. Естественно, каждый внешний класс/библиотека, которую ваше приложение (в данном случае, EJB) использует во время компиляции, должно быть доступно также во время выполнения. В противном случае, ClassNotFoundException будет отброшена, и это именно то, что произошло в вашем случае, поскольку EJB_B использует FirstEJBRemote в компиляции:

private FirstEJBRemote ejb; 

Чтобы обеспечить этот внешний класс/библиотеку в EJB во время выполнения, что нужно сделать что-то из следующего:

  • Поместите класс/библиотеку в LIB каталоге сервера приложений
  • обновления класс/библиотека вместе с EJB
  • Поместите класс/библиотеку в пути к классам EAR, содержащий ваш EJB

Мы проигнорируем третий вариант, потому что вы сказали, что вас не интересуют EAR. Таким образом, вы можете поместить интерфейс FirstEJBRemote (в виде файла .jar, конечно) в каталог lib из Glassfish, где он будет доступен как EJB_A, так и EJB_B (таким образом, вам не нужно упаковывать его ни с EJB_A), ни в вы также можете упаковать этот интерфейс вместе с EJB_B, заботясь о том, чтобы он находился в том же пакете, что и в EJB_A.

В своем комментарии вы задаетесь вопросом, почему эта «сложная» процедура необходима вообще. Ответ довольно прост - если EJB-загрузчики классов не были изолированы друг от друга, каждый класс, который был развернут с EJB_A, будет доступен для EJB_B. В этом конкретном случае это было бы желательным поведением, но представьте, что произойдет, когда EJB_A включает в себя версию1 некоторой библиотеки (например, библиотеку журналов), а EJB_B использует эту же библиотеку, но version2. Оба класса будут загружены, и вы столкнетесь с столкновением повсюду, ClassCastException и т. Д. (Или, если вам повезет, EJB_B будет «только» вынужден использовать версию1, потому что этот класс уже будет загружен загрузчиком классов).

Наконец, выдержка из Oracle GlassFish 3.1 Guide:

обходя загрузчик классов Изоляции

Поскольку каждый загрузчик приложений или индивидуально развернут класса модуля вселенной изолирована, приложение или модуль не может загружать классы от другого приложения или модуля. Это предотвращает взаимодействие двух одинаково названных классов в разных приложениях или модулях от помех друг другу.

+0

Разве не достаточно, чтобы модуль EJB был развернут на сервере? Он также должен быть скопирован во внешние каталоги библиотек, чтобы другие EJB-модули могли ссылаться на него? –

+0

@Pearl Не модуль EJB, а интерфейс, который реализует EJB. В противном случае второй EJB не сможет получить доступ к классу FirstEJBRemote (если вы не упакуете этот класс вместе со вторым EJB, как указано в ответе). –

+0

Это звучит слишком громоздко, я подожду, чтобы увидеть, есть ли у кого-то другая идея. Я имею в виду, что вам нужно, чтобы вы могли развернуть модуль EJB отдельно, если у вас возникнут проблемы с этим? –