REST data service configuration

To configure the REST data service, edit the properties file for REST and define the required entity schema for a WebSphere eXtreme Scale grid.

REST data service properties file

The REST data service properties file is the main configuration file for the eXtreme Scale REST data service. This file is a typical Java property file with key-value pairs. By default, the REST data service runtime will look for a well-named wxsRestService.properties file in the classpath. The file can also be explicitly defined by using the system property: wxs.restservice.props.

Dwxs.restservice.props=/usr/configs/dataservice.properties

When the REST data service is loaded, the property file used is displayed in the log files:

CWOBJ4004I: The eXtreme Scale REST data service properties files were loaded: [/usr/configs/RestService.properties]

The REST data service properties file supports the following properties:

Type Description
Property Description
catalogServiceEndPoints The required comma-delimited list of hosts and ports of a catalog service grid in the format: <host:port>. This is optional if using WebSphere Application Server integrated with eXtreme Scale to host the REST data service. See the WebSphere eXtreme Scale product documentation for details on how to configure and start a catalog service.

catalogServiceEndPoints=

server1:2809,server2:2809

objectGridNames The required names of the ObjectGrids to expose to the REST service. At least one ObjectGrid name is required. Separate multiple ObjectGrid names using a comma:

ECommerceGrid,InventoryGrid

objectGridClientXML The optional name of the ObjectGrid client override XML file. The name specified here will be loaded from the classpath. The default is:

/META-INF/objectGridClient.xml. See the WebSphere eXtreme Scale product documentation for details on how to configure an eXtreme Scale client.

traceFile The optional name of the file to redirect the trace output to. The default is logs/trace.log.
traceSpec The optional trace specification that the eXtreme Scale runtime server should initially use. The default is *=all=disabled. To trace the entire REST data service, use: ObjectGridRest*=all=enabled
verboseOutput If set to true, REST data service clients will receive additional diagnostic information when failures occur. The default is false. This optional value should be set to false for production environments as sensitive information may be revealed.

WebSphere eXtreme Scale configuration

The eXtreme Scale REST data service interacts with eXtreme Scale using the EntityManager API. An entity schema is defined for an eXtreme Scale grid and the meta-data for the entities is automatically consumed by the REST data service. For details on how to configure an entity schema, see the eXtreme Scale EntityManager documentation.

For example, you can define an entity representing a Person in an eXtreme Scale grid as follows:
@Entity															
public class Person {
		@Id String taxId;
		String firstName;
		String lastName;
}
Tip: The annotations used here are in the com.ibm.websphere.projector.annotations package.

The REST service will automatically create an ADO.NET Entity Data Model for Data Services (EDMX) document, which is available using the $metadata URI:

http://localhost:8080/wxsrestservice/restservice/NorthwindGrid/$metadata

Once the eXtreme Scale grid is configured and running, an eXtreme Scale client should be configured and packaged. For details on configuring the eXtreme Scale REST data service client package, see topic:

The following topics describe how eXtreme Scale is exposed as a REST service.

WebSphere eXtreme Scale entities are modeled using the entity annotations or an entity metadata descriptor file. See the topic on defining an entity schema in the Programming Guide of the WebSphere eXtreme Scale V7.1 documentation for details on how to configure an eXtreme Scale entity schema. The eXtreme Scale REST service uses the entity metadata to automatically create an EDMX model for the data service.

This version of the WebSphere eXtreme Scale REST data service has the following schema restrictions:
  • When defining entities in a partitioned grid, all entities must have a direct or indirect single valued association to the root entity (a key association). The WCF data service client runtime must be able to access every entity directly through its canonical address. Therefore, the key of the root entity that is used for partition routing (the schema root) must be part of the key in the child entity.

    For example:

    For example:
    
    @Entity(schemaRoot=true)
    public class Person {
        @Id String taxId;
        String firstName;
        String lastName;
        @OneToMany(mappedBy="person") 
        List<Address> addresses;
    
    }
    
    @Entity
    public class Address {
        @Id int addrId;
        @Id @ManyToOne Person person;
        String street;
    }
  • Bi-directional and uni-directional associations are supported. However, uni-directional associations may not always work from a Microsoft WCF Data Services client since they can only be navigated in one direction and the Microsoft specification requires all associations to be bi-directional.
  • Referential constraints are not supported. The eXtreme Scale runtime does not validate keys between entities. Associations between entities must be managed by the client.
  • Complex types are not supported. The eXtreme Scale EntityManager API does not support embeddable attributes. All attributes are expected to be simple type attributes (see the simple attribute types listed below). Non-simple type attributes are treated as a binary object from the perspective of the client.
  • Entity inheritance is not supported. The eXtreme Scale EntityManager API does not support inheritance.
  • Media Resources and Media Links are not supported. The HasStream attribute of the EntityType in the Conceptual Schema Definition Language Document for Data Services is never used.

