在JAXB XmlAdapter中执行JNDI查找

时间:2011-10-12 07:39:39

标签: java java-ee jaxb jersey

我的项目是一个Java Enterprise项目,由三个模块组成:

  • 装配(EAR)
    • EJB(JAR)
    • Web(WAR)

我的域模型驻留在EJB中。这包括Manufacturer类和Model类。两者之间存在一对多的关系。我通过驻留在我的Web项目中的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>

我通过编写专门的XmlAdapterModelAdapter并使用Manufacturer注释@XmlJavaTypeAdapter(ModelAdapter.class)类中的字段来达到预期的效果。此适配器也驻留在我的EJB模块中。但是,当Model需要解组时会出现问题:

private ModelFacade modelFacade;

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

无状态会话bean ModelFacade无法注入XmlAdapter,因此解组过程将始终失败。

我被建议写一个MessageBodyReader,以便能够“手动”实例化适配器并将外观作为参数传递,但是这个专门的消息体阅读器需要在Web模块中实现。我非常想在EJB模块中包含这种行为,原因很简单,如果我决定创建一个依赖于EJB的桌面应用程序,我不需要再次处理同样的问题。 / p>

为了实现这种行为,我可以在适配器的构造函数中执行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);
}

这将完美无缺,但我不确定这是正确的方法。从EJB模块进行JNDI查找是一个非常好的解决方案还是更有利的?

1 个答案:

答案 0 :(得分:1)

您可以在JAX-RS方法(在会话bean上)指定类型java.io.InputStream的参数。然后你可以解释InputStream利用JAXB。这样,您就可以使用相应的javax.xml.bind.Unmarshaller配置XmlAdapter

了解更多信息