[UIMA-6214] Method signature class in ExternalResourceFactory

* Merge branch '3.0.x' of https://github.com/mjunsilo/uima-uimafit into UIMA-6214-Method-signature-clash-in-ExternalResourceFactory
* This merge brings in the unit test provided by Mario Juric with the original bug report

# Conflicts:
#	uimafit-core/src/test/java/org/apache/uima/fit/factory/ExternalResourceFactoryTest.java
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 236c6de..add194b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -13,8 +13,7 @@
 
 ## Preparing a Pull Request (PR)
 
-In order to contribute to a DKPro project, you need to create a **pull request**. This section
-briefly guides you through the best way of doing this:
+In order to contribute to the uimaFIT project, you need to create a **pull request**. This section briefly guides you through the best way of doing this:
 
 * Before creating a pull request, create an issue in the issue tracker of the project to which
   you wish to contribute
diff --git a/NOTICE b/NOTICE
index 77fe8bf..74e0eb5 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
 Apache UIMA uimaFIT
-Copyright 2013-2019 The Apache Software Foundation
+Copyright 2013-2020 The Apache Software Foundation
 
 Copyright 2009-2012 Regents of the University of Colorado.
 All rights reserved.
diff --git a/README b/README
index 90fd2ec..a83f923 100644
--- a/README
+++ b/README
@@ -1,5 +1,5 @@
 
-      Apache uimaFIT (TM) v3.0.0
+      Apache uimaFIT (TM) v3.1.0
       --------------------------
 
 
@@ -37,20 +37,20 @@
      SimplePipeline.runPipeline(reader, ae1, ..., aeN, consumer1, ... consumerN)
 
 
-What's New in 3.0.0
+What's New in 3.1.0
 -------------------
 
-uimaFIT 3.0.0 is a major release because it upgrades uimaFIT to UIMA v3. Upgrading to the new version 
+uimaFIT 3.1.0 is a major release because it upgrades uimaFIT to UIMA v3. Upgrading to the new version 
 may require minor adjustments to the code depending on uimaFIT.
 
 A full list of issues addressed in this release can be found on the Apache issue tracker:
 
-  https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310570&version=12332458
+  https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310570&version=12343882
 
 Supported Platforms
 -------------------
 
-uimaFIT requires Java 1.8 or higher, UIMA 3.0.2 or higher, and the Spring Framework 4.3.22 or higher.
+uimaFIT requires Java 1.8 or higher, UIMA 3.1.1 or higher, and the Spring Framework 4.3.26 or higher.
 
 
 Availability
@@ -67,7 +67,7 @@
   <dependency>
     <groupId>org.apache.uima</groupId>
     <artifactId>uimafit-core</artifactId>
-    <version>3.0.0</version>
+    <version>3.1.0</version>
   </dependency>
 
 
diff --git a/api-change-report.html b/api-change-report.html
index cb590b3..406fe0c 100644
--- a/api-change-report.html
+++ b/api-change-report.html
@@ -1,4 +1,4 @@
- 	<!--
+<!--
     ***************************************************************
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
@@ -17,7 +17,7 @@
     * specific language governing permissions and limitations
     * under the License.
     ***************************************************************
-   -->
+-->
 <html>
 <head>
   <title>API Change Report - Apache UIMA uimaFIT</title>
diff --git a/pom.xml b/pom.xml
index 5862a5f..1c2e855 100644
--- a/pom.xml
+++ b/pom.xml
@@ -28,11 +28,11 @@
   <parent>
     <groupId>org.apache.uima</groupId>
     <artifactId>uimafit-parent</artifactId>
-    <version>3.0.1-SNAPSHOT</version>
+    <version>3.1.0-SNAPSHOT</version>
     <relativePath>uimafit-parent</relativePath>
   </parent>
   <properties>
-    <jiraVersion>3.0.0uimaFIT</jiraVersion>
+    <jiraVersion>3.1.0uimaFIT</jiraVersion>
   </properties>
   <scm>
     <connection>scm:git:git://github.com/apache/uima-uimafit</connection>
@@ -51,12 +51,12 @@
     <dependency>
       <groupId>org.apache.uima</groupId>
       <artifactId>uimafit-core</artifactId>
-      <version>3.0.1-SNAPSHOT</version>
+      <version>3.1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.apache.uima</groupId>
       <artifactId>uimafit-cpe</artifactId>
-      <version>3.0.1-SNAPSHOT</version>
+      <version>3.1.0-SNAPSHOT</version>
     </dependency>
   </dependencies>
   <build>
@@ -98,7 +98,6 @@
           </execution>
         </executions>
       </plugin>
-
     </plugins>
     <pluginManagement>
       <plugins>
diff --git a/src/main/dist-bin/LICENSE b/src/main/dist-bin/LICENSE
index 5516c5a..df56428 100644
--- a/src/main/dist-bin/LICENSE
+++ b/src/main/dist-bin/LICENSE
@@ -203,9 +203,9 @@
 
 =======================================================================
 
-SPRING FRAMEWORK 4.3.22.RELEASE SUBCOMPONENTS:
+SPRING FRAMEWORK 4.3.26.RELEASE SUBCOMPONENTS:
 
-Spring Framework 4.3.22.RELEASE includes a number of subcomponents
+Spring Framework 4.3.26.RELEASE includes a number of subcomponents
 with separate copyright notices and license terms. The product that
 includes this file does not necessarily use all the open source
 subcomponents referred to below. Your use of the source
@@ -213,7 +213,7 @@
 conditions of the following licenses.
 
 
->>> ASM 4.0 (org.ow2.asm:asm:4.0, org.ow2.asm:asm-commons:4.0):
+>>> ASM 6.0 (org.ow2.asm:asm:6.0, org.ow2.asm:asm-commons:6.0):
 
 Copyright (c) 2000-2011 INRIA, France Telecom
 All rights reserved.
@@ -245,36 +245,39 @@
 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 THE POSSIBILITY OF SUCH DAMAGE.
 
-Copyright (c) 1999-2009, OW2 Consortium <http://www.ow2.org/>
+Copyright (c) 1999-2009, OW2 Consortium <https://www.ow2.org/>
 
 
->>> CGLIB 3.0 (cglib:cglib:3.0):
+>>> CGLIB 3.2.6 (cglib:cglib:3.2.6):
 
 Per the LICENSE file in the CGLIB JAR distribution downloaded from
-http://sourceforge.net/projects/cglib/files/cglib3/3.0/cglib-3.0.jar/download,
-CGLIB 3.0 is licensed under the Apache License, version 2.0, the text of which
-is included above.
+https://github.com/cglib/cglib/releases/download/RELEASE_3_2_6/cglib-3.2.6.jar,
+CGLIB 3.2.6 is licensed under the Apache License, version 2.0, the text of
+which is included above.
 
 
-=======================================================================
+>>> Objenesis 2.6 (org.objenesis:objenesis:2.6):
 
-To the extent any open source subcomponents are licensed under the EPL and/or
+Per the LICENSE file in the Objenesis ZIP distribution downloaded from
+http://objenesis.org/download.html, Objenesis 2.6 is licensed under the
+Apache License, version 2.0, the text of which is included above.
+
+
+===============================================================================
+
+To the extent any open source components are licensed under the EPL and/or
 other similar licenses that require the source code and/or modifications to
 source code to be made available (as would be noted above), you may obtain a
 copy of the source code corresponding to the binaries for such open source
 components and modifications thereto, if any, (the "Source Files"), by
-downloading the Source Files from http://www.springsource.org/download, or by
-sending a request, with your name and address to:
+downloading the Source Files from https://spring.io/projects, Pivotal's website
+at https://network.pivotal.io/open-source, or by sending a request, with your
+name and address to: Pivotal Software, Inc., 875 Howard Street, 5th floor, San
+Francisco, CA 94103, Attention: General Counsel. All such requests should
+clearly specify: OPEN SOURCE FILES REQUEST, Attention General Counsel. Pivotal
+can mail a copy of the Source Files to you on a CD or equivalent physical
+medium.
 
-    Pivotal, Inc., 875 Howard St,
-    San Francisco, CA 94103
-    United States of America
-
-or email info@pivotal.io.  All such requests should clearly specify:
-
-    OPEN SOURCE FILES REQUEST
-    Attention General Counsel
-
-Pivotal shall mail a copy of the Source Files to you on a CD or equivalent
-physical medium. This offer to obtain a copy of the Source Files is valid for
-three years from the date you acquired this Software product.
+This offer to obtain a copy of the Source Files is valid for three years from
+the date you acquired this Software product. Alternatively, the Source Files
+may accompany the Software.
diff --git a/src/main/dist-bin/NOTICE b/src/main/dist-bin/NOTICE
index a661f84..b0cfc2a 100644
--- a/src/main/dist-bin/NOTICE
+++ b/src/main/dist-bin/NOTICE
@@ -1,12 +1,15 @@
+----------------------------------------------------------------
+
 Apache UIMA uimaFIT
-Copyright 2012-2019 The Apache Software Foundation
+Copyright 2012-2020 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
 
+----------------------------------------------------------------
 
 Apache UIMA uimaFIT - Core
-Copyright 2013-2019 The Apache Software Foundation
+Copyright 2013-2020 The Apache Software Foundation
 
 Copyright 2009-2012 Regents of the University of Colorado.
 All rights reserved.
@@ -15,16 +18,18 @@
 Technische Universität Darmstadt.
 All rights reserved.
 
+----------------------------------------------------------------
 
 Apache UIMA uimaFIT - Collection Processing Engine support
 Apache UIMA uimaFIT - Legacy uimaFIT support
-Copyright 2012-2019 The Apache Software Foundation
+Copyright 2012-2020 The Apache Software Foundation
 
+----------------------------------------------------------------
 
-Apache UIMA Base: uimaj-core
-Apache UIMA Base: jVinci: Vinci Transport Library
-Apache UIMA Base: uimaj-adapter-vinci: Vinci Adapter
-Apache UIMA Base: uimaj-cpe: Collection Processing Engine
+Apache UIMA Base 3.0.2: uimaj-core
+Apache UIMA Base 3.0.2: jVinci: Vinci Transport Library
+Apache UIMA Base 3.0.2: uimaj-adapter-vinci: Vinci Adapter
+Apache UIMA Base 3.0.2: uimaj-cpe: Collection Processing Engine
 Copyright 2006-2019 The Apache Software Foundation
 
 Portions of Apache UIMA were originally developed by
@@ -34,21 +39,25 @@
 "IBM UIMA License Agreement".
 Copyright (c) 2003, 2006 IBM Corporation.
 
+----------------------------------------------------------------
 
-Apache Commons IO
+Apache Commons IO 2.6
 Copyright 2002-2017 The Apache Software Foundation
 
+----------------------------------------------------------------
 
-Apache Commons Lang
+Apache Commons Lang 3.8.1
 Copyright 2001-2018 The Apache Software Foundation
 
+----------------------------------------------------------------
 
-Commons Logging
+Commons Logging 1.2
 Copyright 2003-2014 The Apache Software Foundation
   
+----------------------------------------------------------------
   
-Spring Framework 4.3.22.RELEASE
-Copyright (c) 2002-2019 Pivotal, Inc.
+Spring Framework 4.3.26.RELEASE
+Copyright (c) 2002-2020 Pivotal, Inc.
 
 This product is licensed to you under the Apache License, Version 2.0
 (the "License"). You may not use this product except in compliance with
@@ -59,6 +68,7 @@
 these subcomponents is subject to the terms and conditions of the
 subcomponent's license, as noted in the license.txt file.
 
+----------------------------------------------------------------
 
 AnnotationLiteral.java
 
diff --git a/uimafit-benchmark/pom.xml b/uimafit-benchmark/pom.xml
index 6c13ea0..c2ed513 100644
--- a/uimafit-benchmark/pom.xml
+++ b/uimafit-benchmark/pom.xml
@@ -27,7 +27,7 @@
   <parent>
     <groupId>org.apache.uima</groupId>
     <artifactId>uimafit-parent</artifactId>
-    <version>3.0.1-SNAPSHOT</version>
+    <version>3.1.0-SNAPSHOT</version>
     <relativePath>../uimafit-parent</relativePath>
   </parent>
   <properties>
@@ -37,7 +37,7 @@
     <dependency>
       <groupId>org.apache.uima</groupId>
       <artifactId>uimafit-core</artifactId>
-      <version>3.0.1-SNAPSHOT</version>
+      <version>3.1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.apache.uima</groupId>
diff --git a/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/RunnableWithExceptions.java b/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/RunnableWithExceptions.java
index 2cd5669..cbd62e0 100644
--- a/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/RunnableWithExceptions.java
+++ b/uimafit-benchmark/src/main/java/org/apache/uima/fit/benchmark/RunnableWithExceptions.java
@@ -20,4 +20,4 @@
 
 public interface RunnableWithExceptions {
 	void run() throws Exception;
-}
\ No newline at end of file
+}
diff --git a/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/CasUtilBenchmark.java b/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/CasUtilBenchmark.java
index 414c364..2def24a 100644
--- a/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/CasUtilBenchmark.java
+++ b/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/CasUtilBenchmark.java
@@ -155,6 +155,14 @@
       })
       .run();
 
+    new Benchmark("CAS selectCovering", template)
+      .measure(() -> {
+        Type sentenceType = getType(cas, TYPE_NAME_SENTENCE);
+        Type tokenType = getType(cas, TYPE_NAME_TOKEN);
+        select(cas, tokenType).forEach(s -> selectCovering(sentenceType, s));
+      })
+      .run();
+
     new Benchmark("CAS selectCovering v3", template)
       .measure(() -> {
         Type sentenceType = getType(cas, TYPE_NAME_SENTENCE);
diff --git a/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/JCasUtilBenchmark.java b/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/JCasUtilBenchmark.java
index befc574..988a6ca 100644
--- a/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/JCasUtilBenchmark.java
+++ b/uimafit-benchmark/src/test/java/org/apache/uima/fit/benchmark/JCasUtilBenchmark.java
@@ -98,7 +98,6 @@
     new Benchmark("JCas select ALL and iterate", template)
       .measure(() -> selectAll(jcas).forEach(v -> {}))
       .run();
-    
     new Benchmark("JCas select ALL and iterate v3", template)
       .measure(() -> jcas.select().forEach(v -> {}))
       .run();
@@ -144,7 +143,7 @@
           jcas.select(Token.class).forEach(t -> jcas.select(Sentence.class).covering(t).forEach(s -> {}));
       })
     .run();
-    
+
     new Benchmark("JCas indexCovering", template)
       .measure(() -> indexCovering(jcas, Token.class, Sentence.class).forEach((t, l) -> l.forEach(s -> {})))
       .run();
diff --git a/uimafit-core/.settings/org.eclipse.jdt.core.prefs b/uimafit-core/.settings/org.eclipse.jdt.core.prefs
index 77c684a..1e40e06 100644
--- a/uimafit-core/.settings/org.eclipse.jdt.core.prefs
+++ b/uimafit-core/.settings/org.eclipse.jdt.core.prefs
@@ -3,8 +3,10 @@
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
 org.eclipse.jdt.core.compiler.release=disabled
 org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/uimafit-core/.activate-enforce-compatibility b/uimafit-core/marker-file-identifying-api-compatibility-check
similarity index 100%
rename from uimafit-core/.activate-enforce-compatibility
rename to uimafit-core/marker-file-identifying-api-compatibility-check
diff --git a/uimafit-core/pom.xml b/uimafit-core/pom.xml
index 14b38f4..5e980b5 100644
--- a/uimafit-core/pom.xml
+++ b/uimafit-core/pom.xml
@@ -27,7 +27,7 @@
   <parent>
     <groupId>org.apache.uima</groupId>
     <artifactId>uimafit-parent</artifactId>
-    <version>3.0.1-SNAPSHOT</version>
+    <version>3.1.0-SNAPSHOT</version>
     <relativePath>../uimafit-parent</relativePath>
   </parent>
   <dependencies>
@@ -60,11 +60,17 @@
       <artifactId>slf4j-api</artifactId>
     </dependency>
     <dependency>
+      <groupId>org.apache.commons</groupId>
+      <artifactId>commons-collections4</artifactId>
+      <version>4.4</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-test</artifactId>
       <scope>test</scope>
     </dependency>
-    <dependency> <!-- https://issues.apache.org/jira/browse/UIMA-5173  -->
+    <dependency> <!-- https://issues.apache.org/jira/browse/UIMA-5173 -->
       <groupId>xmlunit</groupId>
       <artifactId>xmlunit</artifactId>
       <scope>test</scope>
@@ -79,6 +85,11 @@
       <artifactId>assertj-core</artifactId>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.mockito</groupId>
+      <artifactId>mockito-core</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
   <licenses>
     <license>
@@ -138,17 +149,18 @@
             <execution>
               <id>default-cli</id>
               <configuration>
