Sample Scala Project

Overview

This topic describes a sample project that shows how the GigaSpaces Scala extension can be used in a real project, and how Scala and Java code can be integrated.

Using the Sample Scala Project

Requirements

The sample Scala project uses the maven build tool. Ensure that the following requirements are met:

  • The minimum required Java version is JDK 1.6 .
  • To run the project, Scala libraries must be accessible to the data grid.

Scala is not needed to build the project, because the required libraries are downloaded by maven.

Running the Example

  1. Download the xap-scala package and unzip it.

  2. From the project's main directory $XAP_SCALA, run the following CLI command to install Maven on the host machine:

    mvn clean install
  3. From the project's main directory $XAP_SCALA/example/gs-openspaces-scala-example, run the following command to deploy the JAR files that you will need to deploy the project to the data grid:

    mvn clean package
  4. To start the data grid, run the following command:

    $GS_HOME/bin/gs-agent.sh/bat
  5. Run this command <XAP_HOME>\insightedge\bin\gs maven install:

  6. Deploy the project on the grid (from $XAP_SCALA/example/gs-openspaces-scala-example): mvn os:deploy -Dgroups=$XAP_LOOKUP_GROUPS.

Scala Sample Project Features

Constructor-Based Properties

The Common module defines the Space classes that are used by other modules. The classes are written in Scala, and are also used in other Scala and Java modules. All of these classes are translated into bytecode and can therefore be used interchangeably.

Being in immutable state is sometimes preferable. This requirement is covered in the GigaSpaces Scala extension by classes that use constructor-based properties; in the common module this is the Verification class, which is written only once to the Space and is never changed (instances can be removed).

case class Verification @SpaceClassConstructor() (
  @BeanProperty
  @SpaceId
  id: String,

  @BeanProperty
  dataId: String) extends scala.Serializable {

  override def toString: String = s"id[$id] dataId[$dataId]"
}

The other class (Data) has been rewritten in Scala. However, its behavior has not been modified apart from adding a new field needed by the verifier module:

case class Data (
  @BeanProperty @SpaceId(autoGenerate = true) var id: String = null,
  @BeanProperty @SpaceRouting @SpaceProperty(nullValue = "-1") var `type`: Long = -1,
  @BeanProperty var rawData: String = null,
  @BeanProperty var data: String = null,
  @BooleanBeanProperty var processed: Boolean = false,
  @BooleanBeanProperty var verified: Boolean = false) {

  def this(`type`: Long, rawData: String) = this(null, `type`, rawData, null, false, false)

  def this() = this(-1, null)

  override def toString: String = s"id[${id}] type[${`type`}] rawData[${rawData}] data[${data}] processed[${processed}] verified[${verified}]"
}

Predicate-Based Queries

The verifier module extends the pipeline presented in the baseline project (the one created by the OpenSpaces Maven plugin). The Verifier picks up processed Data instances and tries to verify them. The objects that pass the verification process are then modified (verified is set to true) and saved along with a new, immutable Verification object. The objects that fail the verification process are removed from the Space. The verifier uses the predicate-based queries feature to access the Space in a more readable and natural way (especially for functional languages such as Scala):

@GigaSpaceContext private var gigaSpace: GigaSpace = _ // injected
// ...

// data instances to process further are obtained in the following way
val unverifiedData = gigaSpace.predicate.readMultiple { data: Data => data.processed == true && data.verified == false }

The pu.xml contains a standard description of the gigaSpace:

...
<os-core:giga-space-context/>

<os-core:space-proxy  id="space" space-name="mySpace"/>

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

The gigaSpace in the code above is an instance of ScalaEnhancedGigaSpaceWrapper, which is a wrapper around the gigaSpace in the GigaSpaces Scala shell.

Building Scala and Mixed Java/Scala Modules

The build configuration in Scala or Java/Scala modules is almost as simple in case of pure Java modules.

Scala Module

The common module is a pure Scala module. The build configuration from the pom.xml for the common module has the following form:

<build>
    <sourceDirectory>src/main/scala</sourceDirectory>
    <plugins>
        <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <scalaCompatVersion>${scalaBinaryVersion}</scalaCompatVersion>
            </configuration>
        </plugin>
    </plugins>
    <finalName>gs-openspaces-scala-example-common</finalName>
</build>

In the above example, scalaBinaryVersion is a property defined in a parent pom file (in this case it is 2.11).

Java-Scala Module

The verifier module is a mixed Java-Scala module where Scala classes call Java classes. This configuration can be used when a separate task is implemented in Java, and it only needs to be called from other parts of the application. In this sample project, the Java module is simulated by the VerifierEngine class and is executed by the Scala verifier for ease of use.

In this configuration, the Scala compiler has to access the Java-compiled classes. The build-helper-maven-plugin adds Java classes to the source, then they are compiled, and finally the Scala compiler uses them during Scala code compilation. The build configuration of the verifier module is as follows:

<build>
    <sourceDirectory>src/main/scala</sourceDirectory>

    <plugins>
        <plugin>
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.4</version>
            <executions>
                <execution>
                    <id>add-java-source</id>
                    <phase>generate-sources</phase>
                    <goals>
                        <goal>add-source</goal>
                    </goals>
                    <configuration>
                        <sources>
                            <source>${basedir}/src/main/java</source>
                        </sources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <groupId>net.alchim31.maven</groupId>
            <artifactId>scala-maven-plugin</artifactId>
            <version>3.2.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>compile</goal>
                        <goal>testCompile</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <scalaCompatVersion>${scalaBinaryVersion}</scalaCompatVersion>
            </configuration>
        </plugin>
    </plugins>
</build>