/* * 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.examples.servicegrid; import java.util.Collection; import org.apache.ignite.Ignite; import org.apache.ignite.IgniteServices; import org.apache.ignite.Ignition; import org.apache.ignite.examples.ExampleNodeStartup; import org.apache.ignite.examples.ExamplesUtils; import org.apache.ignite.lang.IgniteCallable; import org.apache.ignite.resources.ServiceResource; /** * Example that demonstrates how to deploy distributed services in Ignite. * Distributed services are especially useful when deploying singletons on the ignite, * be that cluster-singleton, or per-node-singleton, etc... * <p> * To start remote nodes, you must run {@link ExampleNodeStartup} in another JVM * which will start node with {@code examples/config/example-ignite.xml} configuration. * <p> * NOTE:<br/> * Starting {@code ignite.sh} directly will not work, as distributed services * cannot be peer-deployed and classes must be on the classpath for every node. */ public class ServicesExample { /** * Executes example. * * @param args Command line arguments, none required. * @throws Exception If example execution failed. */ public static void main(String[] args) throws Exception { // Mark this node as client node. Ignition.setClientMode(true); try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) { if (!ExamplesUtils.hasServerNodes(ignite)) return; // Deploy services only on server nodes. IgniteServices svcs = ignite.services(ignite.cluster().forServers()); try { // Deploy cluster singleton. svcs.deployClusterSingleton("myClusterSingletonService", new SimpleMapServiceImpl()); // Deploy node singleton. svcs.deployNodeSingleton("myNodeSingletonService", new SimpleMapServiceImpl()); // Deploy 2 instances, regardless of number nodes. svcs.deployMultiple("myMultiService", new SimpleMapServiceImpl(), 2 /*total number*/, 0 /*0 for unlimited*/); // Example for using a service proxy // to access a remotely deployed service. serviceProxyExample(ignite); // Example for auto-injecting service proxy // into remote closure execution. serviceInjectionExample(ignite); } finally { // Undeploy all services. ignite.services().cancelAll(); } } } /** * Simple example to demonstrate service proxy invocation of a remotely deployed service. * * @param ignite Ignite instance. * @throws Exception If failed. */ private static void serviceProxyExample(Ignite ignite) throws Exception { System.out.println(">>>"); System.out.println(">>> Starting service proxy example."); System.out.println(">>>"); // Get a sticky proxy for node-singleton map service. SimpleMapService<Integer, String> mapSvc = ignite.services().serviceProxy("myNodeSingletonService", SimpleMapService.class, true); int cnt = 10; // Each service invocation will go over a proxy to some remote node. // Since service proxy is sticky, we will always be contacting the same remote node. for (int i = 0; i < cnt; i++) mapSvc.put(i, Integer.toString(i)); // Get size from remotely deployed service instance. int mapSize = mapSvc.size(); System.out.println("Map service size: " + mapSize); if (mapSize != cnt) throw new Exception("Invalid map size [expected=" + cnt + ", actual=" + mapSize + ']'); } /** * Simple example to demonstrate how to inject service proxy into distributed closures. * * @param ignite Ignite instance. * @throws Exception If failed. */ private static void serviceInjectionExample(Ignite ignite) throws Exception { System.out.println(">>>"); System.out.println(">>> Starting service injection example."); System.out.println(">>>"); // Get a sticky proxy for cluster-singleton map service. SimpleMapService<Integer, String> mapSvc = ignite.services().serviceProxy("myClusterSingletonService", SimpleMapService.class, true); int cnt = 10; // Each service invocation will go over a proxy to the remote cluster-singleton instance. for (int i = 0; i < cnt; i++) mapSvc.put(i, Integer.toString(i)); // Broadcast closure to every node. final Collection<Integer> mapSizes = ignite.compute().broadcast(new SimpleClosure()); System.out.println("Closure execution result: " + mapSizes); // Since we invoked the same cluster-singleton service instance // from all the remote closure executions, they should all return // the same size equal to 'cnt' value. for (int mapSize : mapSizes) if (mapSize != cnt) throw new Exception("Invalid map size [expected=" + cnt + ", actual=" + mapSize + ']'); } /** * Simple closure to demonstrate auto-injection of the service proxy. */ private static class SimpleClosure implements IgniteCallable<Integer> { // Auto-inject service proxy. @ServiceResource(serviceName = "myClusterSingletonService", proxyInterface = SimpleMapService.class) private transient SimpleMapService mapSvc; /** {@inheritDoc} */ @Override public Integer call() throws Exception { int mapSize = mapSvc.size(); System.out.println("Executing closure [mapSize=" + mapSize + ']'); return mapSize; } } }