[UIMA-6214] Method signature class in ExternalResourceFactory

- Renamed and deprecated methods to resolve signature clashes
- Documented changes in the migratin guide
- Updated version in README file
diff --git a/README b/README
index 6bcfe76..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.1.0 or higher, and the Spring Framework 4.3.26 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/pom.xml b/pom.xml
index 1d525fe..1c2e855 100644
--- a/pom.xml
+++ b/pom.xml
@@ -32,7 +32,7 @@
     <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>
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/factory/AnalysisEngineFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/AnalysisEngineFactory.java
index e374551..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;
@@ -1362,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 5e71002..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;
@@ -850,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/ExternalResourceFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/ExternalResourceFactory.java
index d492f57..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
@@ -21,6 +21,7 @@
 
 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;
@@ -39,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;
@@ -63,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;
@@ -343,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.
@@ -353,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
@@ -380,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 {
@@ -395,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
@@ -414,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);
@@ -520,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
@@ -539,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);
@@ -597,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
@@ -616,7 +655,7 @@
           throws InvalidXMLException, ClassNotFoundException {
     ExternalResourceDescription extRes = createNamedResourceDescriptionUsingUrl(
             uniqueResourceKey(aRes.getName()), aRes, aUrl, aParams);
-    bind((AnalysisEngineDescription) aDesc, extRes);
+    scanRecursivelyForDependenciesByInterfaceAndBind((AnalysisEngineDescription) aDesc, extRes);
   }
 
   /**
@@ -666,7 +705,7 @@
           throws InvalidXMLException {
     ExternalResourceDescription extRes = createNamedResourceDescriptionUsingUrl(
             uniqueResourceKey(aRes.getName()), aRes, aUrl, aParams);
-    bind((AnalysisEngineDescription) aDesc, aKey, extRes);
+    scanRecursivelyForDependenciesByKeyAndBind((AnalysisEngineDescription) aDesc, aKey, extRes);
   }
 
   /**
@@ -715,7 +754,7 @@
           throws InvalidXMLException, ClassNotFoundException {
     // Dispatch
     if (aDesc instanceof AnalysisEngineDescription) {
-      bind((AnalysisEngineDescription) aDesc, aResDesc);
+      scanRecursivelyForDependenciesByInterfaceAndBind((AnalysisEngineDescription) aDesc, aResDesc);
     }
   }
 
@@ -736,7 +775,7 @@
           ExternalResourceDescription aResDesc) throws InvalidXMLException {
     // Dispatch
     if (aDesc instanceof AnalysisEngineDescription) {
-      bind((AnalysisEngineDescription) aDesc, aKey, aResDesc);
+      scanRecursivelyForDependenciesByKeyAndBind((AnalysisEngineDescription) aDesc, aKey, aResDesc);
     }
   }
 
@@ -903,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);
       }
     }
 
@@ -923,7 +963,7 @@
       }
 
       if (apiClass.isAssignableFrom(resClass)) {
-        bindResource(aDesc, dep.getKey(), aResDesc);
+        bindResourceOnce(aDesc, dep.getKey(), aResDesc);
       }
     }
   }
@@ -939,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.
@@ -966,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);
     }
@@ -1004,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"
@@ -1038,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.
@@ -1095,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.
@@ -1104,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) {
@@ -1112,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.
@@ -1125,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.
@@ -1141,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) {
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/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/ExternalResourceFactoryTest.java b/uimafit-core/src/test/java/org/apache/uima/fit/factory/ExternalResourceFactoryTest.java
index 90a9c66..7c03ca3 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
@@ -23,8 +23,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.bindResource;
-import static org.apache.uima.fit.factory.ExternalResourceFactory.*;
+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.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
@@ -167,8 +168,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
diff --git a/uimafit-docbook/src/docbook/tools.uimafit.migration.xml b/uimafit-docbook/src/docbook/tools.uimafit.migration.xml
index c221051..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>
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);