Interoperability


XAP offers interoperability between documents and POJOs via the Space - it is possible to write POJOs and read them back as documents, and vice versa. This is usually useful in scenarios requiring reading and/or manipulating POJO objects without loading the concrete Java classes.

Tip

In previous releases the ExternalEntry class was used to achieve this functionality. Starting with 8.0, the SpaceDocument class should be used to accomplish these needs in a simpler and safer manner, whereas ExternalEntry has been deprecated and should no longer be used.

Requirements

When working with documents, the user is in charge of creating and registering the Space type descriptor manually before interacting with the document types. When working with POJOs, the system implicitly generates a Space type descriptor for the POJO’s class using annotations or gs.xml files when the class is used for the first time. In order to inter-operate, the same type descriptor should be used for both POJOs and documents.

If the POJO’s class is in the application’s classpath, or the POJO is already registered in the Space, there’s no need to register it again - the application will retrieve it automatically when it is used for the first time. For example:

// Create a document template using the POJO class name:
SpaceDocument template = new SpaceDocument(MyPojo.class.getName());
// Count all entries matching the template:
int count = gigaSpace.count(template);

If the POJO’s class is not available in the classpath or in the data grid, the application throws an exception indicating that there is no type descriptor registered for the specified type. In this case, it is possible to manually create a matching type descriptor using the SpaceTypeDescriptorBuilder and register it in the Space. However, this is not recommended because it essentially requires duplicating all the POJO settings and maintaining them if the POJO changes.

Query Result Type

When no interoperability is involved this is a trivial matter - Querying a POJO type returns POJOs, querying a document type returns documents.

When we want to mix and match, we need semantics to determine to query result type - POJO or document.

Template Query

Template query result types are determined by the template class - if the template is an instance of a SpaceDocument, the results will be documents, otherwise they will be POJOs.

For example:

// Read all product entries as POJOs:
Product[] objects = gigaSpace.readMultiple(new Product(), Integer.MAX_VALUE);
// Read all product entries as Documents:
SpaceDocument[] documents = gigaSpace.readMultiple(
    new SpaceDocument(Product.class.getName()), Integer.MAX_VALUE);

SQL Query

The SQLQuery class has been enhanced with a QueryResultType parameter. The following options are available:

  • OBJECT - Return java Object(s) (POJO).
  • DOCUMENT - Return space document(s).
  • DEFAULT - If the type is registered with a concrete java class, return an Object. Otherwise, return a document. This is the default behavior.

For example:

// Read a POJO using an SQL query - same as always:
Product pojo = gigaSpace.read(
    new SQLQuery<Product>(Product.class, "name='Dynamite'"));

// Read a document using an SQLQuery when there's no
// compatible POJO - no need to specify query result type:
SpaceDocument document = gigaSpace.read(
    new SQLQuery<SpaceDocument>("Product", "name='Dynamite'"));

// Read a documnet using an SQLQuery when there is a
// compatible POJO - explicitly specify query result type:
SpaceDocument document = gigaSpace.read(
    new SQLQuery<SpaceDocument>(Product.class.getName(),
        "name='Dynamite'", QueryResultType.DOCUMENT));

This strategy both preserves backwards compatibility and simplifies non-interoperability scenarios, which are more common than interoperability scenarios.

ID-Based Query

In order to support ID queries for documents, the IdQuery class has been introduced, which encapsulates the type, ID, routing and a QueryResultType. New GigaSpace signatures have been added for readById, readIfExistsById, takeById, takeIfExistsById. The result type is determined by the QueryResultType, similar to SQLQuery.

For example:

// Read a POJO by id - same as always:
Product pojo = gigaSpace.readById(new IdQuery<Product>(Product.class, 7));

// Read a document by id when there's no
// compatible POJO - no need to specify query result type:
SpaceDocument document = gigaSpace.readById(
    new IdQuery<SpaceDocument>("Product", 7));

// Read a document by id when there is
// a compatible POJO - explicitly specify query result type:
SpaceDocument document = gigaSpace.readById(
    new IdQuery<SpaceDocument>(Product.class.getName(), 7,
        QueryResultType.DOCUMENT));

Respectively, to support multiple ID queries, IdsQuery was also introduced, with new signatures for readByIds and takeByIds. For example:

Object[] ids = new Object[] {7, 8, 9};
// Read POJOs by ids - same as always:
Product[] pojos = gigaSpace.readByIds(
    new IdsQuery<Product>(Product.class, ids)).getResultsArray();

// Read documents by ids when there's no
// compatible POJO - no need to specify query result type:
SpaceDocument[] documents = gigaSpace.readByIds(
    new IdsQuery<SpaceDocument>("Product", ids)).getResultsArray();

// Read documents by ids when there is a
//  compatible POJO - explicitly specify query result type:
SpaceDocument[] documents = gigaSpace.readByIds(
    new IdsQuery<SpaceDocument>(Product.class.getName(),
        ids, QueryResultType.DOCUMENT)).getResultsArray();
Note