Mapping between EDM data types and Java data types

The OData protocol defines the following list of Entity Data Model (EDM) types in its abstract type system. The following topics describe how the eXtreme Scale REST adapter chooses the EDM type based on the basic type defined in the entity. For details on EDM types, see: http://msdn.microsoft.com/en-us/library/dd541295(PROT.10).aspx.

The following EDM types are available in WCF Data Services:

  • Edm.Binary
  • Edm.Boolean
  • Edm.Byte
  • Edm.DateTime
  • Edm.Time
  • Edm.Decimal
  • Edm.Double
  • Edm.Single
  • Edm.Float
  • Edm.Guid *
  • Edm.Int16
  • Edm.Int32
  • Edm.Int64
  • Edm.SByte Edm.String

* The EDM type: Edm.Guid is not supported by the eXtreme Scale REST data service.

Mapping Java types to EDM types

The eXtreme Scale REST data service will automatically convert basic entity types into EDM types. The type mapping can be seen by displaying the Entity Data Model Extensions (EDMX) metadata document using the $metadata URI. The EDM type is what is used by clients to read and write data to the REST data service. It shows the mapping from the Java type defined for an entity to the EDM data type.

When retrieving data using a query, the data will be represented with these types:

Type Value
Java Type EDM Type
boolean java.lang.Boolean Edm.Boolean
byte java.lang.Byte Edm.SByte
short java.lang.Short Edm.Int16
int java.lang.Integer Edm.Int32
long java.lang.Long Edm.Int64
float java.lang.Float Edm.Single
double java.lang.Double Edm.Double
java.math.BigDecimal java.math.BigInteger Edm.Decimal
java.lang.String char java.lang.Character Char[] java.lang.Character[] Edm.String
java.util.Calendar java.util.Date java.sql.Date java.sql.Timestamp java.sql.Time Edm.DateTime
Other types Edm.Binary
Mapping from EDM types to Java types

For Update requests and Insert requests, the payload specifies the data to be updated or inserted into the eXtreme Scale REST data service. The service can automatically convert compatible data types to the data types defined in the EDMX document. The REST data service converts the XML encoded string representations of the value into the correct type using the following two-step process:

  1. A type check is performed to make sure the EDM type is compatible with the Java type. An EDM type is compatible with a Java type if the data supported by the EDM type is a subset of the data supported by the Java type. For example, Edm.int32 type is compatible with a Java long type, but Edm.int32 type is not compatible with a Java short type.
  2. A target Java type object will be created which represents the string value in the payload.

Compatible EDM type to Java type

Type Description
EDM Type Java Type
Edm.Boolean boolean

java.lang.Boolean

Edm.SByte byte

java.lang.Byte

short

java.lang.Short

int

java.lang.Integer

long

java.lang.Long

float

java.lang.Float

double

java.lang.Double

java.math.BigDecimal

java.math.BigInteger

char

java.lang.Character

Edm.Byte, Edm.Int16 short

java.lang.Short

int

java.lang.Integer

long

java.lang.Long

float

java.lang.Float

double

java.lang.Double

java.math.BigDecimal

java.math.BigInteger

char

java.lang.Character

Edm.Int32 int

java.lang.Integer

long

java.lang.Long

float

java.lang.Float

double

java.lang.Double

java.math.BigDecimal

java.math.BigInteger

Edm.Int64 long

java.lang.Long

double

java.lang.Double

java.math.BigDecimal

java.math.BigInteger

Edm.Double double

java.lang.Double

java.math.BigDecimal

Edm.Decimal double

java.lang.Double

java.math.BigDecimal

java.math.BigInteger

Edm.Single float

java.lang.Float

double

java.lang.Double

java.math.BigDecimal

Edm.String java.lang.String

char

java.lang.Character

Char[]

java.lang.Character[]

java.math.BigDecimal

java.math.BigInteger

Edm.DateTime java.util.Calendar

java.util.Date

java.sql.Date

java.sql.Time

java.sql.Timestamp

Edm.Time java.sql.Time

java.sql.Timestamp

Mapping temporal types

