Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java OO design for handling large XML

Tags:

java

oop

We are designing a system for processing XML messages.

The processing Java class needs to split out various attributes and values from a largish XML and pass these as parameters to individual handler classes for varied operations.

We have thought of following options:

A)

Pass the entire XML to each handler and let it extract the relevant bits - but feel this might be inefficient to pass the XML around each time

B)

Convert the XML into a DTO or set of smaller DTOs and pass each DTO to relevant handler

C)

Cut the XML into snippets and pass these to each handler method

We're not happy with each of these, so any suggestions which way to go?

Example XML

 <IdAction>supplied</IdAction>
    <RegId>true</RegId>
    <DeRegId>false</DeRegId>
    <SaveMessage>false</SaveMessage>
    <ServiceName>abcRequest</ServiceName>
    <timeToPerform>3600</timeToPerform>
    <timeToReceipt/>
    <SendToBES>true</SendToBES>
    <BESQueueName>com.abc.gateway.JMSQueue.forAddRequest</BESQueueName>
    <BESTransform/>
    <BESJMSProperties>
        <property>
            <propName>stateCode</propName>
            <propValue>OK</propValue>
        </property>
    <property>
            <propName>stateResponse</propName>
            <propValue>OK</propValue>
        </property>
    </BESJMSProperties>

This contains 4 blocks processed by 4 handlers one does

 <IdAction>supplied</IdAction>
    <RegId>true</RegId>
    <DeRegId>false</DeRegId>

another does

<timeToPerform>3600</timeToPerform>
    <timeToReceipt/>

next does

<SendToBES>true</SendToBES>
    <BESQueueName>com.abc.gateway.JMSQueue.forAddRequest</BESQueueName>
    <BESTransform/>
    <BESJMSProperties>
        <property>
            <propName>stateCode</propName>
            <propValue>OK</propValue>
        </property>
    <property>
            <propName>stateResponse</propName>
            <propValue>OK</propValue>
        </property>
    </BESJMSProperties>

and so on

like image 322
romesub Avatar asked Aug 10 '11 13:08

romesub


4 Answers

B sounds like the best option to me. A is most inefficient, and C would presumably need one pass to parse it and pick out the fragments, then a 2nd pass to properly handle them?

Use SAX to parse out minimal DTO sets for transmission to dedicated handler classes.

Good question, btw. Good to think about these things in advance, and get 2nd, 3rd, 4th opinions :-)

like image 52
Brian Avatar answered Oct 19 '22 04:10

Brian


I don't think you need any special design considerations in terms of memory usage or performance so I would go with the solution that involved the least amount of coding and that would be to use a JAXB marshaller to parse your xml into DTOs and then going with your plan B. Perhaps it is harder to set up than StAX but it saves you from writing any XML parsing.

http://jaxb.java.net/

if you are using Spring is very easy to set up a bean for org.springframework.oxm.jaxb.Jaxb2Marshaller http://static.springsource.org/spring-ws/site/reference/html/oxm.html (8.5.2)

like image 34
ilcavero Avatar answered Oct 19 '22 04:10

ilcavero


Tried? http://simple.sourceforge.net/

Personally i would create a datamodel for the xml and pass the datamodel around. Take a look at the tutorials. With a custom datamodel you can map only the data you want into the model and for the handler classes you can pass along child nodes or a subset of the xml data model instead of the entire thing.

If you have an xml with the following structure

<book>
  <title>XML</title>
  <author>
     <firstname>John</firstname>
     <lastname>Doe</lastname>
  </author>
  <isbn>123541356eas</isbn>
</book>

Then you would have a datamodel something like this:

[    Book     ]         [      Author    ]
---------------         ------------------
|String title |         |String firstname|
|String isbn  |         |String lastname |
|Author author| ------->|----------------|
---------------        

Where Book has a reference to Author. And then you could pass along the Author object to your handler method.

like image 3
netbrain Avatar answered Oct 19 '22 02:10

netbrain


You could use StAX for this use case. Each processBlock operation will act on the XMLStreamReader advancing its state, then subsequent processBlock operations can do their bit:

package forum7011558;

import java.io.FileReader;

import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamReader;

public class Demo {

    public static void main(String[] args) throws Exception {
        Demo demo = new Demo();

        FileReader xml = new FileReader("src/forum7011558/input.xml");
        XMLInputFactory xif = XMLInputFactory.newFactory();
        XMLStreamReader xsr = xif.createXMLStreamReader(xml);

        demo.processBlock1(xsr);
        demo.processBlock2(xsr);
        demo.processBlock3(xsr);
        demo.processBlock4(xsr);
    }

    private void processBlock1(XMLStreamReader xsr) {
        // PROCESS BLOCK 1
    }

    private void processBlock2(XMLStreamReader xsr) {
        // PROCESS BLOCK 2
    }

    private void processBlock3(XMLStreamReader xsr) {
        // PROCESS BLOCK 3
    }

    private void processBlock4(XMLStreamReader xsr) {
        // PROCESS BLOCK 4
    }

}
like image 2
bdoughan Avatar answered Oct 19 '22 03:10

bdoughan