You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2020/04/10 12:21:04 UTC

[uima-uimafit] branch UIMA-6214-Method-signature-clash-in-ExternalResourceFactory created (now ef979ed)

This is an automated email from the ASF dual-hosted git repository.

rec pushed a change to branch UIMA-6214-Method-signature-clash-in-ExternalResourceFactory
in repository https://gitbox.apache.org/repos/asf/uima-uimafit.git.


      at ef979ed  [UIMA-6214] Method signature class in ExternalResourceFactory

This branch includes the following new commits:

     new ef979ed  [UIMA-6214] Method signature class in ExternalResourceFactory

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[uima-uimafit] 01/01: [UIMA-6214] Method signature class in ExternalResourceFactory

Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rec pushed a commit to branch UIMA-6214-Method-signature-clash-in-ExternalResourceFactory
in repository https://gitbox.apache.org/repos/asf/uima-uimafit.git

commit ef979edd00adab2211f78da7dd5b157483a425f5
Author: Richard Eckart de Castilho <re...@apache.org>
AuthorDate: Fri Apr 10 14:20:53 2020 +0200

    [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
---
 README                                             |  12 +-
 pom.xml                                            |   2 +-
 .../uima/fit/component/ExternalResourceAware.java  |   8 +-
 .../uima/fit/factory/AnalysisEngineFactory.java    |   4 +-
 .../uima/fit/factory/CollectionReaderFactory.java  |   4 +-
 .../uima/fit/factory/ExternalResourceFactory.java  | 231 +++++++++++++++++----
 .../uima/fit/factory/FlowControllerFactory.java    |   4 +-
 .../AnalysisEngineFactoryExternalResourceTest.java |  13 +-
 .../fit/factory/ExternalResourceFactoryTest.java   |   9 +-
 .../src/docbook/tools.uimafit.migration.xml        |  43 ++++
 .../spring/SpringContextResourceManagerTest.java   |   4 +-
 11 files changed, 264 insertions(+), 70 deletions(-)

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 @@ following list highlights some of the features uimaFIT provides:
      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 @@ add uimaFIT as a dependency to your pom.xml file with the following:
   <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 @@ import org.apache.uima.resource.ResourceInitializationException;
 /**
  * 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.descriptor.OperationalProperties.OUTPUTS_NEW_C
 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 @@ public final class AnalysisEngineFactory {
     // 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 @@ package org.apache.uima.fit.factory;
 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 @@ public final class CollectionReaderFactory {
     // 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 @@ 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;
@@ -39,6 +40,7 @@ import java.util.Map.Entry;
 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.ResourceSpecifier;
 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 @@ public final class ExternalResourceFactory {
   }
 
   /**
-   * 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 final class ExternalResourceFactory {
    */
   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 @@ public final class ExternalResourceFactory {
     // 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 @@ public final class ExternalResourceFactory {
       }
     }
 
-    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 final class ExternalResourceFactory {
    */
   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,7 @@ public final class ExternalResourceFactory {
 
   /**
    * 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
@@ -538,9 +548,37 @@ public final class ExternalResourceFactory {
    * @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
+   * 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
+   */
+  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 @@ public final class ExternalResourceFactory {
   /**
    * 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 @@ public final class ExternalResourceFactory {
           throws InvalidXMLException, ClassNotFoundException {
     ExternalResourceDescription extRes = createNamedResourceDescriptionUsingUrl(
             uniqueResourceKey(aRes.getName()), aRes, aUrl, aParams);
-    bind((AnalysisEngineDescription) aDesc, extRes);
+    scanRecursivelyForDependenciesByInterfaceAndBind((AnalysisEngineDescription) aDesc, extRes);
   }
 
   /**
@@ -666,7 +705,7 @@ public final class ExternalResourceFactory {
           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 @@ public final class ExternalResourceFactory {
           throws InvalidXMLException, ClassNotFoundException {
     // Dispatch
     if (aDesc instanceof AnalysisEngineDescription) {
-      bind((AnalysisEngineDescription) aDesc, aResDesc);
+      scanRecursivelyForDependenciesByInterfaceAndBind((AnalysisEngineDescription) aDesc, aResDesc);
     }
   }
 
@@ -736,7 +775,7 @@ public final class ExternalResourceFactory {
           ExternalResourceDescription aResDesc) throws InvalidXMLException {
     // Dispatch
     if (aDesc instanceof AnalysisEngineDescription) {
-      bind((AnalysisEngineDescription) aDesc, aKey, aResDesc);
+      scanRecursivelyForDependenciesByKeyAndBind((AnalysisEngineDescription) aDesc, aKey, aResDesc);
     }
   }
 
@@ -903,12 +942,13 @@ public final class ExternalResourceFactory {
    * @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 @@ public final class ExternalResourceFactory {
       }
 
       if (apiClass.isAssignableFrom(resClass)) {
-        bindResource(aDesc, dep.getKey(), aResDesc);
+        bindResourceOnce(aDesc, dep.getKey(), aResDesc);
       }
     }
   }
@@ -939,25 +979,27 @@ public final class ExternalResourceFactory {
    * @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.
@@ -965,17 +1007,42 @@ public final class ExternalResourceFactory {
    *          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.
+   * @param aBindTo
+   *          what key to bind to.
+   * @param aRes
+   *          the resource that should be bound.
+   */
+  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 @@ public final class ExternalResourceFactory {
    *          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 @@ public final class ExternalResourceFactory {
     // 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 @@ public final class ExternalResourceFactory {
   }
 
   /**
-   * 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 @@ public final class ExternalResourceFactory {
    * @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,21 @@ public final class ExternalResourceFactory {
       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.
@@ -1124,15 +1236,54 @@ public final class ExternalResourceFactory {
    *          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.
+   * @param aBindTo
+   *          what key to bind to.
+   * @param aRes
+   *          the resource that should be bound.
+   */
+  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 @@ public final class ExternalResourceFactory {
    * @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 @@ package org.apache.uima.fit.factory;
 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 @@ public final class FlowControllerFactory {
     // 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 @@ package org.apache.uima.fit.factory;
 
 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 @@ public class AnalysisEngineFactoryExternalResourceTest {
     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 @@ public class AnalysisEngineFactoryExternalResourceTest {
     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 @@ public class AnalysisEngineFactoryExternalResourceTest {
             "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 @@ public class AnalysisEngineFactoryExternalResourceTest {
     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 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.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 @@ public class ExternalResourceFactoryTest extends ComponentTestBase {
     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 @@ public class SpringContextResourceManagerTest {
 
     // 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);