You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2016/08/31 03:40:06 UTC

[2/9] ignite git commit: ignite-2560 Support resource injection for entry processor, optimizations for resource injection.

http://git-wip-us.apache.org/repos/asf/ignite/blob/f9ff97c9/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
index 32d46e2..3f4d812 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractFullApiSelfTest.java
@@ -17,8 +17,6 @@
 
 package org.apache.ignite.internal.processors.cache;
 
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -34,7 +32,10 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.locks.Lock;
 import javax.cache.Cache;
@@ -46,10 +47,13 @@ import javax.cache.processor.EntryProcessor;
 import javax.cache.processor.EntryProcessorException;
 import javax.cache.processor.EntryProcessorResult;
 import javax.cache.processor.MutableEntry;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
 import junit.framework.AssertionFailedError;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
+import org.apache.ignite.IgniteEvents;
 import org.apache.ignite.IgniteException;
 import org.apache.ignite.IgniteLogger;
 import org.apache.ignite.IgniteTransactions;
@@ -61,12 +65,15 @@ import org.apache.ignite.cache.affinity.Affinity;
 import org.apache.ignite.cluster.ClusterNode;
 import org.apache.ignite.configuration.CacheConfiguration;
 import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.events.CacheEvent;
 import org.apache.ignite.events.Event;
+import org.apache.ignite.events.EventType;
 import org.apache.ignite.internal.IgniteEx;
 import org.apache.ignite.internal.IgniteKernal;
 import org.apache.ignite.internal.IgnitionEx;
 import org.apache.ignite.internal.processors.cache.query.GridCacheQueryManager;
 import org.apache.ignite.internal.processors.resource.GridSpringResourceContext;
+import org.apache.ignite.internal.util.future.GridFutureAdapter;
 import org.apache.ignite.internal.util.lang.GridAbsPredicate;
 import org.apache.ignite.internal.util.lang.GridAbsPredicateX;
 import org.apache.ignite.internal.util.lang.IgnitePair;
@@ -76,10 +83,16 @@ import org.apache.ignite.internal.util.typedef.PA;
 import org.apache.ignite.internal.util.typedef.internal.A;
 import org.apache.ignite.internal.util.typedef.internal.CU;
 import org.apache.ignite.internal.util.typedef.internal.U;
+import org.apache.ignite.lang.IgniteBiPredicate;
 import org.apache.ignite.lang.IgniteClosure;
 import org.apache.ignite.lang.IgniteFuture;
 import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.resources.CacheNameResource;
+import org.apache.ignite.resources.IgniteInstanceResource;
 import org.apache.ignite.resources.LoggerResource;
+import org.apache.ignite.resources.ServiceResource;
+import org.apache.ignite.services.Service;
+import org.apache.ignite.services.ServiceContext;
 import org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.swapspace.inmemory.GridTestSwapSpaceSpi;
@@ -124,6 +137,9 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     /** Test timeout */
     private static final long TEST_TIMEOUT = 60 * 1000;
 
+    /** Service name. */
+    private static final String SERVICE_NAME1 = "testService1";
+
     /** */
     public static final CacheEntryProcessor<String, Integer, String> ERR_PROCESSOR =
         new CacheEntryProcessor<String, Integer, String>() {
@@ -202,6 +218,21 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         if (memoryMode() == OFFHEAP_TIERED || memoryMode() == OFFHEAP_VALUES)
             cfg.setSwapSpaceSpi(new GridTestSwapSpaceSpi());
 
+        int[] evtTypes = cfg.getIncludeEventTypes();
+
+        if (evtTypes == null || evtTypes.length == 0)
+            cfg.setIncludeEventTypes(EventType.EVT_CACHE_OBJECT_READ);
+        else {
+            for (int evtType : evtTypes) {
+                if (evtType == EventType.EVT_CACHE_OBJECT_READ)
+                    return cfg;
+            }
+
+            int[] updatedEvtTypes = Arrays.copyOf(evtTypes, evtTypes.length + 1);
+
+            updatedEvtTypes[updatedEvtTypes.length - 1] = EventType.EVT_CACHE_OBJECT_READ;
+        }
+
         return cfg;
     }
 
@@ -261,6 +292,18 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             cacheCfgMap = null;
         }
 
+        // We won't deploy service unless non-client node is configured.
+        for (int i = 0; i < gridCount(); i++) {
+            Boolean clientMode = grid(i).configuration().isClientMode();
+
+            if (clientMode)
+                continue;
+
+            grid(0).services(grid(0).cluster()).deployNodeSingleton(SERVICE_NAME1, new DummyServiceImpl());
+
+            break;
+        }
+
         for (int i = 0; i < gridCount(); i++)
             info("Grid " + i + ": " + grid(i).localNode().id());
     }
@@ -619,9 +662,9 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         cache.put("key1", 1);
         cache.put("key2", 2);
 
-        CacheEntry<String, Integer> key1e =  cache.getEntry("key1");
-        CacheEntry<String, Integer> key2e =  cache.getEntry("key2");
-        CacheEntry<String, Integer> wrongKeye =  cache.getEntry("wrongKey");
+        CacheEntry<String, Integer> key1e = cache.getEntry("key1");
+        CacheEntry<String, Integer> key2e = cache.getEntry("key2");
+        CacheEntry<String, Integer> wrongKeye = cache.getEntry("wrongKey");
 
         assert key1e.getValue() == 1;
         assert key1e.getKey().equals("key1");
@@ -781,7 +824,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         boolean b1 = false;
         boolean b2 = false;
 
