Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating an XML document from Java objects where the structure is very different

The Situation

I have a complex model object graph in Java that needs to be translated back and forth into an XML document. The object graph structure of the XML document's schema is extremely different from the model's object tree. The two are interchangeable, but the translation requires lots of context-driven logic where parent/child-like relationships are used.

The Problem

I'm working with model objects that are well established in a older system and the XML document's schema is fairly new. Since lots of our code depends on the structure of the model objects, we don't want to restructure them. Here is a simplified example of the type of structural differences I'm dealing with:

Example data model tree

Item

  • Description
  • cost
  • ...

Person

  • First Name
  • Last Name
  • Address
  • ...

Address

  • Street
  • City
  • ...

SaleTransaction (*this is the thing being translated)

  • Buyer (Person)
  • Seller (Person)
  • Sold Items[] (List)
  • Exchanged Items[] (List)
  • Location of Transaction (Address)

Example XML Document Structure

Exchange

  • Type
  • Parties
    • party_contact_ref
      • type
      • contact_id
  • Exchange Details
    • type
    • total_amount_exchanged
  • Items
    • Item
      • type
      • owning_party_contact_ref_id
      • exchange_use_type
  • Contacts
    • Contact
      • id
      • type

Exchange Type: [ CASH SALE | BARTER | COMBINATION CASH AND BARTER ]

Contact Type: [ PERSON | ADDRESS ]

Exchange Details Type: [ CASH EXCHANGE | BARTER EXCHANGE ]

Mapping between SaleTransaction and Exchange is possible, just not 1-1. In the example, the "buyer" in the model would be mapped to both a contact and a contact reference element in the XML document. Also, the value of the "owning_party_contact_ref_id" attribute of an "Item" element would be determined by looking at several different values in the SaleTransaction object graph.

If an object graph I'm working with needs some translation in order to be used in an XML document, my go-to tool is an XmlAdapter. In this case though, I don't see using JAXB XML adapters as a viable solution for three reasons.

  1. Which XML element an object in the model graph corresponds too is data dependent. I believe all XmlAdapter to class/property mappings are fixed.
  2. It doesn't seem to be possible to do a many to one, or one to many solution with XmlAdapters. MOXy has an interesting extension, but again, it requires fixed mappings to properties.
  3. As far as I know, XmlAdapters work with individual objects and don't have a way to get at the context of the entire graph being marshalled/unmarshalled.

The Question

I'm sure this type of problem is fairly common, so how do you handle it? Is there a way of handling this problem with standard tools?

What I've come up with

In case it's interesting, here are the possible approaches that I've come up with:

#1 Separate the object graph translation problem from the XML generation problem. I have a home-grown tool that assists with generating object graphs based on some context object. I could create the JAXB classes from the XML schema, then rely on this tool to generate the objects of those classes based on the context of our model object. This would work well to generate an XML document from the model object graph, but not the other way around. It also means relying on non-standard tools, which I'd like to avoid if possible.

#2 Go XmlAdapter crazy and modify the model classes to be able to retain translation state information (e.g. This object in the model tree was used to create this element in the XML document). This would keep the problem very close to the standard usage model for JAXB, but I think it would be a nightmare to develop, test and maintain.

#3 Separate the object graph problem like I would in #1, but use JDOM instead of JAXB. This would remove all of the JAXB required classes and mappings, but require another custom tool be built to manage the model object to DOM tree mappings.

I'm not super excited about any of the three solutions, but I'm most partial to #1.

like image 518
Terence Avatar asked Oct 22 '22 17:10

Terence


1 Answers

1 is your best bet IMHO. Writing mapping code is tedious but you should resist the urge to be too clever. Any mapping tool you use is going to require configuration and I bet that's just as much work as writing the Java mapping code by hand. Just write lots of unit tests.

You can try Dozer for any classes that have similar named fields, it will use reflection to do the mapping. I've used this in the past, but my schema looked more similar to my domain objects, so it might not be that helpful.

To make the code more pleasant, use all the xjc plugins you can find for JAXB, such as the fluent-api and value-constructor ones.

like image 127
artbristol Avatar answered Oct 27 '22 09:10

artbristol