Summary: GigaSpaces JavaSpaces API Plain Old Java Object support - the POJO. This advanced section deals with the annotations and gs.xml mapping file, ways for troubleshooting, considerations, ID generation and usage as well as frequently used code snippets.
When running in a partial replication mode, a false value for this property will not replicates all objects from this class type to the replica space or backup space. To run in a partial replication mode deploy the space cluster using the following property:
IncludeProperties.IMPLICIT takes into account all POJO fields – even if a get method is not declared with a @SpaceProperties annotation, it is taken into account as a space field.
IncludeProperties.EXPLICIT takes into account only the get methods which are declared with a @SpaceProperties annotation.
IMPLICIT
inheritIndexes
boolean
Whether to use the class indexes list only, or to also include the super class indexes.
If the class does not define indexes, superclass indexes are used.
Options:
The space mapping file element name for @SpaceId is id (see below).
Defines whether this field value is used when generating the Object ID. The field value should be unique – i.e., no multiple objects with the same value should be written into the space (each object should have a different field value). When writing an object into the space with an existing id field value, an EntryAlreadyInSpaceException is thrown. The Object ID is created, based on the id field value.
The @SpaceID annotation cannot be used with multiple fields. You may specify only one field to be used as the @SpaceId field.
If autoGenerate is declared as false, the field is indexed automatically. If autoGenerate is declared as true, the field isn't indexed.
If autoGenerate is true, the field must be of the type java.lang.String.
Element
Type
Description
Default Value
autoGenerate
boolean
Specifies if the object ID is generated automatically by the space when written into the space. If false, the field is indexed automatically, and if true, the field isn't indexed
Querying indexed fields speeds up read and take operations. The @SpaceIndex annotation should be used to specify an indexed field. The @SpaceIndex has two attributes:type and path.
The index type is determined by the SpaceIndexType enumeration. This is a mandatory attribute when using the @SpaceIndex annotation. The index types options are:
BASIC - This index speeds up equality matches (equal to/not equal to).
EXTENDED - This index speeds up comparison matches (bigger than/less than).
NONE - Indicates no index type is set, and default should be used.
The path() attribute represents the path of the indexed property within a nested object.
Examples:
The @SpaceIndex example
@SpaceClass
public class Person
{
privateString lastName;
privateString firstName;
privateInteger age;
...
@SpaceIndex(type=SpaceIndexType.BASIC)
publicString getFirstName() {return firstName;}
public void setFirstName(String firstName) {this.firstName = firstName;}
@SpaceIndex(type=SpaceIndexType.EXTENDED)
publicString getAge() {return age;}
public void setAge(String age) {this.age = age;}
}
The @SpaceIndex using path example
@SpaceClass
publicstatic class Person {
privateint id;
private Info personalInfo;
privateString description;
//getter and setter methods
...
// this defines and EXTENDED index on the personalInfo.socialSecurity property
@SpaceIndex(path = "socialSecurity", type = SpaceIndexType.EXTENDED)
public Info getPersonalInfo() {
return personalInfo;
}
}
publicstatic class Info implements Serializable {
privateString name;
private Date birthday;
privatelong socialSecurity;
//getter and setter methods
}
It is highly recommended to index fields used for matching/query. Without the proper index (BASIC or EXTENDED ), the read/readMultiple/take/takeMultiple operations response time might be affected.
Field Level Decoration – @SpaceVersion
This specifies a get method for holding the version ID. This field should be an int data type.
The @SpaceVersion must be an int data type.
Field Level Decoration - @SpacePersist
This specifies a getter method for holding the persistency mode of the object overriding the class level persist declaration. This field should be of the boolean data type.
If the persist class level annotation is true, all objects of this class type will be persisted into the underlying data store (Mirror, ExternalDataSource, Storage Adapter).
When using this option, you must have the space class level persist decoration specified.
Field Level Decoration - @SpaceRouting
The @SpaceRouting annotation specifies a get method for the field to be used to calculate the target space for the space operation (read , write...). The @SpaceRouting field value hash code is used to calculate the target space when the space is running in partitioned mode.
See more details at the Data-Partitioning section.
For details about scaling a running space cluster in runtime see the Dynamic Partitioning section.
Field Level Decoration - @SpaceLeaseExpiration
The @SpaceLeaseExpiration annotation specifies a get and a set method for holding the timestamp of when the instance's lease expires (this is a standard Java timestamp based on the 1/1/1970 epoch). This property should not be populated by the user code. The space will populate this property automatically based on the lease time given by the user when writing the object.
When using an external data source, you can choose to persist this value to the database. Subsequently, when data is reloaded from the external data source (at startup time for example), the space will filter out instances whose lease expiration timestamp has already passed. This field should be a long data type.
Here is how you can load an object into the space via the External Data source with a specific lease:
Have the @SpaceLeaseExpiration decoration on a getter method for a field that will hold the object lease. Usually this will be set by GigaSpaces , but when loading the object you will set it yourself.
@SpaceClass (persist=true)
public class MyData {
privatelong lease;
.............
@SpaceLeaseExpiration
publiclong getLease()
{
return lease;
}
public void setLease(long lease) {
this.lease = lease;
}
}
when loading the object into the space via the External Data source you should set this field lease value - with the example below the loaded object lease will be 10 seconds:
public DataIterator<MyData> initialLoad() throws DataSourceException {
List<MyData> initData = new ArrayList<MyData>();
// load the space with some data
MyData obj = new MyData();
obj.setWhatEver(...);
obj.setLease(System.currentTimeMillis() + 10000);
initData.add(obj);
returnnew MyDataIterator(initData);
}
Once an object has been loaded/written into the space you can also change the lease using the Gigaspace. write(T entry, long lease, long timeout, int modifiers) method.
Field Level Decoration - @SpaceExclude
The @SpaceExclude annotation instructs the client to ignore the fields using this annotation, so that they are not stored within the space.
When IncludeProperties is defined as IMPLICIT as part of the @SpaceClass annotation, @SpaceExclude should usually be used. This is because IMPLICIT instructs the system to take all POJO fields into account.
When IncludeProperties is defined as EXPLICIT, there is no need to use @SpaceExclude.
@SpaceExclude can still be used, even if IncludeProperties is not defined.
POJO Class Example – Person and Employee
This example uses the @SpaceId, @SpaceRouting, @SpaceClass, replicate, persist, @SpaceVersion, @SpaceProperty and SpaceIndex annotations as part of the Person and Employee classes:
Person
package com.j_spaces.examples.hellospacepojo;
import com.gigaspaces.annotation.pojo.*;
@SpaceClass(replicate=true,persist=false)
public class Person {
privateString lastName;
privateString firstName;
public Person(){}
public Person(String lastName, String firstName){
this.lastName = lastName;
this.firstName = firstName;
}
@SpaceIndex(type=SpaceIndexType.BASIC)
publicString getFirstName(){return firstName;}
public void setFirstName(String firstName)
{this.firstName = firstName;}
publicString getLastName(){return lastName;}
public void setLastName(String name) {this.lastName = name;}
}
Employee
package com.j_spaces.examples.hellospacepojo;
import com.gigaspaces.annotation.pojo.SpaceClass;
import com.gigaspaces.annotation.pojo.SpaceId;
import com.gigaspaces.annotation.pojo.SpaceRouting;
import com.gigaspaces.annotation.pojo.SpaceVersion;
@SpaceClass(replicate=true,persist=false)
public class Employee extends Person
{
privateInteger employeeID;
privateint versionID;
public Employee(){}
public Employee(Integer employeeID) {
this.employeeID = employeeID;
}
public Employee(String lastName, Integer employeeID) {
this.employeeID = employeeID;
setLastName(lastName);
}
@SpaceId
@SpaceRouting
publicInteger getEmployeeID(){return employeeID;}
public void setEmployeeID(Integer employeeID) {
this.employeeID = employeeID;
}
publicString toString() {
returnsuper.toString() + ", \temployeeID: "+ employeeID ;
}
@SpaceVersion
publicint getVersionID() {return versionID;}
public void setVersionID(int versionID) {this.versionID = versionID;}
}
The space mapping configuration file gs.xml allows you to define space class metadata when using a POJO class with getter or setter methods. Space mapping files are also required when using POJO objects with the ExternalDataSource interface. The gs.xml configuration file is loaded when the application and space are started. gs.xml files can be edited to include GigaSpaces specific attributes.
The gs.xml file is mainly used with 1.4 JVM which does not support the Java Annotations.
The *.gs.xml file can reside in one of two locations:
The <CLASSPATH>/config/mapping folder. In this case, the gs.xml file can include decorations for multiple classes and can have any name. For example, the mapping file could be placed at "mpApp/config/mapping/myapplication.gs.xml", where the mpApp folder is part of the application CLASSPATH. You may have multiple gs.xml files located at the <CLASSPATH>/config/mapping folder.
In the same folder as the POJO class file. In this case, the gs.xml file should use the same class name as the file prefix. For example, if a POJO class is located at "mpApp/my/package/MyPojo.class" then the mapping file must located at "mpApp/my/package/MyPojo.gs.xml".
The replicate and persist attributes must be defined (either true or false), as part of the class element.
gs.xml Example
When using the version, id and routing elements, place these in the gs.xml file in the following order:
version
id
routing
Below is an example for an Employee class and a Person class XML configuration file named mapping.gs.xml:
The Employee class uses the <reference> tag to inherit metadata from the Person Class.
XML Tags
Class Level Tags
<class> – a class and the associated Java class ClassDescriptor encapsulate meta data information of a concrete class.
Attribute
Description
name
Contains the full qualified name of the specified class. Because this attribute is of the XML type ID, there can only be one class-descriptor per class.
persist
This field indicates the persistency mode of the object. When a space is defined as persistent, a true value for this attribute will persist objects of this type.
For more details, refer to the Persistency section.
replicate
This field indicates the replication mode of the object. When a space is defined as replicated, a true value for this attribute will replicate objects of this type.
For more details, refer to the Replication section.
fifo-support
To enable FIFO operations, set this attribute to one of the FifoSupport enumeration values.
All the fields are written automatically into space. If the field is a reference to another object, it has to be Serializable and it will be written into space as well. Only the fields which need special space behavior need to be specified in the gs.xml file. Specify the fields which are id's, indexes or need exclusions, etc.
<property> - contains mapping info for a primitive type attribute of a persistent class.
Attribute
Description
name
Holds the name of the persistent class attribute.
index
Indicates which fields are indexed in the space. The first indexed member is used for hashing. Querying indexed fields speeds up read and take operations.
<reference> - contains mapping information for an attribute of a class that is not primitive, but references another entity object.
<null-value> - a value that will represent a null. Relevant for primitive fields (int, long).
<class-ref> - contains the full qualified name of the specified class.
<id> - defines whether this field value is used when generating the object ID.
Attribute
Description
name
Specifies a get method that allows identification of the id element in the space.
auto-generate
Specifies if the object ID is generated automatically by the space when written into the space. If false, the field is indexed automatically, and if true, the field isn't indexed.
<version> - saves the POJO's version in the space. This must be an int data type field.
Attribute
Description
name
Specifies a get method for holding the version's ID.
<persist> - allows you to specify whether a POJO is or isn't saved inside the space.
Attribute
Description
name
Specifies a get method for holding the persist flag.
<routing> - Determines the target space for the operation with using partitioned space.
Attribute
Description
name
Specifies a get method that allows identification of the routing element in the space.
<exclude> - causes the POJO field under this element to be excluded, and not be saved in the space.
If you specify a field name that exists as part of the property element, this field is excluded.
If the field name doesn't exist as part of the property element, this means that this field name is part of the Person class, and you do not want it to be saved in the space.
For details about scaling a running space cluster in runtime see the Dynamic Partitioning section.
generateGsXml Utility - Generating the gs.xml File
When a Hibernate class-to-database mapping configuration file (hbm) exists for the classes for which a space mapping configuration file gs.xml is required, a simple utility can be used to generate the gs.xml file from the hbm file.
The utility, generateGsXml, was located at <GigaSpaces Root>\bin till XAP 6.5 and it was move to OpenSpaces.org as an opensource project in XAP 6.5.
The generated space configuration file gs.xml should be located at <CLASSPATH>\config\mapping folder. GigaSpaces client and space load these files when the application and space are started.
generateGsXml Utility Options
Set the Environment variables as follows:
POJO_CLASSPATH - The path for the POJOs class file.
HIBERNATE_HOME - The path for the Hibernate configuration file and *.hbm files.
The generateGsXml command has the following parameters:
Parameter
Required/Optional
Description
Default Value
-beanName
Required if isHibernate is false.
The bean (POJO) name. Represents the full path of the POJO's name.
-outputDir
required
The output directory for all the generated gs.xml files.
-is Hibernate
optional
Indicates whether to generate gs files from all *.hbm hibernate file in classpath.
false
-mapping Type
optional
The mapping type can have a space value or a map value.
space
-isFifo
optional
Indicates whether to use FIFO for all the beans.
false
-isPersist
optional
Indicates whether to use persistent for all the beans.
true
-is Replicate
optional
Indicates whether to use replicate for all the beans.
true
-hibernate ConfigFile
optional
The hibernate configuration file if isHibernate is true.
/hibernate.cfg.xml.
-override File
optional
Indicates whether to override an existing file with the same filename.
false, meaning it will create a new file using the .new suffix.
-inherit Indexes
optional
Two values can be chosen:
hierarchy - takes into account the declared indexes that are set to true, and all their superclasses.
instance - takes into account the instance's indexes; or if it's indexes are false, takes into account the first superclass that contains indexes that are true.
You may use user defined data types (non-primitive data types) with your Space class. These should implement the Serializable interface.
The user defined fields cannot be used by default for queries. You should provide a getter and a setter method for these as part of their parent Space class.
See example below:
The User defined Class
public class MyUserDefinedClass implements Serializable{
String fieldA;
String fieldB;
publicString getFieldA() {
return fieldA;
}
public void setFieldA(String fieldA) {
this.fieldA = fieldA;
}
publicString getFieldB() {
return fieldB;
}
public void setFieldB(String fieldB) {
this.fieldB = fieldB;
}
}
The Space class will have the user defined data type fields getter and setter methods.
You can index these fields as any other Space class fields to allow fast search when performing read or take operations:
The Space Class with the User defined Class fields getters and setters
@SpaceClass
public class Trade implements Serializable {
String _tradeId;
String _instrument;
String _accountId;
MyUserDefinedClass customField = null;
public Trade() {
}
@SpaceIndex(type=SpaceIndexType.BASIC)
publicString getMyClassFieldA()
{
if (customfield == null) returnnull;
return customfield.getFieldA();
}
@SpaceIndex(type=SpaceIndexType.BASIC)
publicString getMyClassFieldB()
{
if (customfield == null) returnnull;
return customfield.getFieldB();
}
public void setMyClassFieldA(String value)
{
customfield.setFieldA(value);
}
public void setMyClassFieldB(String value)
{
customfield.setFieldB(value);
}
....
}
The code to query the Space class will look like this:
Query User defined Class
SQLQuery<Trade> query = new SQLQuery(Trade.class , "myClassFieldA= 'SomeValue' or myClassFieldB = 'someValue2'");
Trade trades[] = _gigaSpace.readMultiple(query ,Integer.MAX_VALUE);
Troubleshooting
Using Logging
Use the com.gigaspaces.pojo.level = ALL as part of the logging file located by default at <GigaSpaces Root>\config\gs_logging.properties, to debug the POJO metadata load and conversion to space object. Having the <GigaSpaces Root> as part of the application CLASSPATH turns on the POJO debug activity at the client side.
When the POJO logging is turned on, the following should appear at the client side console when a class is introduced to the space:
FINEST [com.gigaspaces.pojo]: The annotation structure of class com.j_spaces.examples.hellospacepojo.Employee is :
name = com.j_spaces.examples.hellospacepojo.Employee
fieldNames = [firstName, lastName, employeeID, versionID]
fieldPks = [employeeID]
fieldAutoPkGen = []
fieldIndexs = [employeeID, firstName, lastName]
hashBasedKey = []
version = [versionID]
lazyDeserialization = []
payload = []
serializationTypeFields = {}
defaultNullValueFields = {firstName=null, lastName=null}
refClasses = [com.j_spaces.examples.hellospacepojo.Person]
persist class = false
persist instance = []
routing field name = [employeeID]
timetolive = 9223372036854775807
fifo = false
inheritIndexes = true
includeProperties = IMPLICIT
replicate true
fieldTypes = null
mappingType = space
serializationType = 0
exclude = []
A converted object logging output looks like this:
FINE [com.gigaspaces.pojo]: ExternalEntry after converter is:
ClassName: com.j_spaces.examples.hellospacepojo.Employee
Field Name: firstName
Field Type: java.lang.String
Field Value: first name1
Field Indexed: false
Field Name: lastName
Field Type: java.lang.String
Field Value: Last Name1
Field Indexed: false
Field Name: employeeID
Field Type: java.lang.Integer
Field Value: 1
Field Indexed: true
Using The GUI
Use the GS-UI space class view to examine the POJO meta data. Make sure the annotations/xml decorations have been introduced to the space correctly i.e. correct class name, field names, field types, indexes, routing field, replication mode and FIFO mode etc.