Java includes five temporal types for storing date, time or both: java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp and java.util.Calendar. All of these types are expressed in the entity data model as Edm.DateTime. The eXtreme Scale REST service automatically converts and normalizes the data depending on the Java type. This topic describes several issues that developers must be aware of when using any temporal type.

Time zone differences

In WCF Data Services, the descriptions of time values in the Edm.DateTime type are always expressed using the Coordinated Universal Time (UTC) standard, which is the internationally recognized name for Greenwich Mean Time (GMT). Coordinated Universal Time is the time as measured at zero degrees longitude, the UTC origin point. Daylight saving time is not applicable to UTC.

Converting between entity and EDM types

When a client sends a request to the REST data service, the date and time is represented as a GMT time zone time, like the following example:

"2000-02-29T21:30:30.654123456"

The REST data service will then construct the appropriate Java temporal type instance and insert it into the entity in the grid.

When a client requests a property which is a Java temporal type from the eXtreme Scale REST data service, the value is always normalized as a GMT time zone value. For example, if an entity java.util.Date is constructed as follows:

Calendar c = Calendar.getInstance();
c.clear();									
c.set(2000, 1, 29, 21, 30, 30);
Date d = c.getTime();

The date and time are represented using the default time zone of the Java process because Calendar.getInstance() will create a Calendar object with local time zone. If the local time zone is CST, then the date, when retrieved from the REST data service will be the GMT representation of the time: "2000-03-01T03:30:30"

java.sql.Date normalization

An eXtreme Scale entity can define an attribute with Java type java.sql.Date. This data type does not include the time and is normalized by the REST data service. This means that the eXtreme Scale runtime does not store any hours, minutes, seconds, or milliseconds information in the java.sql.Date attribute. Regardless of the time zone offset, the date is always represented as a local date.

For example, if the client updates a java.sql.Date property with the value “2009-01-01T03:00:00”, the REST data service, which is in the CST time zone (-06:00), will simply create a java.sql.Date instance of which the time is set to “2009-01-01T00:00:00” of the local CST time. There is no time zone conversion done to create the java.sql.Date value. When the REST service client retrieves the value of this attribute, it will be displayed as “2009-01-01T00:00:00Z”. If a time zone conversion were done, the value would be displayed as having the date of “2008-12-31”, which would be incorrect.

java.sql.Time normalization

Similar to java.sql.Date, the java.sql.Time values are normalized and do not include date information. This means that the eXtreme Scale run time does not store the year, month or day. The time is stored using the GMT time from the epoch January 1, 1970, which is consistent with the java.sql.Time implementation.

For example, if the client updates a java.sql.Time property with the value "2009-01-01T03:00:00", the REST data service, will create a java.sql.Time instance with the milliseconds set to 3*60*60*1000, which is equal to 3 hours. When the rest service retrieves the value, it will be displayed as "1970-01-01:03:00:00Z".

Associations

Associations define the relationship between two peer entities. The eXtreme Scale REST service reflects the associations modeled with entities defined with eXtreme Scale annotated entities or entities defined using an entity descriptor XML file.

Association maintenance

The eXtreme Scale REST data service does not support referential integrity constraints. The client should ensure that references are updated when entities are removed or added. If a target entity of an association is removed from the grid, but the link between the source and target entity is not removed, then the link is broken. The eXtreme Scale REST data service and EntityManager API tolerates broken links and will log them as CWPRJ1022W warnings. Broken associations will simply be removed from the request payload.

Use a batch request to group association updates in a single transaction to avoid broken links. See section for details on batch requests.

The ADO.NET Entity Data Model ReferentialConstraint element is not used by the eXtreme Scale REST data service.

Association multiplicity

Entities can have multi-valued associations or single-valued associations. Multi-valued associations, or collections, are one-to-many or many-to-many associations. Single-valued associations are one-to-one or many-to-one associations.

In a partitioned grid, all entities should have a single-valued key-association path to a root entity. Because the root entity is used to partition the entity, many-to-many associations are not allowed for partitioned grids. For an example on how to model a relational entity schema for a partitioned grid, see section . See the following section: for details on how to define a key association.

The following example describes how the EntityManager API association types, modeled using annotated Java classes map to the ADO.NET Entity Data Model:

@Entity
public class Customer {
    @Id String customerId;
    @OneToOne TaxInfo taxInfo;
    @ManyToOne Address homeAddress;
    @OneToMany Collection<Order> orders;
    @ManyToMany Collection<SalesPerson> salespersons;
}

<Association Name="Customer_TaxInfo">
    <End Type="Model1.Customer" Role="Customer" Multiplicity="1" />
    <End Type="Model1.TaxInfo " Role="TaxInfo" Multiplicity="1" />
