Summary: The JavaSpaces API is abstracted in OpenSpaces by a simple wrapper: the GigaSpace interface.

Overview

OpenSpaces provides a simpler space API using the GigaSpace interface, by wrapping the IJSpace (and the Jini JavaSpace), and simplifying both the API and its programming model. The interface allows the POJO domain model to be stored in the space (using GigaSpaces POJO support), declarative transactions, usage of Java 5 Generics, coherent runtime exception hierarchy, and more.

Here is a very simple example of how to define it:

Namespace
<os-core:space id="space" url="/./space" />

<os-core:giga-space id="gigaSpace" space="space"/>

Plain XML
<bean id="space" class="org.openspaces.core.space.UrlSpaceFactoryBean">
    <property name="url" value="/./space" />
</bean>

<bean id="gigaSpace" class="org.openspaces.core.GigaSpaceFactoryBean">
	<property name="space" ref="space" />
</bean>

Code
IJSpace space = // get Space either by injection or code creation

GigaSpace gigaSpace = new GigaSpaceConfigurer(space).gigaSpace();

The GigaSpace interface is a thin wrapper built on top of IJSpace. Within a single Processing Unit (or Spring application context), several GigaSpace instances can be defined, each with different characteristics.

The IJSpace interface is not hidden, and can be used even when using the GigaSpace interface. GigaSpace simplifies most operations used with the space (compared to IJSpace), but some operations still require access to IJSpace, which can be accessed through the GigaSpace API.

Clustered Flag

When configuring a Space an IJSpace instance is registered with Spring application context. When starting an embedded space with a cluster topology, or when looking up a remote space started with a cluster topology, a clustered proxy is returned. A clustered proxy is a smart proxy that performs operations against the whole cluster.

Many times, especially when working with a Processing Unit that starts an embedded space, operations against the space should be performed directly on the cluster member. This is a core concept of SBA and Processing Unit, where most if not all operations should be performed in-memory without leaving the processing unit boundaries when a Processing Unit starts an embedded space.

The decision of working directly with a cluster member or against the whole cluster is done in the GigaSpace level. The GigaSpacesFactoryBean provides a clustered flag with the following logic as the default value: If the space is started in embedded mode (for example, /./space), the clustered flag is set to false. When the space is looked up in a remote protocol (Jini or RMI), the clustered flag is set to true. Naturally, the flag can be set explicitly. Here is an example of how the clustered flag can be configured:

Namespace
<os-core:space id="space" url="/./space" />

<!-- By default, since we are starting in embedded mode, clustered=false -->
<os-core:giga-space id="directGigaSpace" space="space"/>

<os-core:giga-space id="clusteredGigaSpace" space="space" clustered="true"/>

Plain
<bean id="space" class="org.openspaces.core.space.UrlSpaceFactoryBean">
    <property name="url" value="/./space" />
</bean>

<!-- By default, since we are starting in embedded mode, clustered=false -->
<bean id="directGigaSpace" class="org.openspaces.core.GigaSpaceFactoryBean">
	<property name="space" ref="space" />
</bean>

<bean id="clusteredGigaSpace" class="org.openspaces.core.GigaSpaceFactoryBean">
	<property name="space" ref="space" />
	<property name="clustered" value="true" />
</bean>

Code
IJSpace space = // get Space either by injection or code creation

GigaSpace gigaSpace = new GigaSpaceConfigurer(space).clustered(true).gigaSpace();

The above example shows a typical scenario where the clustered flag is used. Within a Processing Unit, an application might need to access both the cluster member and the whole cluster directly.

Simpler API

The GigaSpace interface provides a simpler space API by utilizing Java 5 generics, and allowing sensible defaults. Here is an example of the space take operation as defined within GigaSpace:

public interface GigaSpace {

    // ....
    
    <T> T take(T template) throws DataAccessException;
    
    <T> T take(T template, long timeout) throws DataAccessException;
}

In the example above, the take operation can be performed without specifying a timeout. The default take timeout is 0 (no wait), and can be overridden when configuring the GigaSpace factory. In a similar manner, the read timeout and write lease can be specified.

Namespace
<os-core:space id="space" url="/./space" />

<os-core:giga-space id="gigaSpace" space="space" default-take-timeout="1000"/>

Plain XML
<bean id="space" class="org.openspaces.core.space.UrlSpaceFactoryBean">
    <property name="url" value="/./space" />
</bean>

<bean id="gigaSpace" class="org.openspaces.core.GigaSpaceFactoryBean">
	<property name="space" ref="space" />
    <property name="defaultTakeTimeout" value="1000" />
