我的项目是一个 Java 企业项目,由三个模块组成:
- 汇编 (EAR)
- EJB (JAR)
- 网络( war )
我的域模型驻留在 EJB 中。这包括一个 Manufacturer
类和一个 Model
类。两者之间存在一对多的关系。我通过驻留在我的 Web 项目中的 REST 接口(interface)公开这些制造商和模型的实例。
每当我访问这些制造商之一时,就会生成以下 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
是一个无状态 session bean,不能注入(inject)到 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);
}
这会很好地工作,但我不确定这是正确的方法。从 EJB 模块执行 JNDI 查找是完美的解决方案还是有更有利的解决方案?
最佳答案
您可以在 JAX-RS 方法(位于 session bean 上)上指定 java.io.InputStream
类型的参数。然后您可以利用 JAXB 解码 InputStream
。这将使您有机会使用适当的 XmlAdapter
配置 javax.xml.bind.Unmarshaller
。
了解更多信息
关于java - 在 JAXB XmlAdapter 中执行 JNDI 查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7736730/