ignite-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sboi...@apache.org
Subject [1/3] ignite git commit: IGNITE-3024 - Fixed deadlock in ServiceProcessor
Date Wed, 04 May 2016 11:08:41 GMT
Repository: ignite
Updated Branches:
  refs/heads/ignite-2435 97165b18f -> a149a6a24


IGNITE-3024 - Fixed deadlock in ServiceProcessor


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

Branch: refs/heads/ignite-2435
Commit: 718cf78b626d45e29f02e0ba8e50ecc1d0f27676
Parents: f0daea9
Author: sboikov <sboikov@gridgain.com>
Authored: Wed May 4 12:12:42 2016 +0300
Committer: sboikov <sboikov@gridgain.com>
Committed: Wed May 4 12:12:42 2016 +0300

----------------------------------------------------------------------
 .../service/GridServiceNotFoundException.java   |   4 +-
 .../service/GridServiceProcessor.java           | 199 +++++++++------
 .../processors/service/GridServiceProxy.java    |  15 +-
 .../processors/service/ServiceContextImpl.java  |  29 ++-
 .../GridServiceInjectionSpringResourceTest.java | 245 +++++++++++++++++++
 .../spring/injection/spring-resource.tmpl.xml   |  66 +++++
 .../testsuites/IgniteSpringTestSuite.java       |   3 +
 7 files changed, 463 insertions(+), 98 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/718cf78b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceNotFoundException.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceNotFoundException.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceNotFoundException.java