-                <excludes>
-                                    <!-- Plain documentation -->
-                                    <exclude>README*</exclude>
-                                    <!-- Release files -->
-                                    <exclude>RELEASE_NOTES*</exclude>
-                                    <exclude>issuesFixed/**</exclude>
-                                    <exclude>release.properties</exclude>
-                                    <!-- Build controls -->
-                                    <exclude>.activate-enforce-compatibility</exclude>
+                <excludes combine.children="append">
+                <!-- These test files are unreasonable to bear a license header -->
+                  <exclude>src/test/resources/log4j.properties</exclude>
+                  <!-- Plain documentation -->
+                  <exclude>README*</exclude>
+                  <!-- Release files -->
+                  <exclude>RELEASE_NOTES*</exclude>
+                  <exclude>issuesFixed/**</exclude>
+                  <exclude>release.properties</exclude>
+                  <!-- Build controls -->
+                  <exclude>.activate-enforce-compatibility</exclude>
                   <!-- These test files are unreasonable to bear a license header -->
-                                    <exclude>src/test/resources/log4j.properties</exclude>
                   <exclude>src/test/resources/data/docs/unix-newlines.txt.bin</exclude>
                   <exclude>src/test/resources/data/docs/windows-newlines.txt.bin</exclude>
                   <exclude>src/test/resources/data/docs/bad.xcas</exclude>
@@ -156,7 +168,8 @@
                   <exclude>src/test/resources/data/docs/test.xmi</exclude>
                   <exclude>src/test/resources/data/reference/JCasBuilderTest.dump</exclude>
                   <exclude>src/test/resources/data/reference/test.xmi.dump</exclude>
-                                    <exclude>src/test/resources/data/reference/SerializationTestAnnotator.xml</exclude>
+                  <exclude>src/test/resources/data/reference/SerializationTestAnnotator.xml</exclude>
+                  <exclude>src/test/resources/pear/DateTime.pear</exclude>
                   <!-- These configuration files cannot bear a license header -->
                   <exclude>src/test/resources/META-INF/org.apache.uima.fit/fsindexes.txt</exclude>
                   <exclude>src/test/resources/META-INF/org.apache.uima.fit/typepriorities.txt</exclude>
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/component/ExternalResourceAware.java b/uimafit-core/src/main/java/org/apache/uima/fit/component/ExternalResourceAware.java
index e5e2e12..f5edff0 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/component/ExternalResourceAware.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/component/ExternalResourceAware.java
@@ -25,14 +25,12 @@
 /**
  * Allows an external resource to use the {@link ExternalResource} annotation on member variables to
  * gain access to other external resources.
- * 
  */
 public interface ExternalResourceAware {
   /**
-   * Get the name of the resource. This is set by
-   * {@link ExternalResourceFactory#bindResource(org.apache.uima.resource.ResourceCreationSpecifier, String, org.apache.uima.resource.ExternalResourceDescription)
-   * bindExternalResource()} as the parameter {@link ExternalResourceFactory#PARAM_RESOURCE_NAME
-   * PARAM_RESOURCE_NAME}. <br>
+   * Get the name of the resource. This is set by the different variations of
+   * {@link ExternalResourceFactory#bindResourceOnce} which internally call {@code ExternalResourceFactory.bindNestedResources(...)}
+   * to set the parameter {@link ExternalResourceFactory#PARAM_RESOURCE_NAME PARAM_RESOURCE_NAME}.<br>
    * <b>It is mandatory that any resource implementing this interface declares the configuration
    * parameter {@link ExternalResourceFactory#PARAM_RESOURCE_NAME PARAM_RESOURCE_NAME}.</b>
    * 
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 059b169..6b2f31a 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
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
- * 
+ *
  *   http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -18,6 +18,21 @@
  */
 package org.apache.uima.fit.component.initialize;
 
+import static org.apache.uima.UIMAFramework.getLogger;
+import static org.apache.uima.UIMAFramework.newConfigurationManager;
+import static org.apache.uima.UIMAFramework.newUimaContext;
+import static org.apache.uima.fit.factory.ConfigurationParameterFactory.createConfigurationData;
+import static org.apache.uima.fit.factory.ConfigurationParameterFactory.getConfigurationParameterName;
+import static org.apache.uima.fit.factory.ConfigurationParameterFactory.getDefaultValue;
+import static org.apache.uima.fit.factory.ConfigurationParameterFactory.getParameterSettings;
+import static org.apache.uima.fit.factory.ConfigurationParameterFactory.isConfigurationParameterField;
+import static org.apache.uima.fit.internal.ReflectionUtil.getAnnotation;
+import static org.apache.uima.fit.internal.ReflectionUtil.getFields;
+import static org.apache.uima.fit.internal.ResourceManagerFactory.newResourceManager;
+import static org.apache.uima.fit.internal.propertyeditors.PropertyEditorUtil.registerUimaFITEditors;
+import static org.springframework.beans.PropertyAccessorUtils.canonicalPropertyName;
+import static org.springframework.util.ObjectUtils.isEmpty;
+
 import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -25,14 +40,11 @@
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.apache.uima.UIMAFramework;
 import org.apache.uima.UimaContext;
 import org.apache.uima.UimaContextAdmin;
 import org.apache.uima.fit.descriptor.ConfigurationParameter;
 import org.apache.uima.fit.factory.ConfigurationParameterFactory;
-import org.apache.uima.fit.internal.ReflectionUtil;
-import org.apache.uima.fit.internal.ResourceManagerFactory;
-import org.apache.uima.fit.internal.propertyeditors.PropertyEditorUtil;
+import org.apache.uima.fit.factory.ConfigurationParameterFactory.ConfigurationData;
 import org.apache.uima.resource.ConfigurationManager;
 import org.apache.uima.resource.CustomResourceSpecifier;
 import org.apache.uima.resource.DataResource;
@@ -45,20 +57,14 @@
 import org.apache.uima.resource.metadata.NameValuePair;
 import org.apache.uima.resource.metadata.ResourceMetaData;
 import org.springframework.beans.MutablePropertyValues;
-import org.springframework.beans.PropertyAccessorUtils;
 import org.springframework.beans.PropertyValue;
-import org.springframework.util.ObjectUtils;
 import org.springframework.validation.DataBinder;
 import org.springframework.validation.ObjectError;
 
 /**
- * <p>
  * Initialize an instance of a class with fields that are annotated as
  * {@link ConfigurationParameter}s from the parameter values given in a {@link UimaContext}.
- * </p>
- * 
  */
-
 public final class ConfigurationParameterInitializer {
 
   private ConfigurationParameterInitializer() {
@@ -79,6 +85,7 @@
    * or to not provide one at all. If the context does not have a configuration parameter, then the
    * default value provided by the developer as specified by the defaultValue element of the
    * {@link ConfigurationParameter} will be used. See comments in the code for additional details.
+   *
    * @param component
    *          the component to initialize.
    * @param context
@@ -89,15 +96,15 @@
   public static void initialize(final Object component, final UimaContext context)
           throws ResourceInitializationException {
     MutablePropertyValues values = new MutablePropertyValues();
-    List<String> mandatoryValues = new ArrayList<String>();
+    List<String> mandatoryValues = new ArrayList<>();
 
-    for (Field field : ReflectionUtil.getFields(component)) { // component.getClass().getDeclaredFields())
-      if (ConfigurationParameterFactory.isConfigurationParameterField(field)) {
-        org.apache.uima.fit.descriptor.ConfigurationParameter annotation = ReflectionUtil
-                .getAnnotation(field, org.apache.uima.fit.descriptor.ConfigurationParameter.class);
+    for (Field field : getFields(component)) { // component.getClass().getDeclaredFields())
+      if (isConfigurationParameterField(field)) {
+        org.apache.uima.fit.descriptor.ConfigurationParameter annotation = getAnnotation(field,
+                org.apache.uima.fit.descriptor.ConfigurationParameter.class);
 
         Object parameterValue;
-        String parameterName = ConfigurationParameterFactory.getConfigurationParameterName(field);
+        String parameterName = getConfigurationParameterName(field);
 
         // Obtain either from the context - or - if the context does not provide the
         // parameter, check if there is a default value. Note there are three possibilities:
@@ -110,7 +117,7 @@
         // value.
         parameterValue = context.getConfigParameterValue(parameterName);
         if (parameterValue == null) {
-          parameterValue = ConfigurationParameterFactory.getDefaultValue(field);
+          parameterValue = getDefaultValue(field);
         }
 
         if (parameterValue != null) {
@@ -129,12 +136,11 @@
       @Override
       protected void checkRequiredFields(MutablePropertyValues mpvs) {
         String[] requiredFields = getRequiredFields();
-        if (!ObjectUtils.isEmpty(requiredFields)) {
-          Map<String, PropertyValue> propertyValues = new HashMap<String, PropertyValue>();
+        if (!isEmpty(requiredFields)) {
+          Map<String, PropertyValue> propertyValues = new HashMap<>();
           PropertyValue[] pvs = mpvs.getPropertyValues();
           for (PropertyValue pv : pvs) {
-            String canonicalName = PropertyAccessorUtils.canonicalPropertyName(pv.getName());
-            propertyValues.put(canonicalName, pv);
+            propertyValues.put(canonicalPropertyName(pv.getName()), pv);
           }
           for (String field : requiredFields) {
             PropertyValue pv = propertyValues.get(field);
@@ -152,8 +158,8 @@
             // }
             if (empty) {
               // Use bind error processor to create FieldError.
-              getBindingErrorProcessor()
-                      .processMissingFieldError(field, getInternalBindingResult());
+              getBindingErrorProcessor().processMissingFieldError(field,
+                      getInternalBindingResult());
               // Remove property from property values to bind:
               // It has already caused a field error with a rejected value.
               if (pv != null) {
@@ -166,9 +172,11 @@
       }
     };
     binder.initDirectFieldAccess();
-    PropertyEditorUtil.registerUimaFITEditors(binder);
+    registerUimaFITEditors(binder);
     binder.setRequiredFields(mandatoryValues.toArray(new String[mandatoryValues.size()]));
+
     binder.bind(values);
+
     if (binder.getBindingResult().hasErrors()) {
       StringBuilder sb = new StringBuilder();
       sb.append("Errors initializing [" + component.getClass() + "]");
@@ -184,7 +192,7 @@
 
   /**
    * Initialize a component from a map.
-   * 
+   *
    * @param component
    *          the component to initialize.
    * @param map
@@ -195,19 +203,19 @@
    */
   public static void initialize(final Object component, final Map<String, Object> map)
           throws ResourceInitializationException {
-    // If there is already a UimaContext then re-use that, otherwise create a new one.
-    UimaContextAdmin context;
+    // If there is already a ResourceManager then re-use that, otherwise create a new one.
+    ResourceManager resMgr;
     if (component instanceof Resource) {
-      context = ((Resource) component).getUimaContextAdmin();
+      resMgr = ((Resource) component).getResourceManager();
     } else {
-      ResourceManager resMgr = ResourceManagerFactory.newResourceManager();
-      context = UIMAFramework.newUimaContext(UIMAFramework.getLogger(), resMgr,
-              UIMAFramework.newConfigurationManager());
+      resMgr = newResourceManager();
     }
 
+    UimaContextAdmin context = newUimaContext(getLogger(), resMgr, newConfigurationManager());
+
     ConfigurationManager cfgMgr = context.getConfigurationManager();
     cfgMgr.setSession(context.getSession());
-    
+
     for (Entry<String, Object> e : map.entrySet()) {
       cfgMgr.setConfigParameterValue(context.getQualifiedContextName() + e.getKey(), e.getValue());
     }
@@ -217,7 +225,7 @@
 
   /**
    * Initialize a component from a {@link CustomResourceSpecifier}.
-   * 
+   *
    * @param component
    *          the component to initialize.
    * @param spec
@@ -228,12 +236,12 @@
    */
   public static void initialize(Object component, ResourceSpecifier spec)
           throws ResourceInitializationException {
-    initialize(component, ConfigurationParameterFactory.getParameterSettings(spec));
+    initialize(component, getParameterSettings(spec));
   }
 
   /**
    * Initialize a component from a {@link CustomResourceSpecifier}.
-   * 
+   *
    * @param component
    *          the component to initialize.
    * @param parameters
@@ -244,7 +252,7 @@
    */
   public static void initialize(Object component, Parameter... parameters)
           throws ResourceInitializationException {
-    Map<String, Object> params = new HashMap<String, Object>();
+    Map<String, Object> params = new HashMap<>();
     for (Parameter p : parameters) {
       params.put(p.getName(), p.getValue());
     }
@@ -253,7 +261,7 @@
 
   /**
    * Initialize a component from a {@link ResourceMetaData}.
-   * 
+   *
    * @param component
    *          the component to initialize.
    * @param parameters
@@ -264,7 +272,7 @@
    */
   public static void initialize(Object component, NameValuePair... parameters)
           throws ResourceInitializationException {
-    Map<String, Object> params = new HashMap<String, Object>();
+    Map<String, Object> params = new HashMap<>();
     for (NameValuePair p : parameters) {
       params.put(p.getName(), p.getValue());
     }
@@ -273,7 +281,7 @@
 
   /**
    * Initialize a component from a {@link ResourceMetaData}.
-   * 
+   *
    * @param component
    *          the component to initialize.
    * @param dataResource
@@ -288,4 +296,16 @@
     ConfigurationParameterSettings settings = metaData.getConfigurationParameterSettings();
     initialize(component, settings.getParameterSettings());
   }
+
+  public static void initialize(Object component, Object... aParameters)
+          throws ResourceInitializationException {
+    ConfigurationData configurationData = createConfigurationData(aParameters);
+    Map<String, Object> params = new HashMap<>();
+    for (int i = 0; i < configurationData.configurationParameters.length; i++) {
+      String name = configurationData.configurationParameters[i].getName();
+      Object value = configurationData.configurationValues[i];
+      params.put(name, value);
+    }
+    initialize(component, params);
+  }
 }
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/factory/AnalysisEngineFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/AnalysisEngineFactory.java
index 092cd8a..52058e8 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/factory/AnalysisEngineFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/factory/AnalysisEngineFactory.java
@@ -25,7 +25,7 @@
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.createConfigurationData;
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.ensureParametersComeInPairs;
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.setParameters;
-import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResource;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResourceOnce;
 import static org.apache.uima.fit.factory.ExternalResourceFactory.createResourceDependencies;
 import static org.apache.uima.fit.factory.FsIndexFactory.createFsIndexCollection;
 import static org.apache.uima.fit.factory.TypePrioritiesFactory.createTypePriorities;
@@ -59,6 +59,7 @@
 import org.apache.uima.fit.internal.ResourceManagerFactory;
 import org.apache.uima.flow.FlowControllerDescription;
 import org.apache.uima.resource.ExternalResourceDescription;
+import org.apache.uima.resource.PearSpecifier;
 import org.apache.uima.resource.ResourceInitializationException;
 import org.apache.uima.resource.ResourceSpecifier;
 import org.apache.uima.resource.metadata.Capability;
@@ -827,6 +828,45 @@
   }
 
   /**
+   * Get an {@link AnalysisEngineDescription} from a PEAR and a set of configuration parameters.
+   * 
+   * @param pearSpecifier
+   *          The PEAR specifier.
+   * @param configurationData
+   *          Any additional configuration parameters to be set. These should be supplied as (name,
+   *          value) pairs, so there should always be an even number of parameters.
+   * @return The {@link AnalysisEngineDescription} created from the XML descriptor and the
+   *         configuration parameters.
+   * @throws IOException
+   *           if an I/O error occurs
+   * @throws InvalidXMLException
+   *           if the input XML is not valid or does not specify a valid {@link ResourceSpecifier}
+   */
+  public static AnalysisEngineDescription createEngineDescription(PearSpecifier pearSpecifier,
+          Object... configurationData) throws InvalidXMLException, IOException {
+    ConfigurationParameterFactory.ensureParametersComeInPairs(configurationData);
+    
+    if (configurationData != null) {
+      for (int i = 0; i < configurationData.length / 2; i++) {
+        String name = (String) configurationData[i * 2];
+        String value = (String) configurationData[i * 2 + 1];
+        ConfigurationParameterFactory.setParameter(pearSpecifier, name, value);
+      }
+    }
+    
+    AnalysisEngineDescription desc = new AnalysisEngineDescription_impl();
+    desc.setFrameworkImplementation(Constants.JAVA_FRAMEWORK_NAME);
+    desc.setPrimitive(false);
+    desc.getDelegateAnalysisEngineSpecifiersWithImports().put(pearSpecifier.getPearPath(),
+            pearSpecifier);
+    
+    FixedFlow fixedFlow = new FixedFlow_impl();
+    fixedFlow.setFixedFlow(new String[] { pearSpecifier.getPearPath() });
+    desc.getAnalysisEngineMetaData().setFlowConstraints(fixedFlow);
+    
+    return desc;
+  }
+  /**
    * Get an {@link AnalysisEngineDescription} from an XML descriptor file and a set of configuration
    * parameters.
    * 
@@ -1322,7 +1362,7 @@
     // Bind External Resources
     if (externalResources != null) {
       for (Entry<String, ExternalResourceDescription> e : externalResources.entrySet()) {
-        bindResource(desc, e.getKey(), e.getValue());
+        bindResourceOnce(desc, e.getKey(), e.getValue());
       }
     }
 
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 5913f95..850463c 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
@@ -21,7 +21,7 @@
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.createConfigurationData;
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.ensureParametersComeInPairs;
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.setParameters;
-import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResource;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResourceOnce;
 import static org.apache.uima.fit.factory.ExternalResourceFactory.createResourceDependencies;
 import static org.apache.uima.fit.factory.FsIndexFactory.createFsIndexCollection;
 import static org.apache.uima.fit.factory.ResourceCreationSpecifierFactory.createResourceCreationSpecifier;
@@ -449,8 +449,10 @@
 
   /**
    * A simple factory method for creating a CollectionReaderDescription with a given class, type
-   * system description, and configuration data The type system is detected automatically using
-   * {@link TypeSystemDescriptionFactory#createTypeSystemDescription()}.
+   * system description, and configuration data. The type system is detected automatically using
+   * {@link TypeSystemDescriptionFactory#createTypeSystemDescription()}. Type priorities are
+   * detected automatically using {@link TypePrioritiesFactory#createTypePriorities()}. Indexes are
+   * detected automatically using {@link FsIndexFactory#createFsIndexCollection()}.
    * 
    * @param readerClass
    *          The class of the CollectionReader to be created.
@@ -465,8 +467,11 @@
   public static CollectionReaderDescription createReaderDescription(
           Class<? extends CollectionReader> readerClass, Object... configurationData)
           throws ResourceInitializationException {
-    TypeSystemDescription tsd = createTypeSystemDescription();
-    return createReaderDescription(readerClass, tsd, (TypePriorities) null, configurationData);
+    TypeSystemDescription typeSystem = createTypeSystemDescription();
+    TypePriorities typePriorities = createTypePriorities();
+    FsIndexCollection fsIndexCollection = createFsIndexCollection();
+    return createReaderDescription(readerClass, typeSystem, typePriorities, fsIndexCollection,
+            (Capability[]) null, configurationData);
   }
 
   /**
@@ -845,7 +850,7 @@
     // Bind External Resources
     if (externalResources != null) {
       for (Entry<String, ExternalResourceDescription> e : externalResources.entrySet()) {
-        bindResource(desc, e.getKey(), e.getValue());
+        bindResourceOnce(desc, e.getKey(), e.getValue());
       }
     }
 
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/factory/ConfigurationParameterFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/ConfigurationParameterFactory.java
index 3718b1f..067de15 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/factory/ConfigurationParameterFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/factory/ConfigurationParameterFactory.java
@@ -34,6 +34,7 @@
 import org.apache.uima.resource.ConfigurableDataResourceSpecifier;
 import org.apache.uima.resource.CustomResourceSpecifier;
 import org.apache.uima.resource.Parameter;
+import org.apache.uima.resource.PearSpecifier;
 import org.apache.uima.resource.ResourceCreationSpecifier;
 import org.apache.uima.resource.ResourceSpecifier;
 import org.apache.uima.resource.impl.Parameter_impl;
@@ -546,6 +547,10 @@
       for (Parameter p : ((CustomResourceSpecifier) spec).getParameters()) {
         settings.put(p.getName(), p.getValue());
       }
+    } else if (spec instanceof PearSpecifier) {
+      for (Parameter p : ((PearSpecifier) spec).getParameters()) {
+        settings.put(p.getName(), p.getValue());
+      }
     } else if (spec instanceof ResourceCreationSpecifier) {
       for (NameValuePair p : ((ResourceCreationSpecifier) spec).getMetaData()
               .getConfigurationParameterSettings().getParameterSettings()) {
@@ -601,6 +606,27 @@
         params[params.length - 1].setValue((String) value);
         spec.setParameters(params);
       }
+    } else if (aSpec instanceof PearSpecifier) {
+      PearSpecifier spec = (PearSpecifier) aSpec;
+
+      // If the parameter is already there, update it
+      boolean found = false;
+      for (Parameter p : spec.getParameters()) {
+        if (p.getName().equals(name)) {
+          p.setValue((String) value);
+          found = true;
+        }
+      }
+
+      // If the parameter is not there, add it
+      if (!found) {
+        Parameter[] params = new Parameter[spec.getParameters().length + 1];
+        System.arraycopy(spec.getParameters(), 0, params, 0, spec.getParameters().length);
+        params[params.length - 1] = new Parameter_impl();
+        params[params.length - 1].setName(name);
+        params[params.length - 1].setValue((String) value);
+        spec.setParameters(params);
+      }
     } else if (aSpec instanceof ResourceCreationSpecifier) {
       ResourceMetaData md = ((ResourceCreationSpecifier) aSpec).getMetaData();
 
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/factory/ExternalResourceFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/ExternalResourceFactory.java
index 91491d4..20b1f5c 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/factory/ExternalResourceFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/factory/ExternalResourceFactory.java
@@ -20,6 +20,9 @@
 package org.apache.uima.fit.factory;
 
 import static java.util.Arrays.asList;
+import static java.util.Collections.emptyMap;
+import static org.apache.uima.UIMAFramework.getResourceSpecifierFactory;
+import static org.apache.uima.UIMAFramework.produceResource;
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.canParameterBeSet;
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.createConfigurationData;
 
@@ -37,6 +40,7 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.apache.commons.lang3.ArrayUtils;
+import org.apache.uima.ResourceSpecifierFactory;
 import org.apache.uima.UIMAFramework;
 import org.apache.uima.analysis_engine.AnalysisEngineDescription;
 import org.apache.uima.collection.CollectionReaderDescription;
@@ -61,13 +65,11 @@
 import org.apache.uima.resource.SharedResourceObject;
 import org.apache.uima.resource.impl.ConfigurableDataResourceSpecifier_impl;
 import org.apache.uima.resource.impl.ConfigurableDataResource_impl;
-import org.apache.uima.resource.impl.ExternalResourceDependency_impl;
 import org.apache.uima.resource.impl.ExternalResourceDescription_impl;
 import org.apache.uima.resource.impl.FileResourceSpecifier_impl;
 import org.apache.uima.resource.impl.Parameter_impl;
 import org.apache.uima.resource.metadata.ExternalResourceBinding;
 import org.apache.uima.resource.metadata.ResourceManagerConfiguration;
-import org.apache.uima.resource.metadata.impl.ExternalResourceBinding_impl;
 import org.apache.uima.resource.metadata.impl.ResourceManagerConfiguration_impl;
 import org.apache.uima.resource.metadata.impl.ResourceMetaData_impl;
 import org.apache.uima.util.InvalidXMLException;
@@ -107,8 +109,7 @@
   }
 
   /**
-   * Create an external resource description for a custom resource. This is intended to be used
-   * together with ....
+   * Create an external resource description for a custom resource.
    * 
    * @param aInterface
    *          the interface the resource should implement.
@@ -342,7 +343,10 @@
   }
 
   /**
-   * Create an external resource binding.
+   * Create an external resource binding. This is a more convenient method of creating an
+   * {@link ExternalResourceBinding} than calling
+   * {@link ResourceSpecifierFactory#createExternalResourceBinding()} and setting the resource name
+   * and key manually.
    * 
    * @param aKey
    *          the key to bind to.
@@ -352,15 +356,16 @@
    */
   public static ExternalResourceBinding createResourceBinding(final String aKey,
           final String aResourceKey) {
-    ExternalResourceBinding extResBind = new ExternalResourceBinding_impl();
+    ExternalResourceBinding extResBind = getResourceSpecifierFactory()
+            .createExternalResourceBinding();
     extResBind.setResourceName(aResourceKey);
     extResBind.setKey(aKey);
     return extResBind;
   }
 
   /**
-   * Creates an ExternalResourceDependency for a field annotated with
-   * {@link org.apache.uima.fit.descriptor.ExternalResource}.
+   * Creates an {@link ExternalResourceDependency} for a field annotated with
+   * {@link ExternalResource}.
    * 
    * @param field
    *          the field to analyze
@@ -379,10 +384,13 @@
     // Get the type of class/interface a resource has to implement to bind to the annotated field.
     // If no API is set, get it from the annotated field type.
     Class<? extends Resource> api = era.api();
-    // If no api is specified, look at the annotated field
+    
+    // If no API is specified, look at the annotated field
     if (api == Resource.class) {
-      if (Resource.class.isAssignableFrom(field.getType())
-              || SharedResourceObject.class.isAssignableFrom(field.getType())) {
+      if (
+              Resource.class.isAssignableFrom(field.getType()) || 
+              SharedResourceObject.class.isAssignableFrom(field.getType())
+      ) {
         // If no API is set, check if the field type is already a resource type
         api = (Class<? extends Resource>) field.getType();
       } else {
@@ -394,12 +402,14 @@
       }
     }
 
-    return ExternalResourceFactory.createResourceDependency(key, api, !era.mandatory(),
-            era.description());
+    return createResourceDependency(key, api, !era.mandatory(), era.description());
   }
 
   /**
-   * Creates an ExternalResourceDependency for a given key and interface
+   * Creates an ExternalResourceDependency for a given key and interface. This is a more convenient
+   * method of creating an {@link ExternalResourceDependency} than calling
+   * {@link ResourceSpecifierFactory#createExternalResourceDependency()} and setting the fields
+   * manually.
    * 
    * @param aKey
    *          the resource key
@@ -413,7 +423,8 @@
    */
   public static ExternalResourceDependency createResourceDependency(final String aKey,
           final Class<?> aInterface, final boolean aOptional, String aDescription) {
-    ExternalResourceDependency dep = new ExternalResourceDependency_impl();
+    ExternalResourceDependency dep = getResourceSpecifierFactory()
+            .createExternalResourceDependency();
     dep.setInterfaceName(aInterface.getName());
     dep.setKey(aKey);
     dep.setOptional(aOptional);
@@ -519,7 +530,35 @@
 
   /**
    * Scan the given resource specifier for external resource dependencies and whenever a dependency
-   * is encounter that has the specified key, the resource will be bound.
+   * is encountered that has the specified key, the resource will be bound.
+   * <p>
+   * <b>Caveat</b>: If you use this method, you may expect that {@link DataResource#getUrl()} or
+   * {@link DataResource#getUri()} will return the same URL that you have specified here. This is
+   * may <b>NOT</b> be the case. UIMA will internally try to resolve the URL via a
+   * {@link ResourceManager}. If it cannot resolve a remove URL, this mechanism will think it may be
+   * a local file and will return some local path - or it may redirect it to some location as though
+   * fit by the {@link ResourceManager}.
+   * 
+   * @param aDesc
+   *          a description.
+   * @param aKey
+   *          the key to bind to.
+   * @param aUrl
+   *          a URL.
+   * @throws InvalidXMLException
+   *           if import resolution failed
+   * @see FileResourceSpecifier
+   * @deprecated Use {@link #bindResourceUsingUrl(ResourceSpecifier, String, String)}
+   */
+  @Deprecated
+  public static void bindResource(ResourceSpecifier aDesc, String aKey, String aUrl)
+          throws InvalidXMLException {
+    bindResourceUsingUrl(aDesc, aKey, aUrl);
+  }
+  
+  /**
+   * Scan the given resource specifier for external resource dependencies and whenever a dependency
+   * is encountered that has the specified key, the resource will be bound.
    * <p>
    * <b>Caveat</b>: If you use this method, you may expect that {@link DataResource#getUrl()} or
    * {@link DataResource#getUri()} will return the same URL that you have specified here. This is
@@ -538,7 +577,7 @@
    *           if import resolution failed
    * @see FileResourceSpecifier
    */
-  public static void bindResource(ResourceSpecifier aDesc, String aKey, String aUrl)
+  public static void bindResourceUsingUrl(ResourceSpecifier aDesc, String aKey, String aUrl)
           throws InvalidXMLException {
     ExternalResourceDescription extRes = createNamedFileResourceDescription(aKey, aUrl);
     bindResource(aDesc, aKey, extRes);
@@ -596,6 +635,7 @@
   /**
    * Scan the given resource specifier for external resource dependencies and whenever a dependency
    * with a compatible type is found, the resource will be bound.
+   * 
    * @param aDesc
    *          a description.
    * @param aRes
@@ -615,7 +655,7 @@
           throws InvalidXMLException, ClassNotFoundException {
     ExternalResourceDescription extRes = createNamedResourceDescriptionUsingUrl(
             uniqueResourceKey(aRes.getName()), aRes, aUrl, aParams);
-    bind((AnalysisEngineDescription) aDesc, extRes);
+    scanRecursivelyForDependenciesByInterfaceAndBind((AnalysisEngineDescription) aDesc, extRes);
   }
 
   /**
@@ -665,7 +705,7 @@
           throws InvalidXMLException {
     ExternalResourceDescription extRes = createNamedResourceDescriptionUsingUrl(
             uniqueResourceKey(aRes.getName()), aRes, aUrl, aParams);
-    bind((AnalysisEngineDescription) aDesc, aKey, extRes);
+    scanRecursivelyForDependenciesByKeyAndBind((AnalysisEngineDescription) aDesc, aKey, extRes);
   }
 
   /**
@@ -714,7 +754,7 @@
           throws InvalidXMLException, ClassNotFoundException {
     // Dispatch
     if (aDesc instanceof AnalysisEngineDescription) {
-      bind((AnalysisEngineDescription) aDesc, aResDesc);
+      scanRecursivelyForDependenciesByInterfaceAndBind((AnalysisEngineDescription) aDesc, aResDesc);
     }
   }
 
@@ -735,7 +775,7 @@
           ExternalResourceDescription aResDesc) throws InvalidXMLException {
     // Dispatch
     if (aDesc instanceof AnalysisEngineDescription) {
-      bind((AnalysisEngineDescription) aDesc, aKey, aResDesc);
+      scanRecursivelyForDependenciesByKeyAndBind((AnalysisEngineDescription) aDesc, aKey, aResDesc);
     }
   }
 
@@ -818,7 +858,7 @@
     if (!found) {
       setResourceDependencies(
               aDesc,
-              (ExternalResourceDependency[]) ArrayUtils.add(deps,
+              ArrayUtils.add(deps,
                       createResourceDependency(aKey, aApi, false, null)));
     }
   }
@@ -887,7 +927,7 @@
       if (deps == null) {
         deps = new ExternalResourceDependency[] {};
       }
-      aDesc.setExternalResourceDependencies((ExternalResourceDependency[]) ArrayUtils.add(deps,
+      aDesc.setExternalResourceDependencies(ArrayUtils.add(deps,
               createResourceDependency(aKey, aImpl, false, null)));
     }
     bindResourceUsingUrl(aDesc, aKey, aImpl, aUrl, aParams);
@@ -902,12 +942,13 @@
    * @param aResDesc
    *          the resource description.
    */
-  private static void bind(AnalysisEngineDescription aDesc, ExternalResourceDescription aResDesc)
+  private static void scanRecursivelyForDependenciesByInterfaceAndBind(
+          AnalysisEngineDescription aDesc, ExternalResourceDescription aResDesc)
           throws InvalidXMLException, ClassNotFoundException {
     // Recursively address delegates
     if (!aDesc.isPrimitive()) {
-      for (Object delegate : aDesc.getDelegateAnalysisEngineSpecifiers().values()) {
-        bindResource((ResourceSpecifier) delegate, aResDesc);
+      for (ResourceSpecifier delegate : aDesc.getDelegateAnalysisEngineSpecifiers().values()) {
+        bindResource(delegate, aResDesc);
       }
     }
 
@@ -922,7 +963,7 @@
       }
 
       if (apiClass.isAssignableFrom(resClass)) {
-        bindResource(aDesc, dep.getKey(), aResDesc);
+        bindResourceOnce(aDesc, dep.getKey(), aResDesc);
       }
     }
   }
@@ -938,25 +979,52 @@
    * @param aResDesc
    *          the resource description.
    */
-  private static void bind(AnalysisEngineDescription aDesc, String aKey,
-          ExternalResourceDescription aResDesc) throws InvalidXMLException {
+  private static void scanRecursivelyForDependenciesByKeyAndBind(AnalysisEngineDescription aDesc,
+          String aKey, ExternalResourceDescription aResDesc) throws InvalidXMLException {
     // Recursively address delegates
     if (!aDesc.isPrimitive()) {
-      for (Object delegate : aDesc.getDelegateAnalysisEngineSpecifiers().values()) {
-        bindResource((ResourceSpecifier) delegate, aKey, aResDesc);
+      for (ResourceSpecifier delegate : aDesc.getDelegateAnalysisEngineSpecifiers().values()) {
+        bindResource(delegate, aKey, aResDesc);
       }
     }
 
     // Bind if necessary
     for (ExternalResourceDependency dep : aDesc.getExternalResourceDependencies()) {
       if (aKey.equals(dep.getKey())) {
-        bindResource(aDesc, aKey, aResDesc);
+        bindResourceOnce(aDesc, aKey, aResDesc);
       }
     }
   }
 
   /**
-   * Create a new external resource binding.
+   * Create a binding for the given external resource in the given resource manager. This method
+   * also scans the given external resource for any nested external resources and creates
+   * bindings for them as well.
+   * 
+   * @param aResMgrCfg
+   *          the resource manager to create the binding in.
+   * @param aBindTo
+   *          what key to bind to.
+   * @param aRes
+   *          the resource that should be bound.
+   * @deprecated Use {@link #bindResourceOnce(ResourceManagerConfiguration, String, ExternalResourceDescription)}
+   */
+  @Deprecated
+  public static void bindResource(ResourceManagerConfiguration aResMgrCfg, String aBindTo,
+          ExternalResourceDescription aRes) {
+    bindResourceOnce(aResMgrCfg, aBindTo, aRes);
+  }
+  
+  /**
+   * Create a binding for the given external resource in the given resource manager. This method
+   * also scans the given external resource for any nested external resources and creates
+   * bindings for them as well.
+   * <p>
+   * <b>NOTE:</b>If you use this method on resource manager configurations of aggregate analysis
+   * engine descriptions because it will <b>not have any effects on the delegate analysis
+   * engines</b> of the aggregate. If you want to recursively bind an external resource to the
+   * delegates in an aggregate engine, use e.g.
+   * {@link #bindResource(ResourceSpecifier, String, ExternalResourceDescription)}.
    * 
    * @param aResMgrCfg
    *          the resource manager to create the binding in.
@@ -965,16 +1033,16 @@
    * @param aRes
    *          the resource that should be bound.
    */
-  public static void bindResource(ResourceManagerConfiguration aResMgrCfg, String aBindTo,
+  public static void bindResourceOnce(ResourceManagerConfiguration aResMgrCfg, String aBindTo,
           ExternalResourceDescription aRes) {
     // Create a map of all bindings
-    Map<String, ExternalResourceBinding> bindings = new HashMap<String, ExternalResourceBinding>();
+    Map<String, ExternalResourceBinding> bindings = new HashMap<>();
     for (ExternalResourceBinding b : aResMgrCfg.getExternalResourceBindings()) {
       bindings.put(b.getKey(), b);
     }
 
     // Create a map of all resources
-    Map<String, ExternalResourceDescription> resources = new HashMap<String, ExternalResourceDescription>();
+    Map<String, ExternalResourceDescription> resources = new HashMap<>();
     for (ExternalResourceDescription r : aResMgrCfg.getExternalResources()) {
       resources.put(r.getName(), r);
     }
@@ -1003,9 +1071,37 @@
    *          what key to bind to.
    * @param aNestedRes
    *          the resource that should be bound.
+   * @deprecated Use {@link #bindResourceOnce(ExternalResourceDescription, String, ExternalResourceDescription)}
    */
+  @Deprecated
   public static void bindResource(ExternalResourceDescription aRes, String aBindTo,
           ExternalResourceDescription aNestedRes) {
+    bindResourceOnce(aRes, aBindTo, aNestedRes);
+  }
+  
+  /**
+   * Create a binding for the given external resource in the given resource. This method also scans
+   * the given external resource for any nested external resources and creates bindings for them as
+   * well.
+   * <p>
+   * <b>NOTE:</b> This method only works on {@link ExtendedExternalResourceDescription_impl}
+   * instances. Any {@link ExternalResourceDescription} instances created with uimaFIT use this
+   * implementation. For reasons of convenience, the method signature uses
+   * {@link ExternalResourceDescription} but will thrown an {@link IllegalArgumentException} if the
+   * wrong implementations are provided.
+   * 
+   * @param aRes
+   *          the resource to bind to
+   * @param aBindTo
+   *          what key to bind to.
+   * @param aNestedRes
+   *          the resource that should be bound.
+   * @throws IllegalArgumentException
+   *           if the given resource description is not an instance of
+   *           {@link ExtendedExternalResourceDescription_impl}.
+   */
+  public static void bindResourceOnce(ExternalResourceDescription aRes, String aBindTo,
+          ExternalResourceDescription aNestedRes) {
     if (!(aRes instanceof ExtendedExternalResourceDescription_impl)) {
       throw new IllegalArgumentException("Nested resources are only supported on instances of ["
               + ExtendedExternalResourceDescription_impl.class.getName() + "] which"
@@ -1037,11 +1133,10 @@
     // Commit everything to the resource manager configuration
     extRes.setExternalResourceBindings(bindings.values());
     extRes.setExternalResources(resources.values());
-
   }
 
   /**
-   * Helper method to recursively bind resources bound to resources.
+   * Helper method to recursively bind resources bound to other resources (a.k.a. nested resources).
    * 
    * @param aRes
    *          resource.
@@ -1094,7 +1189,15 @@
   }
 
   /**
-   * Create a new external resource binding.
+   * Create a binding for the given external resource in the resource manager configuration of the
+   * given resource. If no resource manager configuration exists yet, it will be created. This
+   * method also scans the given external resource for any nested external resources and creates
+   * bindings for them as well.
+   * <p>
+   * <b>NOTE:</b>IF you use this method with aggregate analysis engine descriptions because it will
+   * <b>not have any effects on the delegate analysis engines</b> of the aggregate. If you want to
+   * recursively bind an external resource to the delegates in an aggregate engine, use e.g.
+   * {@link #bindResource(ResourceSpecifier, String, ExternalResourceDescription)}.
    * 
    * @param aDesc
    *          the specifier to create the binding in.
@@ -1103,7 +1206,7 @@
    * @param aRes
    *          the resource that should be bound.
    */
-  public static void bindResource(ResourceCreationSpecifier aDesc, String aBindTo,
+  public static void bindResourceOnce(ResourceCreationSpecifier aDesc, String aBindTo,
           ExternalResourceDescription aRes) {
     ResourceManagerConfiguration resMgrCfg = aDesc.getResourceManagerConfiguration();
     if (resMgrCfg == null) {
@@ -1111,11 +1214,49 @@
       aDesc.setResourceManagerConfiguration(resMgrCfg);
     }
 
-    bindResource(resMgrCfg, aBindTo, aRes);
+    bindResourceOnce(resMgrCfg, aBindTo, aRes);
   }
 
   /**
-   * Create a new external resource binding.
+   * Create a binding for the given external resource in the given resource manager configuration.
+   * This method <b>does not</b> scan the given external resource for any nested external resources
+   * and <b>does not</b> create bindings for them. Use
+   * {@link #bindResourceOnce(ResourceCreationSpecifier, String, ExternalResourceDescription)} if
+   * you wish to bind nested resources as well.
+   * <p>
+   * <b>NOTE:</b>If you use this method on resource manager configurations of aggregate analysis
+   * engine descriptions because it will <b>not have any effects on the delegate analysis
+   * engines</b> of the aggregate. If you want to recursively bind an external resource to the
+   * delegates in an aggregate engine, use e.g.
+   * {@link #bindResource(ResourceSpecifier, String, ExternalResourceDescription)}.
+   * 
+   * @param aResMgrCfg
+   *          the resource manager to create the binding in.
+   * @param aBindTo
+   *          what key to bind to.
+   * @param aRes
+   *          the resource that should be bound.
+   * @deprecated Use
+   *             {@link #bindResourceOnceWithoutNested(ResourceManagerConfiguration, String, String)}.
+   */
+  @Deprecated
+  public static void bindResource(ResourceManagerConfiguration aResMgrCfg, String aBindTo,
+          String aRes) {
+    bindResourceOnceWithoutNested(aResMgrCfg, aBindTo, aRes);
+  }
+
+  /**
+   * Create a binding for the given external resource in the given resource manager configuration.
+   * This method <b>does not</b> scan the given external resource for any nested external resources
+   * and <b>does not</b> create bindings for them. Use
+   * {@link #bindResourceOnce(ResourceCreationSpecifier, String, ExternalResourceDescription)} if
+   * you wish to bind nested resources as well.
+   * <p>
+   * <b>NOTE:</b>If you use this method on resource manager configurations of aggregate analysis
+   * engine descriptions because it will <b>not have any effects on the delegate analysis
+   * engines</b> of the aggregate. If you want to recursively bind an external resource to the
+   * delegates in an aggregate engine, use e.g.
+   * {@link #bindResource(ResourceSpecifier, String, ExternalResourceDescription)}.
    * 
    * @param aResMgrCfg
    *          the resource manager to create the binding in.
@@ -1124,14 +1265,25 @@
    * @param aRes
    *          the resource that should be bound.
    */
-  public static void bindResource(ResourceManagerConfiguration aResMgrCfg, String aBindTo,
-          String aRes) {
+  public static void bindResourceOnceWithoutNested(ResourceManagerConfiguration aResMgrCfg,
+          String aBindTo, String aRes) {
     ExternalResourceBinding extResBind = createResourceBinding(aBindTo, aRes);
     aResMgrCfg.addExternalResourceBinding(extResBind);
   }
-
+  
+  
   /**
-   * Create a new external resource binding.
+   * Create a binding for the given external resource in resource manager configuration of the given
+   * resource creation specified. If no resource manager configuration exists yet, it is created.
+   * This method <b>does not</b> scan the given external resource for any nested external resources
+   * and <b>does not</b> create bindings for them. Use
+   * {@link #bindResourceOnce(ResourceCreationSpecifier, String, ExternalResourceDescription)} if
+   * you wish to bind nested resources as well.
+   * <p>
+   * <b>NOTE:</b>If you use this method on an aggregate analysis engine description, it will <b>not
+   * have any effects on the delegate analysis engines</b> of the aggregate. If you want to
+   * recursively bind an external resource to the delegates in an aggregate engine, use e.g.
+   * {@link #bindResource(ResourceSpecifier, String, ExternalResourceDescription)}.
    * 
    * @param aDesc
    *          the specifier to create the binding in.
@@ -1140,14 +1292,14 @@
    * @param aRes
    *          the resource that should be bound.
    */
-  public static void bindResource(ResourceCreationSpecifier aDesc, String aBindTo, String aRes) {
+  public static void bindResourceOnceWithoutNested(ResourceCreationSpecifier aDesc, String aBindTo, String aRes) {
     ResourceManagerConfiguration resMgrCfg = aDesc.getResourceManagerConfiguration();
     if (resMgrCfg == null) {
       resMgrCfg = new ResourceManagerConfiguration_impl();
       aDesc.setResourceManagerConfiguration(resMgrCfg);
     }
 
-    bindResource(resMgrCfg, aBindTo, aRes);
+    bindResourceOnceWithoutNested(resMgrCfg, aBindTo, aRes);
   }
 
   static String uniqueResourceKey(String aKey) {
@@ -1233,8 +1385,7 @@
    * uimaFIT internal use. This method is required by the ConfigurationParameterFactory, so it is
    * package private instead of private.
    */
-  static ResourceValueType getResourceParameterType(Object aValue)
-  {
+  static ResourceValueType getResourceParameterType(Object aValue) {
     if (aValue == null) {
       return ResourceValueType.NO_RESOURCE;
     }
@@ -1248,19 +1399,58 @@
             .iterator().next() instanceof ExternalResourceDescription);
     if (isResourcePrimitive) {
       return ResourceValueType.PRIMITIVE;
-    }
-    else if (isResourceArray) {
+    } else if (isResourceArray) {
       return ResourceValueType.ARRAY;
-    }
-    else if (isResourceCollection) {
+    } else if (isResourceCollection) {
       return ResourceValueType.COLLECTION;
-    }
-    else {
+    } else {
       return ResourceValueType.NO_RESOURCE;
     }
   }
   
   /**
+   * Create an instance of a UIMA shared/external resource class.
+   * 
+   * @param <R>
+   *          the resource type.
+   * @param resourceClass
+   *          the class implementing the resource.
+   * @param params
+   *          parameters passed to the resource when it is created. Each parameter consists of two
+   *          arguments, the first being the name and the second being the parameter value
+   * @return the resource instance.
+   * @throws ResourceInitializationException
+   *           if there was a problem instantiating the resource.
+   */
+  public static <R extends Resource> R createResource(Class<R> resourceClass,
+          Object... params) throws ResourceInitializationException {
+    return createResource(resourceClass, null, params);
+  }
+
+  /**
+   * Create an instance of a UIMA shared/external resource class.
+   * 
+   * @param <R>
+   *          the resource type.
+   * @param resourceClass
+   *          the class implementing the resource.
+   * @param resMgr
+   *          a resource manager (optional).
+   * @param params
+   *          parameters passed to the resource when it is created. Each parameter consists of two
+   *          arguments, the first being the name and the second being the parameter value
+   * @return the resource instance.
+   * @throws ResourceInitializationException
+   *           if there was a problem instantiating the resource.
+   */
+  @SuppressWarnings("unchecked")
+  public static <R extends Resource> R createResource(Class<R> resourceClass,
+          ResourceManager resMgr, Object... params) throws ResourceInitializationException {
+    ExternalResourceDescription res = createResourceDescription(resourceClass, params);
+    return (R) produceResource(resourceClass, res.getResourceSpecifier(), resMgr, emptyMap());
+  }
+  
+  /**
    * Types of external resource values.
    */
   static enum ResourceValueType {
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/factory/FlowControllerFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/FlowControllerFactory.java
index 2d08bcd..9e986a9 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/factory/FlowControllerFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/factory/FlowControllerFactory.java
@@ -21,7 +21,7 @@
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.createConfigurationData;
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.ensureParametersComeInPairs;
 import static org.apache.uima.fit.factory.ConfigurationParameterFactory.setParameters;
-import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResource;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResourceOnce;
 import static org.apache.uima.fit.factory.ExternalResourceFactory.createResourceDependencies;
 
 import java.util.Map;
@@ -130,7 +130,7 @@
     // Bind External Resources
     if (externalResources != null) {
       for (Entry<String, ExternalResourceDescription> e : externalResources.entrySet()) {
-        bindResource(desc, e.getKey(), e.getValue());
+        bindResourceOnce(desc, e.getKey(), e.getValue());
       }
     }
 
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/internal/ResourceManagerFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/internal/ResourceManagerFactory.java
index 46f9c5d..c9d9a11 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/internal/ResourceManagerFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/internal/ResourceManagerFactory.java
@@ -46,6 +46,12 @@
     return resourceManagerCreator.newResourceManager();
   }
   
+  /**
+   * Mind that returning a singleton resource manager from {@link ResourceManagerFactory} is
+   * generally a bad idea because it gets destroyed on a regular basis. For this reason, it is
+   * called {@link ResourceManagerFactory#newResourceManager()} and not
+   * {@code getResourceManager()}.
+   */
   public static synchronized void setResourceManagerCreator(
           ResourceManagerCreator resourceManagerCreator) {
     ResourceManagerFactory.resourceManagerCreator = resourceManagerCreator;
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/internal/propertyeditors/ChatsetEditor.java b/uimafit-core/src/main/java/org/apache/uima/fit/internal/propertyeditors/ChatsetEditor.java
new file mode 100644
index 0000000..0add339
--- /dev/null
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/internal/propertyeditors/ChatsetEditor.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.uima.fit.internal.propertyeditors;
+
+import java.beans.PropertyEditorSupport;
+import java.nio.charset.Charset;
+
+/**
+ * INTERNAL API
+ * 
+ * Custom property editor for {@link Charset}.
+ */
+public class ChatsetEditor extends PropertyEditorSupport {
+
+  @Override
+  public void setAsText(String text) {
+    setValue(Charset.forName(text));
+  }
+
+  @Override
+  public String getAsText() {
+    Object value = getValue();
+    return (value != null ? value.toString() : "");
+  }
+}
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/internal/propertyeditors/PropertyEditorUtil.java b/uimafit-core/src/main/java/org/apache/uima/fit/internal/propertyeditors/PropertyEditorUtil.java
index 97f13f0..88a07f5 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/internal/propertyeditors/PropertyEditorUtil.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/internal/propertyeditors/PropertyEditorUtil.java
@@ -18,10 +18,12 @@
  */
 package org.apache.uima.fit.internal.propertyeditors;
 
+import java.nio.charset.Charset;
 import java.util.LinkedList;
 import java.util.Locale;
 
 import org.springframework.beans.PropertyEditorRegistry;
+import org.springframework.beans.propertyeditors.CharsetEditor;
 import org.springframework.beans.propertyeditors.CustomCollectionEditor;
 
 /**
@@ -39,6 +41,7 @@
    * @param aRegistry a property editor registry
    */
   public static void registerUimaFITEditors(PropertyEditorRegistry aRegistry) {
+    aRegistry.registerCustomEditor(Charset.class, new CharsetEditor());
     aRegistry.registerCustomEditor(Locale.class, new LocaleEditor());
     aRegistry.registerCustomEditor(String.class, new GetAsTextStringEditor(aRegistry));
     aRegistry.registerCustomEditor(LinkedList.class, new CustomCollectionEditor(LinkedList.class));
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 d65eb99..a7f0001 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
@@ -18,13 +18,8 @@
  */
 package org.apache.uima.fit.pipeline;
 
-import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
-
 import org.apache.uima.UIMAException;
-import org.apache.uima.UIMAFramework;
-import org.apache.uima.analysis_engine.AnalysisEngine;
 import org.apache.uima.analysis_engine.AnalysisEngineDescription;
-import org.apache.uima.collection.CollectionReader;
 import org.apache.uima.collection.CollectionReaderDescription;
 import org.apache.uima.fit.internal.ResourceManagerFactory;
 import org.apache.uima.jcas.JCas;
@@ -37,58 +32,66 @@
  * and processed by the AnalysisEngine (if any).
  * </p>
  * <p>
+ * <b>NOTE:</b>If any exception is generated while using the iterator generated by
+ * {@link #iterator()}, an unchecked {@link IllegalStateException} is thrown!
+ * </p>
+ * <p>
  * External resources can be shared between the reader and the analysis engines.
  * </p>
  */
 public class JCasIterable implements Iterable<JCas> {
 
+  private final ResourceManager resMgr;
+  
   private final CollectionReaderDescription reader;
 
   private final AnalysisEngineDescription[] engines;
 
   /**
-   * Iterate over the documents loaded by the CollectionReader, running the AnalysisEngine on each
+   * Iterate over the documents loaded by the collection reader, running the analysis engines on each
    * one before yielding them. When created with this constructor, analysis engines by default
    * receive a collectionProcessComplete call when all documents have been read from the reader and
    * all components get destroyed.
    * 
    * @param aReader
-   *          The CollectionReader for loading documents.
+   *          The collection reader for loading documents.
    * @param aEngines
-   *          The AnalysisEngines for processing documents.
+   *          The analysis engines for processing documents.
    */
   public JCasIterable(final CollectionReaderDescription aReader,
           final AnalysisEngineDescription... aEngines) {
+    this(null, aReader, aEngines);
+  }
+
+  /**
+   * Iterate over the documents loaded by the collection reader, running the analysis engines on each
+   * one before yielding them. When created with this constructor, analysis engines by default
+   * receive a collectionProcessComplete call when all documents have been read from the reader and
+   * all components get destroyed.
+   * 
+   * @param aResMgr
+   *          The {@link ResourceManager} used to create the components and the JCas. If this
+   *          parameter is {@code null} then {@link ResourceManagerFactory#newResourceManager()}
+   *          will be used to obtain a resource manager. If a new resource manager was internally
+   *          created, it is destroyed at the end of the pipeline.
+   * @param aReader
+   *          The collection reader for loading documents.
+   * @param aEngines
+   *          The analysis engines for processing documents.
+   */
+  public JCasIterable(final ResourceManager aResMgr, final CollectionReaderDescription aReader,
+          final AnalysisEngineDescription... aEngines) {
+    resMgr = aResMgr;
     reader = aReader;
     engines = aEngines;
   }
 
   @Override
   public JCasIterator iterator() {
-    ResourceManager resMgr = null;
     try {
-      resMgr = ResourceManagerFactory.newResourceManager();
-      
-      // Create the components
-      CollectionReader readerInst = UIMAFramework.produceCollectionReader(reader, resMgr, null);
-
-      // Create AAE
-      AnalysisEngineDescription aaeDesc = createEngineDescription(engines);
-
-      // Instantiate AAE
-      AnalysisEngine aaeInst = UIMAFramework.produceAnalysisEngine(aaeDesc, resMgr, null);
-      
-      JCasIterator i = new JCasIterator(resMgr, readerInst, aaeInst);
-      i.setSelfComplete(true);
-      i.setSelfDestroy(true);
-      return i;
+      return new JCasIterator(resMgr, reader, engines);
     } 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 79fb434..52e76c4 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
@@ -18,7 +18,11 @@
  */
 package org.apache.uima.fit.pipeline;
 
+import static org.apache.uima.UIMAFramework.produceAnalysisEngine;
+import static org.apache.uima.UIMAFramework.produceCollectionReader;
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngine;
+import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
+import static org.apache.uima.fit.internal.ResourceManagerFactory.newResourceManager;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -26,10 +30,12 @@
 import java.util.Iterator;
 
 import org.apache.uima.analysis_engine.AnalysisEngine;
+import org.apache.uima.analysis_engine.AnalysisEngineDescription;
 import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
 import org.apache.uima.cas.CASException;
 import org.apache.uima.collection.CollectionException;
 import org.apache.uima.collection.CollectionReader;
+import org.apache.uima.collection.CollectionReaderDescription;
 import org.apache.uima.fit.component.NoOpAnnotator;
 import org.apache.uima.fit.internal.ResourceManagerFactory;
 import org.apache.uima.fit.util.LifeCycleUtil;
@@ -54,19 +60,82 @@
 
   private final JCas jCas;
 
+  private final ResourceManager resMgr;
+  
   private boolean selfComplete = false;
 
   private boolean selfDestroy = false;
   
   private boolean destroyed = false;
   
-  private ResourceManager resMgr;
-  
   private boolean resourceManagerCreatedInternally = false;
 
   /**
+   * Iterate over the documents loaded by the given reader, running the analysis engines on each
+   * one before yielding them. By default, components <b>DO get</b> life-cycle events, such as
+   * collectionProcessComplete or destroy when this constructor is used.
+   * 
+   * @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 CollectionReaderDescription aReader,
+          final AnalysisEngineDescription... aEngines)
+          throws CASException, ResourceInitializationException {
+    this(null, aReader, aEngines);
+  }
+  
+  /**
+   * Iterate over the documents loaded by the given reader, running the analysis engines on each
+   * one before yielding them. By default, components <b>DO get</b> life-cycle events, such as
+   * collectionProcessComplete or destroy when this constructor is used.
+   * 
+   * @param aResMgr
+   *          The {@link ResourceManager} used to create the components and the JCas. If this
+   *          parameter is {@code null} then {@link ResourceManagerFactory#newResourceManager()}
+   *          will be used to obtain a resource manager. If a new resource manager was internally
+   *          created, it is destroyed at the end of the pipeline (if {@link #isSelfDestroy()}).
+   * @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 CollectionReaderDescription aReader,
+          final AnalysisEngineDescription... aEngines)
+          throws CASException, ResourceInitializationException {
+    selfComplete = true;
+    selfDestroy = true;
+    
+    if (aResMgr == null) {
+      resMgr = newResourceManager();
+      resourceManagerCreatedInternally = true;
+    }
+    else {
+      resMgr = aResMgr;
+      resourceManagerCreatedInternally = false;
+    }
+    
+    collectionReader = produceCollectionReader(aReader, resMgr, null);
+
+    analysisEngines = new AnalysisEngine[] {
+        produceAnalysisEngine(createEngineDescription(aEngines), resMgr, null) };
+    
+    jCas = createCas(resMgr, collectionReader, analysisEngines);
+    collectionReader.typeSystemInit(jCas.getTypeSystem());
+  }
+  
+  /**
    * 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
+   * one before yielding them. By default, components <b>do NOT get</b> life-cycle events, such as
    * collectionProcessComplete or destroy when this constructor is used.
    * 
    * @param aReader
@@ -85,40 +154,8 @@
   }
 
   /**
-   * 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;
-
-    Collection<MetaDataObject> metaData = new ArrayList<MetaDataObject>();
-    metaData.add(aReader.getProcessingResourceMetaData());
-    for (AnalysisEngine ae : aEngines) {
-      metaData.add(ae.getProcessingResourceMetaData());
-    }
-
-    jCas = CasCreationUtils.createCas(metaData, null, aResMgr).getJCas();
-    collectionReader.typeSystemInit(jCas.getTypeSystem());
-  }
-
-  /**
    * Iterate over the documents loaded by the CollectionReader. (Uses an JCasAnnotatorAdapter to
-   * create the document JCas.) By default, components get no lifecycle events, such as
+   * create the document JCas.) By default, components <b>do NOT get</b> life-cycle events, such as
    * collectionProcessComplete or destroy when this constructor is used.
    * 
    * @param aReader
@@ -135,7 +172,57 @@
           ResourceInitializationException {
     this(aReader, createEngine(NoOpAnnotator.class, aTypeSystemDescription));
   }
+  
+  /**
+   * Iterate over the documents loaded by the CollectionReader, running the AnalysisEngine on each
+   * one before yielding them. By default, components <b>do NOT get</b> life-cycle events, such as
+   * collectionProcessComplete or destroy when this constructor is used.
+   * 
+   * @param aResMgr
+   *          The {@link ResourceManager} used to create the JCas. Should be the one also used by
+   *          the CollectionReader and the AnalysisEngines. If this parameter is {@code null} then
+   *          {@link ResourceManagerFactory#newResourceManager()} will be used to obtain a resource
+   *          manager. If a new resource manager was internally created, it is destroyed at the end
+   *          of the pipeline (if {@link #isSelfDestroy()}).
+   * @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 {
+    if (aResMgr == null) {
+      resMgr = newResourceManager();
+      resourceManagerCreatedInternally = true;
+    }
+    else {
+      resMgr = aResMgr;
+      resourceManagerCreatedInternally = false;
+    }
+    
+    collectionReader = aReader;
+    analysisEngines = aEngines;
 
+    jCas = createCas(resMgr, collectionReader, analysisEngines);
+    collectionReader.typeSystemInit(jCas.getTypeSystem());
+  }
+
+  private JCas createCas(final ResourceManager aResMgr, final CollectionReader aReader,
+          final AnalysisEngine... aEngines) throws CASException, ResourceInitializationException
+  {
+    Collection<MetaDataObject> metaData = new ArrayList<MetaDataObject>();
+    metaData.add(aReader.getProcessingResourceMetaData());
+    for (AnalysisEngine ae : aEngines) {
+      metaData.add(ae.getProcessingResourceMetaData());
+    }
+
+    return CasCreationUtils.createCas(metaData, null, aResMgr).getJCas();
+  }
+  
   @Override
   public boolean hasNext() {
     if (destroyed) {
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java b/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java
index 50beb52..b622b54 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/util/CasUtil.java
@@ -305,7 +305,7 @@
     while (it.isValid()) {
       AnnotationFS a = it.get();
       // If the offsets do not match the specified offets, we're done
-      if (a.getBegin() != aBegin && a.getEnd() != aEnd) {
+      if (a.getBegin() != aBegin || a.getEnd() != aEnd) {
         break;
       }
       it.moveToNext();
@@ -749,6 +749,9 @@
    * offsets are equal to the begin/end of the given annotation or where given 'covered' annotation
    * is properly contained within the span of the 'covering' annotation. Partially overlapping
    * annotations are not returned.
+   * <p>
+   * When querying for the annotations covering a given annotation, the given annotation itself
+   * is never returned, even if it is of the queried type.   
    * 
    * @param cas
    *          a CAS.
@@ -797,7 +800,9 @@
    * The method only returns properly covered annotations, that is annotations where the begin/end
    * offsets are equal to the 'covering' annotation or where both the begin/end are included in
    * the span of the 'covering' annotation. Partially overlapping annotations are not returned.
-   * 
+   * <p>
+   * When querying for the annotations covered by a given annotation, the given annotation itself
+   * is never returned, even if it is of the queried type.   * 
    * @param cas
    *          a CAS.
    * @param type
@@ -834,7 +839,7 @@
     
     // Keeps currently "open" annotations in a sorted order
     Deque<AnnotationFS> memory = new ArrayDeque<>();
-    Deque<AnnotationFS> memory2 = new ArrayDeque<>();
+    //Deque<AnnotationFS> memory2 = new ArrayDeque<>();
     
     // Array cursors
     int o = 0;
@@ -878,7 +883,9 @@
               c = new ArrayList<AnnotationFS>();
               index.put(covering, c);
             }
-            c.add(iFS);
+            if (iFS != covering) {
+              c.add(iFS);
+            }
           }
         }
         
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/util/FSCollectionFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/util/FSCollectionFactory.java
index 67f1d73..40e39a6 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/util/FSCollectionFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/util/FSCollectionFactory.java
@@ -100,9 +100,7 @@
     if (ts.subsumes(cas.getAnnotationType(), type)) {
       return (List) create(cas.getAnnotationIndex(type));
     } else {
-      Collection<FeatureStructure> result = create(cas.getIndexRepository().getAllIndexedFS(type));
-      return asList(result.toArray(new FeatureStructure[result.size()]));
-      // return (List) cas.select(type).asList(); - This call is still buggy in UIMA 3.0.0
+      return (List) cas.select(type).asList();
     }
   }
 
@@ -133,10 +131,7 @@
    */
   @Deprecated
   public static <T extends AnnotationFS> List<T> create(AnnotationIndex<T> aIndex) {
-    // Was: return new AnnotationIndexAdapter<T>(aIndex);
-    // return aIndex.select().asList(); // That call is still buggy in UIMA 3.0.0
-    Collection<T> result = new AnnotationIndexAdapter<T>(aIndex);
-    return (List) asList(result.toArray());
+    return aIndex.select().asList();
   }
 
   /**
@@ -164,7 +159,7 @@
    */
   @SuppressWarnings({ "unchecked", "rawtypes" })
   public static <T extends TOP> List<T> create(ArrayFS aArray, Class<T> aType) {
-    return (List) create(aArray, CasUtil.getType(aArray.getCAS(), aType));
+    return create(aArray, CasUtil.getType(aArray.getCAS(), aType));
   }
 
   /**
@@ -553,7 +548,7 @@
    * @return a new collection of all feature structures of the given type.
    */
   public static <T extends TOP> Collection<T> create(FSList<T> aList, Class<? extends T> aType) {
-    return (Collection<T>) create(aList, CasUtil.getType(aList.getCAS(), aType));
+    return create(aList, CasUtil.getType(aList.getCAS(), aType));
   }
 
   // Using TOP here because FSList is only available in the JCas.
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/util/JCasUtil.java b/uimafit-core/src/main/java/org/apache/uima/fit/util/JCasUtil.java
index c2ffb95..c17c42f 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/util/JCasUtil.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/util/JCasUtil.java
@@ -484,6 +484,9 @@
    * offsets are equal to the begin/end of the given annotation or where given 'covered' annotation
    * is properly contained within the span of the 'covering' annotation. Partially overlapping
    * annotations are not returned.
+   * <p>
+   * When querying for the annotations covering a given annotation, the given annotation itself
+   * is never returned, even if it is of the queried type.   
    * 
    * @param <T>
    *          the covered JCAs type.
@@ -514,6 +517,9 @@
    * The method only returns properly covered annotations, that is annotations where the begin/end
    * offsets are equal to the 'covering' annotation or where both the begin/end are included in
    * the span of the 'covering' annotation. Partially overlapping annotations are not returned.
+   * <p>
+   * When querying for the annotations covered by a given annotation, the given annotation itself
+   * is never returned, even if it is of the queried type.
    * 
    * @param <T>
    *          the covering JCas type.
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/component/initialize/ConfigurationParameterInitializerTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/component/initialize/ConfigurationParameterInitializerTest.java
index 5784a05..fc7d86d 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/component/initialize/ConfigurationParameterInitializerTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/component/initialize/ConfigurationParameterInitializerTest.java
@@ -18,7 +18,14 @@
  */
 package org.apache.uima.fit.component.initialize;
 
+import static java.nio.charset.StandardCharsets.US_ASCII;
+import static java.nio.charset.StandardCharsets.UTF_16;
+import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.Arrays.asList;
+import static java.util.regex.Pattern.compile;
+import static org.apache.commons.collections4.SetUtils.unmodifiableSet;
+import static org.apache.uima.fit.component.initialize.ConfigurationParameterInitializer.initialize;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -31,8 +38,14 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.charset.Charset;
 import java.util.Arrays;
+import java.util.List;
 import java.util.Locale;
+import java.util.Set;
+import java.util.regex.Pattern;
 
 import org.apache.uima.UIMAException;
 import org.apache.uima.UIMAFramework;
@@ -53,11 +66,377 @@
 import org.junit.Test;
 import org.xml.sax.SAXException;
 
-/**
- */
-
 public class ConfigurationParameterInitializerTest extends ComponentTestBase {
 
+  public static class PrimitiveTypesInjection {
+    private @ConfigurationParameter int intValue;
+    private @ConfigurationParameter boolean booleanValue;
+    private @ConfigurationParameter String stringValue;
+    private @ConfigurationParameter float floatValue;
+    private @ConfigurationParameter double doubleValue;
+  }
+  
+  @Test
+  public void thatPrimitiveTypesCanBeInjected() throws Exception {
+    PrimitiveTypesInjection target = new PrimitiveTypesInjection();
+    
+    initialize(target,
+            "intValue", 1,
+            "booleanValue", true,
+            "stringValue", "test",
+            "floatValue", 1.234f,
+            "doubleValue", 1.234d);
+    
+    assertThat(target.intValue).isEqualTo(1);
+    assertThat(target.booleanValue).isEqualTo(true);
+    assertThat(target.stringValue).isEqualTo("test");
+    assertThat(target.floatValue).isEqualTo(1.234f);
+    assertThat(target.doubleValue).isEqualTo(1.234d);
+  }
+  
+  public static class PrimitiveArraysInjection {
+    private @ConfigurationParameter int[] intValues;
+    private @ConfigurationParameter boolean[] booleanValues;
+    private @ConfigurationParameter String[] stringValues;
+    private @ConfigurationParameter float[] floatValues;
+    private @ConfigurationParameter double[] doubleValues;
+  }
+  
+  @Test
+  public void thatPrimitiveArraysCanBeInjected() throws Exception {
+    PrimitiveArraysInjection target = new PrimitiveArraysInjection();
+    
+    initialize(target,
+            "intValues", new int[] {1, 2, 3},
+            "booleanValues", new boolean[] {true, false, true},
+            "stringValues", new String[] { "test1", "test2", "test3" },
+            "floatValues", new float[] { 1.234f, 2.468f, 3.456f },
+            "doubleValues", new double[] { 1.234d, 2.468d, 3.456d });
+    
+    assertThat(target.intValues).containsExactly(1,2,3);
+    assertThat(target.booleanValues).containsExactly(true, false, true);
+    assertThat(target.stringValues).containsExactly("test1", "test2", "test3");
+    assertThat(target.floatValues).containsExactly(1.234f, 2.468f, 3.456f);
+    assertThat(target.doubleValues).containsExactly(1.234d, 2.468d, 3.456d);
+  }
+  
+  @Test
+  public void thatPrimitiveArraysCanBeInjectedAsLists() throws Exception {
+    PrimitiveArraysInjection target = new PrimitiveArraysInjection();
+    
+    initialize(target,
+            "intValues", asList(1, 2, 3),
+            "booleanValues", asList(true, false, true),
+            "stringValues", asList("test1", "test2", "test3"),
+            "floatValues", asList(1.234f, 2.468f, 3.456f),
+            "doubleValues", asList(1.234d, 2.468d, 3.456d));
+    
+    assertThat(target.intValues).containsExactly(1,2,3);
+    assertThat(target.booleanValues).containsExactly(true, false, true);
+    assertThat(target.stringValues).containsExactly("test1", "test2", "test3");
+    assertThat(target.floatValues).containsExactly(1.234f, 2.468f, 3.456f);
+    assertThat(target.doubleValues).containsExactly(1.234d, 2.468d, 3.456d);
+  }
+  
+  @Test
+  public void thatPrimitiveArraysCanBeInjectedAsValues() throws Exception {
+    PrimitiveArraysInjection target = new PrimitiveArraysInjection();
+    
+    initialize(target,
+            "intValues", 1,
+            "booleanValues", true,
+            "stringValues", "test",
+            "floatValues", 1.234f,
+            "doubleValues", 1.234d);
+    
+    assertThat(target.intValues).containsExactly(1);
+    assertThat(target.booleanValues).containsExactly(true);
+    assertThat(target.stringValues).containsExactly("test");
+    assertThat(target.floatValues).containsExactly(1.234f);
+    assertThat(target.doubleValues).containsExactly(1.234d);
+  }
+  
+  public static class FileInjection {
+    private @ConfigurationParameter File file;
+    private @ConfigurationParameter File fileFromString;
+    private @ConfigurationParameter File[] fileArray;
+    private @ConfigurationParameter File[] fileArrayFromString;
+    private @ConfigurationParameter List<File> fileList;
+    private @ConfigurationParameter List<File> fileFromStringList;
+    private @ConfigurationParameter Set<File> fileSet;
+  }
+  
+  @Test
+  public void thatFileObjectCanBeInjected() throws Exception {
+    FileInjection target = new FileInjection();
+    
+    initialize(target,
+            "file", new File("test"),
+            "fileFromString", "test",
+            "fileArray", new File[] {new File("test1"), new File("test2") },
+            "fileArrayFromString", new String[] {"test1", "test2"},
+            "fileList", asList(new File("test1"), new File("test2")),
+            "fileSet", unmodifiableSet(new File("test1"), new File("test2")),
+            "fileFromStringList", asList("test1", "test2"));
+    
+    assertThat(target.file).hasName("test");
+    assertThat(target.fileFromString).hasName("test");
+    assertThat(target.fileArray).extracting(File::getName).containsExactly("test1", "test2");
+    assertThat(target.fileArrayFromString).extracting(File::getName).containsExactly("test1",
+            "test2");
+    assertThat(target.fileList).extracting(File::getName).containsExactly("test1", "test2");
+    assertThat(target.fileFromStringList).extracting(File::getName).containsExactly(
+            "test1", "test2");
+    assertThat(target.fileSet).extracting(File::getName).containsExactlyInAnyOrder(
+            "test1", "test2");
+  }
+  
+  public static class ClassInjection {
+    private @ConfigurationParameter Class<?> clazz;
+    private @ConfigurationParameter Class<?> clazzFromString;
+    private @ConfigurationParameter Class<?>[] clazzArray;
+    private @ConfigurationParameter Class<?>[] clazzArrayFromString;
+    private @ConfigurationParameter List<Class<?>> clazzList;
+    private @ConfigurationParameter List<Class<?>> clazzListFromString;
+    private @ConfigurationParameter Set<Class<?>> clazzSet;
+  }
+  
+  @Test
+  public void thatClassObjectCanBeInjected() throws Exception {
+    ClassInjection target = new ClassInjection();
+    
+    initialize(target,
+            "clazz", Integer.class,
+            "clazzFromString", Integer.class.getName(),
+            "clazzArray", new Class<?>[] { Integer.class, Boolean.class, Float.class },
+            "clazzArrayFromString", new String[] { Integer.class.getName(), Boolean.class.getName(),
+                    Float.class.getName() },
+            "clazzList", asList(Integer.class, Boolean.class, Float.class),
+            "clazzListFromString", asList(Integer.class.getName(), Boolean.class.getName(), 
+                    Float.class.getName()),
+            "clazzSet", unmodifiableSet(Integer.class, Boolean.class, Float.class));
+    
+    assertThat(target.clazz).isEqualTo(Integer.class);
+    assertThat(target.clazzFromString).isEqualTo(Integer.class);
+    assertThat(target.clazzArray).containsExactly(Integer.class, Boolean.class, Float.class);
+    assertThat(target.clazzArrayFromString).containsExactly(Integer.class, Boolean.class,
+            Float.class);
+    assertThat(target.clazzList).containsExactly(Integer.class, Boolean.class, Float.class);
+    assertThat(target.clazzListFromString).containsExactly(Integer.class, Boolean.class,
+            Float.class);
+    assertThat(target.clazzSet).containsExactlyInAnyOrder(Integer.class, Boolean.class,
+            Float.class);
+  }
+  
+  public static class URIInjection {
+    private @ConfigurationParameter URI uri;
+    private @ConfigurationParameter URI uriFromString;
+    private @ConfigurationParameter URI[] uriArray;
+    private @ConfigurationParameter URI[] uriArrayFromString;
+    private @ConfigurationParameter List<URI> uriList;
+    private @ConfigurationParameter List<URI> uriListFromString;
+    private @ConfigurationParameter Set<URI> uriSet;
+  }
+  
+  @Test
+  public void thatURICanBeInjected() throws Exception {
+    URIInjection target = new URIInjection();
+    
+    initialize(target,
+            "uri", URI.create("file:test"),
+            "uriFromString", "file:test",
+            "uriArray", new URI[] { URI.create("file:test1"), URI.create("file:test2"), 
+                    URI.create("file:test3") },
+            "uriArrayFromString", new String[] { "file:test1", "file:test2", "file:test3" },
+            "uriList", asList(URI.create("file:test1"), URI.create("file:test2"), 
+                    URI.create("file:test3")),
+            "uriListFromString", asList("file:test1", "file:test2", "file:test3"),
+            "uriSet", unmodifiableSet(URI.create("file:test1"), URI.create("file:test2"), 
+                    URI.create("file:test3")));
+    
+    assertThat(target.uri).isEqualTo(URI.create("file:test"));
+    assertThat(target.uriFromString).isEqualTo(URI.create("file:test"));
+    assertThat(target.uriArray).containsExactly(URI.create("file:test1"), URI.create("file:test2"), 
+            URI.create("file:test3"));
+    assertThat(target.uriArrayFromString).containsExactly(URI.create("file:test1"), 
+            URI.create("file:test2"), URI.create("file:test3"));
+    assertThat(target.uriList).containsExactly(URI.create("file:test1"), URI.create("file:test2"), 
+            URI.create("file:test3"));
+    assertThat(target.uriListFromString).containsExactly(URI.create("file:test1"), 
+            URI.create("file:test2"), URI.create("file:test3"));
+    assertThat(target.uriSet).containsExactlyInAnyOrder(URI.create("file:test1"), 
+            URI.create("file:test2"), URI.create("file:test3"));
+  }
+  
+  public static class URLInjection {
+    private @ConfigurationParameter URL URL;
+    private @ConfigurationParameter URL URLFromString;
+    private @ConfigurationParameter URL[] URLArray;
+    private @ConfigurationParameter URL[] URLArrayFromString;
+    private @ConfigurationParameter List<URL> URLList;
+    private @ConfigurationParameter List<URL> URLListFromString;
+    private @ConfigurationParameter Set<URL> URLSet;
+  }
+  
+  @Test
+  public void thatURLCanBeInjected() throws Exception {
+    URLInjection target = new URLInjection();
+    
+    initialize(target,
+            "URL", new URL("file:test"),
+            "URLFromString", "file:test",
+            "URLArray", new URL[] { new URL("file:test1"), new URL("file:test2"), 
+                    new URL("file:test3") },
+            "URLArrayFromString", new String[] { "file:test1", "file:test2", "file:test3" },
+            "URLList", asList(new URL("file:test1"), new URL("file:test2"), 
+                    new URL("file:test3")),
+            "URLListFromString", asList("file:test1", "file:test2", "file:test3"),
+            "URLSet", unmodifiableSet(new URL("file:test1"), new URL("file:test2"), 
+                    new URL("file:test3")));
+    
+    assertThat(target.URL).isEqualTo(new URL("file:test"));
+    assertThat(target.URLFromString).isEqualTo(new URL("file:test"));
+    assertThat(target.URLArray).containsExactly(new URL("file:test1"), new URL("file:test2"), 
+            new URL("file:test3"));
+    assertThat(target.URLArrayFromString).containsExactly(new URL("file:test1"), 
+            new URL("file:test2"), new URL("file:test3"));
+    assertThat(target.URLList).containsExactly(new URL("file:test1"), new URL("file:test2"), 
+            new URL("file:test3"));
+    assertThat(target.URLListFromString).containsExactly(new URL("file:test1"), 
+            new URL("file:test2"), new URL("file:test3"));
+    assertThat(target.URLSet).containsExactlyInAnyOrder(new URL("file:test1"), 
+            new URL("file:test2"), new URL("file:test3"));
+  }
+  
+  public static class PatternInjection {
+    private @ConfigurationParameter Pattern pattern;
+    private @ConfigurationParameter Pattern patternFromString;
+    private @ConfigurationParameter Pattern[] patternArray;
+    private @ConfigurationParameter Pattern[] patternArrayFromString;
+    private @ConfigurationParameter List<Pattern> patternList;
+    private @ConfigurationParameter List<Pattern> patternListFromString;
+  }
+  
+  @Test
+  public void thatPatternCanBeInjected() throws Exception {
+    PatternInjection target = new PatternInjection();
+    
+    initialize(target,
+            "pattern", compile("^test$"),
+            "patternFromString", "^test$",
+            "patternArray", new Pattern[] { compile("test1"), compile("test2"), compile("test3") },
+            "patternArrayFromString", new String[] { "test1", "test2", "test3" },
+            "patternList", asList(compile("test1"), compile("test2"), compile("test3")),
+            "patternListFromString", asList("test1", "test2", "test3"));
+    
+    assertThat(target.pattern).matches(p -> p.matcher("test").matches());
+    assertThat(target.patternFromString).matches(p -> p.matcher("test").matches());
+    assertThat(target.patternArray).hasSize(3);
+    assertThat(target.patternArray[0]).matches(p -> p.matcher("test1").matches());
+    assertThat(target.patternArray[1]).matches(p -> p.matcher("test2").matches());
+    assertThat(target.patternArray[2]).matches(p -> p.matcher("test3").matches());
+    assertThat(target.patternArrayFromString).hasSize(3);
+    assertThat(target.patternArrayFromString[0]).matches(p -> p.matcher("test1").matches());
+    assertThat(target.patternArrayFromString[1]).matches(p -> p.matcher("test2").matches());
+    assertThat(target.patternArrayFromString[2]).matches(p -> p.matcher("test3").matches());
+    assertThat(target.patternList).hasSize(3);
+    assertThat(target.patternList.get(0)).matches(p -> p.matcher("test1").matches());
+    assertThat(target.patternList.get(1)).matches(p -> p.matcher("test2").matches());
+    assertThat(target.patternList.get(2)).matches(p -> p.matcher("test3").matches());
+    assertThat(target.patternList).hasSize(3);
+    assertThat(target.patternListFromString.get(0)).matches(p -> p.matcher("test1").matches());
+    assertThat(target.patternListFromString.get(1)).matches(p -> p.matcher("test2").matches());
+    assertThat(target.patternListFromString.get(2)).matches(p -> p.matcher("test3").matches());
+  }  
+
+  public static class CharsetInjection {
+    private @ConfigurationParameter Charset charset;
+    private @ConfigurationParameter String charsetAsString;
+    private @ConfigurationParameter Charset charsetFromString;
+    private @ConfigurationParameter Charset[] charsetArray;
+    private @ConfigurationParameter String[] charsetsAsStringArray;
+    private @ConfigurationParameter Charset[] charsetArrayFromString;
+    private @ConfigurationParameter List<Charset> charsetList;
+    private @ConfigurationParameter List<String> charsetAsStringList;
+    private @ConfigurationParameter List<Charset> charsetListFromString;
+    private @ConfigurationParameter Set<Charset> charsetSet;
+  }
+  
+  @Test
+  public void thatCharsetCanBeInjected() throws Exception {
+    CharsetInjection target = new CharsetInjection();
+    
+    initialize(target,
+            "charset", UTF_8,
+            "charsetAsString", UTF_8,
+            "charsetFromString", UTF_8.toString(),
+            "charsetArray", new Charset[] { UTF_8, UTF_16, US_ASCII },
+            "charsetsAsStringArray", new Charset[] { UTF_8, UTF_16, US_ASCII },
+            "charsetArrayFromString", new String[] { UTF_8.toString(), UTF_16.toString(), 
+                    US_ASCII.toString() },
+            "charsetList", asList(UTF_8, UTF_16, US_ASCII),
+            "charsetAsStringList", asList(UTF_8, UTF_16, US_ASCII),
+            "charsetListFromString", asList(UTF_8.toString(), UTF_16.toString(), 
+                    US_ASCII.toString()),
+            "charsetSet", unmodifiableSet(UTF_8, UTF_16, US_ASCII));
+    
+    assertThat(target.charset).isEqualTo(UTF_8);
+    assertThat(target.charsetAsString).isEqualTo(UTF_8.toString());
+    assertThat(target.charsetFromString).isEqualTo(UTF_8);
+    assertThat(target.charsetArray).containsExactly(UTF_8, UTF_16, US_ASCII);
+    assertThat(target.charsetsAsStringArray).containsExactly(UTF_8.toString(), UTF_16.toString(),
+            US_ASCII.toString());
+    assertThat(target.charsetArrayFromString).containsExactly(UTF_8, UTF_16, US_ASCII);
+    assertThat(target.charsetList).containsExactly(UTF_8, UTF_16, US_ASCII);
+    assertThat(target.charsetAsStringList).containsExactly(UTF_8.toString(), UTF_16.toString(),
+            US_ASCII.toString());
+    assertThat(target.charsetListFromString).containsExactly(UTF_8, UTF_16, US_ASCII);
+    assertThat(target.charsetSet).containsExactlyInAnyOrder(UTF_8, UTF_16, US_ASCII);
+  }
+
+
+  private static class CustomClassWithStringConstructor {
+    private String value;
+    
+    public CustomClassWithStringConstructor(String aValue) {
+      value = aValue;
+    }
+    
+    public String getValue() {
+      return value;
+    }
+  }
+  
+  public static class CustomClassWithStringConstructorInjection {
+    private @ConfigurationParameter CustomClassWithStringConstructor customFromString;
+    private @ConfigurationParameter CustomClassWithStringConstructor[] customArrayFromString;
+    private @ConfigurationParameter List<CustomClassWithStringConstructor> customListFromString;
+  }
+  
+  @Test
+  public void thatCustomClassWithStringConstructorObjectCanBeInjected() throws Exception {
+    CustomClassWithStringConstructorInjection target = 
+            new CustomClassWithStringConstructorInjection();
+    
+    initialize(target,
+            "customFromString", "test",
+            "customArrayFromString", new String[] { "test1", "test2", "test3" },
+            "customListFromString", asList("test1", "test2", "test3"));
+    
+    assertThat(target.customFromString)
+            .extracting(CustomClassWithStringConstructor::getValue)
+            .isEqualTo("test");
+    assertThat(target.customArrayFromString)
+            .extracting(CustomClassWithStringConstructor::getValue)
+            .containsExactly("test1", "test2", "test3");
+    assertThat(target.customListFromString)
+            .extracting(CustomClassWithStringConstructor::getValue)
+            .containsExactly("test1", "test2", "test3");
+
+  }
+  
+  // --- Legacy unit tests below ---
+
   @Test
   public void testInitialize() throws ResourceInitializationException, SecurityException {
 
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/factory/AnalysisEngineFactoryExternalResourceTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/factory/AnalysisEngineFactoryExternalResourceTest.java
index 4f6808c..5d446be 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/factory/AnalysisEngineFactoryExternalResourceTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/factory/AnalysisEngineFactoryExternalResourceTest.java
@@ -21,8 +21,9 @@
 
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngine;
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
-import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResource;
-import static org.apache.uima.fit.factory.ExternalResourceFactory.*;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResourceOnce;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.createResourceDescription;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.createSharedResourceDescription;
 import static org.junit.Assert.assertNotNull;
 
 import java.io.ByteArrayInputStream;
@@ -188,7 +189,7 @@
     ExternalResourceDescription resDesc = createResourceDescription(
             TestExternalResource2.class, TestExternalResource.PARAM_VALUE,
             TestExternalResource.EXPECTED_VALUE);
-    bindResource(resDesc, TestExternalResource2.PARAM_RESOURCE, resDesc);
+    bindResourceOnce(resDesc, TestExternalResource2.PARAM_RESOURCE, resDesc);
 
     AnalysisEngineDescription aeDesc = saveLoad(createEngineDescription(
             TestAnalysisEngineWithResource.class, TestAnalysisEngineWithResource.PARAM_RESOURCE,
@@ -208,7 +209,7 @@
     ExternalResourceDescription resDesc = createResourceDescription(
             TestExternalResource2.class, TestExternalResource.PARAM_VALUE,
             TestExternalResource.EXPECTED_VALUE);
-    bindResource(resDesc, TestExternalResource2.PARAM_RESOURCE, resDesc);
+    bindResourceOnce(resDesc, TestExternalResource2.PARAM_RESOURCE, resDesc);
 
     AnalysisEngineDescription aeDesc1 = saveLoad(createEngineDescription(
             TestAnalysisEngineWithResource.class, TestAnalysisEngineWithResource.PARAM_RESOURCE,
@@ -309,7 +310,7 @@
             "http://dumm.my", TestSharedResourceObject2.class,
             TestSharedResourceObject2.PARAM_VALUE, TestSharedResourceObject2.EXPECTED_VALUE);
 
-    bindResource(res1, TestSharedResourceObject2.PARAM_RESOURCE, res2);
+    bindResourceOnce(res1, TestSharedResourceObject2.PARAM_RESOURCE, res2);
     
     AnalysisEngineDescription aeDesc =createEngineDescription(
             TestAnalysisEngineWithSharedResourceObject.class,
@@ -329,7 +330,7 @@
     ExternalResourceDescription resDesc = createSharedResourceDescription(
             "http://dumm.my", TestSharedResourceObject2.class,
             TestSharedResourceObject.PARAM_VALUE, TestSharedResourceObject.EXPECTED_VALUE);
-    bindResource(resDesc, TestSharedResourceObject2.PARAM_RESOURCE, resDesc);
+    bindResourceOnce(resDesc, TestSharedResourceObject2.PARAM_RESOURCE, resDesc);
 
     AnalysisEngineDescription aeDesc = saveLoad(createEngineDescription(
             TestAnalysisEngineWithSharedResourceObject.class,
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/factory/AnalysisEngineFactoryTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/factory/AnalysisEngineFactoryTest.java
index efd6774..e5ee069 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/factory/AnalysisEngineFactoryTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/factory/AnalysisEngineFactoryTest.java
@@ -21,6 +21,9 @@
 import static java.util.Arrays.asList;
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngine;
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
+import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineFromPath;
+import static org.apache.uima.fit.factory.TypeSystemDescriptionFactory.createTypeSystemDescription;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -60,28 +63,30 @@
 import org.apache.uima.fit.factory.testAes.SerializationTestAnnotator;
 import org.apache.uima.fit.factory.testAes.ViewNames;
 import org.apache.uima.fit.pipeline.SimplePipeline;
+import org.apache.uima.fit.type.AnalyzedText;
 import org.apache.uima.fit.type.Sentence;
 import org.apache.uima.fit.type.Token;
 import org.apache.uima.fit.util.CasIOUtil;
 import org.apache.uima.fit.util.JCasUtil;
 import org.apache.uima.jcas.JCas;
 import org.apache.uima.jcas.tcas.Annotation;
+import org.apache.uima.pear.tools.PackageBrowser;
+import org.apache.uima.pear.tools.PackageInstaller;
+import org.apache.uima.resource.PearSpecifier;
 import org.apache.uima.resource.ResourceInitializationException;
 import org.apache.uima.resource.metadata.Capability;
 import org.apache.uima.resource.metadata.ConfigurationParameter;
 import org.apache.uima.resource.metadata.ConfigurationParameterDeclarations;
 import org.apache.uima.resource.metadata.ConfigurationParameterSettings;
+import org.apache.uima.resource.metadata.FsIndexDescription;
 import org.apache.uima.resource.metadata.ProcessingResourceMetaData;
 import org.apache.uima.resource.metadata.TypePriorities;
 import org.apache.uima.resource.metadata.TypePriorityList;
 import org.apache.uima.resource.metadata.TypeSystemDescription;
+import org.apache.uima.util.XMLInputSource;
 import org.custommonkey.xmlunit.XMLAssert;
-import org.custommonkey.xmlunit.XMLUnit;
 import org.junit.Test;
 
-/**
- */
-
 public class AnalysisEngineFactoryTest extends ComponentTestBase {
 
   @Test
@@ -99,8 +104,8 @@
 
   @Test
   public void testCreateAnalysisEngineFromPath() throws UIMAException, IOException {
-    AnalysisEngine engine = AnalysisEngineFactory
-            .createEngineFromPath("src/main/resources/org/apache/uima/fit/component/NoOpAnnotator.xml");
+    AnalysisEngine engine = createEngineFromPath(
+            "src/main/resources/org/apache/uima/fit/component/NoOpAnnotator.xml");
     assertNotNull(engine);
   }
 
@@ -562,4 +567,54 @@
     XMLAssert.assertXMLEqual(expected, actual);
 //    assertEquals(expected, actual);
   }
+  
+  @Test
+  public void testPear() throws Exception {
+    // Install PEAR package
+    PackageBrowser instPear = PackageInstaller.installPackage(
+            new File("target/test-output/AnalysisEngineFactoryTest/testPear"), 
+            new File("src/test/resources/pear/DateTime.pear"), true);
+
+    // Create analysis engine from the installed PEAR package
+    XMLInputSource in = new XMLInputSource(instPear.getComponentPearDescPath());
+    PearSpecifier specifier = UIMAFramework.getXMLParser().parsePearSpecifier(in);
+    
+    AnalysisEngine ae = createEngine(createEngineDescription(specifier));
+    
+    
+    // Create a CAS with a sample document text and process the CAS   
+    CAS cas = ae.newCAS();
+    cas.setDocumentText("Sample text to process with a date 05/29/07 and a time 9:45 AM");
+    cas.setDocumentLanguage("en");
+    ae.process(cas);
+  }
+  
+  @Test
+  public void thatCreateEngineDescriptorAutoDetectionWorks() throws Exception
+  {
+    AnalysisEngineDescription aed = createEngineDescription(NoOpAnnotator.class);
+    
+    TypeSystemDescription tsd = createTypeSystemDescription();
+    assertThat(tsd.getType(Token.class.getName()))
+        .as("Token type auto-detection")
+        .isNotNull();
+    assertThat(tsd.getType(Sentence.class.getName()))
+        .as("Sentence type auto-detection")
+        .isNotNull();
+    assertThat(tsd.getType(AnalyzedText.class.getName()))
+        .as("AnalyzedText type auto-detection")
+        .isNotNull();
+
+    TypePriorityList[] typePrioritiesLists = typePriorities.getPriorityLists();
+    assertThat(typePrioritiesLists.length).isEqualTo(1);
+    assertThat(typePrioritiesLists[0].getTypes())
+        .as("Type priorities auto-detection")
+        .containsExactly(Sentence.class.getName(), AnalyzedText.class.getName(), Token.class.getName());
+
+    FsIndexDescription[] indexes = aed.getAnalysisEngineMetaData().getFsIndexCollection().getFsIndexes();
+    assertThat(indexes.length).isEqualTo(1);
+    assertThat(indexes[0])
+        .extracting(FsIndexDescription::getLabel, FsIndexDescription::getTypeName, FsIndexDescription::getKind)
+        .containsExactly("Automatically Scanned Index", Token.class.getName(), FsIndexDescription.KIND_SORTED);
+  }
 }
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/factory/CollectionReaderFactoryTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/factory/CollectionReaderFactoryTest.java
index a43eba7..e2f1a73 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/factory/CollectionReaderFactoryTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/factory/CollectionReaderFactoryTest.java
@@ -18,6 +18,11 @@
  */
 package org.apache.uima.fit.factory;
 
+import static org.apache.uima.fit.factory.CollectionReaderFactory.createReader;
+import static org.apache.uima.fit.factory.CollectionReaderFactory.createReaderDescription;
+import static org.apache.uima.fit.factory.CollectionReaderFactory.createReaderFromPath;
+import static org.apache.uima.fit.factory.TypeSystemDescriptionFactory.createTypeSystemDescription;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
@@ -33,24 +38,26 @@
 import org.apache.uima.fit.descriptor.ResourceMetaData;
 import org.apache.uima.fit.factory.testCrs.SingleFileXReader;
 import org.apache.uima.fit.pipeline.JCasIterator;
+import org.apache.uima.fit.type.AnalyzedText;
+import org.apache.uima.fit.type.Sentence;
 import org.apache.uima.fit.type.Token;
 import org.apache.uima.fit.util.JCasUtil;
 import org.apache.uima.resource.ResourceInitializationException;
+import org.apache.uima.resource.metadata.FsIndexDescription;
+import org.apache.uima.resource.metadata.TypePriorityList;
+import org.apache.uima.resource.metadata.TypeSystemDescription;
 import org.apache.uima.util.Progress;
 import org.junit.Test;
 
-/**
- */
-
 public class CollectionReaderFactoryTest extends ComponentTestBase {
 
   @Test
   public void testCreateCollectionReader() throws UIMAException, IOException {
 
     CollectionReader reader = CollectionReaderFactory.createReader(
-            SingleFileXReader.class, typeSystemDescription, SingleFileXReader.PARAM_FILE_NAME,
-            "src/test/resources/data/docs/test.xmi", SingleFileXReader.PARAM_XML_SCHEME,
-            SingleFileXReader.XMI);
+            SingleFileXReader.class, typeSystemDescription, 
+            SingleFileXReader.PARAM_FILE_NAME, "src/test/resources/data/docs/test.xmi", 
+            SingleFileXReader.PARAM_XML_SCHEME, SingleFileXReader.XMI);
 
     JCasIterator jCasIterator = new JCasIterator(reader, typeSystemDescription);
     jCas = jCasIterator.next();
@@ -61,7 +68,7 @@
     assertEquals("A", token.getPos());
     assertEquals("all", token.getStem());
 
-    reader = CollectionReaderFactory.createReader(
+    reader = createReader(
             "org.apache.uima.fit.factory.testCrs.SingleFileXReader",
             SingleFileXReader.PARAM_FILE_NAME, "src/test/resources/data/docs/test.xmi",
             SingleFileXReader.PARAM_XML_SCHEME, SingleFileXReader.XMI);
@@ -75,7 +82,7 @@
     assertEquals(".", token.getPos());
     assertEquals(".", token.getStem());
 
-    reader = CollectionReaderFactory.createReaderFromPath(
+    reader = createReaderFromPath(
             "src/test/resources/org/apache/uima/fit/factory/testCrs/SingleFileXReader.xml",
             SingleFileXReader.PARAM_FILE_NAME, "src/test/resources/data/docs/test.xmi",
             SingleFileXReader.PARAM_XML_SCHEME, SingleFileXReader.XMI);
@@ -88,7 +95,6 @@
     assertEquals("friends", token.getCoveredText());
     assertEquals("F", token.getPos());
     assertEquals("friend", token.getStem());
-
   }
 
   @Test
@@ -103,6 +109,35 @@
   }
 
   @Test
+  public void thatCreateReaderDescriptorAutoDetectionWorks() throws Exception
+  {
+    CollectionReaderDescription aed = createReaderDescription(TestCR.class);
+    
+    TypeSystemDescription tsd = createTypeSystemDescription();
+    assertThat(tsd.getType(Token.class.getName()))
+        .as("Token type auto-detection")
+        .isNotNull();
+    assertThat(tsd.getType(Sentence.class.getName()))
+        .as("Sentence type auto-detection")
+        .isNotNull();
+    assertThat(tsd.getType(AnalyzedText.class.getName()))
+        .as("AnalyzedText type auto-detection")
+        .isNotNull();
+
+    TypePriorityList[] typePrioritiesLists = typePriorities.getPriorityLists();
+    assertThat(typePrioritiesLists.length).isEqualTo(1);
+    assertThat(typePrioritiesLists[0].getTypes())
+        .as("Type priorities auto-detection")
+        .containsExactly(Sentence.class.getName(), AnalyzedText.class.getName(), Token.class.getName());
+
+    FsIndexDescription[] indexes = aed.getCollectionReaderMetaData().getFsIndexCollection().getFsIndexes();
+    assertThat(indexes.length).isEqualTo(1);
+    assertThat(indexes[0])
+        .extracting(FsIndexDescription::getLabel, FsIndexDescription::getTypeName, FsIndexDescription::getKind)
+        .containsExactly("Automatically Scanned Index", Token.class.getName(), FsIndexDescription.KIND_SORTED);
+  }
+
+  @Test
   public void testResourceMetaData() throws Exception
   {
     CollectionReaderDescription desc = CollectionReaderFactory
@@ -117,6 +152,8 @@
     assertEquals("uimaFIT", meta.getVendor());
   }
 
+  
+  
   @ResourceMetaData(name = "dummy", version = "1.0", description = "Just a dummy", copyright = "ASL 2.0", vendor = "uimaFIT")
   private class TestCR extends CollectionReader_ImplBase {
 
@@ -124,19 +161,23 @@
       // do not instantiate
     }
 
+    @Override
     public void getNext(CAS acas) throws IOException, CollectionException {
       // Not required for test
     }
 
+    @Override
     public void close() throws IOException {
       // Not required for test
     }
 
+    @Override
     public Progress[] getProgress() {
       // Not required for test
       return null;
     }
 
+    @Override
     public boolean hasNext() throws IOException, CollectionException {
       // Not required for test
       return false;
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/factory/ExternalResourceFactoryTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/factory/ExternalResourceFactoryTest.java
index fc9af78..6bc7b2f 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/factory/ExternalResourceFactoryTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/factory/ExternalResourceFactoryTest.java
@@ -22,7 +22,13 @@
 import static java.util.Arrays.asList;
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngine;
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
-import static org.apache.uima.fit.factory.ExternalResourceFactory.*;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResource;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResourceOnceWithoutNested;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.createNamedResourceDescription;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.createResourceDescription;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.createSharedResourceDescription;
+import static org.apache.uima.fit.factory.JCasFactory.createJCas;
+import static org.apache.uima.fit.pipeline.SimplePipeline.runPipeline;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -47,7 +53,6 @@
 import org.apache.uima.analysis_engine.AnalysisEngine;
 import org.apache.uima.analysis_engine.AnalysisEngineDescription;
 import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
-import org.apache.uima.cas.CASException;
 import org.apache.uima.fit.ComponentTestBase;
 import org.apache.uima.fit.component.JCasAnnotator_ImplBase;
 import org.apache.uima.fit.component.Resource_ImplBase;
@@ -168,8 +173,8 @@
     bindResources(desc);
 
     // Bind external resources for DummyAE2 - necessary because autowiring is disabled
-    bindResource(desc, DummyAE2.RES_INJECTED_POJO1, "pojoName1");
-    bindResource(desc, DummyAE2.RES_INJECTED_POJO2, "pojoName2");
+    bindResourceOnceWithoutNested(desc, DummyAE2.RES_INJECTED_POJO1, "pojoName1");
+    bindResourceOnceWithoutNested(desc, DummyAE2.RES_INJECTED_POJO2, "pojoName2");
 
     // Create a custom resource manager that allows to inject any Java object as an external
     // dependency
@@ -352,39 +357,44 @@
   }
 
   @Test
-  public void testNestedAggregateBinding() throws CASException, ResourceInitializationException, AnalysisEngineProcessException {
-    ExternalResourceDescription resourceDescription = createSharedResourceDescription("", DummyResource.class);
-//    ExternalResourceDescription resourceDescription = createExternalResourceDescription(DummyResource.class, ""); // This works with UIMA 2.10.4 and uimaFit 2.4.0
+  public void testNestedAggregateBinding() throws Exception {
+    ExternalResourceDescription resourceDescription = createSharedResourceDescription("",
+            DummyResource.class);
+
     AggregateBuilder builder = new AggregateBuilder();
-    AnalysisEngineDescription analysisEngineDescription = AnalysisEngineFactory.createEngineDescription(ResourceDependent.class);
-    builder.add(analysisEngineDescription);
+    builder.add(createEngineDescription(ResourceDependent.class));
     AnalysisEngineDescription aggregateDescription = builder.createAggregateDescription();
+
     bindResource(aggregateDescription, DummyResource.RESOURCE_KEY, resourceDescription);
-    JCas jCas = JCasFactory.createJCas();
+
+    JCas jCas = createJCas();
     jCas.setDocumentText("Hello");
-    SimplePipeline.runPipeline(jCas, aggregateDescription);
+
+    runPipeline(jCas, aggregateDescription);
     int count = 0;
-    for(AnalyzedText annotation: JCasUtil.select(jCas, AnalyzedText.class)) {
-      Assert.assertEquals("World", annotation.getText());
+    for (AnalyzedText annotation : JCasUtil.select(jCas, AnalyzedText.class)) {
+      assertEquals("World", annotation.getText());
       count++;
     }
-    Assert.assertEquals(1, count);
+
+    assertEquals(1, count);
   }
 
   public static class DummyResource implements SharedResourceObject {
 
-      public static final String RESOURCE_KEY = "DummyResource";
+    public static final String RESOURCE_KEY = "DummyResource";
 
-      public DummyResource() { }
+    public DummyResource() {
+    }
 
-      @Override
-      public void load(DataResource aData) throws ResourceInitializationException {
+    @Override
+    public void load(DataResource aData) throws ResourceInitializationException {
+      // Nothing to do
+    }
 
-      }
-
-      public String getText() {
-          return "World";
-      }
+    public String getText() {
+      return "World";
+    }
   }
 
   public static class ResourceDependent extends JCasAnnotator_ImplBase {
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/factory/ResourceManagerFactoryTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/factory/ResourceManagerFactoryTest.java
new file mode 100644
index 0000000..ffc25ca
--- /dev/null
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/factory/ResourceManagerFactoryTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.uima.fit.factory;
+
+import static org.apache.uima.fit.factory.ExternalResourceFactory.createResource;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.apache.uima.fit.component.Resource_ImplBase;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+import org.junit.Test;
+
+public class ResourceManagerFactoryTest {
+  public static class SimpleResource extends Resource_ImplBase {
+    // Nothing to do
+  }
+  
+  @Test
+  public void thatResourceCanBeCreated() throws Exception {
+    SimpleResource sut = createResource(SimpleResource.class);
+    
+    assertThat(sut).isInstanceOf(SimpleResource.class);
+  }
+
+  public static class ResourceWithParameters extends Resource_ImplBase {
+    public @ConfigurationParameter int intValue;
+    public @ConfigurationParameter String stringValue;
+  }
+  
+  @Test
+  public void thatResourceCanBeParametrized() throws Exception {
+    ResourceWithParameters sut = createResource(ResourceWithParameters.class,
+            "intValue", "1",
+            "stringValue", "test");
+    
+    assertThat(sut).isInstanceOf(ResourceWithParameters.class);
+    assertThat(sut.intValue).isEqualTo(1);
+    assertThat(sut.stringValue).isEqualTo("test");
+  }
+}
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/factory/TypePrioritiesFactoryTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/factory/TypePrioritiesFactoryTest.java
index e50a6d7..8d2978a 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/factory/TypePrioritiesFactoryTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/factory/TypePrioritiesFactoryTest.java
@@ -28,6 +28,7 @@
 import org.apache.uima.fit.type.Token;
 import org.apache.uima.jcas.tcas.Annotation;
 import org.apache.uima.resource.metadata.TypePriorities;
+import org.apache.uima.resource.metadata.TypePriorityList;
 import org.apache.uima.util.CasCreationUtils;
 import org.junit.Test;
 
@@ -65,8 +66,10 @@
   public void testAutoDetectTypePriorities() throws Exception {
     TypePriorities prio = createTypePriorities();
 
-    assertThat(prio.getPriorityLists()).hasSize(1);
-    assertThat(prio.getPriorityLists()[0].getTypes()).containsExactly(Sentence.class.getName(),
-            Token.class.getName());
+    TypePriorityList[] typePrioritiesLists = prio.getPriorityLists();
+    assertThat(typePrioritiesLists.length).isEqualTo(1);
+    assertThat(typePrioritiesLists[0].getTypes())
+        .as("Type priorities auto-detection")
+        .containsExactly(Sentence.class.getName(), Token.class.getName());
   }
 }
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/pipeline/JCasIterableTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/pipeline/JCasIterableTest.java
index e9bb13b..f557f5f 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/pipeline/JCasIterableTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/pipeline/JCasIterableTest.java
@@ -21,12 +21,18 @@
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
 import static org.apache.uima.fit.factory.CollectionReaderFactory.createReaderDescription;
 import static org.apache.uima.fit.factory.ExternalResourceFactory.createResourceDescription;
-import static org.apache.uima.fit.pipeline.SimplePipeline.iteratePipeline;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
+import static org.apache.uima.fit.internal.ResourceManagerFactory.getResourceManagerCreator;
+import static org.apache.uima.fit.internal.ResourceManagerFactory.newResourceManager;
+import static org.apache.uima.fit.internal.ResourceManagerFactory.setResourceManagerCreator;
+import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 
 import java.io.IOException;
+import java.util.Iterator;
 
 import org.apache.uima.UimaContext;
 import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
@@ -36,44 +42,100 @@
 import org.apache.uima.fit.component.JCasCollectionReader_ImplBase;
 import org.apache.uima.fit.component.Resource_ImplBase;
 import org.apache.uima.fit.descriptor.ExternalResource;
+import org.apache.uima.fit.internal.ResourceManagerFactory;
+import org.apache.uima.fit.internal.ResourceManagerFactory.ResourceManagerCreator;
 import org.apache.uima.jcas.JCas;
 import org.apache.uima.resource.ExternalResourceDescription;
 import org.apache.uima.resource.ResourceInitializationException;
+import org.apache.uima.resource.ResourceManager;
 import org.apache.uima.util.Progress;
 import org.apache.uima.util.ProgressImpl;
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
 
 public class JCasIterableTest {
 
-  @Test
-  public void test() throws Exception {
-    for (JCas jcas : iteratePipeline(createReaderDescription(ThreeDocsReader.class),
-            createEngineDescription(GetTextAE.class))) {
-      System.out.println(jcas.getDocumentText());
-    }
+  private ResourceManagerCreator originalResourceManagerCreator;
+  
+  @Before
+  public void setup() {
+    // We need to resort to static fields here because there is no way to use Mockito's spy on the
+    // component instances internally created by UIMA.
+    ThreeDocsReader.destroyed = false;
+    GetTextAE.complete = false;
+    GetTextAE.destroyed = false;
+    GetTextAE.resource = null;
+    ThreeDocsReader.resource = null;
     
-    assertEquals("Document 3", GetTextAE.lastText);
-    assertTrue(GetTextAE.complete);
-    assertTrue(GetTextAE.destroyed);
+    originalResourceManagerCreator = getResourceManagerCreator();
+  }
+  
+  @After
+  public void teardown() {
+    setResourceManagerCreator(originalResourceManagerCreator);
+  }
+  
+  @Test
+  public void thatComponentsGetDestroyed() throws Exception {
+    consume(new JCasIterable(
+            createReaderDescription(ThreeDocsReader.class),
+            createEngineDescription(GetTextAE.class)));
+    
+    assertThat(GetTextAE.complete).isTrue();
+    assertThat(GetTextAE.destroyed).isTrue();
+    assertThat(ThreeDocsReader.destroyed).isTrue();
+    assertThat(GetTextAE.lastText).isEqualTo("Document 3");
   }
 
   @Test
-  public void testResourceSharing() throws Exception {
-    ThreeDocsReader.resource = null;
-    GetTextAE.resource = null;
-    
+  public void thatResourceCanBeShared() throws Exception {
     ExternalResourceDescription res = createResourceDescription(DummySharedResource.class);
-    for (@SuppressWarnings("unused") JCas jcas : iteratePipeline(
+    
+    consume(new JCasIterable(
             createReaderDescription(ThreeDocsReader.class, "resource", res),
-            createEngineDescription(GetTextAE.class, "resource", res))) {
+            createEngineDescription(GetTextAE.class, "resource", res)));
+    
+    assertThat(ThreeDocsReader.resource)
+          .isNotNull()
+          .isEqualTo(GetTextAE.resource);
+  }
+  
+  @Test 
+  public void thatSharedResourceManagerIsNotDestroyed() throws Exception {
+    ResourceManager resMgr = spy(newResourceManager());
+    
+    consume(new JCasIterable(resMgr,
+            createReaderDescription(ThreeDocsReader.class),
+            createEngineDescription(GetTextAE.class)));
+    
+    verify(resMgr, never()).destroy();
+  }
+
+  /**
+   * Mind that returning a singleton resource manager from {@link ResourceManagerFactory} is
+   * generally a bad idea exactly because it gets destroyed on a regular basis. For this
+   * reason, it is called {@link ResourceManagerFactory#newResourceManager()} and not 
+   * {@code getResourceManager()}.
+   */
+  @Test 
+  public void thatInternallyCreatedResourceManagerIsDestroyed() throws Exception {
+    ResourceManager resMgr = spy(newResourceManager());
+    setResourceManagerCreator(() -> resMgr); 
+    
+    consume(new JCasIterable(
+            createReaderDescription(ThreeDocsReader.class),
+            createEngineDescription(GetTextAE.class)));
+    
+    verify(resMgr, times(1)).destroy();
+  }
+
+  private static void consume(Iterable<?> aIterable)
+  {
+    Iterator<?> i = aIterable.iterator();
+    while (i.hasNext()) {
+      i.next();
     }
-    
-    assertNotNull(ThreeDocsReader.resource);
-    assertNotNull(GetTextAE.resource);
-    assertTrue(ThreeDocsReader.resource == GetTextAE.resource);
-    
-    ThreeDocsReader.resource = null;
-    GetTextAE.resource = null;
   }
  
   public static final class DummySharedResource extends Resource_ImplBase {
@@ -86,8 +148,9 @@
     private final int N = 3;
     private int n = 0;
 
-    private boolean initTypeSystemCalled = false;
-
+    public boolean initTypeSystemCalled = false;
+    public static boolean destroyed = false;
+    
     @Override
     public void typeSystemInit(TypeSystem aTypeSystem) throws ResourceInitializationException {
       initTypeSystemCalled = true;
@@ -109,6 +172,12 @@
       n++;
       aJCas.setDocumentText("Document " + n);
     }
+    
+    @Override
+    public void destroy() {
+      super.destroy();
+      destroyed = true;
+    }
   }
   
   public static final class GetTextAE extends JCasAnnotator_ImplBase {
@@ -116,9 +185,7 @@
     private static DummySharedResource resource;
     
     public static String lastText = null;
-    
     public static boolean complete = false;
-
     public static boolean destroyed = false;
 
     @Override
diff --git a/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java
index 2451930..f8c70da 100644
--- a/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java
+++ b/uimafit-core/src/test/java/org/apache/uima/fit/util/JCasUtilTest.java
@@ -788,6 +788,37 @@
     index = indexCovering(jCas, Token.class, Sentence.class);
     // Check the first token is not contained in any sentence
     assertFalse(!index.get(tokens.get(0)).isEmpty());
+    
+    // Check if the reference annotation itself is returned
+    Token extra = new Token(jCas, tokens.get(3).getBegin(), tokens.get(3).getEnd());
+    extra.addToIndexes();
+    Map<Token, List<Token>> index2 = indexCovering(jCas, Token.class, Token.class);
+    assertEquals(0, index2.get(0).size());
+    assertEquals(1, index2.get(extra).size());
+    assertEquals(tokens.get(3), index2.get(extra).iterator().next());
+  }
+
+  @Test
+  public void testIndexCovered() throws Exception {
+    String text = "Will you come home today ? \n No , tomorrow !";
+    tokenBuilder.buildTokens(jCas, text);
+
+    List<Sentence> sentences = new ArrayList<Sentence>(select(jCas, Sentence.class));
+    List<Token> tokens = new ArrayList<Token>(select(jCas, Token.class));
+    
+    Map<Sentence, List<Token>> index = indexCovered(jCas, Sentence.class, Token.class);
+    
+    // Check covered annotations are found
+    assertEquals(tokens.subList(0, 6), index.get(sentences.get(0)));
+    assertEquals(tokens.subList(6, 10), index.get(sentences.get(1)));
+    
+    // Check if the reference annotation itself is returned
+    Token extra = new Token(jCas, tokens.get(3).getBegin(), tokens.get(3).getEnd());
+    extra.addToIndexes();
+    Map<Token, List<Token>> index2 = indexCovered(jCas, Token.class, Token.class);
+    assertEquals(0, index2.get(0).size());
+    assertEquals(1, index2.get(extra).size());
+    assertEquals(tokens.get(3), index2.get(extra).iterator().next());
   }
   
   @Test
@@ -796,12 +827,13 @@
     Token a = new Token(this.jCas, 0, 1);
     Token b = new Token(this.jCas, 2, 3);
     Token bc = new Token(this.jCas, 2, 5);
-    Token c = new Token(this.jCas, 4, 5);
-    Token c1 = new Token(this.jCas, 4, 5);
-    Token d = new Token(this.jCas, 4, 7);
-    Token cd = new Token(this.jCas, 6, 7);
-    Token e = new Token(this.jCas, 8, 9);
-    for (Token token : Arrays.asList(a, b, bc, c, c1, d, cd, e)) {
+    Token c = new Token(this.jCas, 4, 6);
+    Token c1 = new Token(this.jCas, 4, 6);
+    Token d = new Token(this.jCas, 4, 5);
+    Token e = new Token(this.jCas, 4, 7);
+    Token cde = new Token(this.jCas, 6, 7);
+    Token f = new Token(this.jCas, 8, 9);
+    for (Token token : Arrays.asList(a, b, bc, c, c1, d, e, cde, e, f)) {
       token.addToIndexes();
     }
 
@@ -820,12 +852,13 @@
     Token a = new Token(this.jCas, 0, 1);
     Token b = new Token(this.jCas, 2, 3);
     Token bc = new Token(this.jCas, 2, 5);
-    Token c = new Token(this.jCas, 4, 5);
-    Token c1 = new Token(this.jCas, 4, 5);
-    Token d = new Token(this.jCas, 4, 7);
-    Token cd = new Token(this.jCas, 6, 7);
-    Token e = new Token(this.jCas, 8, 9);
-    for (Token token : Arrays.asList(a, b, bc, c, c1, d, cd, e)) {
+    Token c = new Token(this.jCas, 4, 6);
+    Token c1 = new Token(this.jCas, 4, 6);
+    Token d = new Token(this.jCas, 4, 5);
+    Token e = new Token(this.jCas, 4, 7);
+    Token cde = new Token(this.jCas, 6, 7);
+    Token f = new Token(this.jCas, 8, 9);
+    for (Token token : Arrays.asList(a, b, bc, c, c1, d, e, cde, e, f)) {
       token.addToIndexes();
     }
 
diff --git a/uimafit-core/src/test/resources/pear/DateTime.pear b/uimafit-core/src/test/resources/pear/DateTime.pear
new file mode 100644
index 0000000..77d935e
--- /dev/null
+++ b/uimafit-core/src/test/resources/pear/DateTime.pear
Binary files differ
diff --git a/uimafit-cpe/.settings/org.eclipse.jdt.core.prefs b/uimafit-cpe/.settings/org.eclipse.jdt.core.prefs
index 77c684a..1e40e06 100644
--- a/uimafit-cpe/.settings/org.eclipse.jdt.core.prefs
+++ b/uimafit-cpe/.settings/org.eclipse.jdt.core.prefs
@@ -3,8 +3,10 @@
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.compliance=1.8
 org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
 org.eclipse.jdt.core.compiler.release=disabled
 org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/uimafit-cpe/.activate-enforce-compatibility b/uimafit-cpe/marker-file-identifying-api-compatibility-check
similarity index 100%
rename from uimafit-cpe/.activate-enforce-compatibility
rename to uimafit-cpe/marker-file-identifying-api-compatibility-check
diff --git a/uimafit-cpe/pom.xml b/uimafit-cpe/pom.xml
index 1a35661..919032a 100644
--- a/uimafit-cpe/pom.xml
+++ b/uimafit-cpe/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>org.apache.uima</groupId>
     <artifactId>uimafit-parent</artifactId>
-    <version>3.0.1-SNAPSHOT</version>
+    <version>3.1.0-SNAPSHOT</version>
     <relativePath>../uimafit-parent</relativePath>
   </parent>
   <artifactId>uimafit-cpe</artifactId>
@@ -31,7 +31,7 @@
     <dependency>
       <groupId>org.apache.uima</groupId>
       <artifactId>uimafit-core</artifactId>
-      <version>3.0.1-SNAPSHOT</version>
+      <version>3.1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.apache.uima</groupId>
diff --git a/uimafit-cpe/src/main/java/org/apache/uima/fit/cpe/CpeBuilder.java b/uimafit-cpe/src/main/java/org/apache/uima/fit/cpe/CpeBuilder.java
index 1ba8ce4..a0f9c60 100644
--- a/uimafit-cpe/src/main/java/org/apache/uima/fit/cpe/CpeBuilder.java
+++ b/uimafit-cpe/src/main/java/org/apache/uima/fit/cpe/CpeBuilder.java
@@ -25,12 +25,14 @@
 import static org.apache.uima.collection.impl.metadata.cpe.CpeDescriptorFactory.produceDescriptor;
 
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.net.URL;
+import java.nio.file.Files;
 import java.util.Map;
 
+import javax.xml.transform.OutputKeys;
+
 import org.apache.uima.analysis_engine.AnalysisEngineDescription;
 import org.apache.uima.analysis_engine.metadata.FixedFlow;
 import org.apache.uima.collection.CollectionProcessingEngine;
@@ -48,6 +50,8 @@
 import org.apache.uima.resource.ResourceManager;
 import org.apache.uima.resource.ResourceSpecifier;
 import org.apache.uima.util.InvalidXMLException;
+import org.apache.uima.util.XMLSerializer;
+import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 
 /**
@@ -177,8 +181,14 @@
     File tempDesc = File.createTempFile("desc", ".xml");
     tempDesc.deleteOnExit();
 
-    try (OutputStream os = new FileOutputStream(tempDesc)) {
-      resource.toXML(os);
+    // Write the descriptor using XML 1.1 to allow a wider range of characters for parameter values
+    try (OutputStream os = Files.newOutputStream(tempDesc.toPath())) {
+      XMLSerializer sax2xml = new XMLSerializer(os, true);
+      sax2xml.setOutputProperty(OutputKeys.VERSION, "1.1");
+      ContentHandler contentHandler = sax2xml.getContentHandler();
+      contentHandler.startDocument();
+      resource.toXML(sax2xml.getContentHandler(), true);
+      contentHandler.endDocument();
     }
 
     return tempDesc;
diff --git a/uimafit-cpe/src/main/java/org/apache/uima/fit/cpe/CpePipeline.java b/uimafit-cpe/src/main/java/org/apache/uima/fit/cpe/CpePipeline.java
index 9089937..7cce0b2 100644
--- a/uimafit-cpe/src/main/java/org/apache/uima/fit/cpe/CpePipeline.java
+++ b/uimafit-cpe/src/main/java/org/apache/uima/fit/cpe/CpePipeline.java
@@ -18,6 +18,7 @@
  */
 package org.apache.uima.fit.cpe;
 
+import static java.lang.Runtime.getRuntime;
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
 
 import java.io.IOException;
@@ -36,16 +37,51 @@
 import org.apache.uima.util.InvalidXMLException;
 import org.xml.sax.SAXException;
 
-/**
- */
 public final class CpePipeline {
   private CpePipeline() {
     // No instances
   }
   
   /**
+   * Run the CollectionReader and AnalysisEngines as a multi-threaded pipeline. This call uses
+   * a number of threads equal to the number of available processors (as reported by Java, so 
+   * usually boiling down to cores) minus 1 - minimum of 1.
+   * 
+   * @param readerDesc
+   *          The CollectionReader that loads the documents into the CAS.
+   * @param descs
+   *          Primitive AnalysisEngineDescriptions that process the CAS, in order. If you have a mix
+   *          of primitive and aggregate engines, then please create the AnalysisEngines yourself
+   *          and call the other runPipeline method.
+   * @throws SAXException
+   *           if there was a XML-related problem materializing the component descriptors that are
+   *           referenced from the CPE descriptor
+   * @throws InvalidXMLException
+   *           if there was a XML-related problem materializing the component descriptors that are
+   *           referenced from the CPE descriptor
+   * @throws IOException
+   *           if there was a I/O-related problem materializing the component descriptors that are
+   *           referenced from the CPE descriptor
+   * @throws CpeDescriptorException
+   *           if there was a problem configuring the CPE descriptor
+   * @throws ResourceInitializationException
+   *           if there was a problem initializing or running the CPE.
+   * @throws AnalysisEngineProcessException
+   *           if there was a problem initializing or running the CPE.
+   */
+  public static void runPipeline(final CollectionReaderDescription readerDesc,
+          final AnalysisEngineDescription... descs)
+          throws SAXException, CpeDescriptorException, IOException, ResourceInitializationException,
+          InvalidXMLException, AnalysisEngineProcessException {
+
+    runPipeline(Math.max(1, getRuntime().availableProcessors() - 1), readerDesc, descs);
+  }
+
+  /**
    * Run the CollectionReader and AnalysisEngines as a multi-threaded pipeline.
    * 
+   * @param parallelism
+   *          Number of threads to use when running the analysis engines in the CPE.
    * @param readerDesc
    *          The CollectionReader that loads the documents into the CAS.
    * @param descs
@@ -67,8 +103,8 @@
    * @throws AnalysisEngineProcessException 
    *           if there was a problem running the CPE.
    */
-  public static void runPipeline(final CollectionReaderDescription readerDesc,
-          final AnalysisEngineDescription... descs)
+  public static void runPipeline(final int parallelism,
+          final CollectionReaderDescription readerDesc, final AnalysisEngineDescription... descs)
           throws SAXException, CpeDescriptorException, IOException, ResourceInitializationException,
           InvalidXMLException, AnalysisEngineProcessException {
     // Create AAE
diff --git a/uimafit-docbook/pom.xml b/uimafit-docbook/pom.xml
index 3dc01b1..09327c2 100644
--- a/uimafit-docbook/pom.xml
+++ b/uimafit-docbook/pom.xml
@@ -22,7 +22,7 @@
   <parent>
     <groupId>org.apache.uima</groupId>
     <artifactId>uimafit-parent</artifactId>
-    <version>3.0.1-SNAPSHOT</version>
+    <version>3.1.0-SNAPSHOT</version>
     <relativePath>../uimafit-parent</relativePath>
   </parent>
   <artifactId>uimafit-docbook</artifactId>
@@ -30,7 +30,7 @@
   <packaging>pom</packaging>
   <properties>
     <uimaScmProject>${project.artifactId}</uimaScmProject>
-        <bookNameRoot>tools.uimafit.book</bookNameRoot>
-        <maven.deploy.skip>true</maven.deploy.skip>
+    <bookNameRoot>tools.uimafit.book</bookNameRoot>
+    <maven.deploy.skip>true</maven.deploy.skip>
   </properties>
 </project>
\ No newline at end of file
diff --git a/uimafit-docbook/src/docbook/tools.uimafit.configurationparameters.xml b/uimafit-docbook/src/docbook/tools.uimafit.configurationparameters.xml
index 886f746..fd277e4 100644
--- a/uimafit-docbook/src/docbook/tools.uimafit.configurationparameters.xml
+++ b/uimafit-docbook/src/docbook/tools.uimafit.configurationparameters.xml
@@ -166,9 +166,20 @@
   }
 }</programlisting>
   <para>Fields that can be annotated with the <classname>@ConfigurationParameter</classname>
-    annotation are any array or collection types of primitive types (<type>int</type>,
-      <type>boolean</type>, <type>float</type>, <type>double</type>), any enum types, any types that
-    define a constructor accepting a single <classname>String</classname> (e.g.
-      <classname>File</classname>), as well as, fields of the types <classname>Pattern</classname>
-    and <classname>Locale</classname>.</para>
+    annotation are any array or collection types (including if they are only typed via interfaces
+    such as <type>List</type> or <type>Set</type>) of primitive types (<type>int</type>,
+      <type>boolean</type>, <type>float</type>, <type>double</type>). Enum types, as well as, 
+      fields of the types 
+      <classname>Charset</classname>, 
+      <classname>File</classname>, 
+      <classname>Locale</classname>, 
+      <classname>Pattern</classname>,
+      <classname>URI</classname>, and
+      <classname>URL</classname> can also be used. 
+      These can be initialized either using an object value (e.g. <code>StandardChartsets.UTF_8</code>)
+      or a string value (e.g. <code>"UTF-8"</code>).
+      Additionally it is possible to inject any fields of types that define a constructor accepting
+      a single <classname>String</classname>. These must be initialized from a string value.</para>
+  <para>Multi-valued parameters can be initialized from single values without having to wrap these
+      into a container.</para>
 </chapter>
diff --git a/uimafit-docbook/src/docbook/tools.uimafit.migration.xml b/uimafit-docbook/src/docbook/tools.uimafit.migration.xml
index 73ca3c5..8a3091b 100644
--- a/uimafit-docbook/src/docbook/tools.uimafit.migration.xml
+++ b/uimafit-docbook/src/docbook/tools.uimafit.migration.xml
@@ -20,6 +20,49 @@
   <title>Migration Guide</title>
   <para>This section provides helpful information on incompatible changes between versions.</para>
   <section>
+    <title>Version 3.0.x to 3.1.x</title>
+    <formalpara>
+      <title>Changes to ExternalResourceFactory</title>
+      <para>The renaming of methods in the <literal>ExternalResourceFactory</literal> had
+      unfortunately introduced another name clash between unrelated methods. To fix this
+      clash, the following methods have been renamed from <literal>bindResource</literal> to 
+      <literal>bindResourceOnce</literal>:
+        <itemizedlist>
+          <listitem><para>
+            <literal>void bindResource(ResourceCreationSpecifier aDesc, String aBindTo, ExternalResourceDescription aRes)</literal>
+            was <emphasis role="strong">removed</emphasis> and replaced by
+            <literal>void bindResourceOnce(ResourceCreationSpecifier aDesc, String aBindTo, ExternalResourceDescription aRes)</literal>
+          </para></listitem>
+          <listitem><para>
+            <literal>void bindResource(ExternalResourceDescription aRes, String aBindTo, ExternalResourceDescription aNestedRes)</literal>
+            was deprecated and replaced by
+            <literal>void bindResourceOnce(ExternalResourceDescription aRes, String aBindTo, ExternalResourceDescription aNestedRes)</literal>
+          </para></listitem>
+          <listitem><para>
+            <literal>void bindResource(ResourceManagerConfiguration aResMgrCfg, String aBindTo, ExternalResourceDescription aRes)</literal>
+            was deprecated and replaced by
+            <literal>void bindResourceOnce(ResourceManagerConfiguration aResMgrCfg, String aBindTo, ExternalResourceDescription aRes)</literal>
+          </para></listitem>
+          <listitem><para>
+            <literal>void bindResource(ResourceCreationSpecifier aDesc, String aBindTo, String aRes)</literal>
+            was <emphasis role="strong">removed</emphasis> and replaced by
+            <literal>void bindResourceOnceWithoutNested(ResourceCreationSpecifier aDesc, String aBindTo, String aRes)</literal>
+          </para></listitem>
+          <listitem><para>
+            <literal>void bindResource(ResourceManagerConfiguration aResMgrCfg, String aBindTo, String aRes)</literal>
+            was deprecated and replaced by
+            <literal>void bindResourceOnceWithoutNested(ResourceManagerConfiguration aResMgrCfg, String aBindTo, String aRes)</literal>
+          </para></listitem>
+          <listitem><para>
+            <literal>void bindResource(ResourceSpecifier aDesc, String aKey, String aUrl)</literal>
+            was deprecated and replaced by
+            <literal>void bindResourceUsingUrl(ResourceSpecifier aDesc, String aKey, String aUrl)</literal>
+          </para></listitem>
+        </itemizedlist>
+      </para>
+    </formalpara>
+  </section>
+  <section>
     <title>Version 2.x to 3.x</title>
     <formalpara>
       <title>Legacy support module removed</title>
@@ -55,6 +98,21 @@
       file included in the release.</para>
     </formalpara>
     <formalpara>
+      <title>Changes to ExternalResourceFactory</title>
+      <para>Most methods in the <literal>ExternalResourceFactory</literal> have seen changes to 
+      their names and signature to avoid problematic ambiguities as well as to be shorter. In 
+      general, the <literal>External</literal> component of the method names was either
+      removed or replaced. So most methods called <literal>createExternalResourceDescription</literal>
+      are now called <literal>createResourceDescription</literal>. However, some have also been 
+      given a more specific name and/or a slightly different order of parameters. For example, this
+      method</para>
+      <programlisting>public static ExternalResourceDescription createExternalResourceDescription(
+  Class&lt;? extends SharedResourceObject&gt; aInterface, String aUrl, Object... aParams)</programlisting>
+      <para>was changed to</para>
+      <programlisting>public static ExternalResourceDescription createSharedResourceDescription(
+  String aUrl, Class&lt;? extends SharedResourceObject&gt; aInterface, Object... aParams)</programlisting>
+    </formalpara>
+    <formalpara>
       <title>Changes to logging</title>
       <para>UIMA v3 has is using SLF4J. As a consequence, the <literal>ExtendedLogger</literal>
       which uimaFIT had returned on calls to <literal>getLogger()</literal> has been removed
@@ -71,6 +129,17 @@
     </formalpara>
   </section>
   <section>
+    <title>Version 2.3.0 to 2.4.0</title>
+    <formalpara>
+      <title>Version requirements</title>
+      <para>Depends on UIMA 2.10.2, Spring Framework 3.2.16 and Java 7.</para>
+    </formalpara>
+    <formalpara>
+      <para>Mind the updated version requirements. There should be no other potentially problematic
+      changes in this upgrade.</para>
+    </formalpara>
+  </section>
+  <section>
     <title>Version 2.2.0 to 2.3.0</title>
     <formalpara>
       <title>CasIOUtil deprecated</title>
diff --git a/uimafit-examples/.settings/org.eclipse.jdt.core.prefs b/uimafit-examples/.settings/org.eclipse.jdt.core.prefs
index d759025..225e1bc 100644
--- a/uimafit-examples/.settings/org.eclipse.jdt.core.prefs
+++ b/uimafit-examples/.settings/org.eclipse.jdt.core.prefs
@@ -1,7 +1,9 @@
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
 org.eclipse.jdt.core.compiler.release=disabled
 org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/uimafit-examples/pom.xml b/uimafit-examples/pom.xml
index 5a04f3f..86d6175 100644
--- a/uimafit-examples/pom.xml
+++ b/uimafit-examples/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.apache.uima</groupId>
     <artifactId>uimafit-parent</artifactId>
-    <version>3.0.1-SNAPSHOT</version>
+    <version>3.1.0-SNAPSHOT</version>
     <relativePath>../uimafit-parent</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
@@ -33,7 +33,7 @@
     <dependency>
       <groupId>org.apache.uima</groupId>
       <artifactId>uimafit-core</artifactId>
-      <version>3.0.1-SNAPSHOT</version>
+      <version>3.1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.apache.uima</groupId>
@@ -61,46 +61,46 @@
     </license>
   </licenses>
   <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.uima</groupId>
-                <artifactId>jcasgen-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <phase>generate-resources</phase>
-                        <goals>
-                            <goal>generate</goal>
-                        </goals>
-                        <configuration>
-                            <typeSystemIncludes>
-                                <typeSystemInclude>src/main/resources/org/apache/uima/fit/examples/TypeSystem.xml</typeSystemInclude>
-                            </typeSystemIncludes>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <!--
-                    This plug-in adds the jcasgen generated source code folder as a project
-                    source folder
-                -->
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>add-test-source</id>
-                        <phase>process-resources</phase>
-                        <goals>
-                            <goal>add-source</goal>
-                        </goals>
-                        <configuration>
-                            <sources>
-                                <source>${project.build.directory}/generated-sources/jcasgen</source>
-                            </sources>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.uima</groupId>
+        <artifactId>jcasgen-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>generate-resources</phase>
+            <goals>
+              <goal>generate</goal>
+            </goals>
+            <configuration>
+              <typeSystemIncludes>
+                <typeSystemInclude>src/main/resources/org/apache/uima/fit/examples/TypeSystem.xml</typeSystemInclude>
+              </typeSystemIncludes>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <!--
+            This plug-in adds the jcasgen generated source code folder as a project
+            source folder
+        -->
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-test-source</id>
+            <phase>process-resources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${project.build.directory}/generated-sources/jcasgen</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-surefire-plugin</artifactId>
diff --git a/uimafit-maven-plugin/.settings/org.eclipse.jdt.core.prefs b/uimafit-maven-plugin/.settings/org.eclipse.jdt.core.prefs
index d759025..225e1bc 100644
--- a/uimafit-maven-plugin/.settings/org.eclipse.jdt.core.prefs
+++ b/uimafit-maven-plugin/.settings/org.eclipse.jdt.core.prefs
@@ -1,7 +1,9 @@
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
 org.eclipse.jdt.core.compiler.release=disabled
 org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/uimafit-maven-plugin/pom.xml b/uimafit-maven-plugin/pom.xml
index 0343098..5a40efe 100644
--- a/uimafit-maven-plugin/pom.xml
+++ b/uimafit-maven-plugin/pom.xml
@@ -22,12 +22,14 @@
   <parent>
     <groupId>org.apache.uima</groupId>
     <artifactId>uimafit-parent</artifactId>
-    <version>3.0.1-SNAPSHOT</version>
+    <version>3.1.0-SNAPSHOT</version>
     <relativePath>../uimafit-parent</relativePath>
   </parent>
   <artifactId>uimafit-maven-plugin</artifactId>
   <name>Apache UIMA uimaFIT - Maven Plugin</name>
   <packaging>maven-plugin</packaging>
+  <url>${uimaWebsiteUrl}</url>
+  <inceptionYear>2012</inceptionYear>
   <licenses>
     <license>
       <name>Apache License, Version 2.0</name>
@@ -56,7 +58,7 @@
     <dependency>
       <groupId>org.apache.uima</groupId>
       <artifactId>uimafit-core</artifactId>
-      <version>3.0.1-SNAPSHOT</version>
+      <version>3.1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.javassist</groupId>
@@ -167,7 +169,24 @@
         </configuration>
       </plugin>
     </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <executions>
+            <execution>
+              <id>default-cli</id>
+              <configuration>
+                <excludes combine.children="append">
+                  <!-- These configuration files cannot bear a license header -->
+                  <exclude>src/it/with-typesystem-in-descriptors/src/main/resources/META-INF/org.apache.uima.fit/types.txt</exclude>
+                </excludes>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+      </plugins>
+    </pluginManagement>
   </build>
-  <url>${uimaWebsiteUrl}</url>
-  <inceptionYear>2012</inceptionYear>
 </project>
\ No newline at end of file
diff --git a/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/pom.xml b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/pom.xml
new file mode 100644
index 0000000..ad4408d
--- /dev/null
+++ b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/pom.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one
+  ~ or more contributor license agreements. See the NOTICE file
+  ~ distributed with this work for additional information
+  ~ regarding copyright ownership. The ASF licenses this file
+  ~ to you under the Apache License, Version 2.0 (the
+  ~ "License"); you may not use this file except in compliance
+  ~ with the License. You may obtain a copy of the License at
+  ~
+  ~ http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing,
+  ~ software distributed under the License is distributed on an
+  ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  ~ KIND, either express or implied. See the License for the
+  ~ specific language governing permissions and limitations
+  ~ under the License.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.apache.uima.fit.maven.it</groupId>
+  <artifactId>default</artifactId>
+  <version>1.0-SNAPSHOT</version>
+
+  <name>Test for default configuration</name>
+
+  <properties>
+    <maven.compiler.source>1.7</maven.compiler.source>
+    <maven.compiler.target>1.7</maven.compiler.target>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.uima</groupId>
+      <artifactId>uimafit-core</artifactId>
+      <version>@pom.version@</version>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.uima</groupId>
+        <artifactId>uimafit-maven-plugin</artifactId>
+        <version>@pom.version@</version>
+        <configuration>
+          <componentVendor>Apache UIMA</componentVendor>
+          <componentCopyright>Copyright by the respective authors.</componentCopyright>
+        </configuration>
+        <executions>
+          <execution>
+            <id>default</id>
+            <phase>process-classes</phase>
+            <goals>
+              <goal>enhance</goal>
+              <goal>generate</goal>
+            </goals>
+            <configuration>
+              <addTypeSystemDescriptions>EMBEDDED</addTypeSystemDescriptions>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/reference/TestAnnotator.xml b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/reference/TestAnnotator.xml
new file mode 100644
index 0000000..7d65136
--- /dev/null
+++ b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/reference/TestAnnotator.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+	~ Licensed to the Apache Software Foundation (ASF) under one
+	~ or more contributor license agreements. See the NOTICE file
+	~ distributed with this work for additional information
+	~ regarding copyright ownership. The ASF licenses this file
+	~ to you under the Apache License, Version 2.0 (the
+	~ "License"); you may not use this file except in compliance
+	~ with the License. You may obtain a copy of the License at
+	~
+	~ http://www.apache.org/licenses/LICENSE-2.0
+	~
+	~ Unless required by applicable law or agreed to in writing,
+	~ software distributed under the License is distributed on an
+	~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+	~ KIND, either express or implied. See the License for the
+	~ specific language governing permissions and limitations
+	~ under the License.
+-->
+<analysisEngineDescription xmlns="http://uima.apache.org/resourceSpecifier">
+    <frameworkImplementation>org.apache.uima.java</frameworkImplementation>
+    <primitive>true</primitive>
+    <annotatorImplementationName>TestAnnotator</annotatorImplementationName>
+    <analysisEngineMetaData>
+        <name>TestAnnotator</name>
+        <version>1.0-SNAPSHOT</version>
+        <vendor>Apache UIMA</vendor>
+        <copyright>Copyright by the respective authors.</copyright>
+        <configurationParameters>
+            <configurationParameter>
+                <name>value1</name>
+                <description>Parameter value 1.</description>
+                <type>String</type>
+                <multiValued>false</multiValued>
+                <mandatory>true</mandatory>
+            </configurationParameter>
+            <configurationParameter>
+                <name>valueParent1</name>
+                <description>Parameter value 1 in parent.</description>
+                <type>String</type>
+                <multiValued>false</multiValued>
+                <mandatory>true</mandatory>
+            </configurationParameter>
+        </configurationParameters>
+        <configurationParameterSettings>
+            <nameValuePair>
+                <name>valueParent1</name>
+                <value>
+                    <string>defaultValue</string>
+                </value>
+            </nameValuePair>
+        </configurationParameterSettings>
+        <typeSystemDescription>
+            <types>
+                <typeDescription>
+                    <name>org.apache.uima.fit.type.Sentence</name>
+                    <description/>
+                    <supertypeName>uima.tcas.Annotation</supertypeName>
+                </typeDescription>
+                <typeDescription>
+                    <name>org.apache.uima.fit.type.Token</name>
+                    <description/>
+                    <supertypeName>uima.tcas.Annotation</supertypeName>
+                    <features>
+                        <featureDescription>
+                            <name>pos</name>
+                            <description/>
+                            <rangeTypeName>uima.cas.String</rangeTypeName>
+                        </featureDescription>
+                        <featureDescription>
+                            <name>stem</name>
+                            <description/>
+                            <rangeTypeName>uima.cas.String</rangeTypeName>
+                        </featureDescription>
+                    </features>
+                </typeDescription>
+            </types>
+        </typeSystemDescription>
+        <typePriorities/>
+        <fsIndexCollection/>
+        <capabilities/>
+        <operationalProperties>
+            <modifiesCas>true</modifiesCas>
+            <multipleDeploymentAllowed>true</multipleDeploymentAllowed>
+            <outputsNewCASes>false</outputsNewCASes>
+        </operationalProperties>
+    </analysisEngineMetaData>
+    <externalResourceDependencies>
+        <externalResourceDependency>
+            <key>res</key>
+            <description>Documentation for resource</description>
+            <interfaceName>org.apache.uima.resource.Resource</interfaceName>
+            <optional>false</optional>
+        </externalResourceDependency>
+    </externalResourceDependencies>
+</analysisEngineDescription>
diff --git a/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/java/AbstractAnnotator.java b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/java/AbstractAnnotator.java
new file mode 100644
index 0000000..c510197
--- /dev/null
+++ b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/java/AbstractAnnotator.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import org.apache.uima.analysis_component.JCasAnnotator_ImplBase;
+import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+import org.apache.uima.jcas.JCas;
+
+public abstract class AbstractAnnotator extends JCasAnnotator_ImplBase {
+
+  /**
+   * Parameter value 1 in parent.
+   */
+  public static final String PARAM_VALUE_PARENT_1 = "valueParent1";
+
+  @ConfigurationParameter(name = PARAM_VALUE_PARENT_1, mandatory = true, defaultValue = "defaultValue")
+  private String valueParent1;
+}
diff --git a/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/java/TestAnnotator.java b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/java/TestAnnotator.java
new file mode 100644
index 0000000..8f35759
--- /dev/null
+++ b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/java/TestAnnotator.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import org.apache.uima.analysis_component.JCasAnnotator_ImplBase;
+import org.apache.uima.analysis_engine.AnalysisEngineProcessException;
+import org.apache.uima.fit.descriptor.ConfigurationParameter;
+import org.apache.uima.fit.descriptor.ExternalResource;
+import org.apache.uima.jcas.JCas;
+import org.apache.uima.resource.Resource;
+
+public class TestAnnotator extends AbstractAnnotator {
+
+  /**
+   * Parameter value 1.
+   */
+  public static final String PARAM_VALUE_1 = "value1";
+  @ConfigurationParameter(name = PARAM_VALUE_1, mandatory=true)
+  private String value1;
+
+  /**
+   * Documentation for resource
+   */
+  public static final String RES_KEY = "res";
+  @ExternalResource(key = RES_KEY)
+  private Resource res;
+
+  @Override
+  public void process(JCas aJCas) throws AnalysisEngineProcessException {
+    // Nothing to do
+  }
+}
diff --git a/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/resources/META-INF/org.apache.uima.fit/types.txt b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/resources/META-INF/org.apache.uima.fit/types.txt
new file mode 100644
index 0000000..1c96dc9
--- /dev/null
+++ b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/resources/META-INF/org.apache.uima.fit/types.txt
@@ -0,0 +1 @@
+classpath*:org/apache/uima/fit/type/**/*.xml
diff --git a/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/resources/org/apache/uima/fit/type/Sentence.xml b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/resources/org/apache/uima/fit/type/Sentence.xml
new file mode 100644
index 0000000..a69681d
--- /dev/null
+++ b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/resources/org/apache/uima/fit/type/Sentence.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+	Licensed to the Apache Software Foundation (ASF) under one
+	or more contributor license agreements. See the NOTICE file
+	distributed with this work for additional information
+	regarding copyright ownership. The ASF licenses this file
+	to you under the Apache License, Version 2.0 (the
+	"License"); you may not use this file except in compliance
+	with the License. You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing,
+	software distributed under the License is distributed on an
+	"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+	KIND, either express or implied. See the License for the
+	specific language governing permissions and limitations
+	under the License.
+-->
+<typeSystemDescription xmlns="http://uima.apache.org/resourceSpecifier">
+  <name>Sentence</name>
+  <description></description>
+  <version>1.0</version>
+  <vendor/>
+  <types>
+    <typeDescription>
+      <name>org.apache.uima.fit.type.Sentence</name>
+      <description/>
+      <supertypeName>uima.tcas.Annotation</supertypeName>
+    </typeDescription>
+  </types>
+</typeSystemDescription>
diff --git a/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/resources/org/apache/uima/fit/type/Token.xml b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/resources/org/apache/uima/fit/type/Token.xml
new file mode 100644
index 0000000..629ae03
--- /dev/null
+++ b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/src/main/resources/org/apache/uima/fit/type/Token.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+	Licensed to the Apache Software Foundation (ASF) under one
+	or more contributor license agreements. See the NOTICE file
+	distributed with this work for additional information
+	regarding copyright ownership. The ASF licenses this file
+	to you under the Apache License, Version 2.0 (the
+	"License"); you may not use this file except in compliance
+	with the License. You may obtain a copy of the License at
+
+	http://www.apache.org/licenses/LICENSE-2.0
+
+	Unless required by applicable law or agreed to in writing,
+	software distributed under the License is distributed on an
+	"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+	KIND, either express or implied. See the License for the
+	specific language governing permissions and limitations
+	under the License.
+-->
+<typeSystemDescription xmlns="http://uima.apache.org/resourceSpecifier">
+  <name>Token</name>
+  <description></description>
+  <version>1.0</version>
+  <vendor/>
+  <types>
+    <typeDescription>
+      <name>org.apache.uima.fit.type.Token</name>
+      <description/>
+      <supertypeName>uima.tcas.Annotation</supertypeName>
+      <features>
+        <featureDescription>
+          <name>pos</name>
+          <description/>
+          <rangeTypeName>uima.cas.String</rangeTypeName>
+        </featureDescription>
+        <featureDescription>
+          <name>stem</name>
+          <description/>
+          <rangeTypeName>uima.cas.String</rangeTypeName>
+        </featureDescription>
+      </features>
+    </typeDescription>
+  </types>
+</typeSystemDescription>
diff --git a/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/verify.bsh b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/verify.bsh
new file mode 100644
index 0000000..34d0f2f
--- /dev/null
+++ b/uimafit-maven-plugin/src/it/with-typesystem-in-descriptors/verify.bsh
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.*;
+import java.util.*;
+import java.util.regex.*;
+import org.apache.commons.io.*;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+
+try
+{
+	String reference = IOUtils.toString(new File(basedir, 
+		"reference/TestAnnotator.xml").toURI().toURL());
+	String actual = IOUtils.toString(new File(basedir, 
+		"target/classes/TestAnnotator.xml").toURI().toURL());
+
+    // In a local build, I get indented XML but on the Apache Jenkins I get non-indented XML. This
+    // settings tells XMLUnit to ignore this difference in whitespace - rec 2013-02-16
+	XMLUnit.setIgnoreWhitespace(true);
+	Diff diff = XMLUnit.compareXML(reference, actual);
+
+	if (!diff.identical()) {
+        System.out.println("Actual descriptor does not match expected descriptor: " + diff);
+        return false;
+	}	
+}
+catch( Throwable t )
+{
+    t.printStackTrace();
+    return false;
+}
+
+return true;
diff --git a/uimafit-maven-plugin/src/main/java/org/apache/uima/fit/maven/GenerateDescriptorsMojo.java b/uimafit-maven-plugin/src/main/java/org/apache/uima/fit/maven/GenerateDescriptorsMojo.java
index feb8458..797eae8 100644
--- a/uimafit-maven-plugin/src/main/java/org/apache/uima/fit/maven/GenerateDescriptorsMojo.java
+++ b/uimafit-maven-plugin/src/main/java/org/apache/uima/fit/maven/GenerateDescriptorsMojo.java
@@ -23,7 +23,6 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.lang.reflect.Modifier;
-
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.exception.ExceptionUtils;
 import org.apache.maven.plugin.AbstractMojo;
@@ -34,12 +33,17 @@
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
+import org.apache.uima.analysis_engine.AnalysisEngineDescription;
+import org.apache.uima.collection.CollectionReaderDescription;
 import org.apache.uima.fit.factory.AnalysisEngineFactory;
 import org.apache.uima.fit.factory.CollectionReaderFactory;
+import org.apache.uima.fit.factory.TypeSystemDescriptionFactory;
 import org.apache.uima.fit.maven.util.Util;
 import org.apache.uima.resource.ResourceCreationSpecifier;
 import org.apache.uima.resource.ResourceInitializationException;
 import org.apache.uima.resource.ResourceSpecifier;
+import org.apache.uima.resource.metadata.ProcessingResourceMetaData;
+import org.apache.uima.resource.metadata.TypeSystemDescription;
 import org.codehaus.plexus.util.FileUtils;
 import org.sonatype.plexus.build.incremental.BuildContext;
 import org.xml.sax.SAXException;
@@ -60,7 +64,7 @@
   /**
    * Path where the generated resources are written.
    */
-  @Parameter(defaultValue="${project.build.directory}/classes", required=true)
+  @Parameter(defaultValue = "${project.build.directory}/classes", required = true)
   private File outputDirectory;
   
   /**
@@ -75,6 +79,17 @@
   @Parameter(defaultValue = "${project.build.sourceEncoding}", required = true)
   private String encoding;
 
+  enum TypeSystemSerialization {
+    NONE, EMBEDDED
+  }
+
+  /**
+   * Mode of adding type systems found on the classpath via the uimaFIT detection mechanism at
+   * compile time to the generated descriptor. By default, no type systems are added.
+   */
+  @Parameter(defaultValue = "NONE")
+  private TypeSystemSerialization addTypeSystemDescriptions;
+
   @Override
   public void execute() throws MojoExecutionException {
     // add the generated sources to the build
@@ -106,24 +121,39 @@
         }
         
         ResourceCreationSpecifier desc = null;
+        ProcessingResourceMetaData metadata = null;
         switch (Util.getType(componentLoader, clazz)) {
           case ANALYSIS_ENGINE:
-            desc = AnalysisEngineFactory.createEngineDescription(clazz);
+            AnalysisEngineDescription aeDesc = AnalysisEngineFactory.createEngineDescription(clazz);
+            metadata = aeDesc.getAnalysisEngineMetaData();
+            desc = aeDesc;
             break;
           case COLLECTION_READER:
-            desc = CollectionReaderFactory.createReaderDescription(clazz);
+            CollectionReaderDescription crDesc = CollectionReaderFactory
+                    .createReaderDescription(clazz);
+            metadata = crDesc.getCollectionReaderMetaData();
+            desc = crDesc;
           default:
             // Do nothing
         }
 
         if (desc != null) {
-          File out = new File(outputDirectory, clazzPath+".xml");
+          switch (addTypeSystemDescriptions) {
+            case EMBEDDED:
+              embedTypeSystems(metadata);
+              break;
+            case NONE: // fall-through
+            default:
+              // Do nothing
+          }
+
+          File out = new File(outputDirectory, clazzPath + ".xml");
           out.getParentFile().mkdirs();
           toXML(desc, out.getPath());
           countGenerated++;
           
           // Remember component
-          componentsManifest.append("classpath*:").append(clazzPath+".xml").append('\n');
+          componentsManifest.append("classpath*:").append(clazzPath + ".xml").append('\n');
         }
       } catch (SAXException e) {
         getLog().warn("Cannot serialize descriptor for [" + clazzName + "]", e);
@@ -153,6 +183,19 @@
     }
   }
 
+  private void embedTypeSystems(ProcessingResourceMetaData metadata)
+          throws ResourceInitializationException {
+    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+    Thread.currentThread().setContextClassLoader(componentLoader);
+    try {
+      TypeSystemDescriptionFactory.forceTypeDescriptorsScan();
+      TypeSystemDescription tsDesc = TypeSystemDescriptionFactory.createTypeSystemDescription();
+      metadata.setTypeSystem(tsDesc);
+    } finally {
+      Thread.currentThread().setContextClassLoader(classLoader);
+    }
+  }
+
   /**
    * Save descriptor XML to file system.
    */
diff --git a/uimafit-parent/pom.xml b/uimafit-parent/pom.xml
index d4992bd..859d83e 100644
--- a/uimafit-parent/pom.xml
+++ b/uimafit-parent/pom.xml
@@ -23,21 +23,23 @@
     <groupId>org.apache.uima</groupId>
     <artifactId>parent-pom</artifactId>
     <relativePath />
-    <version>12</version>
+    <version>13</version>
   </parent>
   <artifactId>uimafit-parent</artifactId>
-  <version>3.0.1-SNAPSHOT</version>
+  <version>3.1.0-SNAPSHOT</version>
   <packaging>pom</packaging>
   <name>Apache UIMA uimaFIT - Parent</name>
   <url>${uimaWebsiteUrl}</url>
   <inceptionYear>2012</inceptionYear>
   <properties>
-    <spring.version>4.3.22.RELEASE</spring.version>
-    <uima.version>3.0.2</uima.version>
+    <spring.version>4.3.26.RELEASE</spring.version>
+    <uima.version>3.1.1</uima.version>
     <slf4j.version>1.7.26</slf4j.version>
     <maven.compiler.source>1.8</maven.compiler.source>
     <maven.compiler.target>1.8</maven.compiler.target>
-    <compat.previous.version>2.4.0</compat.previous.version>
+    <api_check_oldVersion>2.4.0</api_check_oldVersion>
+    
+    <japicmp.postAnalysisScript>${project.basedir}/../uimafit-parent/src/main/groovy/api-report.groovy</japicmp.postAnalysisScript>
   </properties>
   <repositories>
     <!--
@@ -94,7 +96,12 @@
       <dependency>
         <groupId>org.assertj</groupId>
         <artifactId>assertj-core</artifactId>
-        <version>3.12.2</version>
+        <version>3.15.0</version>
+      </dependency>
+      <dependency>
+        <groupId>org.mockito</groupId>
+        <artifactId>mockito-core</artifactId>
+        <version>3.2.4</version>
       </dependency>
       <dependency>
         <groupId>org.apache.commons</groupId>
@@ -238,14 +245,11 @@
           <groupId>org.apache.rat</groupId>
           <artifactId>apache-rat-plugin</artifactId>
           <version>0.13</version>
-          <configuration>
-            <consoleOutput>true</consoleOutput>
-          </configuration>
           <executions>
             <execution>
               <id>default-cli</id>
               <configuration>
-                <excludes>
+                <excludes combine.children="append">
                   <!-- Plain documentation -->
                   <exclude>README*</exclude>
                   <!-- GitHub templates -->
@@ -327,6 +331,42 @@
                     <ignore />
                   </action>
                 </pluginExecution>
+                <!-- *********************************************** -->
+                <!-- The Maven Dev Connector for Eclipse m2e is no   -->
+                <!-- longer maintained. We copy the relevant part    --> 
+                <!-- of the lifecycle mapping for the                -->
+                <!-- maven-plugin-plugin here.                       -->
+                <!--                                                 -->
+                <!-- See https://github.com/ifedorenko/com.ifedorenko.m2e.mavendev/blob/master/com.ifedorenko.m2e.mavendev/lifecycle-mapping-metadata.xml -->
+                <!-- *********************************************** -->
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-plugin-plugin</artifactId>
+                    <versionRange>[3.5.2,)</versionRange>
+                    <goals>
+                      <goal>descriptor</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <execute>
+                      <runOnIncremental>false</runOnIncremental>
+                    </execute>
+                  </action>
+                </pluginExecution>
+                <pluginExecution>
+                  <pluginExecutionFilter>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-plugin-plugin</artifactId>
+                    <versionRange>[3.5.2,)</versionRange>
+                    <goals>
+                      <goal>helpmojo</goal>
+                    </goals>
+                  </pluginExecutionFilter>
+                  <action>
+                    <ignore />
+                  </action>
+                </pluginExecution>
               </pluginExecutions>
             </lifecycleMappingMetadata>
           </configuration>
@@ -334,117 +374,28 @@
       </plugins>
     </pluginManagement>
   </build>
+  
   <profiles>
     <profile>
-      <id>findbugs</id>
-      <build>
-        <pluginManagement>
-          <plugins>
-            <plugin>
-              <groupId>org.codehaus.mojo</groupId>
-              <artifactId>findbugs-maven-plugin</artifactId>
-              <version>3.0.5</version>
-              <executions>
-                <execution>
-                  <phase>package</phase>
-                  <goals>
-                    <goal>findbugs</goal>
-                  </goals>
-                </execution>
-              </executions>
-            </plugin>
-          </plugins>
-        </pluginManagement>
-        <plugins>
-          <plugin>
-            <groupId>org.codehaus.mojo</groupId>
-            <artifactId>findbugs-maven-plugin</artifactId>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-    <profile>
       <id>enforce-compatibility</id>
       <activation>
         <file>
-          <exists>.activate-enforce-compatibility</exists>
+          <exists>marker-file-identifying-api-compatibility-check</exists>
         </file>
       </activation>
       <build>
-        <pluginManagement>
-          <plugins>
-            <plugin>
-              <groupId>org.apache.rat</groupId>
-              <artifactId>apache-rat-plugin</artifactId>
-              <executions>
-                <execution>
-                  <id>default-cli</id>
-                  <configuration>
-                    <excludes combine.children="append">
-                      <exclude>**/api-change-report/**/*.*</exclude>
-                    </excludes>
-                  </configuration>
-                </execution>
-              </executions>
-            </plugin>
-          </plugins>
-        </pluginManagement>
-
         <plugins>
           <!-- https://siom79.github.io/japicmp/MavenPlugin.html -->
           <plugin>
             <groupId>com.github.siom79.japicmp</groupId>
             <artifactId>japicmp-maven-plugin</artifactId>
-            <version>0.13.1</version>
             <configuration>
-              <oldVersion>
-                <dependency>
-                  <groupId>${project.groupId}</groupId>
-                  <artifactId>${project.artifactId}</artifactId>
-                  <version>${compat.previous.version}</version>
-                </dependency>
-              </oldVersion>
               <parameter>
                 <onlyModified>true</onlyModified>
                 <!-- filter out classes with impl in their package or class name -->
-                <postAnalysisScript>${project.basedir}/../uimafit-parent/src/main/groovy/api-report.groovy</postAnalysisScript>
+                <postAnalysisScript>${japicmp.postAnalysisScript}</postAnalysisScript>
               </parameter>
             </configuration>
-            <executions>
-              <execution>
-                <phase>verify</phase>
-                <goals>
-                  <goal>cmp</goal>
-                </goals>
-              </execution>
-            </executions>
-          </plugin>
-
-          <!-- This copy is to have the api change report included in the source distribution -->
-          <plugin>
-            <artifactId>maven-antrun-plugin</artifactId>
-            <executions>
-              <execution>
-                <id>copy-API-change-report</id>
-                <phase>install</phase>  <!-- must follow verify -->
-                <goals>
-                  <goal>run</goal>
-                </goals>
-                <configuration>
-                  <target>
-                    <taskdef name="if" classname="net.sf.antcontrib.logic.IfTask" />
-                    <if>
-                      <available file="${project.build.directory}/japicmp/" />
-                      <then>
-                        <copy toDir="${basedir}/api-change-report">
-                          <fileset dir="${project.build.directory}/japicmp" />
-                        </copy>
-                      </then>
-                    </if>
-                  </target>
-                </configuration>
-              </execution>
-            </executions>
           </plugin>
         </plugins>
       </build>
diff --git a/uimafit-spring/.settings/org.eclipse.jdt.core.prefs b/uimafit-spring/.settings/org.eclipse.jdt.core.prefs
index d759025..225e1bc 100644
--- a/uimafit-spring/.settings/org.eclipse.jdt.core.prefs
+++ b/uimafit-spring/.settings/org.eclipse.jdt.core.prefs
@@ -1,7 +1,9 @@
 eclipse.preferences.version=1
 org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
 org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
 org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
 org.eclipse.jdt.core.compiler.release=disabled
 org.eclipse.jdt.core.compiler.source=1.8
 org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
diff --git a/uimafit-spring/.activate-enforce-compatibility b/uimafit-spring/marker-file-identifying-api-compatibility-check
similarity index 100%
rename from uimafit-spring/.activate-enforce-compatibility
rename to uimafit-spring/marker-file-identifying-api-compatibility-check
diff --git a/uimafit-spring/pom.xml b/uimafit-spring/pom.xml
index 51ab663..8dedc56 100644
--- a/uimafit-spring/pom.xml
+++ b/uimafit-spring/pom.xml
@@ -27,7 +27,7 @@
   <parent>
     <groupId>org.apache.uima</groupId>
     <artifactId>uimafit-parent</artifactId>
-    <version>3.0.1-SNAPSHOT</version>
+    <version>3.1.0-SNAPSHOT</version>
     <relativePath>../uimafit-parent</relativePath>
   </parent>
   <dependencies>
@@ -46,7 +46,7 @@
     <dependency>
       <groupId>org.apache.uima</groupId>
       <artifactId>uimafit-core</artifactId>
-      <version>3.0.1-SNAPSHOT</version>
+      <version>3.1.0-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>org.slf4j</groupId>
@@ -61,4 +61,4 @@
       <distribution>repo</distribution>
     </license>
   </licenses>
-</project>
\ No newline at end of file
+</project>
diff --git a/uimafit-spring/src/test/java/org/apache/uima/fit/spring/SpringContextResourceManagerTest.java b/uimafit-spring/src/test/java/org/apache/uima/fit/spring/SpringContextResourceManagerTest.java
index ba72bf9..aa7c683 100644
--- a/uimafit-spring/src/test/java/org/apache/uima/fit/spring/SpringContextResourceManagerTest.java
+++ b/uimafit-spring/src/test/java/org/apache/uima/fit/spring/SpringContextResourceManagerTest.java
@@ -20,7 +20,7 @@
 package org.apache.uima.fit.spring;
 
 import static org.apache.uima.fit.factory.AnalysisEngineFactory.createEngineDescription;
-import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResource;
+import static org.apache.uima.fit.factory.ExternalResourceFactory.bindResourceOnceWithoutNested;
 import static org.junit.Assert.assertEquals;
 
 import org.apache.uima.UIMAFramework;
@@ -57,7 +57,7 @@
 
     // Create component description
     AnalysisEngineDescription desc = createEngineDescription(MyAnalysisEngine.class);
-    bindResource(desc, "injectedBean", "springBean");
+    bindResourceOnceWithoutNested(desc, "injectedBean", "springBean");
 
     // Instantiate component
     AnalysisEngine ae = UIMAFramework.produceAnalysisEngine(desc, resMgr, null);