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
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 :-)
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)
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.
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With