开发者

Performing a JNDI lookup in a JAXB XmlAdapter

开发者 https://www.devze.com 2023-04-12 05:15 出处:网络
My project is a Java Enterprise project and consists of three modules: Assembly (EAR) EJB (JAR) Web (WAR)

My project is a Java Enterprise project and consists of three modules:

  • Assembly (EAR)
    • EJB (JAR)
    • Web (WAR)

My domain model resides in the EJB. This includes a Manufacturer class and a Model class. A one-to-many relationship exists between the two. I expose instances of these manufacturers and models through a REST interface that resides in my web project.

Whenever I access one of these manufacturers, the following XML-code is generated:

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

However, I want it to be like this:

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

I have achieved the desired effect by writing a specialized XmlAdapter, ModelAdapter and annotate the field in the Manufacturer class with @XmlJavaTypeAdapter(ModelAdapter.class). This adapter resides in my EJB module as well. A problem arises, however, when a Model needs to be unmarshalled:

private ModelFacade modelFacade;

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

The ModelFacade, a stateless session bean, can not be injected into the XmlAdapter and the unmarshalling process will therefore always fail.

I have been advised to write a MessageBodyReader in order to be able to "manually" instantiate the adapter and pass the facade as an argument but this specialized message b开发者_运维问答ody reader would need to be implemented in the web module. I would very much like contain this behaviour in the EJB module for the simple reason that if I ever decide to create, for instance, a desktop application that depends on the EJB, I don't need to deal with the same issue again.

In order to achieve this behaviour, I can perform a JNDI lookup in the constructor of the adapter:

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);
}

and this will work perfectly fine, but I am not sure this is the right way to go. Is doing an JNDI lookup from an EJB module a perfectly fine solution or is there a more favourable one?


You could specify a parameter of type java.io.InputStream on your JAX-RS method (which is on the session bean). Then you could unmarshal that InputStream leveraging JAXB. This would give you the opportunity to configure the javax.xml.bind.Unmarshaller with the appropriate XmlAdapter.

For More Information

  • https://wink.apache.org/documentation/1.0/html/JAX-RS%20Request%20and%20Response%20Entities.html
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号