</Association>
<Association Name="Customer_Address">
    <End Type="Model1.Customer" Role="Customer" Multiplicity="1" />
    <End Type="Model1.Address" Role="TaxInfo" Multiplicity="*" />
</Association>
<Association Name="Customer_Order">
    <End Type="Model1.Customer" Role="Customer" Multiplicity="*" />
    <End Type="Model1.Order" Role="TaxInfo" Multiplicity="1" />
</Association>
<Association Name="Customer_SalesPerson">
    <End Type="Model1.Customer" Role="Customer" Multiplicity="*" />
    <End Type="Model1.SalesPerson" Role="TaxInfo" Multiplicity="*" />
</Association>

Bi-directional and uni-directional associations

Entities associations can be uni-directional or bi-directional. By specifying the "mappedBy" attribute on the @OneToOne, @OneToMany or @ManyToMany annotation or the "mapped-by" attribute on the one-to-one, one-to-many or many-to-many XML attribute tag, the entity becomes bi-directional. The OData protocol currently requires all entities to be bi-directional, allowing clients to generate navigation paths in both directions. The eXtreme Scale EntityManager API allows modeling uni-directional associations which can save memory and simplify maintenance of the associations. If a uni-directional association is used, the REST data services client must only navigate through the association using the defined association.

For example: If a uni-directional many-to-one association is defined between Address and Country, the following URI is not allowed:

/restservice/CustomerGrid/Country('USA')/addresses

Key associations

Single-valued associations (one-to-one and many-to-one) can also be included as all or part of the entities key. This is known as a key-association.

Key associations are required when using a partitioned grid. The key association must be defined for all child entities in a partitioned entity schema. The OData protocol requires that all entities are directly addressable. This means that the key in the child entity must include the key used for partitioning.

In the following example, Customer has a one-to-many association to Order. The Customer entity is the root entity and the customerId attribute is used to partition the entity. Order has included the Customer as part of its identity:

@Entity(schemaRoot="true")
public class Customer {
    @Id String customerId;
    @OneToMany(mappedBy="customer") Order orders
}

@Entity
public class Order {
    @Id int orderId;
    @Id @ManyToOne Customer customer;
    java.util.Date orderDate;
}

When the REST data service generates the EDMX document for this model, the Customer key fields are automatically included as part of the Order entity:

<EntityType Name="Order">
<Key>
    <PropertyRef Name="orderId"/>
    <PropertyRef Name="customer_customerId"/>
</Key>

<Property Name="orderId" Type="Edm.Int64" Nullable="false"/>
<Property Name="customer_customerId" Type="Edm.String" 
    Nullable="false"/>
<Property Name="orderDate" Type="Edm.DateTime" Nullable="true"/>
<NavigationProperty Name="customer" 
    Relationship="NorthwindGridModel.Customer_orders"
    FromRole="Order" ToRole="Customer"/>

<NavigationProperty Name="orderDetails" 
    Relationship="NorthwindGridModel.Order_orderDetails" 
    FromRole="Order" ToRole="OrderDetail"/>
</EntityType>

When an entity is created, the key must never change. This means if the key association between a child entity and its parent must change, the child entity must be removed and re-created with a different parent. In a partitioned grid, this will require two different batch change sets since the move will likely involve more than one partition.

Cascading operations

The EntityManager API allows a flexible cascade policy. Associations can be marked to cascade a persist, remove, invalidate or merge operation. Such cascade operations can happen on one or both sides of a bi-directional association.

The OData protocol only allows cascade delete operations on the single-side of the association. The CascadeType.REMOVE annotation or cascade-remove XML attribute cannot be defined on both sides of a one-to-one bi-directional association or on the many-side of a one-to-many association. The following example illustrates a valid Cascade.REMOVE bi-directional association:

@Entity(schemaRoot="true")
public class Customer {
    @Id String customerId;
    @OneToMany(mappedBy="customer", cascade=CascadeType.REMOVE)
    Order orders
}

@Entity
public class Order {
    @Id int orderId;
    @Id @ManyToOne Customer customer;
    java.util.Date orderDate;
}

The resulting EDMX association looks as follows:

<Association Name="Customer_orders">
    <End Type="NorthwindGridModel.Customer" Role="Customer" 
        Multiplicity="1">
        <OnDelete Action="Cascade"/>
    </End>
    <End Type="NorthwindGridModel.Order" Role="Order" 
        Multiplicity="*"/>
</Association>