index e23db7c..f41bceb 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceNotFoundException.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceNotFoundException.java
@@ -30,11 +30,11 @@ public class GridServiceNotFoundException extends IgniteCheckedException
{
      * @param name Service name.
      */
     public GridServiceNotFoundException(String name) {
-        super("Service node found: " + name);
+        super("Service not found: " + name);
     }
 
     /** {@inheritDoc} */
     @Override public String toString() {
         return getClass() + ": " + getMessage();
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/718cf78b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
index eded5e1..abfc325 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProcessor.java
@@ -240,7 +240,11 @@ public class GridServiceProcessor extends GridProcessorAdapter {
 
         for (ServiceContextImpl ctx : ctxs) {
             ctx.setCancelled(true);
-            ctx.service().cancel(ctx);
+
+            Service svc = ctx.service();
+
+            if (svc != null)
+                svc.cancel(ctx);
 
             ctx.executor().shutdownNow();
         }
@@ -653,7 +657,14 @@ public class GridServiceProcessor extends GridProcessorAdapter {
             if (ctxs.isEmpty())
                 return null;
 
-            return (T)ctxs.iterator().next().service();
+            for (ServiceContextImpl ctx : ctxs) {
+                Service svc = ctx.service();
+
+                if (svc != null)
+                    return (T)svc;
+            }
+
+            return null;
         }
     }
 
@@ -675,7 +686,12 @@ public class GridServiceProcessor extends GridProcessorAdapter {
             if (ctxs.isEmpty())
                 return null;
 
-            return ctxs.iterator().next();
+            for (ServiceContextImpl ctx : ctxs) {
+                if (ctx.service() != null)
+                    return ctx;
+            }
+
+            return null;
         }
     }
 
@@ -695,11 +711,15 @@ public class GridServiceProcessor extends GridProcessorAdapter {
             ServiceContextImpl ctx = serviceContext(name);
 
             if (ctx != null) {
-                if (!svcItf.isAssignableFrom(ctx.service().getClass()))
-                    throw new IgniteException("Service does not implement specified interface
[svcItf=" +
-                        svcItf.getName() + ", svcCls=" + ctx.service().getClass().getName()
+ ']');
+                Service svc = ctx.service();
+
+                if (svc != null) {
+                    if (!svcItf.isAssignableFrom(svc.getClass()))
+                        throw new IgniteException("Service does not implement specified interface
[svcItf=" +
+                            svcItf.getName() + ", svcCls=" + svc.getClass().getName() + ']');
 
-                return (T)ctx.service();
+                    return (T)svc;
+                }
             }
         }
 
@@ -738,8 +758,12 @@ public class GridServiceProcessor extends GridProcessorAdapter {
         synchronized (ctxs) {
             Collection<T> res = new ArrayList<>(ctxs.size());
 
-            for (ServiceContextImpl ctx : ctxs)
-                res.add((T)ctx.service());
+            for (ServiceContextImpl ctx : ctxs) {
+                Service svc = ctx.service();
+
+                if (svc != null)
+                    res.add((T)svc);
+            }
 
             return res;
         }
@@ -911,8 +935,6 @@ public class GridServiceProcessor extends GridProcessorAdapter {
         if (assignCnt == null)
             assignCnt = 0;
 
-        Service svc = assigns.service();
-
         Collection<ServiceContextImpl> ctxs;
 
         synchronized (locSvcs) {
@@ -922,6 +944,8 @@ public class GridServiceProcessor extends GridProcessorAdapter {
                 locSvcs.put(svcName, ctxs = new ArrayList<>());
         }
 
+        Collection<ServiceContextImpl> toInit = new ArrayList<>();
+
         synchronized (ctxs) {
             if (ctxs.size() > assignCnt) {
                 int cancelCnt = ctxs.size() - assignCnt;
@@ -932,75 +956,86 @@ public class GridServiceProcessor extends GridProcessorAdapter {
                 int createCnt = assignCnt - ctxs.size();
 
                 for (int i = 0; i < createCnt; i++) {
-                    final Service cp = copyAndInject(svc);
+                    ServiceContextImpl svcCtx = new ServiceContextImpl(assigns.name(),
+                        UUID.randomUUID(),
+                        assigns.cacheName(),
+                        assigns.affinityKey(),
+                        Executors.newSingleThreadExecutor(threadFactory));
 
-                    final ExecutorService exe = Executors.newSingleThreadExecutor(threadFactory);
+                    ctxs.add(svcCtx);
 
-                    final ServiceContextImpl svcCtx = new ServiceContextImpl(assigns.name(),
-                        UUID.randomUUID(), assigns.cacheName(), assigns.affinityKey(), cp,
exe);
+                    toInit.add(svcCtx);
+                }
+            }
+        }
 
-                    ctxs.add(svcCtx);
+        for (final ServiceContextImpl svcCtx : toInit) {
+            final Service svc = copyAndInject(assigns.service());
 
-                    try {
-                        // Initialize service.
-                        cp.init(svcCtx);
-                    }
-                    catch (Throwable e) {
-                        log.error("Failed to initialize service (service will not be deployed):
" + assigns.name(), e);
+            try {
+                // Initialize service.
+                svc.init(svcCtx);
 
-                        ctxs.remove(svcCtx);
+                svcCtx.service(svc);
+            }
+            catch (Throwable e) {
+                log.error("Failed to initialize service (service will not be deployed): "
+ assigns.name(), e);
 
-                        if (e instanceof Error)
-                            throw (Error)e;
+                synchronized (ctxs) {
+                    ctxs.removeAll(toInit);
+                }
 
-                        if (e instanceof RuntimeException)
-                            throw (RuntimeException)e;
+                if (e instanceof Error)
+                    throw (Error)e;
 
-                        return;
-                    }
+                if (e instanceof RuntimeException)
+                    throw (RuntimeException)e;
 
-                    if (log.isInfoEnabled())
-                        log.info("Starting service instance [name=" + svcCtx.name() + ",
execId=" +
-                            svcCtx.executionId() + ']');
+                return;
+            }
 
-                    // Start service in its own thread.
-                    exe.submit(new Runnable() {
-                        @Override public void run() {
-                            try {
-                                cp.execute(svcCtx);
-                            }
-                            catch (InterruptedException | IgniteInterruptedCheckedException
ignore) {
-                                if (log.isDebugEnabled())
-                                    log.debug("Service thread was interrupted [name=" + svcCtx.name()
+ ", execId=" +
-                                        svcCtx.executionId() + ']');
-                            }
-                            catch (IgniteException e) {
-                                if (e.hasCause(InterruptedException.class) ||
-                                    e.hasCause(IgniteInterruptedCheckedException.class))
{
-                                    if (log.isDebugEnabled())
-                                        log.debug("Service thread was interrupted [name="
+ svcCtx.name() +
-                                            ", execId=" + svcCtx.executionId() + ']');
-                                }
-                                else {
-                                    U.error(log, "Service execution stopped with error [name="
+ svcCtx.name() +
-                                        ", execId=" + svcCtx.executionId() + ']', e);
-                                }
-                            }
-                            catch (Throwable e) {
-                                log.error("Service execution stopped with error [name=" +
svcCtx.name() +
-                                    ", execId=" + svcCtx.executionId() + ']', e);
+            if (log.isInfoEnabled())
+                log.info("Starting service instance [name=" + svcCtx.name() + ", execId="
+
+                    svcCtx.executionId() + ']');
 
-                                if (e instanceof Error)
-                                    throw (Error)e;
-                            }
-                            finally {
-                                // Suicide.
-                                exe.shutdownNow();
-                            }
+            // Start service in its own thread.
+            final ExecutorService exe = svcCtx.executor();
+
+            exe.submit(new Runnable() {
+                @Override public void run() {
+                    try {
+                        svc.execute(svcCtx);
+                    }
+                    catch (InterruptedException | IgniteInterruptedCheckedException ignore)
{
+                        if (log.isDebugEnabled())
+                            log.debug("Service thread was interrupted [name=" + svcCtx.name()
+ ", execId=" +
+                                svcCtx.executionId() + ']');
+                    }
+                    catch (IgniteException e) {
+                        if (e.hasCause(InterruptedException.class) ||
+                            e.hasCause(IgniteInterruptedCheckedException.class)) {
+                            if (log.isDebugEnabled())
+                                log.debug("Service thread was interrupted [name=" + svcCtx.name()
+
+                                    ", execId=" + svcCtx.executionId() + ']');
                         }
-                    });
+                        else {
+                            U.error(log, "Service execution stopped with error [name=" +
svcCtx.name() +
+                                ", execId=" + svcCtx.executionId() + ']', e);
+                        }
+                    }
+                    catch (Throwable e) {
+                        log.error("Service execution stopped with error [name=" + svcCtx.name()
+
+                            ", execId=" + svcCtx.executionId() + ']', e);
+
+                        if (e instanceof Error)
+                            throw (Error)e;
+                    }
+                    finally {
+                        // Suicide.
+                        exe.shutdownNow();
+                    }
                 }
-            }
+            });
         }
     }
 
@@ -1040,22 +1075,26 @@ public class GridServiceProcessor extends GridProcessorAdapter {
             svcCtx.setCancelled(true);
 
             // Notify service about cancellation.
-            try {
-                svcCtx.service().cancel(svcCtx);
-            }
-            catch (Throwable e) {
-                log.error("Failed to cancel service (ignoring) [name=" + svcCtx.name() +
-                    ", execId=" + svcCtx.executionId() + ']', e);
+            Service svc = svcCtx.service();
 
-                if (e instanceof Error)
-                    throw e;
-            }
-            finally {
+            if (svc != null) {
                 try {
-                    ctx.resource().cleanup(svcCtx.service());
+                    svc.cancel(svcCtx);
                 }
-                catch (IgniteCheckedException e) {
-                    log.error("Failed to clean up service (will ignore): " + svcCtx.name(),
e);
+                catch (Throwable e) {
+                    log.error("Failed to cancel service (ignoring) [name=" + svcCtx.name()
+
+                        ", execId=" + svcCtx.executionId() + ']', e);
+
+                    if (e instanceof Error)
+                        throw e;
+                }
+                finally {
+                    try {
+                        ctx.resource().cleanup(svc);
+                    }
+                    catch (IgniteCheckedException e) {
+                        U.error(log, "Failed to clean up service (will ignore): " + svcCtx.name(),
e);
+                    }
                 }
             }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/718cf78b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProxy.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProxy.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProxy.java
index 578c549..564a13a 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProxy.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/GridServiceProxy.java
@@ -40,7 +40,7 @@ import org.apache.ignite.cluster.ClusterGroup;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.internal.GridClosureCallMode;
 import org.apache.ignite.internal.GridKernalContext;
-import org.apache.ignite.internal.IgniteKernal;
+import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.cluster.ClusterTopologyCheckedException;
 import org.apache.ignite.internal.util.tostring.GridToStringExclude;
 import org.apache.ignite.internal.util.typedef.F;
@@ -48,6 +48,7 @@ import org.apache.ignite.internal.util.typedef.internal.S;
 import org.apache.ignite.internal.util.typedef.internal.U;
 import org.apache.ignite.lang.IgniteCallable;
 import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.services.Service;
 import org.jsr166.ThreadLocalRandom8;
 
 /**
@@ -157,8 +158,12 @@ public class GridServiceProxy<T> implements Serializable {
                     if (node.isLocal()) {
                         ServiceContextImpl svcCtx = ctx.service().serviceContext(name);
 
-                        if (svcCtx != null)
-                            return mtd.invoke(svcCtx.service(), args);
+                        if (svcCtx != null) {
+                            Service svc = svcCtx.service();
+
+                            if (svc != null)
+                                return mtd.invoke(svc, args);
+                        }
                     }
                     else {
                         // Execute service remotely.
@@ -372,9 +377,9 @@ public class GridServiceProxy<T> implements Serializable {
 
         /** {@inheritDoc} */
         @Override public Object call() throws Exception {
-            ServiceContextImpl svcCtx = ((IgniteKernal) ignite).context().service().serviceContext(svcName);
+            ServiceContextImpl svcCtx = ((IgniteEx)ignite).context().service().serviceContext(svcName);
 
-            if (svcCtx == null)
+            if (svcCtx == null || svcCtx.service() == null)
                 throw new GridServiceNotFoundException(svcName);
 
             GridServiceMethodReflectKey key = new GridServiceMethodReflectKey(mtdName, argTypes);

http://git-wip-us.apache.org/repos/asf/ignite/blob/718cf78b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceContextImpl.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceContextImpl.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceContextImpl.java
index 6746e29..66061d5 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceContextImpl.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/service/ServiceContextImpl.java
@@ -50,10 +50,6 @@ public class ServiceContextImpl implements ServiceContext {
     /** Affinity key. */
     private final Object affKey;
 
-    /** Service. */
-    @GridToStringExclude
-    private final Service svc;
-
     /** Executor service. */
     @GridToStringExclude
     private final ExecutorService exe;
@@ -61,25 +57,29 @@ public class ServiceContextImpl implements ServiceContext {
     /** Methods reflection cache. */
     private final ConcurrentMap<GridServiceMethodReflectKey, Method> mtds = new ConcurrentHashMap<>();
 
+    /** Service. */
+    @GridToStringExclude
+    private volatile Service svc;
+
     /** Cancelled flag. */
     private volatile boolean isCancelled;
 
-
     /**
      * @param name Service name.
      * @param execId Execution ID.
      * @param cacheName Cache name.
      * @param affKey Affinity key.
-     * @param svc Service.
      * @param exe Executor service.
      */
-    ServiceContextImpl(String name, UUID execId, String cacheName, Object affKey, Service
svc,
+    ServiceContextImpl(String name,
+        UUID execId,
+        String cacheName,
+        Object affKey,
         ExecutorService exe) {
         this.name = name;
         this.execId = execId;
         this.cacheName = cacheName;
         this.affKey = affKey;
-        this.svc = svc;
         this.exe = exe;
     }
 
@@ -110,9 +110,16 @@ public class ServiceContextImpl implements ServiceContext {
     }
 
     /**
-     * @return Service instance.
+     * @param svc Service instance.
+     */
+    void service(Service svc) {
+        this.svc = svc;
+    }
+
+    /**
+     * @return Service instance or {@code null} if service initialization is not finished
yet.
      */
-    Service service() {
+    @Nullable Service service() {
         return svc;
     }
 
@@ -136,7 +143,7 @@ public class ServiceContextImpl implements ServiceContext {
 
                 mtd.setAccessible(true);
             }
-            catch (NoSuchMethodException e) {
+            catch (NoSuchMethodException ignored) {
                 mtd = NULL_METHOD;
             }
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/718cf78b/modules/spring/src/test/java/org/apache/ignite/spring/injection/GridServiceInjectionSpringResourceTest.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/spring/injection/GridServiceInjectionSpringResourceTest.java
b/modules/spring/src/test/java/org/apache/ignite/spring/injection/GridServiceInjectionSpringResourceTest.java
new file mode 100644
index 0000000..c6a6d05
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/spring/injection/GridServiceInjectionSpringResourceTest.java
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.spring.injection;
+
+import java.io.InputStreamReader;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.internal.util.typedef.G;
+import org.apache.ignite.lang.IgniteCallable;
+import org.apache.ignite.resources.ServiceResource;
+import org.apache.ignite.resources.SpringResource;
+import org.apache.ignite.services.Service;
+import org.apache.ignite.services.ServiceContext;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.FileSystemXmlApplicationContext;
+
+import javax.annotation.PostConstruct;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+/**
+ * Tests for injected service.
+ */
+public class GridServiceInjectionSpringResourceTest extends GridCommonAbstractTest {
+    /** Service name. */
+    private static final String SERVICE_NAME = "testService";
+
+    /** Bean name. */
+    private static final String DUMMY_BEAN = "dummyResourceBean";
+
+    /** */
+    private static final int NODES = 8;
+
+    /** */
+    private static final int TEST_ITERATIONS = 5;
+
+    /** */
+    private static FileSystem FS = FileSystems.getDefault();
+
+    /** */
+    private static final String springCfgFileTemplate = "spring-resource.tmpl.xml";
+
+    /** */
+    private static String springCfgFileOutTmplName = "spring-resource.xml-";
+
+    /** {@inheritDoc} */
+    @Override protected void afterTest() throws Exception {
+        stopAllGrids();
+
+        for (int i = 0; i < NODES; ++i)
+            Files.deleteIfExists(FS.getPath(springCfgFileOutTmplName + i));
+
+        super.afterTest();
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testDeployServiceWithSpring() throws Exception {
+        generateConfigXmls(NODES);
+
+        for (int i = 0; i < TEST_ITERATIONS; ++i) {
+            log.info("Iteration: " + i);
+
+            doOneTestIteration();
+        }
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    private void doOneTestIteration() throws Exception {
+        startNodes();
+
+        for (int i = 0; i < 10; ++i) {
+            for (Ignite ignite : G.allGrids())
+                ignite.compute().call(new TestJob());
+        }
+
+        stopAllGrids();
+    }
+
+    /**
+     *
+     * @throws Exception If failed.
+     */
+    private void startNodes() throws Exception {
+        AbstractApplicationContext ctxSpring = new FileSystemXmlApplicationContext(springCfgFileOutTmplName
+ 0);
+
+        // We have to deploy Services for service is available at the bean creation time
for other nodes.
+        Ignite ignite = (Ignite)ctxSpring.getBean("testIgnite");
+
+        ignite.services().deployMultiple(SERVICE_NAME, new DummyServiceImpl(), NODES, 1);
+
+        // Add other nodes.
+        for (int i = 1; i < NODES; ++i)
+            new FileSystemXmlApplicationContext(springCfgFileOutTmplName + i);
+
+        assertEquals(NODES, G.allGrids().size());
+        assertEquals(NODES, ignite.cluster().nodes().size());
+    }
+
+    /**
+     * @param nodes Nodes.
+     * @throws IOException on read/write config error
+     */
+    private void generateConfigXmls(int nodes) throws IOException {
+        StringBuilder cfg = new StringBuilder();
+
+        try (BufferedReader br = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(springCfgFileTemplate))))
{
+            while (true) {
+                String str = br.readLine();
+
+                if (str == null)
+                    break;
+
+                cfg.append(str);
+            }
+        }
+
+        for (int i = 0; i < nodes; ++i) {
+            try (BufferedWriter bw = Files.newBufferedWriter(FS.getPath(springCfgFileOutTmplName
+ i), UTF_8)) {
+                String str = cfg.toString();
+
+                str = str.replaceAll("@GRID_IDX@", Integer.toString(i));
+
+                bw.write(str);
+            }
+        }
+    }
+
+    /**
+     *
+     */
+    private static class TestJob implements IgniteCallable {
+        /** */
+        @ServiceResource(serviceName = SERVICE_NAME, proxyInterface = DummyService.class)
+        private DummyService svc;
+
+        /** {@inheritDoc} */
+        @Override public Object call() throws Exception {
+            assertNotNull(svc);
+
+            svc.noop();
+
+            return null;
+        }
+    }
+
+    /**
+     * Dummy Service.
+     */
+    public interface DummyService {
+        /**
+         *
+         */
+        void noop();
+    }
+
+    /**
+     * No-op test service.
+     */
+    public static class DummyServiceImpl implements DummyService, Service {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** */
+        @SpringResource(resourceName = DUMMY_BEAN)
+        private transient DummyResourceBean dummyRsrcBean;
+
+        /** {@inheritDoc} */
+        @Override public void noop() {
+            System.out.println("DummyServiceImpl.noop()");
+        }
+
+        /** {@inheritDoc} */
+        @Override public void cancel(ServiceContext ctx) {
+            System.out.println("Cancelling service: " + ctx.name());
+        }
+
+        /** {@inheritDoc} */
+        @Override public void init(ServiceContext ctx) throws Exception {
+            System.out.println("Initializing service: " + ctx.name());
+        }
+
+        /** {@inheritDoc} */
+        @Override public void execute(ServiceContext ctx) {
+            System.out.println("Executing service: " + ctx.name());
+        }
+    }
+
+    /**
+     * Dummy resource bean.
+     */
+    public static class DummyResourceBean {
+        /** */
+        private transient Ignite ignite;
+
+        /**
+         * @return Ignite.
+         */
+        public Ignite getIgnite() {
+            return ignite;
+        }
+
+        /**
+         * @param ignite Ignite.
+         */
+        public void setIgnite(Ignite ignite) {
+            this.ignite = ignite;
+        }
+
+        /**
+         * @throws Exception If failed.
+         */
+        @PostConstruct
+        public void init() throws Exception {
+            DummyService srv = ignite.services().serviceProxy(SERVICE_NAME, DummyService.class,
false);
+
+            assertNotNull(srv);
+        }
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/ignite/blob/718cf78b/modules/spring/src/test/java/org/apache/ignite/spring/injection/spring-resource.tmpl.xml
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/spring/injection/spring-resource.tmpl.xml
b/modules/spring/src/test/java/org/apache/ignite/spring/injection/spring-resource.tmpl.xml
new file mode 100644
index 0000000..aeee4ec
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/spring/injection/spring-resource.tmpl.xml
@@ -0,0 +1,66 @@
+<?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"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xsi:schemaLocation="
+        http://www.springframework.org/schema/beans
+        http://www.springframework.org/schema/beans/spring-beans.xsd
+        http://www.springframework.org/schema/context
+        http://www.springframework.org/schema/context/spring-context.xsd">
+
+    <context:annotation-config/>
+
+    <bean id="dummyResourceBean"
+          class="org.apache.ignite.spring.injection.GridServiceInjectionSpringResourceTest$DummyResourceBean">
+        <property name="ignite" ref="testIgnite"/>
+    </bean>
+
+
+    <bean id="testIgnite" class="org.apache.ignite.IgniteSpringBean">
+        <property name="configuration">
+            <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
+                <property name="localHost" value="127.0.0.1"/>
+
+                <property name="gridName" value="springTest@GRID_IDX@"/>
+
+                <property name="discoverySpi">
+                    <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi">
+                        <property name="ipFinder">
+                            <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">
+                                <property name="addresses">
+                                    <list>
+                                        <value>127.0.0.1:47500</value>
+                                        <value>127.0.0.1:47501</value>
+                                        <value>127.0.0.1:47502</value>
+                                        <value>127.0.0.1:47503</value>
+                                        <value>127.0.0.1:47504</value>
+                                        <value>127.0.0.1:47505</value>
+                                        <value>127.0.0.1:47506</value>
+                                        <value>127.0.0.1:47507</value>
+                                    </list>
+                                </property>
+                            </bean>
+                        </property>
+                    </bean>
+                </property>
+            </bean>
+        </property>
+    </bean>
+</beans>

http://git-wip-us.apache.org/repos/asf/ignite/blob/718cf78b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
index c42c7e0..4fc159e 100644
--- a/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
+++ b/modules/spring/src/test/java/org/apache/ignite/testsuites/IgniteSpringTestSuite.java
@@ -28,6 +28,7 @@ import org.apache.ignite.p2p.GridP2PUserVersionChangeSelfTest;
 import org.apache.ignite.spring.GridSpringCacheManagerSelfTest;
 import org.apache.ignite.spring.IgniteExcludeInConfigurationTest;
 import org.apache.ignite.spring.IgniteStartFromStreamConfigurationTest;
+import org.apache.ignite.spring.injection.GridServiceInjectionSpringResourceTest;
 import org.apache.ignite.transactions.spring.GridSpringTransactionManagerSelfTest;
 
 /**
@@ -65,6 +66,8 @@ public class IgniteSpringTestSuite extends TestSuite {
 
         suite.addTest(new TestSuite(GridSpringTransactionManagerSelfTest.class));
 
+        suite.addTestSuite(GridServiceInjectionSpringResourceTest.class);
+
         return suite;
     }
 }


Mime
View raw message