Correct the processing of resources with <injection-target>s defined in web.xml. First look for a match using JavaBean property names and then, only if a match is not found, look for a match using fields.

git-svn-id: https://svn.apache.org/repos/asf/tomcat/tc8.0.x/trunk@1830804 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/java/org/apache/catalina/core/DefaultInstanceManager.java b/java/org/apache/catalina/core/DefaultInstanceManager.java
index 110bded..62b364c 100644
--- a/java/org/apache/catalina/core/DefaultInstanceManager.java
+++ b/java/org/apache/catalina/core/DefaultInstanceManager.java
@@ -297,6 +297,7 @@
             InvocationTargetException, NamingException {
 
         List<AnnotationCacheEntry> annotations = null;
+        Set<String> injectionsMatchedToSetter = new HashSet<>();
 
         while (clazz != null) {
             AnnotationCacheEntry[] annotationsArray = annotationCache.get(clazz);
@@ -307,48 +308,6 @@
                     annotations.clear();
                 }
 
-                if (context != null) {
-                    // Initialize fields annotations for resource injection if
-                    // JNDI is enabled
-                    Field[] fields = Introspection.getDeclaredFields(clazz);
-                    for (Field field : fields) {
-                        Resource resourceAnnotation;
-                        Annotation ejbAnnotation;
-                        Annotation webServiceRefAnnotation;
-                        Annotation persistenceContextAnnotation;
-                        Annotation persistenceUnitAnnotation;
-                        if (injections != null && injections.containsKey(field.getName())) {
-                            annotations.add(new AnnotationCacheEntry(
-                                    field.getName(), null,
-                                    injections.get(field.getName()),
-                                    AnnotationCacheEntryType.FIELD));
-                        } else if ((resourceAnnotation =
-                                field.getAnnotation(Resource.class)) != null) {
-                            annotations.add(new AnnotationCacheEntry(field.getName(), null,
-                                    resourceAnnotation.name(), AnnotationCacheEntryType.FIELD));
-                        } else if (EJB_PRESENT &&
-                                (ejbAnnotation = field.getAnnotation(EJB.class)) != null) {
-                            annotations.add(new AnnotationCacheEntry(field.getName(), null,
-                                    ((EJB) ejbAnnotation).name(), AnnotationCacheEntryType.FIELD));
-                        } else if (WS_PRESENT && (webServiceRefAnnotation =
-                                field.getAnnotation(WebServiceRef.class)) != null) {
-                            annotations.add(new AnnotationCacheEntry(field.getName(), null,
-                                    ((WebServiceRef) webServiceRefAnnotation).name(),
-                                    AnnotationCacheEntryType.FIELD));
-                        } else if (JPA_PRESENT && (persistenceContextAnnotation =
-                                field.getAnnotation(PersistenceContext.class)) != null) {
-                            annotations.add(new AnnotationCacheEntry(field.getName(), null,
-                                    ((PersistenceContext) persistenceContextAnnotation).name(),
-                                    AnnotationCacheEntryType.FIELD));
-                        } else if (JPA_PRESENT && (persistenceUnitAnnotation =
-                                field.getAnnotation(PersistenceUnit.class)) != null) {
-                            annotations.add(new AnnotationCacheEntry(field.getName(), null,
-                                    ((PersistenceUnit) persistenceUnitAnnotation).name(),
-                                    AnnotationCacheEntryType.FIELD));
-                        }
-                    }
-                }
-
                 // Initialize methods annotations
                 Method[] methods = Introspection.getDeclaredMethods(clazz);
                 Method postConstruct = null;
@@ -358,9 +317,9 @@
                 for (Method method : methods) {
                     if (context != null) {
                         // Resource injection only if JNDI is enabled
-                        if (injections != null &&
-                                Introspection.isValidSetter(method)) {
+                        if (injections != null && Introspection.isValidSetter(method)) {
                             String fieldName = Introspection.getPropertyName(method);
+                            injectionsMatchedToSetter.add(fieldName);
                             if (injections.containsKey(fieldName)) {
                                 annotations.add(new AnnotationCacheEntry(
                                         method.getName(),
@@ -375,8 +334,7 @@
                         Annotation webServiceRefAnnotation;
                         Annotation persistenceContextAnnotation;
                         Annotation persistenceUnitAnnotation;
-                        if ((resourceAnnotation =
-                                method.getAnnotation(Resource.class)) != null) {
+                        if ((resourceAnnotation = method.getAnnotation(Resource.class)) != null) {
                             annotations.add(new AnnotationCacheEntry(
                                     method.getName(),
                                     method.getParameterTypes(),
@@ -438,6 +396,50 @@
                         + preDestroyFromXml + " for class " + clazz.getName()
                         + " is declared in deployment descriptor but cannot be found.");
                 }
+
+                if (context != null) {
+                    // Initialize fields annotations for resource injection if
+                    // JNDI is enabled
+                    Field[] fields = Introspection.getDeclaredFields(clazz);
+                    for (Field field : fields) {
+                        Resource resourceAnnotation;
+                        Annotation ejbAnnotation;
+                        Annotation webServiceRefAnnotation;
+                        Annotation persistenceContextAnnotation;
+                        Annotation persistenceUnitAnnotation;
+                        String fieldName = field.getName();
+                        if (injections != null && injections.containsKey(fieldName) && !injectionsMatchedToSetter.contains(fieldName)) {
+                            annotations.add(new AnnotationCacheEntry(
+                                    fieldName, null,
+                                    injections.get(fieldName),
+                                    AnnotationCacheEntryType.FIELD));
+                        } else if ((resourceAnnotation =
+                                field.getAnnotation(Resource.class)) != null) {
+                            annotations.add(new AnnotationCacheEntry(fieldName, null,
+                                    resourceAnnotation.name(), AnnotationCacheEntryType.FIELD));
+                        } else if (EJB_PRESENT &&
+                                (ejbAnnotation = field.getAnnotation(EJB.class)) != null) {
+                            annotations.add(new AnnotationCacheEntry(fieldName, null,
+                                    ((EJB) ejbAnnotation).name(), AnnotationCacheEntryType.FIELD));
+                        } else if (WS_PRESENT && (webServiceRefAnnotation =
+                                field.getAnnotation(WebServiceRef.class)) != null) {
+                            annotations.add(new AnnotationCacheEntry(fieldName, null,
+                                    ((WebServiceRef) webServiceRefAnnotation).name(),
+                                    AnnotationCacheEntryType.FIELD));
+                        } else if (JPA_PRESENT && (persistenceContextAnnotation =
+                                field.getAnnotation(PersistenceContext.class)) != null) {
+                            annotations.add(new AnnotationCacheEntry(fieldName, null,
+                                    ((PersistenceContext) persistenceContextAnnotation).name(),
+                                    AnnotationCacheEntryType.FIELD));
+                        } else if (JPA_PRESENT && (persistenceUnitAnnotation =
+                                field.getAnnotation(PersistenceUnit.class)) != null) {
+                            annotations.add(new AnnotationCacheEntry(fieldName, null,
+                                    ((PersistenceUnit) persistenceUnitAnnotation).name(),
+                                    AnnotationCacheEntryType.FIELD));
+                        }
+                    }
+                }
+
                 if (annotations.isEmpty()) {
                     // Use common object to save memory
                     annotationsArray = ANNOTATIONS_EMPTY;
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 5bf6dd4..7c650b1 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -54,6 +54,12 @@
         annotation. Both now attempt to set the <code>mappedName</code> property
         of the resource. (markt)
       </fix>
+      <fix>
+        Correct the processing of resources with
+        <code>&lt;injection-target&gt;</code>s defined in web.xml. First look
+        for a match using JavaBean property names and then, only if a match is
+        not found, look for a match using fields. (markt)
+      </fix>
     </changelog>
   </subsection>
 </section>