You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2016/06/28 13:07:10 UTC

[23/50] [abbrv] ignite git commit: ignite-3233 Added 'resourceClass' for SpringResource annotation.

ignite-3233 Added 'resourceClass' for SpringResource annotation.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/d59e5f56
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/d59e5f56
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/d59e5f56

Branch: refs/heads/ignite-1232
Commit: d59e5f5612bc916432e13bfa38a034d9120274fc
Parents: 41f81da
Author: sboikov <sb...@gridgain.com>
Authored: Thu Jun 23 12:48:13 2016 +0300
Committer: sboikov <sb...@gridgain.com>
Committed: Thu Jun 23 12:48:13 2016 +0300

----------------------------------------------------------------------
 .../apache/ignite/resources/SpringResource.java |  15 +-
 .../GridResourceSpringBeanInjector.java         |  39 ++-
 .../GridSpringResourceInjectionSelfTest.java    | 311 ++++++++++++++++---
 .../spring-resource-with-duplicate-beans.xml    |  30 ++
 .../processors/resource/spring-resource.xml     |   2 +-
 5 files changed, 353 insertions(+), 44 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/d59e5f56/modules/core/src/main/java/org/apache/ignite/resources/SpringResource.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/resources/SpringResource.java b/modules/core/src/main/java/org/apache/ignite/resources/SpringResource.java