</bean>

Code
IJSpace space = // get Space either by injection or code creation

GigaSpace gigaSpace = new GigaSpaceConfigurer(space).defaultTakeTimeout(1000).gigaSpace();

Declarative Transactions

As seen in the take API above, there is no need to provide a Jini transaction object for the different space operations. GigaSpace with the different OpenSpaces transaction managers and Spring allow simple declarative definition of transactions. This boils down to the fact that if there is an ongoing transaction running, any operation performed using the GigaSpace interface joins it, using Spring's rich transaction support.

In order to have GigaSpace transactional, the transaction manager must be provided as a reference when constructing the GigaSpace bean. For example (using the local transaction manager):

Namespace
<os-core:space id="space" url="/./space" />

<os-core:local-tx-manager id="transactionManager" space="space"/>

<os-core:giga-space id="gigaSpace" space="space" tx-manager="transactionManager"/>

Plain XML
<bean id="space" class="org.openspaces.core.space.UrlSpaceFactoryBean">
    <property name="url" value="/./space" />
</bean>

<bean id="transactionManager" class="org.openspaces.core.transaction.manager.LocalJiniTransactionManager">
	<property name="space" ref="space" />
</bean>

<bean id="gigaSpace" class="org.openspaces.core.GigaSpaceFactoryBean">
    <property name="space" ref="space" />
	<property name="transactionManager" ref="transactionManager" />
</bean>

It is highly recommended to read the transaction management chapter in the Spring reference documentation.

Transaction Provider

OpenSpaces provides a pluggable transaction provider using the following interface:

public interface TransactionProvider {

    Transaction getCurrentTransaction(Object transactionalContext, IJSpace space);

    int getCurrentTransactionIsolationLevel(Object transactionalContext);
}

OpenSpaces comes with a default transaction provider implementation, which uses Spring and its transaction manager in order to obtain the currently running transactions and automatically use them under transactional operations.

GigaSpace allows access to the current running transaction using the transaction provider. The following code example shows how the take operation can be performed using IJspace (users normally won't be required to do so):

gigaSpace.getSpace().take(obj, gigaSpace.getCurrentTransaction(), 1000);

Transaction Isolation Level

GigaSpaces supports three isolation levels: READ_UNCOMMITTED, READ_COMMITTED and REPEATABLE_READ (default). When using GigaSpace, the default isolation level that it will perform under can be defined in the following manner:

Namespace
<os-core:space id="space" url="/./space" />

<os-core:giga-space id="gigaSpace" space="space" default-isolation="READ_COMMITTED"/>

Plain XML
<bean id="space" class="org.openspaces.core.space.UrlSpaceFactoryBean">
    <property name="url" value="/./space" />
</bean>

<bean id="gigaSpace" class="org.openspaces.core.GigaSpaceFactoryBean">
	<property name="space" ref="space" />
    <property name="defaultIsolationLevelName" value="READ_COMMITTED" />
</bean>

Code
IJSpace space = // get Space either by injection or code creation

GigaSpace gigaSpace = new GigaSpaceConfigurer(space).defaultIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED)
                                                    .gigaSpace();

In addition, Spring allows you to define the isolation level on the transaction definition itself:

@Transactional(readOnly = true)
public class DefaultFooService implements FooService {

    private GigaSpace gigaSpace;
    
    public void setGigaSpace(GigaSpace gigaSpace) {
    	this.gigaSpace = gigaSpace;
    }

    public Foo getFoo(String fooName) {
        // do something
    }

    // these settings have precedence for this method
    @Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, isolation  = Isolation.READ_COMMITTED)
    public void updateFoo(Foo foo) {
        // do something
    }
}

In the above example, any operation performed using GigaSpace in the updateFoo method automatically works under the READ_COMMITTED isolation level.

Exception Hierarchy

OpenSpaces is built on top of the Spring consistent exception hierarchy by translating all of the different JavaSpaces exceptions and GigaSpaces exceptions into runtime exceptions, consistent with the Spring exception hierarchy. All the different exceptions exist in the org.openspaces.core package.

OpenSpaces provides a pluggable exception translator using the following interface:

public interface ExceptionTranslator {

    DataAccessException translate(Throwable e);
}

A default implementation of the exception translator is automatically used, which translates most of the relevant exceptions into either Spring data access exceptions, or concrete OpenSpaces runtime exceptions (in the org.openspaces.core package).

GigaSpaces.com - Legal Notice - 3rd Party Licenses - Site Map - API Docs - Forum - Downloads - Blog - White Papers - Contact Tech Writing - Gen. by Atlassian Confluence