Skip to main content

Question: how to bind SOAP ORM JPA ?

Posted by felipegaucho on September 3, 2008 at 1:57 AM PDT

Few days evaluating my options about binding my SOAP message
objects to my JPA entities.... I have:

A soap serializable type, let's say SoapType: A JPA entity type, let's say SoapEntity:
package soap.objects;
   
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {"number",})
@XmlRootElement(name = "Domain")
class SoapType implements Serializable {
    @XmlElement(name = "entity.id")
    protected long entityId;
    public long getEntityId() { return entityId; }
    public void setEntityId(long value) { this.entityId = value; }
   
    @XmlElement(required = true)
    protected String uri;
    public String getUri() { return uri; }
    public void setUri(String value) { this.uri = value; }
   
    // [prettify]....other.fields.and.methods.here...
}[/prettify]
<?>
package jpa.objects;
   
@Entity
@Table(name = "SOAP_TYPE")
public class SoapEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "ID")
    protected long id;
    public long getId() { return id; }
    public long setId(long id) { this.id = id; }
 
    @Column(name = "URI", nullable = false, unique = true)
    protected String uri;
    public String getUri() { return uri; }
    public String setUri(String uri) { this.uri = uri; }
   
    // [prettify]....other.fields.and.methods.here...
}[/prettify]

As you can deduct from the short code samples, every time my
web-service receives a SOAP message containing values that should be
persistent in the database, I should convert the received objects to the
JPA entities. And every time I read the data base to respond a
service request, I should convert the read entity in the respective
object that can be serialized in the SOAP messages. A dual channel
repetitive copy mechanism - a copy layer - or binding framework. I don't
like the term binding since the objects not only differs in
format but the objects are part of completely different models - this is
another topic I prefer to skip here.

Questions: How to copy the values between the SOAP Message
elements and the JPA entities?

Options I am considering right now:

  1. Brute force, copying one by one the fields
    and properties from one side to another. Simple, fast and the most
    reliable solution, but with a lot of identical code for all entities.
    The number of line codes required to copy is linearly coupled with the
    number of entities and their attributes (can be thousands of lines to
    code and maintain).
  2. Recursive Reflection: trying to match the
    getters and setters names.. it works fine for shallow copy but becomes
    weird with collections and nested complex types. Reflection reduces
    the number of lines and, depending on the simplicity of the models, can
    be a good option. You pay a bit of performance but in my early
    experiments, the cost/benefit of reflection is good. href='http://dozer.sourceforge.net/'>Dozer is a nice option here
    but it imposes quite a lot of dependencies and seems Spring oriented -
    so, if you are using Spring, go for it.
  3. Adapters using annotations: similar to the
    solution proposed href='http://tssblog.blogs.techtarget.com/2007/02/08/combining-orm-and-soap-part-1/'>here,
    but instead of mapping XML to Objects I plan to map different objects
    (from different models).
  4. Inheritance between the soap objects and
    entities
    : entities are declared subclasses of XML generated objects,
    so I need to copy only from xml to entites, the reverse order is
    naturally bounded by casting. What means you solve half of the problem
    :). This points to an unwanted coupling between the models, but reduce
    the processing effort, so the bargain between the beauty and the power
    is up to you.

I certainly will blog here if I find a good workaround to this
problem, so I hope to hear from you something new :)

* This is a reviewed text of href='http://forums.java.net/jive/thread.jspa?threadID=46448&tstart=0'>the
same question I posted few days ago on the Metro forum. So, feel free to
offer your wisdom here or in the forum.

Related Topics >>

Comments

When we started designing the DocDoku project we had the same problem. And we decided to not bind but to use the same object ! JPA and JAXWS push some constraints on entity type and Soap type design. But finally, these frameworks are enough flexible to make it possible to use the same object for the both concept. For example our Activity class is annoted by annotation from JPA and JAX. https://docdoku.dev.java.net/source/browse/docdoku/trunk/DocDoku-Common/... Of course, that strategy is easer to apply when starting from scratch.

I have 2 examples in my blog, one that uses jax-ws and JPA http://weblogs.java.net/blog/caroljmcdonald/archive/2007/09/sample_appli... and one that uses JAX-RS and JPA http://weblogs.java.net/blog/caroljmcdonald/archive/2008/08/a_restful_pe... I built both of them using code that Netbeans generates for JPA and JAX-RS or JPA, JSF, and JAX-WS respectively. Here is an example of JAXB code generated by the Netbeans JAX-RS wizard , Item is a JPA entity class: @XmlRootElement(name = "item") public class ItemConverter { public ItemConverter(Item entity) { this.entity = entity; } @XmlElement public Long getId() { return getEntity().getId(); } ....

http://dozer.sourceforge.net/ might help. Best,
Laird

Felipe, Whatever you do, definitely keep the code outside these two classes. Don't go with option 4. You'll be kicking yourself in six months. How many of these do you have to do? What are you trying to accomplish? If it's a dozen or so for a short-term project, go brute force and pound out the code. (You could try generating both sets of data access code in a one-way code generator. Not sure I'd recommend that. There's better approaches.) If you've got a huge number of these and can sink some time into it: You can rescue the recursive reflection option for deep copies if you imitate serialization's approach. Build up a list of all of the objects to be stored and a directed graph of the relationships between them, then walk the directed graph to rebuild the structure in the new form. You might consider building out an intermediate set of objects independent of both the SOAP and JPA code. That way you'll retain some control of the system when someone else moves to a new version of the SOAP or database. (You could try generating the SOAP and JPA code from the code for the independent objects. It's light work, but hard to do well if you have to share with others.) Hope that helps, Dave

I'd stay with the "Simple, fast and the most reliable solution".