http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/messaging/MessagingPingPongExample.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/messaging/MessagingPingPongExample.java b/examples/src/main/java/org/apache/ignite/examples/messaging/MessagingPingPongExample.java new file mode 100644 index 0000000..1c24f77 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/messaging/MessagingPingPongExample.java @@ -0,0 +1,133 @@ +/* + * 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.messaging; + +import org.apache.ignite.*; +import org.apache.ignite.cluster.*; +import org.apache.ignite.examples.*; +import org.apache.ignite.internal.util.lang.*; +import org.apache.ignite.lang.*; +import org.apache.ignite.resources.*; + +import java.util.*; +import java.util.concurrent.*; + +/** + * Demonstrates simple message exchange between local and remote nodes. + * <p> + * To run this example you must have at least one remote node started. + * <p> + * Remote nodes should always be started with special configuration file which + * enables P2P class loading: {@code 'ignite.{sh|bat} examples/config/example-ignite.xml'}. + * <p> + * Alternatively you can run {@link ExampleNodeStartup} in another JVM which will start node + * with {@code examples/config/example-ignite.xml} configuration. + */ +public class MessagingPingPongExample { + /** + * Executes example. + * + * @param args Command line arguments, none required. + * @throws Exception If example execution failed. + */ + public static void main(String[] args) throws Exception { + // Game is played over the default ignite. + try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) { + if (!ExamplesUtils.checkMinTopologySize(ignite.cluster(), 2)) + return; + + System.out.println(); + System.out.println(">>> Messaging ping-pong example started."); + + // Pick random remote node as a partner. + ClusterGroup nodeB = ignite.cluster().forRemotes().forRandom(); + + // Note that both nodeA and nodeB will always point to + // same nodes regardless of whether they were implicitly + // serialized and deserialized on another node as part of + // anonymous closure's state during its remote execution. + + // Set up remote player. + ignite.message(nodeB).remoteListen(null, new IgniteBiPredicate<UUID, String>() { + /** This will be injected on node listener comes to. */ + @IgniteInstanceResource + private Ignite ignite; + + @Override public boolean apply(UUID nodeId, String rcvMsg) { + System.out.println("Received message [msg=" + rcvMsg + ", sender=" + nodeId + ']'); + + try { + if ("PING".equals(rcvMsg)) { + ignite.message(ignite.cluster().forNodeId(nodeId)).send(null, "PONG"); + + return true; // Continue listening. + } + + return false; // Unsubscribe. + } + catch (IgniteException e) { + throw new GridClosureException(e); + } + } + }); + + int MAX_PLAYS = 10; + + final CountDownLatch cnt = new CountDownLatch(MAX_PLAYS); + + // Set up local player. + ignite.message().localListen(null, new IgniteBiPredicate<UUID, String>() { + @Override public boolean apply(UUID nodeId, String rcvMsg) { + System.out.println("Received message [msg=" + rcvMsg + ", sender=" + nodeId + ']'); + + try { + if (cnt.getCount() == 1) { + ignite.message(ignite.cluster().forNodeId(nodeId)).send(null, "STOP"); + + cnt.countDown(); + + return false; // Stop listening. + } + else if ("PONG".equals(rcvMsg)) + ignite.message(ignite.cluster().forNodeId(nodeId)).send(null, "PING"); + else + throw new RuntimeException("Received unexpected message: " + rcvMsg); + + cnt.countDown(); + + return true; // Continue listening. + } + catch (IgniteException e) { + throw new GridClosureException(e); + } + } + }); + + // Serve! + ignite.message(nodeB).send(null, "PING"); + + // Wait til the game is over. + try { + cnt.await(); + } + catch (InterruptedException e) { + System.err.println("Hm... let us finish the game!\n" + e); + } + } + } +}
http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/messaging/MessagingPingPongListenActorExample.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/messaging/MessagingPingPongListenActorExample.java b/examples/src/main/java/org/apache/ignite/examples/messaging/MessagingPingPongListenActorExample.java new file mode 100644 index 0000000..79a64ec --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/messaging/MessagingPingPongListenActorExample.java @@ -0,0 +1,106 @@ +/* + * 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.messaging; + +import org.apache.ignite.*; +import org.apache.ignite.cluster.*; +import org.apache.ignite.examples.*; +import org.apache.ignite.messaging.*; + +import java.util.*; +import java.util.concurrent.*; + +/** + * Demonstrates messaging with {@link MessagingListenActor} convenience adapter. + * <p> + * To run this example you must have at least one remote node started. + * <p> + * Remote nodes should always be started with special configuration file which + * enables P2P class loading: {@code 'ignite.{sh|bat} examples/config/example-ignite.xml'}. + * <p> + * Alternatively you can run {@link ExampleNodeStartup} in another JVM which will start node + * with {@code examples/config/example-ignite.xml} configuration. + */ +public class MessagingPingPongListenActorExample { + /** + * Executes example. + * + * @param args Command line arguments, none required. + */ + public static void main(String[] args) { + // Game is played over the default ignite. + try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) { + if (!ExamplesUtils.checkMinTopologySize(ignite.cluster(), 2)) + return; + + System.out.println(); + System.out.println(">>> Messaging ping-pong listen actor example started."); + + // Pick first remote node as a partner. + Collection<ClusterNode> rmtNodes = ignite.cluster().forRemotes().nodes(); + + ClusterGroup nodeB = ignite.cluster().forNode(rmtNodes.iterator().next()); + + // Note that both nodeA and nodeB will always point to + // same nodes regardless of whether they were implicitly + // serialized and deserialized on another node as part of + // anonymous closure's state during its remote execution. + + // Set up remote player. + ignite.message(nodeB).remoteListen(null, new MessagingListenActor<String>() { + @Override public void receive(UUID nodeId, String rcvMsg) { + System.out.println(rcvMsg); + + if ("PING".equals(rcvMsg)) + respond("PONG"); + else if ("STOP".equals(rcvMsg)) + stop(); + } + }); + + int MAX_PLAYS = 10; + + final CountDownLatch cnt = new CountDownLatch(MAX_PLAYS); + + // Set up local player. + ignite.message().localListen(null, new MessagingListenActor<String>() { + @Override protected void receive(UUID nodeId, String rcvMsg) throws IgniteException { + System.out.println(rcvMsg); + + if (cnt.getCount() == 1) + stop("STOP"); + else if ("PONG".equals(rcvMsg)) + respond("PING"); + + cnt.countDown(); + } + }); + + // Serve! + ignite.message(nodeB).send(null, "PING"); + + // Wait til the game is over. + try { + cnt.await(); + } + catch (InterruptedException e) { + System.err.println("Hm... let us finish the game!\n" + e); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/messaging/package-info.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/messaging/package-info.java b/examples/src/main/java/org/apache/ignite/examples/messaging/package-info.java new file mode 100644 index 0000000..c1a6244 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/messaging/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Demonstrates how to exchange messages between nodes. + */ +package org.apache.ignite.examples.messaging; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/MemcacheRestExample.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/MemcacheRestExample.java b/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/MemcacheRestExample.java new file mode 100644 index 0000000..f48e6fb --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/MemcacheRestExample.java @@ -0,0 +1,125 @@ +/* + * 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.misc.client.memcache; + +import net.spy.memcached.*; +import org.apache.ignite.*; + +import java.io.*; +import java.net.*; +import java.util.*; + +/** + * This example shows how to use Memcache client for manipulating Ignite cache. + * <p> + * Ignite implements Memcache binary protocol and it is available if + * REST is enabled on the node. + * Remote nodes should always be started using {@link MemcacheRestExampleNodeStartup}. + */ +public class MemcacheRestExample { + /** Hostname for client connection. */ + private static final String host = "localhost"; + + /** Port number for client connection. */ + private static final int port = 11211; + + /** + * @param args Command line arguments. + * @throws Exception In case of error. + */ + public static void main(String[] args) throws Exception { + MemcachedClient client = null; + + try (Ignite ignite = Ignition.start(MemcacheRestExampleNodeStartup.configuration())) { + System.out.println(); + System.out.println(">>> Memcache REST example started."); + + IgniteCache<String, Object> cache = ignite.jcache(null); + + client = startMemcachedClient(host, port); + + // Put string value to cache using Memcache binary protocol. + if (client.add("strKey", 0, "strVal").get()) + System.out.println(">>> Successfully put string value using Memcache client."); + + // Check that string value is actually in cache using traditional + // Ignite API and Memcache binary protocol. + System.out.println(">>> Getting value for 'strKey' using Ignite cache API: " + cache.get("strKey")); + System.out.println(">>> Getting value for 'strKey' using Memcache client: " + client.get("strKey")); + + // Remove string value from cache using Memcache binary protocol. + if (client.delete("strKey").get()) + System.out.println(">>> Successfully removed string value using Memcache client."); + + // Check that cache is empty. + System.out.println(">>> Current cache size: " + cache.size() + " (expected: 0)."); + + // Put integer value to cache using Memcache binary protocol. + if (client.add("intKey", 0, 100).get()) + System.out.println(">>> Successfully put integer value using Memcache client."); + + // Check that integer value is actually in cache using traditional + // Ignite API and Memcache binary protocol. + System.out.println(">>> Getting value for 'intKey' using Ignite cache API: " + cache.get("intKey")); + System.out.println(">>> Getting value for 'intKey' using Memcache client: " + client.get("intKey")); + + // Remove string value from cache using Memcache binary protocol. + if (client.delete("intKey").get()) + System.out.println(">>> Successfully removed integer value using Memcache client."); + + // Check that cache is empty. + System.out.println(">>> Current cache size: " + cache.size() + " (expected: 0)."); + + // Create atomic long. + IgniteAtomicLong l = ignite.atomicLong("atomicLong", 10, true); + + // Increment atomic long by 5 using Memcache client. + if (client.incr("atomicLong", 5, 0) == 15) + System.out.println(">>> Successfully incremented atomic long by 5."); + + // Increment atomic long using Ignite API and check that value is correct. + System.out.println(">>> New atomic long value: " + l.incrementAndGet() + " (expected: 16)."); + + // Decrement atomic long by 3 using Memcache client. + if (client.decr("atomicLong", 3, 0) == 13) + System.out.println(">>> Successfully decremented atomic long by 3."); + + // Decrement atomic long using Ignite API and check that value is correct. + System.out.println(">>> New atomic long value: " + l.decrementAndGet() + " (expected: 12)."); + } + finally { + if (client != null) + client.shutdown(); + } + } + + /** + * Creates Memcache client that uses binary protocol and connects to Ignite. + * + * @param host Hostname. + * @param port Port number. + * @return Client. + * @throws IOException If connection failed. + */ + private static MemcachedClient startMemcachedClient(String host, int port) throws IOException { + assert host != null; + assert port > 0; + + return new MemcachedClient(new BinaryConnectionFactory(), Arrays.asList(new InetSocketAddress(host, port))); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java b/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java new file mode 100644 index 0000000..1c79b64 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/MemcacheRestExampleNodeStartup.java @@ -0,0 +1,92 @@ +/* + * 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.misc.client.memcache; + +import org.apache.ignite.*; +import org.apache.ignite.configuration.*; +import org.apache.ignite.marshaller.optimized.*; +import org.apache.ignite.spi.discovery.tcp.*; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.*; + +import java.util.*; + +import static org.apache.ignite.cache.CacheAtomicityMode.*; +import static org.apache.ignite.cache.CacheRebalanceMode.*; +import static org.apache.ignite.cache.CacheWriteSynchronizationMode.*; +import static org.apache.ignite.configuration.DeploymentMode.*; + +/** + * Starts up an empty node with cache configuration that contains default cache. + * <p> + * The difference is that running this class from IDE adds all example classes to classpath + * but running from command line doesn't. + */ +public class MemcacheRestExampleNodeStartup { + /** + * Start up an empty node with specified cache configuration. + * + * @param args Command line arguments, none required. + * @throws IgniteException If example execution failed. + */ + public static void main(String[] args) throws IgniteException { + Ignition.start(configuration()); + } + + /** + * Create Ignite configuration with IGFS and enabled IPC. + * + * @return Ignite configuration. + * @throws IgniteException If configuration creation failed. + */ + public static IgniteConfiguration configuration() throws IgniteException { + IgniteConfiguration cfg = new IgniteConfiguration(); + + cfg.setLocalHost("127.0.0.1"); + cfg.setDeploymentMode(SHARED); + cfg.setPeerClassLoadingEnabled(true); + + cfg.setConnectorConfiguration(new ConnectorConfiguration()); + + OptimizedMarshaller marsh = new OptimizedMarshaller(); + + marsh.setRequireSerializable(false); + + cfg.setMarshaller(marsh); + + CacheConfiguration cacheCfg = new CacheConfiguration(); + + cacheCfg.setAtomicityMode(TRANSACTIONAL); + cacheCfg.setWriteSynchronizationMode(FULL_SYNC); + cacheCfg.setRebalanceMode(SYNC); + cacheCfg.setAtomicityMode(TRANSACTIONAL); + + cfg.setCacheConfiguration(cacheCfg); + + TcpDiscoverySpi discoSpi = new TcpDiscoverySpi(); + + TcpDiscoveryVmIpFinder ipFinder = new TcpDiscoveryVmIpFinder(); + + ipFinder.setAddresses(Collections.singletonList("127.0.0.1:47500..47509")); + + discoSpi.setIpFinder(ipFinder); + + cfg.setDiscoverySpi(discoSpi); + + return cfg; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/package-info.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/package-info.java b/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/package-info.java new file mode 100644 index 0000000..b3e7c9d --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/client/memcache/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Demonstrates Java Client usage with Memcache protocol. + */ +package org.apache.ignite.examples.misc.client.memcache; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/client/package-info.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/client/package-info.java b/examples/src/main/java/org/apache/ignite/examples/misc/client/package-info.java new file mode 100644 index 0000000..e0c62e8 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/client/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Demonstrates Java Client usage. + */ +package org.apache.ignite.examples.misc.client; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/deployment/DeploymentExample.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/deployment/DeploymentExample.java b/examples/src/main/java/org/apache/ignite/examples/misc/deployment/DeploymentExample.java new file mode 100644 index 0000000..5336620 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/deployment/DeploymentExample.java @@ -0,0 +1,129 @@ +/* + * 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.misc.deployment; + +import org.apache.ignite.*; +import org.apache.ignite.compute.*; +import org.apache.ignite.examples.*; +import org.jetbrains.annotations.*; + +import java.io.*; +import java.util.*; + +/** + * Demonstrates how to explicitly deploy a task. Note that + * it is very rare when you would need such functionality as tasks are + * auto-deployed on demand first time you execute them. So in most cases + * you would just apply any of the {@code Ignite.execute(...)} methods directly. + * However, sometimes a task is not in local class path, so you may not even + * know the code it will execute, but you still need to execute it. For example, + * you have two independent components in the system, and one loads the task + * classes from some external source and deploys it; then another component + * can execute it just knowing the name of the task. + * <p> + * Also note that for simplicity of the example, the task we execute is + * in system classpath, so even in this case the deployment step is unnecessary. + * <p> + * Remote nodes should always be started with special configuration file which + * enables P2P class loading: {@code 'ignite.{sh|bat} examples/config/example-ignite.xml'}. + * <p> + * Alternatively you can run {@link ExampleNodeStartup} in another JVM which will + * start node with {@code examples/config/example-ignite.xml} configuration. + */ +public final class DeploymentExample { + /** Name of the deployed task. */ + static final String TASK_NAME = "ExampleTask"; + + /** + * Executes example. + * + * @param args Command line arguments, none required. + * @throws Exception If example execution failed. + */ + public static void main(String[] args) throws Exception { + try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) { + System.out.println(); + System.out.println(">>> Deployment example started."); + + // This task will be deployed on local node and then peer-loaded + // onto remote nodes on demand. For this example this task is + // available on the classpath, however in real life that may not + // always be the case. In those cases you should use explicit + // 'IgniteCompute.localDeployTask(Class, ClassLoader) apply and + // then use 'IgniteCompute.execute(String, Object)' method + // passing your task name as first parameter. + ignite.compute().localDeployTask(ExampleTask.class, ExampleTask.class.getClassLoader()); + + for (Map.Entry<String, Class<? extends ComputeTask<?, ?>>> e : ignite.compute().localTasks().entrySet()) + System.out.println(">>> Found locally deployed task [alias=" + e.getKey() + ", taskCls=" + e.getValue()); + + // Execute the task passing its name as a parameter. The system will find + // the deployed task by its name and execute it. + ignite.compute().execute(TASK_NAME, null); + + // Execute the task passing class name as a parameter. The system will find + // the deployed task by its class name and execute it. + // g.compute().execute(ExampleTask.class.getName(), null).get(); + + // Undeploy task + ignite.compute().undeployTask(TASK_NAME); + + System.out.println(); + System.out.println(">>> Finished executing Ignite Direct Deployment Example."); + System.out.println(">>> Check participating nodes output."); + } + } + + /** + * Example task used to demonstrate direct task deployment through API. + * For this example this task as available on the classpath, however + * in real life that may not always be the case. In those cases + * you should use explicit {@link IgniteCompute#localDeployTask(Class, ClassLoader)} apply and + * then use {@link IgniteCompute#execute(String, Object)} + * method passing your task name as first parameter. + * <p> + * Note that this task specifies explicit task name. Task name is optional + * and is added here for demonstration purpose. If not provided, it will + * default to the task class name. + */ + @ComputeTaskName(TASK_NAME) + public static class ExampleTask extends ComputeTaskSplitAdapter<String, Object> { + /** {@inheritDoc} */ + @Override protected Collection<? extends ComputeJob> split(int clusterSize, String arg) { + Collection<ComputeJob> jobs = new ArrayList<>(clusterSize); + + for (int i = 0; i < clusterSize; i++) { + jobs.add(new ComputeJobAdapter() { + @Nullable @Override public Serializable execute() { + System.out.println(">>> Executing deployment example job on this node."); + + // This job does not return any result. + return null; + } + }); + } + + return jobs; + } + + /** {@inheritDoc} */ + @Override public Object reduce(List<ComputeJobResult> results) { + return null; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/deployment/package-info.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/deployment/package-info.java b/examples/src/main/java/org/apache/ignite/examples/misc/deployment/package-info.java new file mode 100644 index 0000000..20be358 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/deployment/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Deployment examples for direct deployments. + */ +package org.apache.ignite.examples.misc.deployment; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/lifecycle/LifecycleExample.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/lifecycle/LifecycleExample.java b/examples/src/main/java/org/apache/ignite/examples/misc/lifecycle/LifecycleExample.java new file mode 100644 index 0000000..497872a --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/lifecycle/LifecycleExample.java @@ -0,0 +1,92 @@ +/* + * 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.misc.lifecycle; + +import org.apache.ignite.*; +import org.apache.ignite.configuration.*; +import org.apache.ignite.lifecycle.*; +import org.apache.ignite.resources.*; + +import static org.apache.ignite.lifecycle.LifecycleEventType.*; + +/** + * This example shows how to provide your own {@link LifecycleBean} implementation + * to be able to hook into Ignite lifecycle. The {@link LifecycleExampleBean} bean + * will output occurred lifecycle events to the console. + * <p> + * This example does not require remote nodes to be started. + */ +public final class LifecycleExample { + /** + * Executes example. + * + * @param args Command line arguments, none required. + * @throws IgniteException If example execution failed. + */ + public static void main(String[] args) throws IgniteException { + System.out.println(); + System.out.println(">>> Lifecycle example started."); + + // Create new configuration. + IgniteConfiguration cfg = new IgniteConfiguration(); + + LifecycleExampleBean bean = new LifecycleExampleBean(); + + // Provide lifecycle bean to configuration. + cfg.setLifecycleBeans(bean); + + try (Ignite ignite = Ignition.start(cfg)) { + // Make sure that lifecycle bean was notified about ignite startup. + assert bean.isStarted(); + } + + // Make sure that lifecycle bean was notified about ignite stop. + assert !bean.isStarted(); + } + + /** + * Simple {@link LifecycleBean} implementation that outputs event type when it is occurred. + */ + public static class LifecycleExampleBean implements LifecycleBean { + /** Auto-inject ignite instance. */ + @IgniteInstanceResource + private Ignite ignite; + + /** Started flag. */ + private boolean isStarted; + + /** {@inheritDoc} */ + @Override public void onLifecycleEvent(LifecycleEventType evt) { + System.out.println(); + System.out.println(">>> Lifecycle event occurred: " + evt); + System.out.println(">>> Ignite name: " + ignite.name()); + + if (evt == AFTER_NODE_START) + isStarted = true; + else if (evt == AFTER_NODE_STOP) + isStarted = false; + } + + /** + * @return {@code True} if ignite has been started. + */ + public boolean isStarted() { + return isStarted; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/lifecycle/package-info.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/lifecycle/package-info.java b/examples/src/main/java/org/apache/ignite/examples/misc/lifecycle/package-info.java new file mode 100644 index 0000000..2feda25 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/lifecycle/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Demonstrates how to write and use lifecycle beans. + */ +package org.apache.ignite.examples.misc.lifecycle; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/package-info.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/package-info.java b/examples/src/main/java/org/apache/ignite/examples/misc/package-info.java new file mode 100644 index 0000000..c103603 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Contains examples taht are common across all editions. + */ +package org.apache.ignite.examples.misc; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/springbean/SpringBeanExample.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/springbean/SpringBeanExample.java b/examples/src/main/java/org/apache/ignite/examples/misc/springbean/SpringBeanExample.java new file mode 100644 index 0000000..69c84f4 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/springbean/SpringBeanExample.java @@ -0,0 +1,88 @@ +/* + * 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.misc.springbean; + +import org.apache.ignite.*; +import org.apache.ignite.examples.*; +import org.springframework.context.support.*; + +import java.util.concurrent.*; + +/** + * Demonstrates a simple use of Ignite configured with Spring. + * <p> + * String "Hello World." is printed out by Callable passed into + * the executor service provided by Ignite. This statement could be printed + * out on any node in the cluster. + * <p> + * The major point of this example is to show ignite injection by Spring + * framework. Ignite bean is described in {@code spring-bean.xml} file and instantiated + * by Spring context. Once application completed its execution Spring will + * apply ignite bean destructor and stop the ignite. + * <p> + * Remote nodes should always be started with special configuration file which + * enables P2P class loading: {@code 'ignite.{sh|bat} examples/config/example-ignite.xml'}. + * <p> + * Alternatively you can run {@link ExampleNodeStartup} in another JVM which will start node + * with {@code examples/config/example-ignite.xml} configuration. + */ +public final class SpringBeanExample { + /** + * Executes example. + * + * @param args Command line arguments, none required. + * @throws Exception If example execution failed. + */ + public static void main(String[] args) throws Exception { + System.out.println(); + System.out.println(">>> Spring bean example started."); + + // Initialize Spring factory. + ClassPathXmlApplicationContext ctx = + new ClassPathXmlApplicationContext("org/apache/ignite/examples/misc/springbean/spring-bean.xml"); + + try { + // Get ignite from Spring (note that local cluster node is already started). + Ignite ignite = (Ignite)ctx.getBean("mySpringBean"); + + // Execute any method on the retrieved ignite instance. + ExecutorService exec = ignite.executorService(); + + Future<String> res = exec.submit(new Callable<String>() { + @Override public String call() throws Exception { + System.out.println("Hello world!"); + + return null; + } + }); + + // Wait for callable completion. + res.get(); + + System.out.println(">>>"); + System.out.println(">>> Finished executing Ignite \"Spring bean\" example."); + System.out.println(">>> You should see printed out of 'Hello world' on one of the nodes."); + System.out.println(">>> Check all nodes for output (this node is also part of the cluster)."); + System.out.println(">>>"); + } + finally { + // Stop local cluster node. + ctx.destroy(); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/springbean/package-info.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/springbean/package-info.java b/examples/src/main/java/org/apache/ignite/examples/misc/springbean/package-info.java new file mode 100644 index 0000000..6f77b2e --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/springbean/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * HelloWorld example that accesses ignite started directly from Spring bean. + */ +package org.apache.ignite.examples.misc.springbean; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/misc/springbean/spring-bean.xml ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/misc/springbean/spring-bean.xml b/examples/src/main/java/org/apache/ignite/examples/misc/springbean/spring-bean.xml new file mode 100644 index 0000000..393b9cf --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/misc/springbean/spring-bean.xml @@ -0,0 +1,70 @@ +<?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. +--> + +<!-- + Command line (default) ignite configuration. +--> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:util="http://www.springframework.org/schema/util" + xsi:schemaLocation=" + http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"> + <description>Main Spring file for ignite configuration.</description> + + <!-- Example of bean definition with given configuration. --> + <bean id="mySpringBean" class="org.apache.ignite.IgniteSpringBean"> + <property name="configuration"> + <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration"> + <!-- Set to true to enable ignite-aware class loading for examples, default is false. --> + <property name="peerClassLoadingEnabled" value="true"/> + + <property name="marshaller"> + <bean class="org.apache.ignite.marshaller.optimized.OptimizedMarshaller"> + <!-- Set to false to allow non-serializable objects in examples, default is true. --> + <property name="requireSerializable" value="false"/> + </bean> + </property> + + <!-- Enable task execution events for examples. --> + <property name="includeEventTypes"> + <util:constant static-field="org.apache.ignite.events.EventType.EVTS_TASK_EXECUTION"/> + </property> + + <!-- Explicitly configure TCP discovery SPI to provide list of initial nodes. --> + <property name="discoverySpi"> + <bean class="org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi"> + <property name="ipFinder"> + <!-- Uncomment static IP finder to enable static-based discovery of initial nodes. --> + <!--<bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder">--> + <bean class="org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder"> + <property name="addresses"> + <list> + <!-- In distributed environment, replace with actual host IP address. --> + <value>127.0.0.1:47500..47509</value> + </list> + </property> + </bean> + </property> + </bean> + </property> + </bean> + </property> + </bean> +</beans> http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/package-info.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/package-info.java b/examples/src/main/java/org/apache/ignite/examples/package-info.java new file mode 100644 index 0000000..ab184d8 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/package-info.java @@ -0,0 +1,22 @@ +/* + * 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 description. --> + * Basic examples for ignite functionality. + */ +package org.apache.ignite.examples; http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/servicegrid/ServicesExample.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/servicegrid/ServicesExample.java b/examples/src/main/java/org/apache/ignite/examples/servicegrid/ServicesExample.java new file mode 100644 index 0000000..c8786cf --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/servicegrid/ServicesExample.java @@ -0,0 +1,167 @@ +/* + * 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 org.apache.ignite.*; +import org.apache.ignite.cluster.*; +import org.apache.ignite.examples.*; +import org.apache.ignite.lang.*; +import org.apache.ignite.resources.*; + +import java.util.*; + +/** + * 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 { + try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) { + ClusterGroup rmts = ignite.cluster().forRemotes(); + + if (rmts.nodes().isEmpty()) { + System.err.println(">>>"); + System.err.println(">>> Must start at least one remote node using " + + ExampleNodeStartup.class.getSimpleName() + '.'); + System.err.println(">>>"); + + return; + } + + IgniteServices svcs = ignite.services(rmts); + + 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; + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/servicegrid/SimpleMapService.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/servicegrid/SimpleMapService.java b/examples/src/main/java/org/apache/ignite/examples/servicegrid/SimpleMapService.java new file mode 100644 index 0000000..5e32bd2 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/servicegrid/SimpleMapService.java @@ -0,0 +1,49 @@ +/* + * 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; + +/** + * Simple map service. + */ +public interface SimpleMapService<K, V> { + /** + * Puts key-value pair into map. + * + * @param key Key. + * @param val Value. + */ + void put(K key, V val); + + /** + * Gets value based on key. + * + * @param key Key. + * @return Value. + */ + V get(K key); + + /** + * Clears map. + */ + void clear(); + + /** + * @return Map size. + */ + int size(); +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/servicegrid/SimpleMapServiceImpl.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/servicegrid/SimpleMapServiceImpl.java b/examples/src/main/java/org/apache/ignite/examples/servicegrid/SimpleMapServiceImpl.java new file mode 100644 index 0000000..5e6a9e7 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/servicegrid/SimpleMapServiceImpl.java @@ -0,0 +1,71 @@ +/* + * 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 org.apache.ignite.services.*; + +import java.util.*; +import java.util.concurrent.*; + +/** + * Simple service which loops infinitely and prints out a counter. + */ +public class SimpleMapServiceImpl<K, V> implements Service, SimpleMapService<K, V> { + /** Serial version UID. */ + private static final long serialVersionUID = 0L; + + /** Underlying cache map. */ + private Map<K, V> map; + + /** {@inheritDoc} */ + @Override public void put(K key, V val) { + map.put(key, val); + } + + /** {@inheritDoc} */ + @Override public V get(K key) { + return map.get(key); + } + + /** {@inheritDoc} */ + @Override public void clear() { + map.clear(); + } + + /** {@inheritDoc} */ + @Override public int size() { + return map.size(); + } + + /** {@inheritDoc} */ + @Override public void cancel(ServiceContext ctx) { + System.out.println("Service was cancelled: " + ctx.name()); + } + + /** {@inheritDoc} */ + @Override public void init(ServiceContext ctx) throws Exception { + System.out.println("Service was initialized: " + ctx.name()); + + map = new ConcurrentHashMap<>(); + } + + /** {@inheritDoc} */ + @Override public void execute(ServiceContext ctx) throws Exception { + System.out.println("Executing distributed service: " + ctx.name()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/CacheConfig.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/CacheConfig.java b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/CacheConfig.java new file mode 100644 index 0000000..7a2850e --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/CacheConfig.java @@ -0,0 +1,44 @@ +/* + * 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.streaming.marketdata; + +import org.apache.ignite.configuration.*; + +/** + * Configuration for the streaming caches for market data and financial instruments. + */ +public class CacheConfig { + /** + * Configure streaming cache for market ticks. + */ + public static CacheConfiguration<String, MarketTick> marketTicksCache() { + return new CacheConfiguration<>("marketTicks"); + } + + /** + * Configure cache for financial instruments. + */ + public static CacheConfiguration<String, Instrument> instrumentCache() { + CacheConfiguration<String, Instrument> instCache = new CacheConfiguration<>("instCache"); + + // Index some fields for querying portfolio positions. + instCache.setIndexedTypes(String.class, Instrument.class); + + return instCache; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/Instrument.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/Instrument.java b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/Instrument.java new file mode 100644 index 0000000..23f002a --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/Instrument.java @@ -0,0 +1,106 @@ +/* + * 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.streaming.marketdata; + +import org.apache.ignite.cache.query.annotations.*; + +import java.io.*; + +/** + * Financial instrument. + */ +public class Instrument implements Serializable { + /** Instrument symbol. */ + @QuerySqlField(index = true) + private final String symbol; + + /** Open price. */ + @QuerySqlField(index = true) + private double open; + + /** High price. */ + private double high; + + /** Low price. */ + private double low = Long.MAX_VALUE; + + /** Close price. */ + @QuerySqlField(index = true) + private double latest; + + /** + * @param symbol Symbol. + */ + Instrument(String symbol) { + this.symbol = symbol; + } + + /** + * Updates this instrument based on the latest market tick. + * + * @param tick Market tick. + */ + public void update(MarketTick tick) { + if (open == 0) + open = tick.price(); + + high = Math.max(high, tick.price()); + low = Math.min(low, tick.price()); + this.latest = tick.price(); + } + + /** + * @return Symbol. + */ + public String symbol() { + return symbol; + } + + /** + * @return Open price. + */ + public double open() { + return open; + } + + /** + * @return High price. + */ + public double high() { + return high; + } + + /** + * @return Low price. + */ + public double low() { + return low; + } + + /** + * @return Close price. + */ + public double latest() { + return latest; + } + + /** {@inheritDoc} */ + @Override public synchronized String toString() { + return "Instrument [symbol=" + symbol + ", latest=" + latest + ", change=" + (latest - open) + ']'; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/MarketTick.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/MarketTick.java b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/MarketTick.java new file mode 100644 index 0000000..949921ba --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/MarketTick.java @@ -0,0 +1,59 @@ +/* + * 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.streaming.marketdata; + +import java.io.*; + +/** + * Represents a market tick data. + */ +public class MarketTick implements Serializable { + /** Instrument symbol. */ + private final String symbol; + + /** Price. */ + private final double price; + + /** + * @param symbol Symbol. + * @param price Price. + */ + MarketTick(String symbol, double price) { + this.symbol = symbol; + this.price = price; + } + + /** + * @return Symbol. + */ + public String symbol() { + return symbol; + } + + /** + * @return Price. + */ + public double price() { + return price; + } + + /** {@inheritDoc} */ + @Override public String toString() { + return "MarketTick [symbol=" + symbol + ", price=" + price + ']'; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/QueryTopInstruments.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/QueryTopInstruments.java b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/QueryTopInstruments.java new file mode 100644 index 0000000..4bcb2ba --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/QueryTopInstruments.java @@ -0,0 +1,73 @@ +/* + * 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.streaming.marketdata; + +import org.apache.ignite.*; +import org.apache.ignite.cache.query.*; +import org.apache.ignite.examples.*; + +import java.util.*; + +/** + * Periodically query popular numbers from the streaming cache. + * To start the example, you should: + * <ul> + * <li>Start a few nodes using {@link ExampleNodeStartup} or by starting remote nodes as specified below.</li> + * <li>Start streaming using {@link StreamMarketData}.</li> + * <li>Start querying top performing instruments using {@link QueryTopInstruments}.</li> + * </ul> + * <p> + * You should start remote nodes by running {@link ExampleNodeStartup} in another JVM. + */ +public class QueryTopInstruments { + public static void main(String[] args) throws Exception { + // Mark this cluster member as client. + Ignition.setClientMode(true); + + try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) { + if (!ExamplesUtils.hasServerNodes(ignite)) + return; + + IgniteCache<String, Instrument> instCache = ignite.getOrCreateCache(CacheConfig.instrumentCache()); + + // Select top 3 instruments. + SqlFieldsQuery top3qry = new SqlFieldsQuery( + "select symbol, (latest - open) from Instrument order by (latest - open) desc limit 3"); + + // Select total profit. + SqlFieldsQuery profitQry = new SqlFieldsQuery("select sum(latest - open) from Instrument"); + + // Query top 3 best performing instruments every 5 seconds. + while (true) { + // Execute queries. + List<List<?>> top3 = instCache.query(top3qry).getAll(); + List<List<?>> profit = instCache.query(profitQry).getAll(); + + List<?> row = profit.get(0); + + if (row.get(0) != null) + System.out.printf("Total profit: %.2f%n", row.get(0)); + + // Print top 10 words. + ExamplesUtils.printQueryResults(top3); + + Thread.sleep(5000); + } + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/StreamMarketData.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/StreamMarketData.java b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/StreamMarketData.java new file mode 100644 index 0000000..e1a59d7 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/streaming/marketdata/StreamMarketData.java @@ -0,0 +1,109 @@ +/* + * 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.streaming.marketdata; + +import org.apache.ignite.*; +import org.apache.ignite.examples.*; +import org.apache.ignite.stream.*; + +import java.util.*; + +/** + * Stream random numbers into the streaming cache. + * To start the example, you should: + * <ul> + * <li>Start a few nodes using {@link ExampleNodeStartup} or by starting remote nodes as specified below.</li> + * <li>Start streaming using {@link StreamMarketData}.</li> + * <li>Start querying top performing instruments using {@link QueryTopInstruments}.</li> + * </ul> + * <p> + * You should start remote nodes by running {@link ExampleNodeStartup} in another JVM. + */ +public class StreamMarketData { + /** Random number generator. */ + private static final Random RAND = new Random(); + + /** Count of total numbers to generate. */ + private static final int CNT = 10000000; + + /** The list of instruments. */ + private static final String[] INSTRUMENTS = {"IBM", "GOOG", "MSFT", "GE", "EBAY", "YHOO", "ORCL", "CSCO", "AMZN", "RHT"}; + + /** The list of initial instrument prices. */ + private static final double[] INITIAL_PRICES = {194.9, 893.49, 34.21, 23.24, 57.93, 45.03, 44.41, 28.44, 378.49, 69.50}; + + public static void main(String[] args) throws Exception { + // Mark this cluster member as client. + Ignition.setClientMode(true); + + try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) { + if (!ExamplesUtils.hasServerNodes(ignite)) + return; + + // The cache is configured with sliding window holding 1 second of the streaming data. + IgniteCache<String, MarketTick> mktCache = ignite.getOrCreateCache(CacheConfig.marketTicksCache()); + final IgniteCache<String, Instrument> instCache = ignite.getOrCreateCache(CacheConfig.instrumentCache()); + + try (IgniteDataStreamer<String, MarketTick> mktStmr = ignite.dataStreamer(mktCache.getName())) { + // Note that we receive market data, but do not populate 'mktCache' (it remains empty). + // Instead we update the instruments in the 'instCache'. + mktStmr.receiver(new StreamVisitor<String, MarketTick>() { + @Override + public void visit(IgniteCache<String, MarketTick> mktCache, Map.Entry<String, MarketTick> e) { + String symbol = e.getKey(); + MarketTick tick = e.getValue(); + + Instrument inst = instCache.get(symbol); + + if (inst == null) + inst = new Instrument(symbol); + + // Don't populate market cache, as we don't use it for querying. + // Update cached instrument based on the latest market tick. + inst.update(tick); + + instCache.put(symbol, inst); + } + }); + + // Stream market data into market data stream cache. + while (true) { + for (int j = 0; j < INSTRUMENTS.length; j++) { + // Use gaussian distribution to ensure that + // numbers closer to 0 have higher probability. + double price = round2(INITIAL_PRICES[j] + RAND.nextGaussian()); + + MarketTick tick = new MarketTick(INSTRUMENTS[j], price); + + mktStmr.addData(tick.symbol(), tick); + } + } + } + } + } + + /** + * Rounds double value to two significant signs. + * + * @param val value to be rounded. + * @return rounded double value. + */ + private static double round2(double val) { + return Math.floor(100 * val + 0.5) / 100; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/streaming/numbers/CacheConfig.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/streaming/numbers/CacheConfig.java b/examples/src/main/java/org/apache/ignite/examples/streaming/numbers/CacheConfig.java new file mode 100644 index 0000000..58592e1 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/streaming/numbers/CacheConfig.java @@ -0,0 +1,46 @@ +/* + * 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.streaming.numbers; + +import org.apache.ignite.configuration.*; + +import javax.cache.configuration.*; +import javax.cache.expiry.*; + +import static java.util.concurrent.TimeUnit.*; + +/** + * Configuration for the streaming cache to store the stream of random numbers. + * This cache is configured with sliding window of 1 second, which means that + * data older than 1 second will be automatically removed from the cache. + */ +public class CacheConfig { + /** + * Configure streaming cache. + */ + public static CacheConfiguration<Integer, Long> randomNumbersCache() { + CacheConfiguration<Integer, Long> cfg = new CacheConfiguration<>("randomNumbers"); + + cfg.setIndexedTypes(Integer.class, Long.class); + + // Sliding window of 1 seconds. + cfg.setExpiryPolicyFactory(FactoryBuilder.factoryOf(new CreatedExpiryPolicy(new Duration(SECONDS, 1)))); + + return cfg; + } +} http://git-wip-us.apache.org/repos/asf/incubator-ignite/blob/b473e309/examples/src/main/java/org/apache/ignite/examples/streaming/numbers/QueryPopularNumbers.java ---------------------------------------------------------------------- diff --git a/examples/src/main/java/org/apache/ignite/examples/streaming/numbers/QueryPopularNumbers.java b/examples/src/main/java/org/apache/ignite/examples/streaming/numbers/QueryPopularNumbers.java new file mode 100644 index 0000000..e08ae09 --- /dev/null +++ b/examples/src/main/java/org/apache/ignite/examples/streaming/numbers/QueryPopularNumbers.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.examples.streaming.numbers; + +import org.apache.ignite.*; +import org.apache.ignite.cache.query.*; +import org.apache.ignite.examples.*; + +import java.util.*; + +/** + * Periodically query popular numbers from the streaming cache. + * To start the example, you should: + * <ul> + * <li>Start a few nodes using {@link ExampleNodeStartup} or by starting remote nodes as specified below.</li> + * <li>Start streaming using {@link StreamRandomNumbers}.</li> + * <li>Start querying popular numbers using {@link QueryPopularNumbers}.</li> + * </ul> + * <p> + * You should start remote nodes by running {@link ExampleNodeStartup} in another JVM. + */ +public class QueryPopularNumbers { + public static void main(String[] args) throws Exception { + // Mark this cluster member as client. + Ignition.setClientMode(true); + + try (Ignite ignite = Ignition.start("examples/config/example-ignite.xml")) { + if (!ExamplesUtils.hasServerNodes(ignite)) + return; + + // The cache is configured with sliding window holding 1 second of the streaming data. + IgniteCache<Integer, Long> stmCache = ignite.getOrCreateCache(CacheConfig.randomNumbersCache()); + + // Select top 10 words. + SqlFieldsQuery top10Qry = new SqlFieldsQuery("select _key, _val from Long order by _val desc limit 10"); + + // Select average, min, and max counts among all the words. + SqlFieldsQuery statsQry = new SqlFieldsQuery("select avg(_val), min(_val), max(_val) from Long"); + + // Query top 10 popular numbers every 5 seconds. + while (true) { + // Execute queries. + List<List<?>> top10 = stmCache.query(top10Qry).getAll(); + List<List<?>> stats = stmCache.query(statsQry).getAll(); + + // Print average count. + List<?> row = stats.get(0); + + if (row.get(0) != null) + System.out.printf("Query results [avg=%.2f, min=%d, max=%d]%n", row.get(0), row.get(1), row.get(2)); + + // Print top 10 words. + ExamplesUtils.printQueryResults(top10); + + Thread.sleep(5000); + } + } + } +}