Выполнение поиска JNDI в XAAdBter JAXB - PullRequest
3 голосов
/ 12 октября 2011

Мой проект является проектом Java Enterprise и состоит из трех модулей:

  • Сборка (EAR)
    • EJB (JAR)
    • Веб (WAR)

Моя модель домена находится в EJB. Это включает в себя класс Manufacturer и класс Model. Между двумя существует связь один ко многим. Я раскрываю экземпляры этих производителей и моделей через интерфейс REST, который находится в моем веб-проекте.

Каждый раз, когда я обращаюсь к одному из этих производителей, генерируется следующий XML-код:

<manufacturer id=1>
    <name>Ford</name>
    <models>
        <model id=1>
            <name>Fiesta</name>
        </model>
        <model id=2>
            <name>Focus</name>
        </model>
    </models>
</manufacturer>

Однако я хочу, чтобы это было так:

<manufacturer id=1>
    <name>Ford</name>
    <models>
        <model>1</model>
        <model>2</model>
    </models>
</manufacturer>

Я достиг желаемого эффекта, написав специализированные XmlAdapter, ModelAdapter и аннотирую поле в классе Manufacturer с помощью @XmlJavaTypeAdapter(ModelAdapter.class). Этот адаптер также находится в моем модуле EJB. Однако возникает проблема, когда Model необходимо разобрать:

private ModelFacade modelFacade;

@Override
public Model unmarshal(Long id) throws Exception {
    return modelFacade.find(id);
}

ModelFacade, сессионный компонент без состояния, не может быть введен в XmlAdapter, и поэтому процесс демаршаллинга всегда будет завершаться неудачей.

Мне посоветовали написать MessageBodyReader, чтобы иметь возможность "вручную" создать экземпляр адаптера и передать фасад в качестве аргумента, но это специальное средство чтения тела сообщения должно быть реализовано в веб-модуле. Мне бы очень хотелось, чтобы такое поведение содержалось в модуле EJB по той простой причине, что, если я когда-нибудь решу создать, например, настольное приложение, которое зависит от EJB, мне больше не придется заниматься той же проблемой.

Чтобы добиться такого поведения, я могу выполнить поиск JNDI в конструкторе адаптера:

public AbstractAdapter(String name) throws NamingException {
    facade = (AbstractFacade<B>) lookup("java:app/MyEJB/" + name);
}

private Object lookup(String name) throws NamingException {
    Context c = new InitialContext();
    return c.lookup(name);
}

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

1 Ответ

1 голос
/ 14 октября 2011

Вы можете указать параметр типа java.io.InputStream в своем методе JAX-RS (который находится в сессионном компоненте). Тогда вы могли бы распаковать это InputStream используя JAXB. Это даст вам возможность настроить javax.xml.bind.Unmarshaller с соответствующим XmlAdapter.

Для получения дополнительной информации

...