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
精彩评论