1

I have multiple packages with similar JAXB JAVA objects. The java objects are automatically generated from different XSDs and seem to have a similar structure but I cannot assume that there will be no difference and I cannot marshal two similar XML documents to the same JAVA classes even though they have a lot of similarities.

I am trying to find a way to reduce code duplication and not write the same code again for each package with the same objects when fetching the data from similar objects but different packages.

public void function1(JAXBElement documentJAXB)
{
    ObjType obj =  new ObjType ();

    // parse the document
    path.to.package1.Document doc = (path.to.package1.Document) documentJAXB.getValue();
    obj.setMsgid(doc.getFIToFIPmtStsRpt().getGrpHdr().getMsgId());
    obj.setCredtm(Util.getSqlDate(doc.getFIToFIPmtStsRpt().getGrpHdr().getCreDtTm()));
    ....
}

The second function applies the same behavior to similar object under package2

public void function2(JAXBElement documentJAXB)
{
    ObjType obj =  new ObjType ();

    // parse the document
    path.to.package2.Document doc = (path.to.package2.Document) documentJAXB.getValue();
    obj.setMsgid(doc.getFIToFIPmtStsRpt().getGrpHdr().getMsgId());
    obj.setCredtm(Util.getSqlDate(doc.getFIToFIPmtStsRpt().getGrpHdr().getCreDtTm()));
    ....
}

Is there a way to combine this code? I thought of generics but it fails to compile function calls getFIToFIPmtStsRpt for example since there is no interface that these classes implement.

Is there a way to define the package name dynamically?

KAD
  • 10,972
  • 4
  • 31
  • 73
  • 1
    You could create a common interface for them, and set it in jaxb settings, similarly to this: https://stackoverflow.com/questions/1271980/generating-a-jaxb-class-that-implements-an-interface – abbath Jun 15 '17 at 07:08
  • I need to create interfaces to the `document` class and all the nested classes calling each others methods.. I was hoping to find a better and faster way to do this.. – KAD Jun 15 '17 at 07:31
  • Depending on the situation, it is sometimes better to not try to maximally reuse objects. If the XSD share the same objects, why are they not in the same namespaces? That would make them being generated in the same package. If the XSD are not related and they use the same objects (by coincidence), then I would let them live separately and make it possible to evolve independently of each other. – Manuel Jun 15 '17 at 07:39
  • The XSDs are for different types of messages with like 70% similar structure, and the data we need from these messages lies in the common objects so we do not have any difference in our case and by the nature of the XSDs we cannot combine them in the same package. – KAD Jun 15 '17 at 07:43
  • interfaces would be only needed to be created for the similar classes which you want to handle the same way. Can be cumbersome, of course, but you get type safety. The other way could be using reflection, but I wouldn't suggest that, it just obfuscates the intent. – abbath Jun 15 '17 at 09:11

2 Answers2

1

Perhaps you can use a JAXB bindings file to make parts of the XSD being generated to a certain package.

following shows a binding from namespace to package. Depending on the xsd structure, you might need to select something different (complextype, element,...)

<jaxb:bindings 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xs="http://www.w3.org/2001/XMLSchema" 
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="--schemalocation here--">
    <jaxb:bindings node="//xs:schema[@targetNamespace='--namespace here--']">
        <jaxb:schemaBindings>
            <jaxb:package name="--packagename here--" />
        </jaxb:schemaBindings>
    </jaxb:bindings>
</jaxb:bindings>

Billal Begueradj
  • 20,717
  • 43
  • 112
  • 130
Manuel
  • 239
  • 1
  • 4
0

I think Generics is the way to go. You can try something like this;

class SomeClass<T> {
   public void doSomethingInteresting(T document) {
       ....
       obj.setMsgid(doc.getFIToFIPmtStsRpt().getGrpHdr().getMsgId());
       ....
   }
}

And then call this function as follows;

....
SomeClass<path.to.package2.Document> utility = new SomeClass<>();
utility.doSomethingInteresting(documentJAXB.getValue())
....

I think this should get you going...

code-4-fun
  • 41
  • 2
  • This will fail at compile time since the compiler will not identify the methods called `getFIToFIPmtStsRpt().getGrpHdr().getMsgId()` – KAD Jun 15 '17 at 07:26
  • 1
    T should extend the Document this way, and then you would need a common interface for all the classes needed. – abbath Jun 15 '17 at 09:13