Merge pull request #10 from apache/feature/5808-destroy-auto-created-resource-managers-if-feasible-v2
[UIMA-5808] Destroy auto-created resource managers if feasible
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/component/initialize/ConfigurationParameterInitializer.java b/uimafit-core/src/main/java/org/apache/uima/fit/component/initialize/ConfigurationParameterInitializer.java
index 1b2f3ba..059b169 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/component/initialize/ConfigurationParameterInitializer.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/component/initialize/ConfigurationParameterInitializer.java
@@ -37,7 +37,9 @@
import org.apache.uima.resource.CustomResourceSpecifier;
import org.apache.uima.resource.DataResource;
import org.apache.uima.resource.Parameter;
+import org.apache.uima.resource.Resource;
import org.apache.uima.resource.ResourceInitializationException;
+import org.apache.uima.resource.ResourceManager;
import org.apache.uima.resource.ResourceSpecifier;
import org.apache.uima.resource.metadata.ConfigurationParameterSettings;
import org.apache.uima.resource.metadata.NameValuePair;
@@ -193,13 +195,23 @@
*/
public static void initialize(final Object component, final Map<String, Object> map)
throws ResourceInitializationException {
- UimaContextAdmin context = UIMAFramework.newUimaContext(UIMAFramework.getLogger(),
- ResourceManagerFactory.newResourceManager(), UIMAFramework.newConfigurationManager());
+ // If there is already a UimaContext then re-use that, otherwise create a new one.
+ UimaContextAdmin context;
+ if (component instanceof Resource) {
+ context = ((Resource) component).getUimaContextAdmin();
+ } else {
+ ResourceManager resMgr = ResourceManagerFactory.newResourceManager();
+ context = UIMAFramework.newUimaContext(UIMAFramework.getLogger(), resMgr,
+ UIMAFramework.newConfigurationManager());
+ }
+
ConfigurationManager cfgMgr = context.getConfigurationManager();
cfgMgr.setSession(context.getSession());
+
for (Entry<String, Object> e : map.entrySet()) {
cfgMgr.setConfigParameterValue(context.getQualifiedContextName() + e.getKey(), e.getValue());
}
+
initialize(component, context);
}
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/factory/CollectionReaderFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/CollectionReaderFactory.java
index 2ecb0c1..de53ef7 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/factory/CollectionReaderFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/factory/CollectionReaderFactory.java
@@ -43,6 +43,7 @@
import org.apache.uima.resource.ExternalResourceDescription;
import org.apache.uima.resource.ResourceCreationSpecifier;
import org.apache.uima.resource.ResourceInitializationException;
+import org.apache.uima.resource.ResourceManager;
import org.apache.uima.resource.ResourceSpecifier;
import org.apache.uima.resource.metadata.Capability;
import org.apache.uima.resource.metadata.ConfigurationParameter;
@@ -162,12 +163,12 @@
*/
public static CollectionReader createReader(String descriptorName,
Object... configurationData) throws UIMAException, IOException {
+ ResourceManager resMgr = ResourceManagerFactory.newResourceManager();
Import imp = UIMAFramework.getResourceSpecifierFactory().createImport();
imp.setName(descriptorName);
- URL url = imp.findAbsoluteUrl(ResourceManagerFactory.newResourceManager());
+ URL url = imp.findAbsoluteUrl(resMgr);
ResourceSpecifier specifier = createResourceCreationSpecifier(url, configurationData);
- return UIMAFramework.produceCollectionReader(specifier,
- ResourceManagerFactory.newResourceManager(), null);
+ return UIMAFramework.produceCollectionReader(specifier, resMgr, null);
}
/**
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/JCasIterable.java b/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/JCasIterable.java
index f9af785..d65eb99 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/JCasIterable.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/JCasIterable.java
@@ -63,9 +63,11 @@
engines = aEngines;
}
+ @Override
public JCasIterator iterator() {
+ ResourceManager resMgr = null;
try {
- ResourceManager resMgr = ResourceManagerFactory.newResourceManager();
+ resMgr = ResourceManagerFactory.newResourceManager();
// Create the components
CollectionReader readerInst = UIMAFramework.produceCollectionReader(reader, resMgr, null);
@@ -76,12 +78,17 @@
// Instantiate AAE
AnalysisEngine aaeInst = UIMAFramework.produceAnalysisEngine(aaeDesc, resMgr, null);
- JCasIterator i = new JCasIterator(readerInst, aaeInst);
+ JCasIterator i = new JCasIterator(resMgr, readerInst, aaeInst);
i.setSelfComplete(true);
i.setSelfDestroy(true);
return i;
} catch (UIMAException e) {
throw new IllegalStateException(e);
}
+ finally {
+ if (resMgr != null) {
+ resMgr.destroy();
+ }
+ }
}
}
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/JCasIterator.java b/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/JCasIterator.java
index b820847..79fb434 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/JCasIterator.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/JCasIterator.java
@@ -45,7 +45,6 @@
* A class implementing iteration over a the documents of a collection. Each element in the Iterable
* is a JCas containing a single document. The documents have been loaded by the CollectionReader
* and processed by the AnalysisEngine (if any).
- *
*/
public class JCasIterator implements Iterator<JCas> {
@@ -60,6 +59,10 @@
private boolean selfDestroy = false;
private boolean destroyed = false;
+
+ private ResourceManager resMgr;
+
+ private boolean resourceManagerCreatedInternally = false;
/**
* Iterate over the documents loaded by the CollectionReader, running the AnalysisEngine on each
@@ -77,6 +80,29 @@
*/
public JCasIterator(final CollectionReader aReader, final AnalysisEngine... aEngines)
throws CASException, ResourceInitializationException {
+ this(ResourceManagerFactory.newResourceManager(), aReader, aEngines);
+ resourceManagerCreatedInternally = true;
+ }
+
+ /**
+ * Iterate over the documents loaded by the CollectionReader, running the AnalysisEngine on each
+ * one before yielding them. By default, components get no lifecycle events, such as
+ * collectionProcessComplete or destroy when this constructor is used.
+ * @param aResMgr
+ * The ResourceManager. Should be the one also used by the CollectionReader and
+ * AnalysisEngines.
+ * @param aReader
+ * The CollectionReader for loading documents.
+ * @param aEngines
+ * The AnalysisEngines for processing documents.
+ * @throws ResourceInitializationException
+ * if a failure occurs during initialization of the components
+ * @throws CASException
+ * if the JCas could not be initialized
+ */
+ public JCasIterator(final ResourceManager aResMgr, final CollectionReader aReader,
+ final AnalysisEngine... aEngines) throws CASException, ResourceInitializationException {
+ resMgr = aResMgr;
collectionReader = aReader;
analysisEngines = aEngines;
@@ -86,8 +112,7 @@
metaData.add(ae.getProcessingResourceMetaData());
}
- ResourceManager resMgr = ResourceManagerFactory.newResourceManager();
- jCas = CasCreationUtils.createCas(metaData, null, resMgr).getJCas();
+ jCas = CasCreationUtils.createCas(metaData, null, aResMgr).getJCas();
collectionReader.typeSystemInit(jCas.getTypeSystem());
}
@@ -111,6 +136,7 @@
this(aReader, createEngine(NoOpAnnotator.class, aTypeSystemDescription));
}
+ @Override
public boolean hasNext() {
if (destroyed) {
return false;
@@ -132,6 +158,7 @@
}
}
+ @Override
public JCas next() {
jCas.reset();
boolean error = true;
@@ -170,6 +197,7 @@
return jCas;
}
+ @Override
public void remove() {
throw new UnsupportedOperationException();
}
@@ -192,6 +220,9 @@
LifeCycleUtil.close(collectionReader);
LifeCycleUtil.destroy(collectionReader);
LifeCycleUtil.destroy(analysisEngines);
+ if (resourceManagerCreatedInternally) {
+ LifeCycleUtil.destroy(resMgr);
+ }
destroyed = true;
}
}
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/SimplePipeline.java b/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/SimplePipeline.java
index 72365cc..25ab4ff 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/SimplePipeline.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/pipeline/SimplePipeline.java
@@ -67,6 +67,9 @@
* Note that with this method, external resources cannot be shared between the reader and the
* analysis engines. They can be shared amongst the analysis engines.
* </p>
+ * <p>
+ * The CAS is created using the resource manager used by the collection reader.
+ * </p>
*
* @param reader
* The CollectionReader that loads the documents into the CAS.
@@ -90,9 +93,8 @@
aae = createEngine(aaeDesc);
// Create CAS from merged metadata
- ResourceManager resMgr = ResourceManagerFactory.newResourceManager();
final CAS cas = CasCreationUtils.createCas(asList(reader.getMetaData(), aae.getMetaData()),
- null, resMgr);
+ null, reader.getResourceManager());
reader.typeSystemInit(cas.getTypeSystem());
// Process
@@ -153,8 +155,9 @@
CollectionReader reader = null;
AnalysisEngine aae = null;
+ ResourceManager resMgr = null;
try {
- ResourceManager resMgr = ResourceManagerFactory.newResourceManager();
+ resMgr = ResourceManagerFactory.newResourceManager();
// Create the components
reader = UIMAFramework.produceCollectionReader(readerDesc, resMgr, null);
@@ -183,6 +186,7 @@
// Destroy
LifeCycleUtil.destroy(reader);
LifeCycleUtil.destroy(aae);
+ LifeCycleUtil.destroy(resMgr);
}
}
@@ -199,6 +203,9 @@
* External resources can only be shared between the reader and/or the analysis engines if the
* reader/engines have been previously instantiated using a shared resource manager.
* </p>
+ * <p>
+ * The CAS is created using the resource manager used by the collection reader.
+ * </p>
*
* @param reader
* a collection reader
@@ -211,14 +218,44 @@
*/
public static void runPipeline(final CollectionReader reader, final AnalysisEngine... engines)
throws UIMAException, IOException {
+ runPipeline(reader.getResourceManager(), reader, engines);
+ }
+
+ /**
+ * <p>
+ * Provides a simple way to run a pipeline for a given collection reader and sequence of analysis
+ * engines. After processing all CASes provided by the reader, the method calls
+ * {@link AnalysisEngine#collectionProcessComplete() collectionProcessComplete()} on the engines.
+ * Note that {@link AnalysisEngine#destroy()} and {@link CollectionReader#destroy()} are
+ * <b>NOT</b> called. As the components were instantiated by the caller, they must also be managed
+ * (i.e. destroyed) the caller.
+ * </p>
+ * <p>
+ * External resources can only be shared between the reader and/or the analysis engines if the
+ * reader/engines have been previously instantiated using a shared resource manager.
+ * </p>
+ *
+ * @param aResMgr
+ * a resource manager. Normally the same one used by the collection reader and analysis
+ * engines.
+ * @param reader
+ * a collection reader
+ * @param engines
+ * a sequence of analysis engines
+ * @throws UIMAException
+ * if there is a problem initializing or running the CPE.
+ * @throws IOException
+ * if there is an I/O problem in the reader
+ */
+ public static void runPipeline(final ResourceManager aResMgr, final CollectionReader reader,
+ final AnalysisEngine... engines) throws UIMAException, IOException {
final List<ResourceMetaData> metaData = new ArrayList<ResourceMetaData>();
metaData.add(reader.getMetaData());
for (AnalysisEngine engine : engines) {
metaData.add(engine.getMetaData());
}
- ResourceManager resMgr = ResourceManagerFactory.newResourceManager();
- final CAS cas = CasCreationUtils.createCas(metaData, null, resMgr);
+ final CAS cas = CasCreationUtils.createCas(metaData, null, aResMgr);
reader.typeSystemInit(cas.getTypeSystem());
while (reader.hasNext()) {
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/util/LifeCycleUtil.java b/uimafit-core/src/main/java/org/apache/uima/fit/util/LifeCycleUtil.java
index 799785e..5a10dc7 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/util/LifeCycleUtil.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/util/LifeCycleUtil.java
@@ -24,6 +24,7 @@
import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
import org.apache.uima.collection.base_cpm.BaseCollectionReader;
import org.apache.uima.resource.Resource;
+import org.apache.uima.resource.ResourceManager;
/**
* Helper methods to handle the life cycle of UIMA components.
@@ -51,6 +52,18 @@
}
/**
+ * Destroy a set of {@link ResourceManager resource manager}.
+ *
+ * @param aResMgr
+ * the resource manager to destroy
+ */
+ public static void destroy(final ResourceManager aResMgr) {
+ if (aResMgr != null) {
+ aResMgr.destroy();
+ }
+ }
+
+ /**
* Destroy a set of {@link Resource resources}.
*
* @param resources