Alistair sends us a pretty big blob of code, but it’s a blob which touches upon everyone’s favorite design pattern: the singleton. It’s a lot of Java code, so we’re going to take this as chunks. Let’s start with the two methods responsible for constructing the object.
The purpose of this code is to parse an XML file, and construct a mapping from a “name” field in the XML to a “batch descriptor”.
<span class="hljs-comment">/**
* Instantiates a new batch manager.
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-title function_">BatchManager</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">final</span> <span class="hljs-type">XMLReader</span> <span class="hljs-variable">xmlReader</span> <span class="hljs-operator">=</span> XMLReaderFactory.createXMLReader();
xmlReader.setContentHandler(<span class="hljs-built_in">this</span>);
xmlReader.parse(<span class="hljs-keyword">new</span> <span class="hljs-title class_">InputSource</span>(<span class="hljs-built_in">this</span>.getClass().getClassLoader().getResourceAsStream(<span class="hljs-string">"templates/"</span> + DOCUMENT)));
} <span class="hljs-keyword">catch</span> (<span class="hljs-keyword">final</span> Exception e) {
logger.error(<span class="hljs-string">"Error parsing Batch XML."</span>, e);
}
}
<span class="hljs-comment">/*
* (non-Javadoc)
*
* @see nz.this.is.absolute.crap.sax.XMLEntity#initChild(java.lang.String,
* java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> ContentHandler <span class="hljs-title function_">initChild</span><span class="hljs-params">(String uri, String localName,
String qName, Attributes attributes)</span> <span class="hljs-keyword">throws</span> SAXException {
<span class="hljs-keyword">final</span> <span class="hljs-type">BatchDescriptor</span> <span class="hljs-variable">batchDescriptor</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BatchDescriptor</span>();
<span class="hljs-comment">// put it in the map</span>
batchMap.put(attributes.getValue(<span class="hljs-string">"name"</span>), batchDescriptor);
<span class="hljs-keyword">return</span> batchDescriptor;
}
Here we see a private constructor, which is reasonable for a singleton. It creates a SAX based reader. SAX is event driven- instead of loading the whole document into a DOM, it emits an event as it encounters each new key element in the XML document. It’s cumbersome to use, but far more memory efficient, and I’d hardly say this.is.absolute.crap
, but whatever.
This code is perfectly reasonable. But do you know what’s unreasonable? There’s a lot more code, and these are the only things not marked as static
. So let’s keep going.
<span class="hljs-comment">// singleton instance so that static batch map can be initialised using</span>
<span class="hljs-comment">// xml</span>
<span class="hljs-comment">/** The Constant singleton. */</span>
<span class="hljs-meta">@SuppressWarnings("unused")</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">Object</span> <span class="hljs-variable">singleton</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BatchManager</span>();
Wait… why is the singleton object throwing warnings about being unused? And wait a second, what is that comment saying, “so the static batch map can be initalalised”? I saw a batchMap
up in the initChild
method above, but it can’t be…
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Map<String, BatchDescriptor> batchMap = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><String, BatchDescriptor>();
Oh. Oh no.
<span class="hljs-comment">/**
* Gets the.
*
* <span class="hljs-doctag">@param</span> batchName
* the batch name
*
* <span class="hljs-doctag">@return</span> the batch descriptor
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> BatchDescriptor <span class="hljs-title function_">get</span><span class="hljs-params">(String batchName)</span> {
<span class="hljs-keyword">return</span> batchMap.get(batchName);
}
<span class="hljs-comment">/**
* Gets the post to selector name.
*
* <span class="hljs-doctag">@param</span> batchName
* the batch name
*
* <span class="hljs-doctag">@return</span> the post to selector name
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title function_">getPostToSelectorName</span><span class="hljs-params">(String batchName)</span> {
<span class="hljs-keyword">final</span> <span class="hljs-type">BatchDescriptor</span> <span class="hljs-variable">batchDescriptor</span> <span class="hljs-operator">=</span> batchMap.get(batchName);
<span class="hljs-keyword">if</span> (batchDescriptor == <span class="hljs-literal">null</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
<span class="hljs-keyword">return</span> batchDescriptor.getPostTo();
}
There are more methods, and I’ll share the whole code at the end, but this gives us a taste. Here’s what this code is actually doing.
It creates a static
Map
. static
, in this context, means that this instance is shared across all instances of BatchManager
.They also create a static
instance of BatchManager
inside of itself. The constructor of that instance then executes, populating that static
Map
. Now, when anyone invokes BatchManager.get
it will use that static
Map
to resolve that.
This certainly works, and it offers a certain degree of cleanness in its implementation. A more conventional singleton would have the Map
being owned by an instance, and it’s just using the singleton convention to ensure there’s only a single instance. This version’s calling convention is certainly nicer than doing something like BatchManager.getInstance().get(…)
, but there’s just something unholy about this that sticks into me.
I can’t say for certain if it’s because I just hate Singletons, or if it’s this specific abuse of constructors and static members.
This is certainly one of the cases of misusing a singleton- it does not represent something there can be only one of, it’s ensuring that an expensive computation is only allowed to be done once. There are better ways to handle that lifecycle. This approach also forces that expensive operation to happen at application startup, instead of being something flexible that can be evaluated lazily. It’s not wrong to do this eagerly, but building something that can only do it eagerly is a mistake.
In any case, the full code submission follows:
<span class="hljs-keyword">package</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.server.template;
<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.Collection;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.Iterator;
<span class="hljs-keyword">import</span> java.util.Map;
<span class="hljs-keyword">import</span> java.util.ResourceBundle;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.KupengaException;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.SafeComparator;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.sax.XMLEntity;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.selector.Selector;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.selector.SelectorItem;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.server.BatchValidator;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.server.Validatable;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.server.ValidationException;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.server.business.BusinessObject;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.server.database.EntityHandler;
<span class="hljs-keyword">import</span> nz.<span class="hljs-built_in">this</span>.is.absolute.crap.server.database.SQLEntityHandler;
<span class="hljs-keyword">import</span> org.apache.log4j.Logger;
<span class="hljs-keyword">import</span> org.xml.sax.Attributes;
<span class="hljs-keyword">import</span> org.xml.sax.ContentHandler;
<span class="hljs-keyword">import</span> org.xml.sax.InputSource;
<span class="hljs-keyword">import</span> org.xml.sax.SAXException;
<span class="hljs-keyword">import</span> org.xml.sax.XMLReader;
<span class="hljs-keyword">import</span> org.xml.sax.helpers.XMLReaderFactory;
<span class="hljs-comment">/**
* The Class BatchManager.
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">BatchManager</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">XMLEntity</span> {
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">Logger</span> <span class="hljs-variable">logger</span> <span class="hljs-operator">=</span> Logger.getLogger(BatchManager.class);
<span class="hljs-comment">/** The Constant DOCUMENT. */</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">static</span> <span class="hljs-type">String</span> <span class="hljs-variable">DOCUMENT</span> <span class="hljs-operator">=</span> <span class="hljs-string">"Batches.xml"</span>;
<span class="hljs-comment">/**
* The Class BatchDescriptor.
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">BatchDescriptor</span> <span class="hljs-keyword">extends</span> <span class="hljs-title class_">XMLEntity</span> {
<span class="hljs-comment">/** The batchSelectors. */</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Collection<String> batchSelectors = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><String>();
<span class="hljs-comment">/** The dependentCollections. */</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Collection<String> dependentCollections = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><String>();
<span class="hljs-comment">/** The directSelectors. */</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Collection<String> directSelectors = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><String>();
<span class="hljs-comment">/** The postTo. */</span>
<span class="hljs-keyword">private</span> String postTo;
<span class="hljs-comment">/** The properties. */</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> Collection<String> properties = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><String>();
<span class="hljs-comment">/**
* Gets the batch selectors iterator.
*
* <span class="hljs-doctag">@return</span> the batch selectors iterator
*/</span>
<span class="hljs-keyword">public</span> Iterator<String> <span class="hljs-title function_">getBatchSelectorsIterator</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.batchSelectors.iterator();
}
<span class="hljs-comment">/**
* Gets the dependent collections iterator.
*
* <span class="hljs-doctag">@return</span> the dependent collections iterator
*/</span>
<span class="hljs-keyword">public</span> Iterator<String> <span class="hljs-title function_">getDependentCollectionsIterator</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.dependentCollections.iterator();
}
<span class="hljs-comment">/**
* Gets the post to.
*
* <span class="hljs-doctag">@return</span> the post to
*/</span>
<span class="hljs-keyword">public</span> String <span class="hljs-title function_">getPostTo</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.postTo;
}
<span class="hljs-comment">/**
* Gets the post to business object.
*
* <span class="hljs-doctag">@param</span> businessObject
* the business object
* <span class="hljs-doctag">@param</span> postHandler
* the post handler
*
* <span class="hljs-doctag">@return</span> the post to business object
*
* <span class="hljs-doctag">@throws</span> ValidationException
* the validation exception
*/</span>
<span class="hljs-keyword">private</span> BusinessObject <span class="hljs-title function_">getPostToBusinessObject</span><span class="hljs-params">(
BusinessObject businessObject, EntityHandler postHandler)</span>
<span class="hljs-keyword">throws</span> ValidationException {
<span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.postTo == <span class="hljs-literal">null</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
<span class="hljs-keyword">final</span> <span class="hljs-type">BusinessObject</span> <span class="hljs-variable">postToBusinessObject</span> <span class="hljs-operator">=</span> businessObject
.getBusinessObjectFromMap(<span class="hljs-built_in">this</span>.postTo, postHandler);
<span class="hljs-comment">// copy properties</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">final</span> String propertyName : <span class="hljs-built_in">this</span>.properties) {
String postToPropertyName;
<span class="hljs-keyword">if</span> (<span class="hljs-string">"postToStatus"</span>.equals(propertyName)) {
<span class="hljs-comment">// status field on batch entity refers to the batch entity</span>
<span class="hljs-comment">// itself</span>
<span class="hljs-comment">// so postToStatus is used for updating the status property</span>
<span class="hljs-comment">// of the postToBusinessObject itself</span>
postToPropertyName = <span class="hljs-string">"status"</span>;
} <span class="hljs-keyword">else</span> {
postToPropertyName = propertyName;
}
<span class="hljs-keyword">final</span> <span class="hljs-type">SelectorItem</span> <span class="hljs-variable">destinationItem</span> <span class="hljs-operator">=</span> postToBusinessObject
.find(postToPropertyName);
<span class="hljs-keyword">if</span> (destinationItem != <span class="hljs-literal">null</span>) {
<span class="hljs-keyword">final</span> <span class="hljs-type">Object</span> <span class="hljs-variable">oldValue</span> <span class="hljs-operator">=</span> destinationItem.getValue();
<span class="hljs-keyword">final</span> <span class="hljs-type">Object</span> <span class="hljs-variable">newValue</span> <span class="hljs-operator">=</span> businessObject.get(propertyName);
<span class="hljs-keyword">if</span> (SafeComparator.areDifferent(oldValue, newValue)) {
destinationItem.setValue(newValue);
}
}
}
<span class="hljs-comment">// copy direct selectors</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">final</span> String selectorName : <span class="hljs-built_in">this</span>.directSelectors) {
<span class="hljs-keyword">final</span> <span class="hljs-type">SelectorItem</span> <span class="hljs-variable">destinationItem</span> <span class="hljs-operator">=</span> postToBusinessObject
.find(selectorName);
<span class="hljs-keyword">if</span> (destinationItem != <span class="hljs-literal">null</span>) {
<span class="hljs-comment">// get the old and new values for the selectors</span>
<span class="hljs-type">Selector</span> <span class="hljs-variable">oldSelector</span> <span class="hljs-operator">=</span> (Selector) destinationItem
.getValue();
<span class="hljs-type">Selector</span> <span class="hljs-variable">newSelector</span> <span class="hljs-operator">=</span> (Selector) businessObject
.get(selectorName);
<span class="hljs-comment">// strip them down to bare identifiers for comparison</span>
<span class="hljs-keyword">if</span> (oldSelector != <span class="hljs-literal">null</span>) {
oldSelector = oldSelector.getAsIdentifier();
}
<span class="hljs-keyword">if</span> (newSelector != <span class="hljs-literal">null</span>) {
newSelector = newSelector.getAsIdentifier();
}
<span class="hljs-comment">// if they're different then update</span>
<span class="hljs-keyword">if</span> (SafeComparator.areDifferent(oldSelector, newSelector)) {
destinationItem.setValue(newSelector);
}
}
}
<span class="hljs-comment">// copy batch selectors</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">final</span> String batchSelectorName : <span class="hljs-built_in">this</span>.batchSelectors) {
<span class="hljs-keyword">final</span> <span class="hljs-type">Selector</span> <span class="hljs-variable">batchSelector</span> <span class="hljs-operator">=</span> (Selector) businessObject
.get(batchSelectorName);
<span class="hljs-keyword">if</span> (batchSelector == <span class="hljs-literal">null</span>) {
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ValidationException</span>(
<span class="hljs-string">""PostTo" selector missing."</span>);
}
<span class="hljs-keyword">final</span> <span class="hljs-type">BusinessObject</span> <span class="hljs-variable">batchObject</span> <span class="hljs-operator">=</span> postHandler
.find(batchSelector);
<span class="hljs-keyword">if</span> (batchObject != <span class="hljs-literal">null</span>) {
<span class="hljs-comment">// get the postTo selector for the batch object we depend on</span>
<span class="hljs-keyword">final</span> <span class="hljs-type">BatchDescriptor</span> <span class="hljs-variable">batchDescriptor</span> <span class="hljs-operator">=</span> batchMap
.get(batchObject.getName());
<span class="hljs-keyword">if</span> (batchDescriptor.postTo != <span class="hljs-literal">null</span>
&& postToBusinessObject
.containsKey(batchDescriptor.postTo)) {
<span class="hljs-keyword">final</span> <span class="hljs-type">Selector</span> <span class="hljs-variable">realSelector</span> <span class="hljs-operator">=</span> batchObject
.getBusinessObjectFromMap(
batchDescriptor.postTo, postHandler);
postToBusinessObject.put(batchDescriptor.postTo,
realSelector);
}
}
}
businessObject.put(<span class="hljs-built_in">this</span>.postTo, postToBusinessObject);
<span class="hljs-keyword">return</span> postToBusinessObject;
}
<span class="hljs-comment">/*
* (non-Javadoc)
*
* @see
* nz.this.is.absolute.crap.sax.XMLEntity#initChild(java.lang.String,
* java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> ContentHandler <span class="hljs-title function_">initChild</span><span class="hljs-params">(String uri, String localName,
String qName, Attributes attributes)</span> <span class="hljs-keyword">throws</span> SAXException {
<span class="hljs-keyword">if</span> (<span class="hljs-string">"Properties"</span>.equals(qName)) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">XMLEntity</span>() {
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> ContentHandler <span class="hljs-title function_">initChild</span><span class="hljs-params">(String uri,
String localName, String qName,
Attributes attributes)</span> <span class="hljs-keyword">throws</span> SAXException {
BatchDescriptor.<span class="hljs-built_in">this</span>.properties.add(attributes
.getValue(<span class="hljs-string">"name"</span>));
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
};
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-string">"DirectSelectors"</span>.equals(qName)) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">XMLEntity</span>() {
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> ContentHandler <span class="hljs-title function_">initChild</span><span class="hljs-params">(String uri,
String localName, String qName,
Attributes attributes)</span> <span class="hljs-keyword">throws</span> SAXException {
BatchDescriptor.<span class="hljs-built_in">this</span>.directSelectors.add(attributes
.getValue(<span class="hljs-string">"name"</span>));
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
};
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-string">"BatchSelectors"</span>.equals(qName)) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">XMLEntity</span>() {
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> ContentHandler <span class="hljs-title function_">initChild</span><span class="hljs-params">(String uri,
String localName, String qName,
Attributes attributes)</span> <span class="hljs-keyword">throws</span> SAXException {
BatchDescriptor.<span class="hljs-built_in">this</span>.batchSelectors.add(attributes
.getValue(<span class="hljs-string">"name"</span>));
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
};
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-string">"PostTo"</span>.equals(qName)) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">XMLEntity</span>() {
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> ContentHandler <span class="hljs-title function_">initChild</span><span class="hljs-params">(String uri,
String localName, String qName,
Attributes attributes)</span> <span class="hljs-keyword">throws</span> SAXException {
BatchDescriptor.<span class="hljs-built_in">this</span>.postTo = attributes
.getValue(<span class="hljs-string">"name"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
};
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (<span class="hljs-string">"DependentCollections"</span>.equals(qName)) {
<span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">XMLEntity</span>() {
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> ContentHandler <span class="hljs-title function_">initChild</span><span class="hljs-params">(String uri,
String localName, String qName,
Attributes attributes)</span> <span class="hljs-keyword">throws</span> SAXException {
BatchDescriptor.<span class="hljs-built_in">this</span>.dependentCollections
.add(attributes.getValue(<span class="hljs-string">"name"</span>));
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
};
}
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
}
<span class="hljs-comment">/** The batchMap. */</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Map<String, BatchDescriptor> batchMap = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><String, BatchDescriptor>();
<span class="hljs-comment">/**
* Gets the.
*
* <span class="hljs-doctag">@param</span> batchName
* the batch name
*
* <span class="hljs-doctag">@return</span> the batch descriptor
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> BatchDescriptor <span class="hljs-title function_">get</span><span class="hljs-params">(String batchName)</span> {
<span class="hljs-keyword">return</span> batchMap.get(batchName);
}
<span class="hljs-comment">/**
* Gets the post to selector name.
*
* <span class="hljs-doctag">@param</span> batchName
* the batch name
*
* <span class="hljs-doctag">@return</span> the post to selector name
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> String <span class="hljs-title function_">getPostToSelectorName</span><span class="hljs-params">(String batchName)</span> {
<span class="hljs-keyword">final</span> <span class="hljs-type">BatchDescriptor</span> <span class="hljs-variable">batchDescriptor</span> <span class="hljs-operator">=</span> batchMap.get(batchName);
<span class="hljs-keyword">if</span> (batchDescriptor == <span class="hljs-literal">null</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
}
<span class="hljs-keyword">return</span> batchDescriptor.getPostTo();
}
<span class="hljs-comment">// singleton instance so that static batch map can be initialised using</span>
<span class="hljs-comment">// xml</span>
<span class="hljs-comment">/** The Constant singleton. */</span>
<span class="hljs-meta">@SuppressWarnings("unused")</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> <span class="hljs-type">Object</span> <span class="hljs-variable">singleton</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BatchManager</span>();
<span class="hljs-comment">/**
* Post.
*
* <span class="hljs-doctag">@param</span> businessObject
* the business object
*
* <span class="hljs-doctag">@throws</span> Exception
* the exception
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">post</span><span class="hljs-params">(BusinessObject businessObject)</span> <span class="hljs-keyword">throws</span> Exception {
<span class="hljs-comment">// validate the batch root object only - it can validate the rest if it</span>
<span class="hljs-comment">// needs to</span>
<span class="hljs-keyword">if</span> (businessObject <span class="hljs-keyword">instanceof</span> Validatable) {
<span class="hljs-keyword">if</span> (!BatchValidator.validate(businessObject)) {
logger.warn(String.format(<span class="hljs-string">"Validating %s failed"</span>, businessObject.getClass().getSimpleName()));
<span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ValidationException</span>(
<span class="hljs-string">"Batch did not validate - it was not posted"</span>);
}
((Validatable) businessObject).validator().prepareToPost();
}
<span class="hljs-keyword">final</span> <span class="hljs-type">SQLEntityHandler</span> <span class="hljs-variable">postHandler</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">SQLEntityHandler</span>(<span class="hljs-literal">true</span>);
<span class="hljs-keyword">final</span> Iterator<BusinessObject> batchIterator = <span class="hljs-keyword">new</span> <span class="hljs-title class_">BatchIterator</span>(
businessObject, <span class="hljs-literal">null</span>, postHandler);
<span class="hljs-comment">// iterate through batch again posting each object</span>
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">while</span> (batchIterator.hasNext()) {
post(batchIterator.next(), postHandler);
}
postHandler.commit();
} <span class="hljs-keyword">catch</span> (<span class="hljs-keyword">final</span> Exception e) {
logger.error(<span class="hljs-string">"Exception occurred while posting batches"</span>, e);
<span class="hljs-comment">// something went wrong</span>
postHandler.rollback();
<span class="hljs-keyword">throw</span> e;
}
<span class="hljs-keyword">return</span>;
}
<span class="hljs-comment">/**
* Post.
*
* <span class="hljs-doctag">@param</span> businessObject
* the business object
* <span class="hljs-doctag">@param</span> postHandler
* the post handler
*
* <span class="hljs-doctag">@throws</span> KupengaException
* the kupenga exception
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">post</span><span class="hljs-params">(BusinessObject businessObject,
EntityHandler postHandler)</span> <span class="hljs-keyword">throws</span> KupengaException {
<span class="hljs-keyword">if</span> (businessObject == <span class="hljs-literal">null</span>) {
<span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">if</span> (Boolean.TRUE.equals(businessObject.get(<span class="hljs-string">"posted"</span>))) {
<span class="hljs-keyword">return</span>;
}
<span class="hljs-keyword">final</span> <span class="hljs-type">BatchDescriptor</span> <span class="hljs-variable">batchDescriptor</span> <span class="hljs-operator">=</span> batchMap.get(businessObject
.getName());
<span class="hljs-keyword">final</span> <span class="hljs-type">BusinessObject</span> <span class="hljs-variable">postToBusinessObject</span> <span class="hljs-operator">=</span> batchDescriptor
.getPostToBusinessObject(businessObject, postHandler);
<span class="hljs-keyword">if</span> (postToBusinessObject != <span class="hljs-literal">null</span>) {
postToBusinessObject.save(postHandler);
}
businessObject.setItemValue(<span class="hljs-string">"posted"</span>, Boolean.TRUE);
businessObject.save(postHandler);
}
<span class="hljs-comment">/**
* Instantiates a new batch manager.
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-title function_">BatchManager</span><span class="hljs-params">()</span> {
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">final</span> <span class="hljs-type">XMLReader</span> <span class="hljs-variable">xmlReader</span> <span class="hljs-operator">=</span> XMLReaderFactory.createXMLReader();
xmlReader.setContentHandler(<span class="hljs-built_in">this</span>);
xmlReader.parse(<span class="hljs-keyword">new</span> <span class="hljs-title class_">InputSource</span>(<span class="hljs-built_in">this</span>.getClass().getClassLoader().getResourceAsStream(<span class="hljs-string">"templates/"</span> + DOCUMENT)));
} <span class="hljs-keyword">catch</span> (<span class="hljs-keyword">final</span> Exception e) {
logger.error(<span class="hljs-string">"Error parsing Batch XML."</span>, e);
}
}
<span class="hljs-comment">/*
* (non-Javadoc)
*
* @see nz.this.is.absolute.crap.sax.XMLEntity#initChild(java.lang.String,
* java.lang.String, java.lang.String, org.xml.sax.Attributes)
*/</span>
<span class="hljs-meta">@Override</span>
<span class="hljs-keyword">protected</span> ContentHandler <span class="hljs-title function_">initChild</span><span class="hljs-params">(String uri, String localName,
String qName, Attributes attributes)</span> <span class="hljs-keyword">throws</span> SAXException {
<span class="hljs-keyword">final</span> <span class="hljs-type">BatchDescriptor</span> <span class="hljs-variable">batchDescriptor</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">BatchDescriptor</span>();
<span class="hljs-comment">// put it in the map</span>
batchMap.put(attributes.getValue(<span class="hljs-string">"name"</span>), batchDescriptor);
<span class="hljs-keyword">return</span> batchDescriptor;
}
}

Keep all your packages and Docker containers in one place, scan for vulnerabilities, and control who can access different feeds. ProGet installs in minutes and has a powerful free version with a lot of great features that you can upgrade when ready.Learn more.
Source: Read MoreÂ