-        for (CacheEntry<String, Integer> e: c1){
+        for (CacheEntry<String, Integer> e : c1) {
             if (e.getKey().equals("key1") && e.getValue().equals(1))
                 b1 = true;
 
@@ -800,7 +843,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         b1 = false;
         b2 = false;
 
-        for (CacheEntry<String, Integer> e: c2){
+        for (CacheEntry<String, Integer> e : c2) {
             if (e.getKey().equals("key1") && e.getValue().equals(1))
                 b1 = true;
 
@@ -1481,8 +1524,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     private void checkTransformReturnValue(boolean put,
         TransactionConcurrency concurrency,
         TransactionIsolation isolation)
-        throws Exception
-    {
+        throws Exception {
         IgniteCache<String, Integer> cache = jcache();
 
         if (!put)
@@ -1790,7 +1832,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             cache.put(key, 1);
 
-            assertEquals(1, (int) cache.get(key));
+            assertEquals(1, (int)cache.get(key));
 
             GridTestUtils.assertThrows(log, new Callable<Void>() {
                 @Override public Void call() throws Exception {
@@ -1808,7 +1850,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
                 }
             }, NullPointerException.class, null);
 
-            assertEquals(1, (int) cache.get(key));
+            assertEquals(1, (int)cache.get(key));
 
             cache.put(key, 2);
 
@@ -1839,7 +1881,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             assertNull(cache.get("k1"));
             assertNull(cache.get("k2"));
 
-            assertEquals(2, (int) cache.get(key));
+            assertEquals(2, (int)cache.get(key));
 
             cache.put(key, 3);
 
@@ -1890,7 +1932,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             cache.putAll(m);
 
-            assertEquals(3, (int) cache.get("key3"));
+            assertEquals(3, (int)cache.get("key3"));
             assertEquals(4, (int)cache.get("key4"));
         }
 
@@ -2215,7 +2257,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     }
 
     /**
-     * @param  inTx In tx flag.
+     * @param inTx In tx flag.
      * @throws Exception If failed.
      */
     private void checkPutxIfAbsentAsync(boolean inTx) throws Exception {
@@ -2857,7 +2899,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     /**
      * @return Count of entries to be removed in removeAll() test.
      */
-    protected long hugeRemoveAllEntryCount(){
+    protected long hugeRemoveAllEntryCount() {
         return 1000L;
     }
 
@@ -3627,7 +3669,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
                 assertNotNull(curEntryTtl.get1());
                 assertNotNull(curEntryTtl.get2());
-                assertEquals(ttl, (long) curEntryTtl.get1());
+                assertEquals(ttl, (long)curEntryTtl.get1());
                 assertTrue(curEntryTtl.get2() > startTime);
 
                 expireTimes[i] = curEntryTtl.get2();
@@ -3656,7 +3698,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
                 assertNotNull(curEntryTtl.get1());
                 assertNotNull(curEntryTtl.get2());
-                assertEquals(ttl, (long) curEntryTtl.get1());
+                assertEquals(ttl, (long)curEntryTtl.get1());
                 assertTrue(curEntryTtl.get2() > startTime);
 
                 expireTimes[i] = curEntryTtl.get2();
@@ -3685,7 +3727,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
                 assertNotNull(curEntryTtl.get1());
                 assertNotNull(curEntryTtl.get2());
-                assertEquals(ttl, (long) curEntryTtl.get1());
+                assertEquals(ttl, (long)curEntryTtl.get1());
                 assertTrue(curEntryTtl.get2() > startTime);
 
                 expireTimes[i] = curEntryTtl.get2();
@@ -3897,7 +3939,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             cache.localPromote(Collections.singleton(k2));
 
-            assertEquals((Integer) 2, cache.localPeek(k2, ONHEAP_PEEK_MODES));
+            assertEquals((Integer)2, cache.localPeek(k2, ONHEAP_PEEK_MODES));
 
             cnt++;
         }
@@ -5021,7 +5063,6 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
      * @param keys Keys list.
      * @param txConcurrency Concurrency mode.
      * @param txIsolation Isolation mode.
-     *
      * @throws Exception If failed.
      */
     private void checkSkipStoreWithTransaction(IgniteCache<String, Integer> cache,
@@ -5030,8 +5071,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         List<String> keys,
         TransactionConcurrency txConcurrency,
         TransactionIsolation txIsolation)
-        throws  Exception
-    {
+        throws Exception {
         info("Test tx skip store [concurrency=" + txConcurrency + ", isolation=" + txIsolation + ']');
 
         cache.removeAll(data.keySet());
@@ -5043,10 +5083,10 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         // Several put check.
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
-            for (String key: keys)
+            for (String key : keys)
                 cacheSkipStore.put(key, val);
 
-            for (String key: keys) {
+            for (String key : keys) {
                 assertEquals(val, cacheSkipStore.get(key));
                 assertEquals(val, cache.get(key));
                 assertFalse(storeStgy.isInStore(key));
@@ -5055,7 +5095,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             tx.commit();
         }
 
-        for (String key: keys) {
+        for (String key : keys) {
             assertEquals(val, cacheSkipStore.get(key));
             assertEquals(val, cache.get(key));
             assertFalse(storeStgy.isInStore(key));
@@ -5070,7 +5110,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             tx.commit();
         }
 
-        for (String key: keys) {
+        for (String key : keys) {
             val = data.get(key);
 
             assertEquals(val, cacheSkipStore.get(key));
@@ -5086,7 +5126,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             tx.commit();
         }
 
-        for (String key: keys) {
+        for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNotNull(cache.get(key));
             assertTrue(storeStgy.isInStore(key));
@@ -5100,7 +5140,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         try (Transaction tx = txs.txStart(txConcurrency, txIsolation)) {
             cache.putAll(data);
 
-            for (String key: keys) {
+            for (String key : keys) {
                 assertNotNull(cacheSkipStore.get(key));
                 assertNotNull(cache.get(key));
                 assertFalse(storeStgy.isInStore(key));
@@ -5108,7 +5148,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             cache.removeAll(data.keySet());
 
-            for (String key: keys) {
+            for (String key : keys) {
                 assertNull(cacheSkipStore.get(key));
                 assertNull(cache.get(key));
                 assertFalse(storeStgy.isInStore(key));
@@ -5135,7 +5175,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
             cache.putAll(subMap);
 
-            for (String key: keys) {
+            for (String key : keys) {
                 assertNotNull(cacheSkipStore.get(key));
                 assertNotNull(cache.get(key));
                 assertFalse(storeStgy.isInStore(key));
@@ -5162,7 +5202,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
 
         cache.removeAll(data.keySet());
 
-        for (String key: keys) {
+        for (String key : keys) {
             assertNull(cacheSkipStore.get(key));
             assertNull(cache.get(key));
             assertFalse(storeStgy.isInStore(key));
@@ -5257,7 +5297,6 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     /**
      * @param cache Cache instance.
      * @param cacheSkipStore Cache skip store projection.
-     *
      * @throws Exception If failed.
      */
     private void checkEmpty(IgniteCache<String, Integer> cache, IgniteCache<String, Integer> cacheSkipStore)
@@ -5426,6 +5465,155 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     }
 
     /**
+     * @throws Exception If failed.
+     */
+    public void testTransformResourceInjection() throws Exception {
+        IgniteCache<String, Integer> cache = jcache();
+        Ignite ignite = ignite(0);
+
+        doTransformResourceInjection(ignite, cache);
+        doTransformResourceInjection(ignite, cache.withAsync());
+
+        if (txEnabled()) {
+            doTransformResourceInjectionInTx(ignite, cache);
+            doTransformResourceInjectionInTx(ignite, cache.withAsync());
+        }
+    }
+
+    /**
+     * @param ignite Node.
+     * @param cache Cache.
+     * @throws Exception If failed.
+     */
+    private void doTransformResourceInjectionInTx(Ignite ignite, IgniteCache<String, Integer> cache) throws Exception {
+        for (TransactionConcurrency concurrency : TransactionConcurrency.values()) {
+            for (TransactionIsolation isolation : TransactionIsolation.values()) {
+                IgniteTransactions txs = ignite.transactions();
+
+                try (Transaction tx = txs.txStart(concurrency, isolation)) {
+                    doTransformResourceInjection(ignite, cache);
+
+                    tx.commit();
+                }
+            }
+        }
+    }
+
+    /**
+     * @param ignite Node.
+     * @param cache Cache.
+     * @throws Exception If failed.
+     */
+    private void doTransformResourceInjection(Ignite ignite, IgniteCache<String, Integer> cache) throws Exception {
+        final Collection<ResourceType> required = Arrays.asList(ResourceType.IGNITE_INSTANCE,
+            ResourceType.CACHE_NAME,
+            ResourceType.LOGGER,
+            ResourceType.SERVICE);
+
+        final CacheEventListener lsnr = new CacheEventListener();
+
+        IgniteEvents evts = ignite.events(ignite.cluster());
+
+        UUID opId = evts.remoteListen(lsnr, null, EventType.EVT_CACHE_OBJECT_READ);
+
+        try {
+            checkResourceInjectionOnInvoke(cache, required);
+
+            checkResourceInjectionOnInvokeAll(cache, required);
+
+            checkResourceInjectionOnInvokeAllMap(cache, required);
+        }
+        finally {
+            evts.stopRemoteListen(opId);
+        }
+    }
+
+    /**
+     * Tests invokeAll method for map of pairs (key, entryProcessor).
+     *
+     * @param cache Cache.
+     * @param required Expected injected resources.
+     */
+    private void checkResourceInjectionOnInvokeAllMap(IgniteCache<String, Integer> cache,
+        Collection<ResourceType> required) {
+        Map<String, EntryProcessorResult<Integer>> results;
+
+        Map<String, EntryProcessor<String, Integer, Integer>> map = new HashMap<>();
+
+        map.put(UUID.randomUUID().toString(), new ResourceInjectionEntryProcessor());
+        map.put(UUID.randomUUID().toString(), new ResourceInjectionEntryProcessor());
+        map.put(UUID.randomUUID().toString(), new ResourceInjectionEntryProcessor());
+        map.put(UUID.randomUUID().toString(), new ResourceInjectionEntryProcessor());
+
+        results = cache.invokeAll(map);
+
+        if (cache.isAsync())
+            results = cache.<Map<String, EntryProcessorResult<Integer>>>future().get();
+
+        assertEquals(map.size(), results.size());
+
+        for (EntryProcessorResult<Integer> res : results.values()) {
+            Collection<ResourceType> notInjected = ResourceInfoSet.valueOf(res.get()).notInjected(required);
+
+            if (!notInjected.isEmpty())
+                fail("Can't inject resource(s): " + Arrays.toString(notInjected.toArray()));
+        }
+    }
+
+    /**
+     * Tests invokeAll method for set of keys.
+     *
+     * @param cache Cache.
+     * @param required Expected injected resources.
+     */
+    private void checkResourceInjectionOnInvokeAll(IgniteCache<String, Integer> cache,
+        Collection<ResourceType> required) {
+        Set<String> keys = new HashSet<>(Arrays.asList(UUID.randomUUID().toString(),
+            UUID.randomUUID().toString(),
+            UUID.randomUUID().toString(),
+            UUID.randomUUID().toString()));
+
+        Map<String, EntryProcessorResult<Integer>> results = cache.invokeAll(keys,
+            new ResourceInjectionEntryProcessor());
+
+        if (cache.isAsync())
+            results = cache.<Map<String, EntryProcessorResult<Integer>>>future().get();
+
+        assertEquals(keys.size(), results.size());
+
+        for (EntryProcessorResult<Integer> res : results.values()) {
+            Collection<ResourceType> notInjected1 = ResourceInfoSet.valueOf(res.get()).notInjected(required);
+
+            if (!notInjected1.isEmpty())
+                fail("Can't inject resource(s): " + Arrays.toString(notInjected1.toArray()));
+        }
+    }
+
+    /**
+     * Tests invoke for single key.
+     *
+     * @param cache Cache.
+     * @param required Expected injected resources.
+     */
+    private void checkResourceInjectionOnInvoke(IgniteCache<String, Integer> cache,
+        Collection<ResourceType> required) {
+
+        String key = UUID.randomUUID().toString();
+
+        Integer flags = cache.invoke(key, new GridCacheAbstractFullApiSelfTest.ResourceInjectionEntryProcessor());
+
+        if (cache.isAsync())
+            flags = cache.<Integer>future().get();
+
+        assertTrue("Processor result is null", flags != null);
+
+        Collection<ResourceType> notInjected = ResourceInfoSet.valueOf(flags).notInjected(required);
+
+        if (!notInjected.isEmpty())
+            fail("Can't inject resource(s): " + Arrays.toString(notInjected.toArray()));
+    }
+
+    /**
      * Sets given value, returns old value.
      */
     public static final class SetValueProcessor implements EntryProcessor<String, Integer, Integer> {
@@ -5440,7 +5628,8 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         }
 
         /** {@inheritDoc} */
-        @Override public Integer process(MutableEntry<String, Integer> entry, Object... arguments) throws EntryProcessorException {
+        @Override public Integer process(MutableEntry<String, Integer> entry,
+            Object... arguments) throws EntryProcessorException {
             Integer val = entry.getValue();
 
             entry.setValue(newVal);
@@ -5498,6 +5687,86 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
     /**
      *
      */
+    public static class ResourceInjectionEntryProcessor extends ResourceInjectionEntryProcessorBase<String, Integer> {
+        /** */
+        protected transient Ignite ignite;
+
+        /** */
+        protected transient String cacheName;
+
+        /** */
+        protected transient IgniteLogger log;
+
+        /** */
+        protected transient DummyService svc;
+
+        /**
+         * @param ignite Ignite.
+         */
+        @IgniteInstanceResource
+        public void setIgnite(Ignite ignite) {
+            assert ignite != null;
+
+            checkSet();
+
+            infoSet.set(ResourceType.IGNITE_INSTANCE, true);
+
+            this.ignite = ignite;
+        }
+
+        /**
+         * @param cacheName Cache name.
+         */
+        @CacheNameResource
+        public void setCacheName(String cacheName) {
+            checkSet();
+
+            infoSet.set(ResourceType.CACHE_NAME, true);
+
+            this.cacheName = cacheName;
+        }
+
+        /**
+         * @param log Logger.
+         */
+        @LoggerResource
+        public void setLoggerResource(IgniteLogger log) {
+            assert log != null;
+
+            checkSet();
+
+            infoSet.set(ResourceType.LOGGER, true);
+
+            this.log = log;
+        }
+
+        /**
+         * @param svc Service.
+         */
+        @ServiceResource(serviceName = SERVICE_NAME1)
+        public void setDummyService(DummyService svc) {
+            assert svc != null;
+
+            checkSet();
+
+            infoSet.set(ResourceType.SERVICE, true);
+
+            this.svc = svc;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Integer process(MutableEntry<String, Integer> e, Object... args) {
+            Integer oldVal = e.getValue();
+
+            e.setValue(ThreadLocalRandom.current().nextInt() + (oldVal == null ? 0 : oldVal));
+
+            return super.process(e, args);
+        }
+    }
+
+    /**
+     *
+     */
     private static class CheckEntriesTask extends TestIgniteIdxRunnable {
         /** Keys. */
         private final Collection<String> keys;
@@ -5674,6 +5943,7 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
      *
      */
     private static class SwapEvtsLocalListener implements IgnitePredicate<Event> {
+        /** */
         @LoggerResource
         private IgniteLogger log;
 
@@ -5711,13 +5981,21 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
         }
     }
 
+    /**
+     *
+     */
     private static class CheckEntriesDeletedTask extends TestIgniteIdxRunnable {
+        /** */
         private final int cnt;
 
+        /**
+         * @param cnt Keys count.
+         */
         public CheckEntriesDeletedTask(int cnt) {
             this.cnt = cnt;
         }
 
+        /** {@inheritDoc} */
         @Override public void run(int idx) throws Exception {
             for (int i = 0; i < cnt; i++) {
                 String key = String.valueOf(i);
@@ -5816,4 +6094,64 @@ public abstract class GridCacheAbstractFullApiSelfTest extends GridCacheAbstract
             return val;
         }
     }
+
+    /**
+     * Dummy Service.
+     */
+    public interface DummyService {
+        /**
+         *
+         */
+        public void noop();
+    }
+
+    /**
+     * No-op test service.
+     */
+    public static class DummyServiceImpl implements DummyService, Service {
+        /** */
+        private static final long serialVersionUID = 0L;
+
+        /** {@inheritDoc} */
+        @Override public void noop() {
+            // No-op.
+        }
+
+        /** {@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());
+        }
+    }
+
+    /**
+     *
+     */
+    public static class CacheEventListener implements IgniteBiPredicate<UUID, CacheEvent>, IgnitePredicate<CacheEvent> {
+        /** */
+        public final LinkedBlockingQueue<CacheEvent> evts = new LinkedBlockingQueue<>();
+
+        /** {@inheritDoc} */
+        @Override public boolean apply(UUID uuid, CacheEvent evt) {
+            evts.add(evt);
+
+            return true;
+        }
+
+        /** {@inheritDoc} */
+        @Override public boolean apply(CacheEvent evt) {
+            evts.add(evt);
+
+            return true;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f9ff97c9/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
index d58e560..af31635 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/GridCacheAbstractSelfTest.java
@@ -17,9 +17,15 @@
 
 package org.apache.ignite.internal.processors.cache;
 
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.concurrent.atomic.AtomicInteger;
 import javax.cache.Cache;
 import javax.cache.configuration.Factory;
+import javax.cache.processor.EntryProcessor;
+import javax.cache.processor.MutableEntry;
 import org.apache.ignite.Ignite;
 import org.apache.ignite.IgniteCache;
 import org.apache.ignite.IgniteCheckedException;
@@ -80,6 +86,8 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
         int cnt = gridCount();
 
         assert cnt >= 1 : "At least one grid must be started";
@@ -188,7 +196,8 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
         assert jcache().unwrap(Ignite.class).transactions().tx() == null;
         assertEquals("Cache is not empty", 0, jcache().localSize(CachePeekMode.ALL));
 
-        storeStgy.resetStore();
+        if (storeStgy != null)
+            storeStgy.resetStore();
     }
 
     /** {@inheritDoc} */
@@ -410,20 +419,20 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
      */
     protected static IgnitePredicate<Cache.Entry<String, Integer>> entryKeyFilter =
         new P1<Cache.Entry<String, Integer>>() {
-        @Override public boolean apply(Cache.Entry<String, Integer> entry) {
-            return entry.getKey().contains("key");
-        }
-    };
+            @Override public boolean apply(Cache.Entry<String, Integer> entry) {
+                return entry.getKey().contains("key");
+            }
+        };
 
     /**
      * Filters cache entry projections leaving only ones with keys not containing 'key'.
      */
     protected static IgnitePredicate<Cache.Entry<String, Integer>> entryKeyFilterInv =
         new P1<Cache.Entry<String, Integer>>() {
-        @Override public boolean apply(Cache.Entry<String, Integer> entry) {
-            return !entry.getKey().contains("key");
-        }
-    };
+            @Override public boolean apply(Cache.Entry<String, Integer> entry) {
+                return !entry.getKey().contains("key");
+            }
+        };
 
     /**
      * Filters cache entry projections leaving only ones with values less than 50.
@@ -528,4 +537,117 @@ public abstract class GridCacheAbstractSelfTest extends GridCommonAbstractTest {
         }
     }
 
+    /** */
+    protected enum ResourceType {
+        /** */
+        IGNITE_INSTANCE,
+
+        /** */
+        CACHE_NAME,
+
+        /** */
+        SPRING_APPLICATION_CONTEXT,
+
+        /** */
+        LOGGER,
+
+        /** */
+        SERVICE,
+
+        /** */
+        SPRING_BEAN,
+
+    }
+
+    /**
+     *
+     */
+    protected static class ResourceInfoSet {
+        /** */
+        int val;
+
+        /** */
+        public ResourceInfoSet() {
+            this(0);
+        }
+
+        /** */
+        public ResourceInfoSet(int val) {
+            this.val = val;
+        }
+
+        /**
+         * @param val Value.
+         */
+        public static ResourceInfoSet valueOf(int val) {
+            return new ResourceInfoSet(val);
+        }
+
+        /** */
+        public int getValue() {
+            return val;
+        }
+
+        /**
+         * @param type Type.
+         * @param injected Injected.
+         */
+        public ResourceInfoSet set(ResourceType type, boolean injected) {
+            int mask = 1 << type.ordinal();
+
+            if (injected)
+                val |= mask;
+            else
+                val &= ~mask;
+
+            return this;
+        }
+
+        /**
+         * @see {@link #set(ResourceType, boolean)}
+         */
+        public ResourceInfoSet set(ResourceType type, Object toCheck) {
+            return set(type, toCheck != null);
+        }
+
+        /**
+         * @return collection of not injected resources
+         */
+        public Collection<ResourceType> notInjected(Collection<ResourceType> exp) {
+            ArrayList<ResourceType> res = null;
+
+            for (ResourceType type : exp) {
+                int mask = 1 << type.ordinal();
+
+                if ((this.val & mask) == 0) {
+                    if (res == null)
+                        res = new ArrayList<>();
+
+                    res.add(type);
+                }
+            }
+
+            return res == null ? Collections.<ResourceType>emptyList() : res;
+        }
+    }
+
+    /**
+     *
+     */
+    protected static abstract class ResourceInjectionEntryProcessorBase<K, V>
+        implements EntryProcessor<K, V, Integer>, Serializable {
+        /** */
+        protected transient ResourceInfoSet infoSet;
+
+        /** {@inheritDoc} */
+        @Override public Integer process(MutableEntry<K, V> e, Object... args) {
+            return infoSet == null ? null : infoSet.getValue();
+        }
+
+        /** */
+        protected void checkSet() {
+            if (infoSet == null)
+                infoSet = new ResourceInfoSet();
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f9ff97c9/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTransformEventSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTransformEventSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTransformEventSelfTest.java
index a3caba6..f36b060 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTransformEventSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/GridCacheTransformEventSelfTest.java
@@ -38,6 +38,7 @@ import org.apache.ignite.events.CacheEvent;
 import org.apache.ignite.events.Event;
 import org.apache.ignite.internal.util.typedef.F;
 import org.apache.ignite.lang.IgnitePredicate;
+import org.apache.ignite.resources.IgniteInstanceResource;
 import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder;
 import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder;
@@ -74,9 +75,6 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
     /** Cache name. */
     private static final String CACHE_NAME = "cache";
 
-    /** Closure name. */
-    private static final String CLO_NAME = Transformer.class.getName();
-
     /** Key 1. */
     private Integer key1;
 
@@ -98,7 +96,7 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
     /** Caches. */
     private IgniteCache<Integer, Integer>[] caches;
 
-    /** Recorded events.*/
+    /** Recorded events. */
     private ConcurrentHashSet<CacheEvent> evts;
 
     /** Cache mode. */
@@ -477,13 +475,25 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
 
         caches[0].invoke(key1, new Transformer());
 
-        checkEventNodeIdsStrict(primaryIdsForKeys(key1));
+        checkEventNodeIdsStrict(Transformer.class.getName(), primaryIdsForKeys(key1));
 
         assert evts.isEmpty();
 
         caches[0].invokeAll(keys, new Transformer());
 
-        checkEventNodeIdsStrict(primaryIdsForKeys(key1, key2));
+        checkEventNodeIdsStrict(Transformer.class.getName(), primaryIdsForKeys(key1, key2));
+
+        assert evts.isEmpty();
+
+        caches[0].invoke(key1, new TransformerWithInjection());
+
+        checkEventNodeIdsStrict(TransformerWithInjection.class.getName(), primaryIdsForKeys(key1));
+
+        assert evts.isEmpty();
+
+        caches[0].invokeAll(keys, new TransformerWithInjection());
+
+        checkEventNodeIdsStrict(TransformerWithInjection.class.getName(), primaryIdsForKeys(key1, key2));
     }
 
     /**
@@ -492,7 +502,6 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
      * @param cacheMode Cache mode.
      * @param txConcurrency TX concurrency.
      * @param txIsolation TX isolation.
-     *
      * @throws Exception If failed.
      */
     private void checkTx(CacheMode cacheMode, TransactionConcurrency txConcurrency,
@@ -505,13 +514,29 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
 
         System.out.println("AFTER: " + evts.size());
 
-        checkEventNodeIdsStrict(idsForKeys(key1));
+        checkEventNodeIdsStrict(Transformer.class.getName(), idsForKeys(key1));
 
         assert evts.isEmpty();
 
         caches[0].invokeAll(keys, new Transformer());
 
-        checkEventNodeIdsStrict(idsForKeys(key1, key2));
+        checkEventNodeIdsStrict(Transformer.class.getName(), idsForKeys(key1, key2));
+
+        assert evts.isEmpty();
+
+        System.out.println("BEFORE: " + evts.size());
+
+        caches[0].invoke(key1, new TransformerWithInjection());
+
+        System.out.println("AFTER: " + evts.size());
+
+        checkEventNodeIdsStrict(TransformerWithInjection.class.getName(), idsForKeys(key1));
+
+        assert evts.isEmpty();
+
+        caches[0].invokeAll(keys, new TransformerWithInjection());
+
+        checkEventNodeIdsStrict(TransformerWithInjection.class.getName(), idsForKeys(key1, key2));
     }
 
     /**
@@ -572,9 +597,10 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
     /**
      * Ensure that events were recorded on the given nodes.
      *
+     * @param cClsName Entry processor class name.
      * @param ids Event IDs.
      */
-    private void checkEventNodeIdsStrict(UUID... ids) {
+    private void checkEventNodeIdsStrict(String cClsName, UUID... ids) {
         if (ids == null)
             assertTrue(evts.isEmpty());
         else {
@@ -585,7 +611,7 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
 
                 for (CacheEvent evt : evts) {
                     if (F.eq(id, evt.node().id())) {
-                        assertEquals(CLO_NAME, evt.closureClassName());
+                        assertEquals(cClsName, evt.closureClassName());
 
                         foundEvt = evt;
 
@@ -625,4 +651,22 @@ public class GridCacheTransformEventSelfTest extends GridCommonAbstractTest {
             return null;
         }
     }
+
+    /**
+     * Transform closure.
+     */
+    private static class TransformerWithInjection implements EntryProcessor<Integer, Integer, Void>, Serializable {
+        /** */
+        @IgniteInstanceResource
+        private transient Ignite ignite;
+
+        /** {@inheritDoc} */
+        @Override public Void process(MutableEntry<Integer, Integer> e, Object... args) {
+            assert ignite != null;
+
+            e.setValue(e.getValue() + 1);
+
+            return null;
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/ignite/blob/f9ff97c9/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedBasicStoreMultiNodeSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedBasicStoreMultiNodeSelfTest.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedBasicStoreMultiNodeSelfTest.java
index e78f329..bcf4ccd 100644
--- a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedBasicStoreMultiNodeSelfTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/distributed/near/GridCachePartitionedBasicStoreMultiNodeSelfTest.java
@@ -70,6 +70,8 @@ public class GridCachePartitionedBasicStoreMultiNodeSelfTest extends GridCommonA
 
     /** {@inheritDoc} */
     @Override protected void beforeTestsStarted() throws Exception {
+        super.beforeTestsStarted();
+
         stores = Collections.synchronizedList(new ArrayList<GridCacheTestStore>());
 
         startGridsMultiThreaded(GRID_CNT);

http://git-wip-us.apache.org/repos/asf/ignite/blob/f9ff97c9/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridTransformSpringInjectionSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridTransformSpringInjectionSelfTest.java b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridTransformSpringInjectionSelfTest.java
new file mode 100644
index 0000000..cc61514
--- /dev/null
+++ b/modules/spring/src/test/java/org/apache/ignite/internal/processors/resource/GridTransformSpringInjectionSelfTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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.internal.processors.resource;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import javax.cache.processor.EntryProcessorResult;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.IgniteSpring;
+import org.apache.ignite.IgniteTransactions;
+import org.apache.ignite.cache.CacheAtomicityMode;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.internal.processors.cache.GridCacheAbstractSelfTest;
+import org.apache.ignite.resources.SpringApplicationContextResource;
+import org.apache.ignite.resources.SpringResource;
+import org.apache.ignite.transactions.Transaction;
+import org.apache.ignite.transactions.TransactionConcurrency;
+import org.apache.ignite.transactions.TransactionIsolation;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import static org.apache.ignite.cache.CacheAtomicityMode.ATOMIC;
+import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
+
+/**
+ *
+ */
+public class GridTransformSpringInjectionSelfTest extends GridCacheAbstractSelfTest {
+    /** {@inheritDoc} */
+    @Override protected int gridCount() {
+        return 1;
+    }
+
+    /** {@inheritDoc} */
+    @Override public void beforeTestsStarted() throws Exception {
+        IgniteSpring.start(getConfiguration(getTestGridName(0)),
+            new ClassPathXmlApplicationContext("/org/apache/ignite/internal/processors/resource/spring-resource.xml"));
+    }
+
+    /**
+     * @throws Exception If failed.
+     */
+    public void testTransformResourceInjection() throws Exception {
+        Ignite grid = grid(0);
+
+        IgniteCache<String, Integer> cache = grid.createCache(cacheConfiguration(ATOMIC));
+
+        try {
+            doTransformResourceInjection(cache);
+        }
+        finally {
+            cache.destroy();
+        }
+
+        cache = grid.createCache(cacheConfiguration(TRANSACTIONAL));
+
+        try {
+            doTransformResourceInjection(cache);
+
+            for (TransactionConcurrency concurrency : TransactionConcurrency.values()) {
+                for (TransactionIsolation isolation : TransactionIsolation.values()) {
+                    IgniteTransactions txs = grid.transactions();
+
+                    try (Transaction tx = txs.txStart(concurrency, isolation)) {
+                        doTransformResourceInjection(cache);
+
+                        tx.commit();
+                    }
+                }
+            }
+        }
+        finally {
+            cache.destroy();
+        }
+    }
+
+    /**
+     * @param atomicityMode Cache atomicity mode.
+     * @return Cache configuration.
+     */
+    private CacheConfiguration<String, Integer> cacheConfiguration(CacheAtomicityMode atomicityMode) {
+        CacheConfiguration<String, Integer> ccfg = new CacheConfiguration<>();
+
+        ccfg.setName(getClass().getSimpleName());
+        ccfg.setAtomicityMode(atomicityMode);
+
+        return ccfg;
+    }
+
+    /**
+     * @param cache Cache.
+     * @throws Exception If failed.
+     */
+    private void doTransformResourceInjection(IgniteCache<String, Integer> cache) throws Exception {
+        final Collection<ResourceType> required = Arrays.asList(
+            ResourceType.SPRING_APPLICATION_CONTEXT,
+            ResourceType.SPRING_BEAN);
+
+        Integer flags = cache.invoke(UUID.randomUUID().toString(), new SpringResourceInjectionEntryProcessor());
+
+        assertTrue("Processor result is null", flags != null);
+
+        log.info("Injection flag: " + Integer.toBinaryString(flags));
+
+        Collection<ResourceType> notInjected = ResourceInfoSet.valueOf(flags).notInjected(required);
+
+        if (!notInjected.isEmpty())
+            fail("Can't inject resource(s): " + Arrays.toString(notInjected.toArray()));
+
+        Set<String> keys = new HashSet<>(Arrays.asList(UUID.randomUUID().toString(),
+            UUID.randomUUID().toString(),
+            UUID.randomUUID().toString(),
+            UUID.randomUUID().toString()));
+
+        Map<String, EntryProcessorResult<Integer>> results = cache.invokeAll(keys,
+            new SpringResourceInjectionEntryProcessor());
+
+        assertEquals(keys.size(), results.size());
+
+        for (EntryProcessorResult<Integer> res : results.values()) {
+            Collection<ResourceType> notInjected1 = ResourceInfoSet.valueOf(res.get()).notInjected(required);
+
+            if (!notInjected1.isEmpty())
+                fail("Can't inject resource(s): " + Arrays.toString(notInjected1.toArray()));
+        }
+    }
+
+    /**
+     *
+     */
+    static class SpringResourceInjectionEntryProcessor extends ResourceInjectionEntryProcessorBase<String, Integer> {
+        /** */
+        private transient ApplicationContext appCtx;
+
+        /** */
+        private transient GridSpringResourceInjectionSelfTest.DummyResourceBean dummyBean;
+
+        /**
+         * @param appCtx Context.
+         */
+        @SpringApplicationContextResource
+        public void setApplicationContext(ApplicationContext appCtx) {
+            assert appCtx != null;
+
+            checkSet();
+
+            infoSet.set(ResourceType.SPRING_APPLICATION_CONTEXT, true);
+
+            this.appCtx = appCtx;
+        }
+
+        /**
+         * @param dummyBean Resource bean.
+         */
+        @SpringResource(resourceName = "dummyResourceBean")
+        public void setDummyBean(GridSpringResourceInjectionSelfTest.DummyResourceBean dummyBean) {
+            assert dummyBean != null;
+
+            checkSet();
+
+            infoSet.set(ResourceType.SPRING_BEAN, true);
+
+            this.dummyBean = dummyBean;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f9ff97c9/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 cd5645d..67b117d 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
@@ -18,17 +18,18 @@
 package org.apache.ignite.testsuites;
 
 import junit.framework.TestSuite;
+import org.apache.ignite.cache.spring.GridSpringCacheManagerSelfTest;
+import org.apache.ignite.cache.spring.SpringCacheManagerContextInjectionTest;
 import org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactorySelfTest;
 import org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactorySelfTest;
 import org.apache.ignite.cache.store.spring.CacheSpringStoreSessionListenerSelfTest;
 import org.apache.ignite.internal.GridFactorySelfTest;
 import org.apache.ignite.internal.GridSpringBeanSerializationSelfTest;
 import org.apache.ignite.internal.IgniteDynamicCacheConfigTest;
+import org.apache.ignite.internal.processors.resource.GridTransformSpringInjectionSelfTest;
 import org.apache.ignite.p2p.GridP2PUserVersionChangeSelfTest;
-import org.apache.ignite.cache.spring.GridSpringCacheManagerSelfTest;
 import org.apache.ignite.spring.IgniteExcludeInConfigurationTest;
 import org.apache.ignite.spring.IgniteStartFromStreamConfigurationTest;
-import org.apache.ignite.cache.spring.SpringCacheManagerContextInjectionTest;
 import org.apache.ignite.spring.injection.GridServiceInjectionSpringResourceTest;
 import org.apache.ignite.transactions.spring.GridSpringTransactionManagerSelfTest;
 import org.apache.ignite.transactions.spring.SpringTransactionManagerContextInjectionTest;
@@ -70,6 +71,8 @@ public class IgniteSpringTestSuite extends TestSuite {
 
         suite.addTestSuite(GridServiceInjectionSpringResourceTest.class);
 
+        suite.addTestSuite(GridTransformSpringInjectionSelfTest.class);
+
         suite.addTestSuite(SpringCacheManagerContextInjectionTest.class);
         suite.addTestSuite(SpringTransactionManagerContextInjectionTest.class);
 

http://git-wip-us.apache.org/repos/asf/ignite/blob/f9ff97c9/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteInvokeWithInjectionBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteInvokeWithInjectionBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteInvokeWithInjectionBenchmark.java
new file mode 100644
index 0000000..ef9d17b
--- /dev/null
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteInvokeWithInjectionBenchmark.java
@@ -0,0 +1,74 @@
+/*
+ * 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.yardstick.cache;
+
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.cache.CacheEntryProcessor;
+import org.apache.ignite.resources.IgniteInstanceResource;
+import org.apache.ignite.yardstick.cache.model.SampleValue;
+
+import javax.cache.processor.MutableEntry;
+import java.util.Map;
+
+/**
+ * Ignite benchmark that performs invoke operations.
+ */
+public class IgniteInvokeWithInjectionBenchmark extends IgniteCacheAbstractBenchmark<Integer, Object> {
+    /** {@inheritDoc} */
+    @Override public boolean test(Map<Object, Object> ctx) throws Exception {
+        int key = nextRandom(args.range());
+
+        cache.invoke(key, new SetValueEntryProcessor(new SampleValue(key)));
+
+        return true;
+    }
+
+    /** {@inheritDoc} */
+    @Override protected IgniteCache<Integer, Object> cache() {
+        return ignite().cache("atomic");
+    }
+
+    /**
+     *
+     */
+    public static class SetValueEntryProcessor implements CacheEntryProcessor<Integer, Object, Object> {
+        /** */
+        @IgniteInstanceResource
+        private transient Ignite ignite;
+
+        /** */
+        private Object val;
+
+        /**
+         * @param val Value.
+         */
+        public SetValueEntryProcessor(Object val) {
+            this.val = val;
+        }
+
+        /** {@inheritDoc} */
+        @Override public Object process(MutableEntry<Integer, Object> entry, Object... args) {
+            assert ignite != null;
+
+            entry.setValue(val);
+
+            return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/f9ff97c9/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteInvokeWithInjectionTxBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteInvokeWithInjectionTxBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteInvokeWithInjectionTxBenchmark.java
new file mode 100644
index 0000000..2df93ee
--- /dev/null
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/cache/IgniteInvokeWithInjectionTxBenchmark.java
@@ -0,0 +1,30 @@
+/*
+ * 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.yardstick.cache;
+
+import org.apache.ignite.IgniteCache;
+
+/**
+ * Ignite benchmark that performs invoke operations.
+ */
+public class IgniteInvokeWithInjectionTxBenchmark extends IgniteInvokeWithInjectionBenchmark {
+    /** {@inheritDoc} */
+    @Override protected IgniteCache<Integer, Object> cache() {
+        return ignite().cache("tx");
+    }
+}