The following tabs show the services and configuration for each Processing Unit.
Domain Model
Domain Model The domain model is comprised of the Account object preloaded to the space and used by the Validator for order validation. The Account object is a simple POJO representing a user account. It includes the user's first and last name attributes, an amount of money in the account attribute, and a risk allowed factor for this account, to compare against an order risk involved factor, during the order validation process: /** * A POJO account object used for query containing four fields: * firstName, lastName, amount and riskAllowed * * Annotations: * @SpaceProperty(index=IndexType.BASIC) annotated getters mark the attribute as indexed. * Querying indexed fields speeds up read and take operations. * * @SpaceClass annotation in this example is only to indicate that this class is a space class. */ @SpaceClass public class Account { private String firstName; private String lastName; private Integer amount; private Integer riskAllowed; . . /** * <code>@SpaceProperty</code> Defines this field data as indexed. * Querying indexed fields speeds up read and take operations. Possible values of NONE and BASIC. */ @SpaceProperty(index=IndexType.BASIC) public String getFirstName() { return firstName; } . . more constructors/setters/getters } View Account.java class source code The OrderEvent POJO represents an order placed by the Feeder, to be validated by the Validator. The order includes the user name, order type and order status attributes – an orderID attribute that acts as the unique order identifier in the space (annotated as @SpaceID – see code snippet below), and a risk involved factor attribute used by the Validator business logic to validate the order: /** * Some important properties: * orderID - annotated as the object unique space id (see the getter method for the annotation). * firstName (used to perform routing when working with partitioned space, see getter method for annotation). * status - indicating if this OrderEvent object in new, processed, or rejected. * type - Normal or Insecure * * Annotations: * * Fields with getters annotated as @SpaceProperty(index=IndexType.BASIC) are indexed. * Querying indexed fields speeds up read and take operations. * * @SpaceRouting annotation (see getFirstName()) indicates that firstName field * will be used as a routing index to perform routing when working with partitioned space. * * @SpaceClass annotation in this example is only to indicate that this class is a space class. */ @SpaceClass public class OrderEvent { public static final String STATUS_NEW = "New"; public static final String STATUS_APPROVED = "Approved"; public static final String STATUS_REJECTED = "Rejected"; public static final String PRIORITY_URGENT = "Insecure"; public static final String PRIORITY_NORMAL = "Normal"; private String orderID; private String feederID; private String firstName; private String lastName; private Integer riskInvolved; private Integer price; /** Order status, Possible values: New, Approved, Rejected. */ private String status; /** Order type, Possible values: Normal, Insecure */ private String type; /** * Gets the ID of the orderEvent. * @SpaceID annotation indicates that its value will be auto generated * when it is written to the space. */ @SpaceId(autoGenerate = true) public String getOrderID() { return orderID; } /** * @return userName - Gets the user name of the orderEvent object. * @SpaceProperty Defines if this field data is indexed. */ @SpaceProperty(index = IndexType.BASIC) public String getFirstName() { return firstName; } . . more constructors/getters/setters } Feeder - PreLoader Service PreLoader Service (Within the Feeder) The Feeder's preloader service bean writes 100 unique Account objects to the space. /* * Copyright 2008 GigaSpaces Technologies Ltd. All rights reserved. * * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. GIGASPACES WILL NOT * BE LIABLE FOR ANY DAMAGE OR LOSS IN CONNECTION WITH THE SOFTWARE. */ package com.gigaspaces.examples.tutorials.queries.feeder; import org.openspaces.core.GigaSpace; import org.openspaces.core.context.GigaSpaceContext; import org.springframework.beans.factory.InitializingBean; import com.gigaspaces.examples.tutorials.queries.common.Account; /** * A loader bean that writes Account objects with unique user names to the * space. Since the write is executed in the init() method called directly in the afterPropertiesSet method * (and not in a new thread), the processing unit waits until the loading is * finished before initializing the next bean. */ public class AccountPreLoader implements InitializingBean { /** * Number of accounts to be loaded by the loader, hard-coded to 100, can be overridden * in the pu.xml (by setting the prop key "numberOfAccounts") */ private int numberOfAccounts = 100; @GigaSpaceContext(name = "gigaSpace") private GigaSpace gigaSpace; public void setGigaSpace(GigaSpace gigaSpace) { this.gigaSpace = gigaSpace; } /** * Allows to control the number of accounts that will be initially * loaded to the Space. Defaults to <code>100</code>. */ public void setNumberOfAccounts(int numberOfAccounts) { this.numberOfAccounts = numberOfAccounts; } /** * The first method to run upon bean Initialization when implementing InitializingBean. * Runs the pre-loader init() method */ public void afterPropertiesSet() throws Exception { init(); } /** * init - Initializes the pre-loader: * Writes <numberOfAccounts> unique accounts to the space. */ public void init() throws Exception { System.out.println("\nFeeder Pre-Loader Starts writing accounts"); // Writing <numberOfAccounts> accountData objects to the space. for (int i = 1; i <= numberOfAccounts; i++) { Account account = new Account("FN"+i /* firstName */ ,"LN"+i /* lastName */ ,1000 /* amount */ ,50); /* riskAllowedFactor */ gigaSpace.write(account); } System.out.println("Feeder Wrote "+numberOfAccounts+" Accounts\n"); } } Feeder - Feeder Service Feeder Service (Within the Feeder) The Feeder's service bean (started after the Feeder's preloader has finished – defined in the configuration as dependent) starts periodic cycles of an order feeding task to the space. /* * Copyright 2008 GigaSpaces Technologies Ltd. All rights reserved. * * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. GIGASPACES WILL NOT * BE LIABLE FOR ANY DAMAGE OR LOSS IN CONNECTION WITH THE SOFTWARE. */ package com.gigaspaces.examples.tutorials.queries.feeder; import org.openspaces.core.GigaSpace; import org.openspaces.core.context.GigaSpaceContext; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.InitializingBean; import com.gigaspaces.examples.tutorials.queries.common.OrderEvent; import java.util.Random; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; /** * A feeder bean that starts a scheduled task that writes a new OrderEvent object to the space. * The orderEvent type attribute is set randomly to "normal" or "Insecure". <p> * * The space is injected into this bean using OpenSpaces support for @GigaSpaceContext * annotation. <p> * * The scheduled support uses the java.util.concurrent Scheduled Executor Service. It * is started and stopped based on Spring life-cycle events. */ public class OrderEventFeeder implements InitializingBean, DisposableBean { private Random randomGen = new Random(); private ScheduledExecutorService executorService; // Delayed result bearing action private ScheduledFuture<?> sf; /** * Delay between scheduled tasks */ private long defaultDelay = 1000; /** * The scheduled orderEvent feeding task. */ private OrderEventFeederTask orderEventFeederTask; @GigaSpaceContext(name = "gigaSpace") private GigaSpace gigaSpace; public void setGigaSpace(GigaSpace gigaSpace) { this.gigaSpace = gigaSpace; } /** * Unique ID for this client */ private Double feederID; /** * @param defaultDelay - Sets default delay between feeding tasks. */ public void setDefaultDelay(long defaultDelay) { this.defaultDelay = defaultDelay; } /** * The first method to run upon bean Initialization, when implementing InitializingBean. * Runs init() method which starts a scheduled orderEvent feeding task. */ public void afterPropertiesSet() throws Exception { init(); } /** * init - Starts a scheduled orderEvent feeding task. * @throws Exception */ public void init() throws Exception { // Create unique ID for this feeder feederID = new Double(System.nanoTime()); System.out.println("Feeder ["+feederID.toString()+"], Starting order feeding cycles (Delay between cycles "+defaultDelay+" msec)"); // Create a thread pool containing 1 thread capable of performing scheduled tasks executorService = Executors.newScheduledThreadPool(1); orderEventFeederTask = new OrderEventFeederTask(); // Schedule the thread to execute the task at fixed rate with the default delay defined sf = executorService.scheduleAtFixedRate( orderEventFeederTask // The task to schedule ,defaultDelay // Initial Delay before starting ,defaultDelay // Delay between tasks ,TimeUnit.MILLISECONDS // Time unit for the delay ); } public void destroy() throws Exception { // Shutting down the thread pool upon bean disposal sf.cancel(true); sf = null; executorService.shutdown(); } public class OrderEventFeederTask implements Runnable { // Counts number of fed orderEvents private int counter; Integer randomizedNameSuffix; String randomizedType; public void run() { try { // Prepare randomized values to set the orderEvent attributes with randomizedNameSuffix = randomGen.nextInt(99)+1; if (randomGen.nextBoolean()) { randomizedType=OrderEvent.TYPE_NORMAL; } else { randomizedType=OrderEvent.TYPE_INSECURE; } // Create a new orderEvent with randomized attributes OrderEvent orderEvent = new OrderEvent("FN" + randomizedNameSuffix /* firstName */ ,"LN" + randomizedNameSuffix/* lastName */ ,feederID.toString() /* feederID */ ,randomizedType /* type */ ,randomGen.nextInt(99)+1 /* riskInvolvedFactor */ ,(randomGen.nextInt(19)+1)*100); /* price */ // Write the new orderEvent to the space gigaSpace.write(orderEvent); System.out.println("\nFeeder wrote order:\n"+orderEvent); } catch (Exception e) { e.printStackTrace(); } } public int getCounter() { return counter; } } public int getFeedCount() { return orderEventFeederTask.getCounter(); } public void setFeederID(Double feederID) { this.feederID = feederID; } public Double getFeederID() { return feederID; } } Feeder - Config Feeder Configuration The XML file/code based application, holding the Feeder beans configuration. Here the Preloader and Feeder services are wired and configured. Configured using pu.xml file: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:os-core="http://www.openspaces.org/schema/core" xmlns:os-events="http://www.openspaces.org/schema/events" xmlns:os-remoting="http://www.openspaces.org/schema/remoting" xmlns:os-sla="http://www.openspaces.org/schema/sla" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.openspaces.org/schema/core http://www.openspaces.org/schema/core/openspaces-core.xsd http://www.openspaces.org/schema/events http://www.openspaces.org/schema/events/openspaces-events.xsd http://www.openspaces.org/schema/remoting http://www.openspaces.org/schema/remoting/openspaces-remoting.xsd http://www.openspaces.org/schema/sla http://www.openspaces.org/schema/sla/openspaces-sla.xsd"> <!-- ========================================================================================================================== --> <!-- Spring property configurer which allows us to use system properties (such as user.name). Here we can define the numberOfAccounts to feed, injected to the PreLoader bean --> <bean id="propertiesConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="properties"> <props> <prop key="numberOfAccounts">100</prop> </props> </property> </bean> <!-- Enables the usage of @GigaSpaceContext annotation based injection. --> <os-core:giga-space-context/> <!-- A bean representing a space (an IJSpace implementation). Note, we perform a lookup on the space since we are working against a remote space. --> <os-core:space id="space" url="jini://*/*/spaceQueries"/> <!-- OpenSpaces simplified space API built on top of IJSpace/JavaSpace. --> <os-core:giga-space id="gigaSpace" space="space"/> <!-- ================================================================================================ --> <!-- The Account pre-loader bean, writing new 100 unique accounts to the space. --> <bean id="accountPreLoader" class="com.gigaspaces.examples.tutorials.queries.feeder.AccountPreLoader"> <property name="numberOfAccounts" value="${numberOfAccounts}" /> </bean> <!-- The Data feeder bean, writing new OrderEvents objects to the space in a constant interval. The depends-on attribute ensures the feeder bean will start only after the pre-loader bean is done --> <bean id="orderEventFeeder" class="com.gigaspaces.examples.tutorials.queries.feeder.OrderEventFeeder" depends-on="accountPreLoader"/> </beans> Configured using code: /* * Copyright 2008 GigaSpaces Technologies LTD. All rights reserved. * * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. GIGASPACES WILL NOT * BE LIABLE FOR ANY DAMAGE OR LOSS IN CONNECTION WITH THE SOFTWARE. */ package com.gigaspaces.examples.tutorials.queries.codebasedfeeder; import org.openspaces.core.GigaSpace; import org.openspaces.core.GigaSpaceConfigurer; import org.openspaces.core.space.UrlSpaceConfigurer; import com.j_spaces.core.IJSpace; import com.gigaspaces.examples.tutorials.queries.feeder.AccountPreLoader; import com.gigaspaces.examples.tutorials.queries.feeder.OrderEventFeeder; /** * The feeder connects to the remote space and: * 1. Pre-loads the space with 100 accounts. * 2. Starts feeding the space with orderEvent objects, type set * randomly as "Normal" or "Insecure". <p> * * This "CodeBased" version of the feeder is configured inside the main() method. * The Processing Unit version of the feeder uses a pu.xml configuration file and can * run inside a stand alone container or deployed onto GigaSpaces' ServiceGrid. */ public class CodeBasedFeeder { public static IJSpace space; public static GigaSpace gigaSpace; /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // Connect to the space // ==================== // Connect to a remote space. space = new UrlSpaceConfigurer("jini://*/*/spaceQueries").space(); // Create a GigaSpace simpler interface to interact with the space gigaSpace = new GigaSpaceConfigurer(space).gigaSpace(); // Create the account pre-loader, connect it to the space, and initiate it. // (The pre-loader writes 100 unique accounts to the space). // ========================================================= AccountPreLoader accountPreLoader = new AccountPreLoader(); accountPreLoader.setGigaSpace(gigaSpace); accountPreLoader.init(); // Create the orderEvent feeder, connect it to the space, and initiate it. // (The feeder starts cycles of "New", "Normal"/"Insecure" order feeding task). // ========================================================================== OrderEventFeeder orderEventFeeder = new OrderEventFeeder(); orderEventFeeder.setGigaSpace(gigaSpace); orderEventFeeder.init(); } } Validator - Normal Validator Service Normal Orders Validator Service (Within the Validator) The Validator's validating bean in charge of validating Normal orders: /* * Copyright 2008 GigaSpaces Technologies LTD. All rights reserved. * * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. GIGASPACES WILL NOT * BE LIABLE FOR ANY DAMAGE OR LOSS IN CONNECTION WITH THE SOFTWARE. */ package com.gigaspaces.examples.tutorials.queries.validator; import org.openspaces.core.GigaSpace; import org.openspaces.events.adapter.SpaceDataEvent; import com.gigaspaces.examples.tutorials.queries.common.Account; import com.gigaspaces.examples.tutorials.queries.common.OrderEvent; import com.j_spaces.core.client.SQLQuery; /** * Simple bean used to validate the "Normal" orderEvent objects. * Showing use of template parameterized query. */ public class NormalOrderEventValidator { private long workDuration = 100; /** * Sets the simulated work duration (in milliseconds). Default to 100. */ public void setWorkDuration(long workDuration) { this.workDuration = workDuration; } /** * Validates the given OrderEvent object and returns the validated OrderEvent with * status field set to Approved/Rejected according to the validation. * Can be invoked using OpenSpaces Events when a matching event * occurs. * The order is approved if an account for the user is found holding enough money * to buy the order (compared to orderEvent.price attribute). */ @SpaceDataEvent // This annotation marks the method as the event listener. public OrderEvent validatesOrderEvent(OrderEvent orderEvent, GigaSpace gigaSpace) { // sleep to simulate some work try { Thread.sleep(workDuration); } catch (InterruptedException e) { // do nothing } System.out.println("\nValidator validates [Normal] order: First Name["+orderEvent.getFirstName()+ "] Last Name ["+orderEvent.getLastName()+ "] Price ["+orderEvent.getPrice()+"]"); // Querying using template query // ============================= // Create the template for the query Account queryTemplate = new Account(orderEvent.getFirstName()/* account first name*/ ,orderEvent.getLastName()/* account last name*/ ,orderEvent.getPrice());/* account amount*/ // Create the query using the values from the template, each ? sign is replaced with the corresponding value // The query is actually "firstName=(queryTemplate.firstName) and lastName=(queryTemplate.lastName) and amount>(queryTemplate.amount)" SQLQuery<Account> query = new SQLQuery<Account>(queryTemplate,"firstName = ? and lastName = ? and amount > ?"); // REMARK: Instead of using the constructor the query can also be // set using the setTemplate and setQuery methods: // =============================================== // query.setTemplate(queryTemplate); // query.setQuery("firstName = ? and lastName = ? and amount > ?"); // Read from the space the account matching the query Account account=(Account)gigaSpace.read((Object)query); // Set the order status according to the query result if (account!= null) { orderEvent.setStatus(OrderEvent.STATUS_APPROVED); } else { orderEvent.setStatus(OrderEvent.STATUS_REJECTED); } System.out.println("Validator set order status to: ["+orderEvent.getStatus()+"]"); // orderID is declared as primary key and as auto-generated. // It must be null before writing an operation. orderEvent.setOrderID(null); return orderEvent; } } Validator - Insecure Counter Service Risky Insecure Orders Counting Service (Within in Validator) The Validator counting bean in charge of counting risky Insecure orders. /* * Copyright 2008 GigaSpaces Technologies LTD. All rights reserved. * * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. GIGASPACES WILL NOT * BE LIABLE FOR ANY DAMAGE OR LOSS IN CONNECTION WITH THE SOFTWARE. */ package com.gigaspaces.examples.tutorials.queries.counter; import java.util.concurrent.atomic.AtomicInteger; import org.openspaces.core.GigaSpace; import org.openspaces.core.IteratorBuilder; import org.openspaces.core.context.GigaSpaceContext; import org.springframework.beans.factory.InitializingBean; import com.gigaspaces.examples.tutorials.queries.common.Account; import com.gigaspaces.examples.tutorials.queries.common.OrderEvent; import com.j_spaces.core.client.GSIterator; import com.j_spaces.core.client.SQLQuery; /** * Simple bean used to read and display the "Insecure" orderEvent objects. * Shows use of GSIterator. */ public class RiskyOrderEventCounter implements InitializingBean{ private AtomicInteger riskyOrderEventCounter = new AtomicInteger(0); @GigaSpaceContext(name = "gigaSpace") private GigaSpace gigaSpace; public void setGigaSpace(GigaSpace gigaSpace) { this.gigaSpace = gigaSpace; } /** * The first method to run upon bean Initialization when implementing InitializingBean. * Runs the init() method */ public void afterPropertiesSet() throws Exception { init(); } /** * Starts a new thread running the OrderEventIteratorTask. */ public void init(){ Thread thread = new Thread(new OrderEventIteratorTask()); thread.start(); } /** * Iterates through all the orderEvents matching the specified templates. * Counts every orderEvent read, that has an associated account (same user name as the orderEvent) * with a satisfying risk allowed. */ public class OrderEventIteratorTask implements Runnable { // Create a query for "New" and "Insecure" orderEvent objects. SQLQuery<OrderEvent> queryInsecureOrders = new SQLQuery<OrderEvent>(OrderEvent.class,"status='"+OrderEvent.STATUS_NEW+"' and type='"+OrderEvent.TYPE_INSECURE+"'"); // Create and configure an iteratorBuilder to build iterators for the space with the specified templates. IteratorBuilder iteratorBuilder = new IteratorBuilder(gigaSpace) .addTemplate(queryInsecureOrders) .bufferSize(100) // Limit of the number of objects to store for each iteration. .withHistory(); // Indicates that this iterator will be first pre-filled with matching objects, // otherwise it will start iterating only on newly arriving objects to the space. public void run() { try { System.out.println("Counter creats iterator over the space insecure orders:"); // Build the iterator using the previously configured iteratorBuilder. GSIterator gsIterator = iteratorBuilder.iterate(); System.out.println("Counter iterator thread reading messages"); OrderEvent insecureOrderEvent; // Create the query for an account object, each ? place-holder will be replaced inside the following loop using the setParameters method. SQLQuery<Account> accountQuery = new SQLQuery<Account>(Account.class,"firstName = ? and lastName = ? and riskAllowed > ?"); while (true) { while (gsIterator.hasNext()) { insecureOrderEvent = (OrderEvent)gsIterator.next(); System.out.println("\nCounter examines order: "+insecureOrderEvent); // Updating the query parameters, the query will actually equal: // firstName=(accountQuery.firstName value) and lastName=(accountQuery.lastName value) and amount>(accountQuery.amount value) accountQuery.setParameters(insecureOrderEvent.getFirstName(), /* account user first name*/ insecureOrderEvent.getLastName(), /* account user last name*/ insecureOrderEvent.getRiskInvolved()); /* account amount*/ // Read an account matching the query Account account = (Account)gigaSpace.read((Object)accountQuery); // Set the order status according to the query result if (account != null) { System.out.println("Counter - examined order's risk is higher then allowed."); riskyOrderEventCounter.incrementAndGet(); } else { System.out.println("Counter - examined order's risk is allowed."); } System.out.println("Counter - total of ["+riskyOrderEventCounter+"] insecure risky orders (with risk higher then allowed) counted."); } } } catch(Exception e) { e.printStackTrace(); } } } } Validator - Config Validator Configuration The XML file/code based application, holding the Validator beans configuration. The Normal Validator service bean is defined inside a query-based polling container, and the Insecure Counter service bean is defined in a query-based notify container: Configured using pu.xml file: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:os-core="http://www.openspaces.org/schema/core" xmlns:os-events="http://www.openspaces.org/schema/events" xmlns:os-remoting="http://www.openspaces.org/schema/remoting" xmlns:os-sla="http://www.openspaces.org/schema/sla" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.openspaces.org/schema/core http://www.openspaces.org/schema/core/openspaces-core.xsd http://www.openspaces.org/schema/events http://www.openspaces.org/schema/events/openspaces-events.xsd http://www.openspaces.org/schema/remoting http://www.openspaces.org/schema/remoting/openspaces-remoting.xsd http://www.openspaces.org/schema/sla http://www.openspaces.org/schema/sla/openspaces-sla.xsd"> <!-- ========================================================================================================================== --> <!-- Enables the usage of @GigaSpaceContext annotation based injection. --> <os-core:giga-space-context/> <!-- A bean representing a space (an IJSpace implementation). Note, we do not specify here the cluster topology of the space. It is declared outside of the processing unit or within the SLA bean. --> <os-core:space id="space" url="jini://*/*/spaceQueries"/> <!-- OpenSpaces simplified space API built on top of IJSpace/JavaSpace. --> <os-core:giga-space id="gigaSpace" space="space" tx-manager="transactionManager"/> <!-- Defines a local Jini transaction manager. --> <os-core:local-tx-manager id="transactionManager" space="space"/> <!-- The normalOrderEvent validator bean --> <bean id="normalOrderEventValidator" class="com.gigaspaces.examples.tutorials.queries.validator.NormalOrderEventValidator"/> <!-- The insecureRiskyOrderEvent Counter bean --> <bean id="insecureRiskyOrderEventCounter" class="com.gigaspaces.examples.tutorials.queries.validator.InsecureRiskyOrderEventCounter"/> <!-- ========================================================================================================================== --> <!-- A polling event container that performs (by default) polling take operations against the space using the provided query template (in this case, the new normal orderEvents objects). Once a match is found, the orderEvent validator bean event listener is triggered using the annotation adapter, the listener method is annotated inside the bean with the @SpaceDataEvent annotation. --> <os-events:polling-container id="orderEventValidatorPollingEventContainer" giga-space="gigaSpace"> <os-events:tx-support tx-manager="transactionManager"/> <os-core:sql-query where="type='Normal' and status='New'" class="com.gigaspaces.examples.tutorials.queries.common.OrderEvent"/> <os-events:listener> <os-events:annotation-adapter> <os-events:delegate ref="normalOrderEventValidator"/> </os-events:annotation-adapter> </os-events:listener> </os-events:polling-container> <!-- The notification container, registers for notification on every orderEvent write (notify on write is default) that satisfies the query (in this case with type="Insecure" and status="New"). Upon notification invokes the insecureRiskyOrderEventCounter listner on a copy of the object that triggered the event. --> <os-events:notify-container id="orderEventNotifyContainer" giga-space="gigaSpace"> <!-- perform-take-on-notify="true" ignore-event-on-null-take="true">--> <os-events:tx-support tx-manager="transactionManager"/> <os-core:sql-query where="type='Insecure' and status='New'" class="com.gigaspaces.examples.tutorials.queries.common.OrderEvent"/> <os-events:listener> <os-events:annotation-adapter> <os-events:delegate ref="insecureRiskyOrderEventCounter"/> </os-events:annotation-adapter> </os-events:listener> </os-events:notify-container> </beans> Configured using code: /* * Copyright 2008 GigaSpaces Technologies LTD. All rights reserved. * * THIS SOFTWARE IS PROVIDED "AS IS," WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. GIGASPACES WILL NOT * BE LIABLE FOR ANY DAMAGE OR LOSS IN CONNECTION WITH THE SOFTWARE. */ package com.gigaspaces.examples.tutorials.queries.codebasedvalidator; import org.openspaces.core.GigaSpace; import org.openspaces.core.GigaSpaceConfigurer; import org.openspaces.core.space.UrlSpaceConfigurer; import org.openspaces.events.notify.SimpleNotifyContainerConfigurer; import org.openspaces.events.notify.SimpleNotifyEventListenerContainer; import org.openspaces.events.polling.SimplePollingContainerConfigurer; import org.openspaces.events.polling.SimplePollingEventListenerContainer; import com.j_spaces.core.IJSpace; import com.j_spaces.core.client.SQLQuery; import com.gigaspaces.examples.tutorials.queries.common.OrderEvent; import com.gigaspaces.examples.tutorials.queries.validator.NormalOrderEventValidator; import com.gigaspaces.examples.tutorials.queries.validator.InsecureRiskyOrderEventCounter; /** * CodeBasedValidator * <p> * The validator connects to the remote space and: * 1. Registers a notify container that receives by notification "Insecure"&"New" * orders using query, examines and counts according to their risk. * 2. Starts a polling container that takes "Normal"&"New" orders using query, * validates them and writes them back to the space as approved/rejected. * * This "CodeBased" version of the validator is configured inside the main() method. * The Processing Unit version of the validator uses a pu.xml configuration file and can * ran inside a stand alone container or onto GigaSpaces ServiceGrid. */ public class CodeBasedValidator { public static IJSpace space; public static GigaSpace gigaSpace; /** * @param args * @throws Exception */ public static void main(String[] args) throws Exception { // Connect to the space // ==================== // Connects to the remote space using its URL space = new UrlSpaceConfigurer("jini://*/*/spaceQueries").space(); // Create a GigaSpace simpler interface to interact with the space gigaSpace = new GigaSpaceConfigurer(space).gigaSpace(); // Create a Notify event container registered for notification when an orderEvent object // matching the query is written to the space. //============================================ // Create a SQLQuery to query orderEvent objects with attributes status="New" and type="Insecure" SQLQuery<OrderEvent> queryInsecureOrders = new SQLQuery<OrderEvent>(new OrderEvent(),"type='"+OrderEvent.TYPE_INSECURE+"' and status='"+OrderEvent.STATUS_NEW+"'"); // Create the Notify event container SimpleNotifyEventListenerContainer notifyEventListenerContainer = new SimpleNotifyContainerConfigurer(gigaSpace) /* The space the notify container is connected to */ .template(queryInsecureOrders) /* The query to match */ .eventListenerAnnotation(new InsecureRiskyOrderEventCounter()) /* The listener class containing the method to invoke upon notification (annotated @SpaceDataEvent) */ .notifyContainer(); // Create a Polling event container to periodically try to take // orderEvent objects matching the query, from the space. //======================================================= // Create a SQLQuery to query orderEvent objects with attributes status="New" and type="Normal" SQLQuery<OrderEvent> queryNormalOrders = new SQLQuery<OrderEvent>(new OrderEvent(),"type='"+OrderEvent.TYPE_NORMAL+"' and status='"+OrderEvent.STATUS_NEW+"'"); // Create the Polling event container SimplePollingEventListenerContainer pollingEventListenerContainer = new SimplePollingContainerConfigurer(gigaSpace) /* The space the polling container is connected to */ .template(queryNormalOrders) /* The query to match */ .eventListenerAnnotation(new NormalOrderEventValidator()) /* The class containing the method to invoke upon match (annotated @SpaceDataEvent) */ .pollingContainer(); } } Expected Output
Feeder
Feeder Pre-Loader Starts writing accounts Feeder Wrote 100 Accounts Feeder [1.10211539569135E14], Starting order feeding cycles (Delay between cycles 1000 msec) Feeder wrote order: type[Insecure] status[New] price[1200] first Name[FN82] last Name[LN82] risk involved[96] Feeder wrote order: type[Normal] status[New] price[700] first Name[FN93] last Name[LN93] risk involved[23] Feeder wrote order: type[Normal] status[New] price[600] first Name[FN11] last Name[LN11] risk involved[93] . . . Validator . . . Validator validates [Normal] order: First Name[FN4] Last Name [LN4] Price [500] Validator set order status to: [Approved] Validator validates [Normal] order: First Name[FN39] Last Name [LN39] Price [100] Validator set order status to: [Approved] Validator examines [Insecure] order with Risk Factor[53] Validator - examined order's risk is allowed. Validator - total of [3] insecure risky orders (with risk higher then allowed) counted. Validator validates [Normal] order: First Name[FN8] Last Name [LN8] Price [1500] Validator set order status to: [Rejected] . . . |
![]() |
GigaSpaces.com - Legal Notice - 3rd Party Licenses - Site Map - API Docs - Forum - Downloads - Blog - White Papers - Contact Tech Writing - Gen. by Atlassian Confluence |