Использование Hibernate Ejb3Configuration с управлением контейнерами

Есть ли способ использовать программную конфигурацию, предоставляемую Ejb3Configuration, с управлением объектами, управляемыми контейнером? Я хотел бы динамически добавлять (дополнительные) аннотированные классы, которые были обнаружены с помощью ServiceLoader после обработки файла persistence.xml.

Я попытался расширить HibernatePersistence, чтобы переопределить метод createContainerEntityManagerFactory, где я добавил функциональность для добавления классов, но обнаружил две проблемы: 1) Когда я пытаюсь вызвать метод configure(PersistenceUnitInfo, Map) экземпляров EjbConfiguration в новом PersistenceProvider, я получаю значение null. . 2) Я получаю NPE, созданный моим сервером приложений (как GF 3.0.1, так и GF 3.1) при завершении работы приложения, происходящем либо из org.glassfish.persistnce.jpa.JPAApplicationContainer.closeAllEMFs, либо из org.glassfish.persistence.jpa.JPADeployer.closeEMFs , соответственно

Ниже приведен мой PersistenceProvider:

//left out createEntityManagerFactory for brevity

public class DynamicEntityProvider extends HibernatePersistence {

    @Override
    public EntityManagerFactory createContainerEntityManagerFactory 
        (PersistenceUnitInfo info, Map props) {

        final Ejb3Configuration config = new Ejb3Configuration();
        final Ejb3Configuration configured = config.configure(info, props);

        if (configured != null) {
            //never gets here, configured is always returned null
            addDynamicEntities(configured);
            return configured.buildEntityManagerFactory();
        }
        //logging code which notifies me that configured was null
        return null;
    }

    //addDynamicEntities() method impl

Я просто заменяю тег в моем файле persistence.xml на класс, и он действительно вызывается, как и ожидалось... только с перечисленными выше проблемами =)

Благодарим за любую идею!


person Steve Siebert    schedule 03.06.2011    source источник


Ответы (2)


Я не знаю, решили ли вы уже свою проблему, но...

Он возвращает значение null, поскольку класс HibernatePersistence, который вы расширяете, проверяет, установлен ли в файле persistence.xml поставщик, а не подкласс, поэтому он не распознает ваш класс (DynamicEntityProvider) в качестве поставщика, поэтому он не анализирует ваш XML.

if ( metadata.getProvider() == null || IMPLEMENTATION_NAME.equalsIgnoreCase(metadata.getProvider()) ) {

Где IMPLEMENTATION_NAME

private static final String IMPLEMENTATION_NAME = HibernatePersistence.class.getName();

Вы можете изменить его внутренне с помощью отражения, но это не "хороший" способ сделать это.

person 0x3333    schedule 09.09.2011
comment
Совершенно верно, это было проблемой. Я еще не нашел хороший способ сделать это, но я совершенно уверен, что это снова появится. - person Steve Siebert; 21.12.2011

Похоже, это какая-то проблема с видимостью загрузчика классов. Я знаю, что GF использует связку OSGi, поэтому я не совсем удивлен.

По сути, config.configure возвращает null, если не обнаруживает, что единица сохраняемости, описанная в информации, соответствует используемому поставщику сохраняемости. Попробуйте отобразить информацию и посмотреть, правильно ли настроен поставщик постоянства, и следить за проблемами с загрузчиком классов (например, myClass != yourClass, если CL загружает его не то же самое)

person Emmanuel Bernard    schedule 05.06.2011
comment
Учитывая сложность среды CL, которую создает OSGi + GF + Hibernate, я готов поставить деньги на вашу теорию =). Итак, мой DynamicEntityProvider (я предполагаю) создается контейнером и передает объект PUInfo, а оттуда я создаю экземпляр объекта Ejb3Configuration... так как же они могут иметь разные цепочки CL? Я просто заменяю класс HibernatePersistence своим в файле persistence.xml. Информационный объект имеет правильный класс в вызове getPersistenceProviderClassName() из моего провайдера (это не удивительно). Я уверен, что я что-то упускаю здесь... - person Steve Siebert; 06.06.2011