index f4c041e..0a8b832 100644
--- a/modules/core/src/main/java/org/apache/ignite/resources/SpringResource.java
+++ b/modules/core/src/main/java/org/apache/ignite/resources/SpringResource.java
@@ -112,5 +112,18 @@ public @interface SpringResource {
      *
      * @return Resource bean name.
      */
-    String resourceName();
+    String resourceName() default "";
+
+    /**
+     * Resource bean class in provided {@code ApplicationContext} to look up
+     * a Spring bean.
+     *
+     * @return Resource bean class.
+     */
+    Class<?> resourceClass() default DEFAULT.class;
+
+    /** Dummy class to compensate for impossibility of having default null value for annotation method. */
+    final class DEFAULT {
+        // No-op.
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/d59e5f56/modules/spring/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceSpringBeanInjector.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceSpringBeanInjector.java b/modules/spring/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceSpringBeanInjector.java
index adcf141..816a597 100644
--- a/modules/spring/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceSpringBeanInjector.java
+++ b/modules/spring/src/main/java/org/apache/ignite/internal/processors/resource/GridResourceSpringBeanInjector.java
@@ -24,6 +24,7 @@ import org.apache.ignite.internal.managers.deployment.GridDeployment;
 import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.resources.SpringResource;
 import org.springframework.context.ApplicationContext;
+import org.springframework.util.StringUtils;
 
 /**
  * Spring bean injector implementation works with resources provided
@@ -59,10 +60,8 @@ public class GridResourceSpringBeanInjector implements GridResourceInjector {
                 field.getField());
         }
 
-        String name = ann.resourceName();
-
         if (springCtx != null) {
-            Object bean = springCtx.getBean(name);
+            Object bean = getBeanByResourceAnnotation(ann);
 
             GridResourceUtils.inject(field.getField(), target, bean);
         }
@@ -78,10 +77,8 @@ public class GridResourceSpringBeanInjector implements GridResourceInjector {
         if (mtd.getMethod().getParameterTypes().length != 1)
             throw new IgniteCheckedException("Method injection setter must have only one parameter: " + mtd.getMethod());
 
-        String name = ann.resourceName();
-
         if (springCtx != null) {
-            Object bean = springCtx.getBean(name);
+            Object bean = getBeanByResourceAnnotation(ann);
 
             GridResourceUtils.inject(mtd.getMethod(), target, bean);
         }
@@ -96,4 +93,34 @@ public class GridResourceSpringBeanInjector implements GridResourceInjector {
     @Override public String toString() {
         return S.toString(GridResourceSpringBeanInjector.class, this);
     }
+
+    /**
+     * Retrieves from {@link #springCtx} the bean specified by {@link SpringResource} annotation.
+     *
+     * @param annotation {@link SpringResource} annotation instance from field or method.
+     * @return Bean object retrieved from spring context.
+     * @throws IgniteCheckedException If failed.
+     */
+    private Object getBeanByResourceAnnotation(SpringResource annotation) throws IgniteCheckedException {
+        assert springCtx != null;
+
+        String beanName = annotation.resourceName();
+        Class<?> beanCls = annotation.resourceClass();
+
+        boolean oneParamSet = !StringUtils.isEmpty(beanName) ^ beanCls != SpringResource.DEFAULT.class;
+
+        if (!oneParamSet) {
+            throw new IgniteCheckedException("Either bean name or its class must be specified in @SpringResource, " +
+                "but not both");
+        }
+
+        Object bean;
+
+        if (!StringUtils.isEmpty(beanName))
+            bean = springCtx.getBean(beanName);
+        else
+            bean = springCtx.getBean(beanCls);
+
+        return bean;
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/d59e5f56/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridSpringResourceInjectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridSpringResourceInjectionSelfTest.java b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridSpringResourceInjectionSelfTest.java
index 968c8c4..b989ac8 100644
--- a/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridSpringResourceInjectionSelfTest.java
+++ b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridSpringResourceInjectionSelfTest.java
@@ -17,17 +17,22 @@
 
 package org.apache.ignite.internal.processors.resource;
 
+import java.util.concurrent.Callable;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteSpring;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.G;
 import org.apache.ignite.lang.IgniteCallable;
 import org.apache.ignite.resources.SpringResource;
+import org.apache.ignite.testframework.GridTestUtils;
 import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
 
 /**
  * Tests for injected resource.
  */
+@SuppressWarnings("unused")
 public class GridSpringResourceInjectionSelfTest extends GridCommonAbstractTest {
     /** Bean name. */
     private static final String DUMMY_BEAN = "dummyResourceBean";
@@ -49,13 +54,13 @@ public class GridSpringResourceInjectionSelfTest extends GridCommonAbstractTest
     /**
      * @throws Exception If failed.
      */
-    public void testClosureField() throws Exception {
+    public void testClosureFieldByResourceName() throws Exception {
         grid.compute().call(new IgniteCallable<Object>() {
             @SpringResource(resourceName = DUMMY_BEAN)
-            private transient DummyResourceBean dummyResourceBean;
+            private transient DummyResourceBean dummyRsrcBean;
 
             @Override public Object call() throws Exception {
-                assertNotNull(dummyResourceBean);
+                assertNotNull(dummyRsrcBean);
 
                 return null;
             }
@@ -63,81 +68,315 @@ public class GridSpringResourceInjectionSelfTest extends GridCommonAbstractTest
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testClosureFieldByResourceClass() throws Exception {
+        grid.compute().call(new IgniteCallable<Object>() {
+            @SpringResource(resourceClass = DummyResourceBean.class)
+            private transient DummyResourceBean dummyRsrcBean;
+
+            @Override public Object call() throws Exception {
+                assertNotNull(dummyRsrcBean);
+
+                return null;
+            }
+        });
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testClosureFieldByResourceClassWithMultipleBeans() throws Exception {
+        IgniteConfiguration anotherCfg = new IgniteConfiguration();
+        anotherCfg.setGridName("anotherGrid");
+
+        Ignite anotherGrid = IgniteSpring.start(anotherCfg, new ClassPathXmlApplicationContext(
+            "/org/apache/ignite/internal/processors/resource/spring-resource-with-duplicate-beans.xml"));
+
+        Throwable err = assertError(new IgniteCallable<Object>() {
+            @SpringResource(resourceClass = DummyResourceBean.class)
+            private transient DummyResourceBean dummyRsrcBean;
+
+            @Override public Object call() throws Exception {
+                assertNotNull(dummyRsrcBean);
+
+                return null;
+            }
+        }, anotherGrid, null);
+
+        assertTrue("Unexpected message: " + err.getMessage(), err.getMessage().startsWith("No qualifying bean of type " +
+            "[org.apache.ignite.internal.processors.resource.GridSpringResourceInjectionSelfTest$DummyResourceBean]" +
+            " is defined: expected single matching bean but found 2:"));
+
+        G.stop("anotherGrid", false);
+    }
+
+    /**
      * Resource injection with non-existing resource name.
      */
-    public void testClosureFieldWithWrongResourceName() throws Exception {
-        try {
-            grid.compute().call(new IgniteCallable<Object>() {
-                @SpringResource(resourceName = "")
-                private transient DummyResourceBean dummyResourceBean;
+    public void testClosureFieldWithWrongResourceName() {
+        assertError(new IgniteCallable<Object>() {
+            @SpringResource(resourceName = "nonExistentResource")
+            private transient DummyResourceBean dummyRsrcBean;
 
-                @Override public Object call() throws Exception {
-                    assertNull(dummyResourceBean);
+            @Override public Object call() throws Exception {
+                assertNull(dummyRsrcBean);
 
-                    return null;
-                }
-            });
-        }
-        catch (IgniteException e) {
-            if (e.getMessage().contains("No bean named '' is defined"))
-                return;
-        }
+                return null;
+            }
+        }, "No bean named 'nonExistentResource' is defined");
+    }
+
+    /**
+     * Resource injection with non-existing resource class.
+     */
+    public void testClosureFieldWithWrongResourceClass() {
+        assertError(new IgniteCallable<Object>() {
+            @SpringResource(resourceClass = AnotherDummyResourceBean.class)
+            private transient AnotherDummyResourceBean dummyRsrcBean;
+
+            @Override public Object call() throws Exception {
+                assertNull(dummyRsrcBean);
+
+                return null;
+            }
+        }, "No qualifying bean of type [org.apache.ignite.internal.processors.resource." +
+            "GridSpringResourceInjectionSelfTest$AnotherDummyResourceBean] is defined");
+    }
 
-        fail();
+    /**
+     * Resource injection with both resource and class set (ambiguity).
+     */
+    public void testClosureFieldByResourceClassAndName() {
+        assertError(new IgniteCallable<Object>() {
+            @SpringResource(resourceClass = DummyResourceBean.class, resourceName = DUMMY_BEAN)
+            private transient DummyResourceBean dummyRsrcBean;
+
+            @Override public Object call() throws Exception {
+                assertNull(dummyRsrcBean);
+
+                return null;
+            }
+        }, "Either bean name or its class must be specified in @SpringResource, but not both");
+    }
+
+    /**
+     * Resource injection with no name and class set.
+     */
+    public void testClosureFieldWithNoParams() {
+        assertError(new IgniteCallable<Object>() {
+            @SpringResource
+            private transient DummyResourceBean dummyRsrcBean;
+
+            @Override public Object call() throws Exception {
+                assertNull(dummyRsrcBean);
+
+                return null;
+            }
+        }, "Either bean name or its class must be specified in @SpringResource, but not both");
     }
 
     /**
      * @throws Exception If failed.
      */
-    public void testClosureMethod() throws Exception {
+    public void testClosureMethodWithResourceName() throws Exception {
         grid.compute().call(new IgniteCallable<Object>() {
-            private DummyResourceBean dummyResourceBean;
+            private DummyResourceBean dummyRsrcBean;
 
             @SpringResource(resourceName = DUMMY_BEAN)
-            private void setDummyResourceBean(DummyResourceBean dummyResourceBean) {
-                assertNotNull(dummyResourceBean);
+            private void setDummyResourceBean(DummyResourceBean dummyRsrcBean) {
+                assertNotNull(dummyRsrcBean);
 
-                this.dummyResourceBean = dummyResourceBean;
+                this.dummyRsrcBean = dummyRsrcBean;
             }
 
             @Override public Object call() throws Exception {
+                assertNotNull(dummyRsrcBean);
+
                 return null;
             }
         });
     }
 
     /**
-     * Resource injection with non-existing resource name.
+     * @throws Exception If failed.
      */
-    public void testClosureMethodWithWrongResourceName() throws Exception {
+    public void testClosureMethodWithResourceClass() throws Exception {
+        grid.compute().call(new IgniteCallable<Object>() {
+            private DummyResourceBean dummyRsrcBean;
+
+            @SpringResource(resourceClass = DummyResourceBean.class)
+            private void setDummyResourceBean(DummyResourceBean dummyRsrcBean) {
+                assertNotNull(dummyRsrcBean);
+
+                this.dummyRsrcBean = dummyRsrcBean;
+            }
+
+            @Override public Object call() throws Exception {
+                assertNotNull(dummyRsrcBean);
+
+                return null;
+            }
+        });
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    public void testClosureMethodWithResourceClassWithMultipleBeans() throws Exception {
+        IgniteConfiguration anotherCfg = new IgniteConfiguration();
+        anotherCfg.setGridName("anotherGrid");
+
+        Ignite anotherGrid = IgniteSpring.start(anotherCfg, new ClassPathXmlApplicationContext(
+            "/org/apache/ignite/internal/processors/resource/spring-resource-with-duplicate-beans.xml"));
+
         try {
-            grid.compute().call(new IgniteCallable<Object>() {
-                private DummyResourceBean dummyResourceBean;
+            Throwable err = assertError(new IgniteCallable<Object>() {
+                private DummyResourceBean dummyRsrcBean;
+
+                @SpringResource(resourceClass = DummyResourceBean.class)
+                private void setDummyResourceBean(DummyResourceBean dummyRsrcBean) {
+                    assertNotNull(dummyRsrcBean);
 
-                @SpringResource(resourceName = "")
-                private void setDummyResourceBean(DummyResourceBean dummyResourceBean) {
+                    this.dummyRsrcBean = dummyRsrcBean;
                 }
 
                 @Override public Object call() throws Exception {
-                    assertNull(dummyResourceBean);
+                    assertNotNull(dummyRsrcBean);
 
                     return null;
                 }
-            });
+            }, anotherGrid, null);
+
+            assertTrue("Unexpected message: " + err.getMessage(), err.getMessage().startsWith("No qualifying bean of type " +
+                "[org.apache.ignite.internal.processors.resource.GridSpringResourceInjectionSelfTest$DummyResourceBean]" +
+                " is defined: expected single matching bean but found 2:"));
         }
-        catch (IgniteException e) {
-            if (e.getMessage().contains("No bean named '' is defined"))
-                return;
+        finally {
+            G.stop("anotherGrid", false);
         }
+    }
+
+    /**
+     * Resource injection with non-existing resource name.
+     */
+    public void testClosureMethodWithWrongResourceName() {
+        assertError(new IgniteCallable<Object>() {
+            private DummyResourceBean dummyRsrcBean;
 
-        fail();
+            @SpringResource(resourceName = "nonExistentResource")
+            private void setDummyResourceBean(DummyResourceBean dummyRsrcBean) {
+                // No-op.
+            }
+
+            @Override public Object call() throws Exception {
+                assertNull(dummyRsrcBean);
+
+                return null;
+            }
+        }, "No bean named 'nonExistentResource' is defined");
+    }
+
+    /**
+     * Resource injection with non-existing resource class.
+     */
+    public void testClosureMethodWithWrongResourceClass() {
+        assertError(new IgniteCallable<Object>() {
+            private AnotherDummyResourceBean dummyRsrcBean;
+
+            @SpringResource(resourceClass = AnotherDummyResourceBean.class)
+            private void setDummyResourceBean(AnotherDummyResourceBean dummyRsrcBean) {
+                // No-op.
+            }
+
+            @Override public Object call() throws Exception {
+                assertNull(dummyRsrcBean);
+
+                return null;
+            }
+        }, "No qualifying bean of type [org.apache.ignite.internal.processors.resource" +
+                ".GridSpringResourceInjectionSelfTest$AnotherDummyResourceBean] is defined");
+    }
+
+    /**
+     * Resource injection with both resource and class set (ambiguity).
+     */
+    public void testClosureMethodByResourceClassAndName() {
+        assertError(new IgniteCallable<Object>() {
+            @SpringResource(resourceClass = DummyResourceBean.class, resourceName = DUMMY_BEAN)
+            private transient DummyResourceBean dummyRsrcBean;
+
+            @Override public Object call() throws Exception {
+                assertNull(dummyRsrcBean);
+
+                return null;
+            }
+        }, "Either bean name or its class must be specified in @SpringResource, but not both");
+    }
+
+    /**
+     * Resource injection with no params.
+     */
+    public void testClosureMethodWithNoParams() {
+        assertError(new IgniteCallable<Object>() {
+            @SpringResource
+            private transient DummyResourceBean dummyRsrcBean;
+
+            @Override public Object call() throws Exception {
+                assertNull(dummyRsrcBean);
+
+                return null;
+            }
+        }, "Either bean name or its class must be specified in @SpringResource, but not both");
+    }
+
+    /**
+     * @param job {@link IgniteCallable} to be run
+     * @param grid Node.
+     * @param expEMsg Message that {@link IgniteException} thrown from <tt>job</tt> should bear
+     * @return Thrown error.
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    private Throwable assertError(final IgniteCallable<?> job, final Ignite grid, String expEMsg) {
+        return GridTestUtils.assertThrows(log, new Callable<Object>() {
+            @Override public Object call() throws Exception {
+                grid.compute(grid.cluster().forLocal()).call(job);
+                return null;
+            }
+        }, IgniteException.class, expEMsg);
+    }
+
+    /**
+     * @param job {@link IgniteCallable} to be run
+     * @param expEMsg Message that {@link IgniteException} thrown from <tt>job</tt> should bear
+     */
+    @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+    private void assertError(final IgniteCallable<?> job, String expEMsg) {
+        assertError(job, grid, expEMsg);
     }
 
     /**
      * Dummy resource bean.
      */
     public static class DummyResourceBean {
+        /**
+         *
+         */
         public DummyResourceBean() {
+            // No-op.
+        }
+    }
+
+    /**
+     * Another dummy resource bean.
+     */
+    private static class AnotherDummyResourceBean {
+        /**
+         *
+         */
+        public AnotherDummyResourceBean() {
+            // No-op.
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/d59e5f56/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource-with-duplicate-beans.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource-with-duplicate-beans.xml b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource-with-duplicate-beans.xml
new file mode 100644
index 0000000..98a94f8
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource-with-duplicate-beans.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+    <bean id="dummyBean1"
+          class="org.apache.ignite.internal.processors.resource.GridSpringResourceInjectionSelfTest$DummyResourceBean">
+    </bean>
+    <bean id="dummyBean2"
+          class="org.apache.ignite.internal.processors.resource.GridSpringResourceInjectionSelfTest$DummyResourceBean">
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/d59e5f56/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource.xml b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource.xml
index 3abb521..6baf116 100644
--- a/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource.xml
+++ b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/spring-resource.xml
@@ -19,7 +19,7 @@
 <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
-    	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
 
     <bean id="dummyResourceBean"
           class="org.apache.ignite.internal.processors.resource.GridSpringResourceInjectionSelfTest$DummyResourceBean">