Fichier de propriétés du service de données REST

Pour configurer le service de données REST, éditez le fichier de propriétés de REST et définissez le schéma d'entité requis pour une grille de données.

Le fichier de propriétés du service de données REST est le fichier de configuration principal du service de données REST d'eXtreme Scale. Ce fichier est un fichier de propriétés Java http://java.sun.com/j2se/1.5.0/docs/api/java/util/Properties.html#load(java.io.InputStream) avec des paires clé-valeur. Par défaut, l'environnement d'exécution du service de données REST recherche un fichier nommé wxsRestService.properties dans le chemin d'accès aux classes. Ce fichier peut également être défini de manière explicite à l'aide de la propriété système suivante : wxs.restservice.props.

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

Lorsque le service de données REST est chargé, le fichier de propriétés utilisé est affiché dans les fichiers journaux :

CWOBJ4004I: Les fichiers de propriétés du service de données REST de WebSphere eXtreme Scale ont été chargés : [/usr/configs/RestService.properties]

Le fichier de propriétés du service de données REST prend en charge les propriétés suivantes :

Tableau 1. Propriétés du service de données REST
Propriété Description
catalogServiceEndPoints La liste requise, délimitée par des virgules, des hôtes et des ports d'un domaine de service de catalogue au format <hôte:port>. Elle est facultative si vous utilisez WebSphere Application Server intégré à WebSphere eXtreme Scale pour héberger le service de données REST. Pour plus d'informations, voir Démarrage d'un service de catalogue autonome.

catalogServiceEndPoints=

server1:2809,server2:2809

objectGridNames Les noms requis pour les grilles de données à exposer au service REST. Au moins un nom ObjectGrid est requis. Séparez par des virgules les noms d'ObjectGrids multiples :

ECommerceGrid,InventoryGrid

objectGridClientXML Le nom facultatif du fichier XML de remplacement ObjectGrid par les clients. Le nom spécifié ici est chargé à partir du chemin d'accès aux classes. La valeur par défaut est :

/META-INF/objectGridClient.xml.

ogClientPropertyFile Le nom facultatif du fichier de propriétés du client ObjectGrid. Ce fichier contient les propriétés de sécurité qui sont requises pour l'activation de la sécurité dans le client ObjectGrid. Si l'attribut securityEnabled est défini dans le fichier de propriétés, la sécurité sera activée dans le client ObjectGrid utilisé par le service REST. La propriété credentialGeneratorProps doit elle aussi être définie dans le fichier des propriétés, avec une valeur au format "user:pass" ou {xor_encoded user:pass}
loginType Le type d'authentification utilisé par le service REST lorsque la sécurité du client ObjectGrid est activée. Si cette sécurité n'est pas activée, cette propriété est ignorée.
Si la sécurité du client ObjectGrid est activée et que loginType a la valeur basic, le service de données REST :
  • pour les opérations ObjectGrid lors de l'initialisation du service, utilisera les données d'identification spécifiées dans la propriété credentialGeneratorProps du fichier de propriétés du client ObjectGrid
  • pour les opérations de session ObjectGrid par demande, utilisera l'authentification Basic HTTP
Si la sécurité du client ObjectGrid est activée et que loginType a la valeur none, le service de données REST :
  • pour les opérations ObjectGrid lors de l'initialisation du service, utilisera les données d'identification spécifiées dans la propriété credentialGeneratorProps du fichier de propriétés du client ObjectGrid
  • pour les opérations de session ObjectGrid par demande, utilisera les données d'identification spécifiées dans la propriété credentialGeneratorProps du fichier des propriétés du client ObjectGrid
traceFile Nom facultatif du fichier dans lequel la sortie de la trace sera redirigée. La valeur par défaut est : logs/trace.log.
traceSpec La spécification facultative de trace que le serveur d'exécution d'eXtreme Scale doit utiliser au départ. La valeur par défaut est *=all=disabled. Pour la trace de l'intégralité du service de données REST, utilisez ObjectGridRest*=all=enabled
verboseOutput Si la valeur est true, les clients du service de données REST reçoivent des informations de diagnostic supplémentaires en cas d'incidents. La valeur par défaut est false. Cette valeur facultative doit être false pour les environnements de production car des informations confidentielles peuvent être révélées.
maxResultsPerCollection Le nombre maximal de résultats retournés dans une requête (facultatif). La valeur par défaut est unlimited. Un entier positive est une valeur valide.
wxsRestAccessRightsFile Le nom facultatif du fichier de propriétés des droits d'accès au service REST d'eXtreme Scale, qui spécifie les droits d'accès pour les opérations du service et les entités ObjectGrid. Si cette propriété est spécifiée, le service REST essaiera de charger le fichier à partir du chemin spécifié ; sinon, il essaiera de le charge à partir de son chemin d'accès aux classes.

Configuration de WebSphere eXtreme Scale

Le service de données REST d'eXtreme Scale interagit avec eXtreme Scale à l'aide de l'API EntityManager. Un schéma d'entité est défini pour une grille de données eXtreme Scale et les métadonnées des entités sont automatiquement utilisées par le service de données REST. Voir Définition d'un schéma d'entité pour plus d'informations sur la configuration d'un schéma d'entité.

Par exemple, vous pouvez définir une entité représentant une personne dans une grille de données eXtreme Scale comme suit :
@Entity															
public class Person {
		@Id String taxId;
		String firstName;
		String lastName;
}
Conseil : Les annotations utilisées ici se trouvent dans le package com.ibm.websphere.projector.annotations.

Le service REST crée automatiquement un document EDMX (Entity Data Model for Data Services) ADO.NET, accessible par l'URI $metadata :

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

Une fois que la grille de données est configurée et en cours d'exécution, configurez et modularisez un client eXtreme Scale. Pour des explications détaillées sur la configuration du package client de service de données REST d'eXtreme Scale, voir dans Installation du service de données REST les explications sur le packaging et le déploiement.

Modèle d'entité

Les entités WebSphere eXtreme Scalesont modélisées à l'aide des annotations d'entité ou d'un fichier descripteur de métadonnées d'entité. Pour plus de détails sur la configuration d'un schéma d'entité, voir Définition d'un schéma d'entité. Le service REST d'eXtreme Scale utilise les métadonnées d'entité pour créer automatiquement un modèle EDMX pour le service de données.

Cette version du service de données REST WebSphere eXtreme Scale a les restrictions de schéma suivantes :
  • Lors de la définition d'entités dans une grille de données partitionnée, toutes les entités doivent posséder une association directe ou indirecte à valeur unique avec l'entité racine (association de clés). L'environnement d'exécution du client du service de données WCF doit pouvoir accéder à toutes les entités directement via son adresse canonique. Par conséquent, la clé de l'entité racine utilisée pour le routage des partitions (racine du schéma) doit faire partie de la clé dans l'entité enfant.

    Par exemple :

    @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;
    }
  • Les associations unidirectionnelles et bidirectionnelles sont prises en charge. Toutefois, les associations risquent de ne pas toujours fonctionner à partir d'un client Microsoft WCF Data Services car elles ne sont parcourues que dans un sens et la spécification Microsoft requiert que toutes les associations soient bidirectionnelles.
  • Les contraintes référentielles ne sont pas prises en charge. L'environnement d'exécution WebSphere eXtreme Scale ne valide pas les clés entre les entités. Les associations entre les entités doivent être gérées par le client.
  • Les types complexes ne sont pas pris en charge. L'API EntityManager ne prend pas en charge les attributs intégrables. Tous les attributs doivent être des attributs de type simple (voir les attributs de type simple répertoriés ci-après). Les attributs non simples sont traités comme un objet binaire du point de vue du client.
  • L'héritage des entités n'est pas pris en charge. L'API EntityManager ne prend pas en charge l'héritage.
  • Les ressources de support et les liens de support ne sont pas pris en charge. L'attribut HasStream du type d'entité dans le document CSDL (Conceptual Schema Definition Language) des services de données n'est jamais utilisé.

Mappage entre les types de données EDM et les types de données Java

Le protocole OData définit la liste ci-après des types de modèle de données d'entité (EDM) et son système de type abstrait. Les rubriques qui suivent décrivent comment l'adaptateur REST d'eXtreme Scale choisit le type EDM en fonction du type de base défini dans l'entité. Pour des détails sur les types EDM, voir MSDN Library: Abstract Type System.

Les types EDM suivants sont disponibles dans les services de données WCF :

  • 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

Le type EDM Edm.Guid n'est pas pris en charge par le service de données REST d'eXtreme Scale.

Mappage des types Java avec les types EDM

Le service de données REST eXtreme Scale convertit automatiquement les types d'entité de base en types EDM. Le mappage des types peut être consulté en affichant le document des métadonnées EDMX (Entity Data Model Extensions) à l'aide de l'URI $metadata. Le type EDM est utilisé par les clients pour lire et écrire les données dans le service de données REST
Tableau 2. Types Java mappés à des types EDM. Le tableau montre le mappage vers un type de données EDM du type Java défini pour une entité. Lors de l'extraction de données à l'aide d'une requête, les données seront représentées avec ces types :
Type Java Type EDM
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 Edm.Decimal
java.math.BigInteger java.math.BigInteger
java.lang.String Edm.String
char char
java.lang.Character java.lang.Character
Char[] Char[]
java.lang.Character[] java.lang.Character[]
java.util.Calendar Edm.DateTime
java.util.Date java.util.Date
java.sql.Date java.sql.Date
java.sql.Timestamp java.sql.Timestamp
java.sql.Time java.sql.Time
Autres types Edm.Binary

Mappage des types EDM vers les types Java

Pour les demandes Update et Insert, la charge spécifie les données à actualiser ou à insérer dans le service de données REST d'eXtreme Scale. Le service peut automatiquement convertir les types de données compatibles vers les types de données définis dans le document EDMX. Le service de données REST convertit les représentations de chaîne codées en XML de la valeur dans le type approprié à l'aide de la procédure en deux étapes suivante :

  1. Une vérification du type est effectuée pour s'assurer que le type EDM est compatible avec le type Java. Un type EDM est compatible avec un type Java si les données prises en charge par le type EDM sont un sous-ensemble des données prises en charge par le type Java. Par exemple, le type Edm.int32 est compatible avec un type Java long, mais le type Edm.int32 n'est pas compatible avec un type Java court.
  2. Un objet cible de type Java est créé pour représenter la valeur de la chaîne dans la charge.
Tableau 3. Types EDM compatibles avec les types Java
Type EDM Type Java
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

entier

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 entier

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

Mappage des types temporels

Java inclut cinq types temporels permettant de stocker la date et/ou l'heure : java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp et java.util.Calendar. Tous ces types sont exprimés dans le modèle de données d'entité au format Edm.DateTime. Le service de données REST eXtreme Scale convertit et normalise automatiquement les données en fonction du type Java. Cette rubrique décrit plusieurs problèmes dont les développeurs doivent être conscients lorsqu'ils utilisent un type temporel.

Décalages horaires

Dans WCF Data Services, les descriptions des valeurs temporelles dans le type Edm.DateTime sont toujours exprimées à l'aide de la norme UTC (temps universel coordonné), qui correspond au nom international du temps moyen de Greenwich (GMT). Le temps universel coordonné correspond à l'heure mesurée à la longitude de zéro degrés (le point d'origine UTC). L'heure d'été ne s'applique pas à l'heure UTC.

Conversion entre les types d'entité et les types EDM

Lorsqu'un client envoie une demande au service de données REST, la date et l'heure sont représentées comme une heure GMT, comme dans l'exemple suivant :

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

Le service de données REST construit l'instance de type temporel Java et l'insère dans l'entité dans la grille de données.

Lorsqu'un client demande au service de données REST d'eXtreme Scale une propriété qui est un type Java temporel, la valeur est toujours normalisée en valeur GMT. Par exemple, si une entité java.util.Date est construite comme suit :

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

La date et l'heure sont représentées à l'aide du fuseau horaire par défaut du processus Java car Calendar.getInstance() crée un objet Calendar avec le fuseau horaire local. Si, le fuseau horaire local est CST, la date, lorsqu'elle est extraite du service de données REST correspond à la représentation GMT de l'heure : "2000-03-01T03:30:30"

Normalisation de java.sql.Date

Une entité eXtreme Scale peut définir un attribut avec le type Java java.sql.Date. Ce type de données n'inclut pas l'heure et est normalisé par le service de données REST. Cela signifie que l'environnement d'exécution d'eXtreme Scale ne stocke pas les heures, minutes, secondes ou millisecondes dans l'attribut java.sql.Date. Quel que soit le décalage horaire, la date est toujours représentée comme une date locale.

Par exemple, si le client met à jour une propriété java.sql.Date avec la valeur “2009-01-01T03:00:00”, le service de données REST, qui se trouve dans le fuseau horaire CST (-06:00), crée simplement une instance java.sql.Date dont l'heure est “2009-01-01T00:00:00” (heure CST locale). Aucun décalage horaire n'est appliqué pour créer la valeur java.sql.Date. Lorsque le client du service REST extrait la valeur de cet attribut, cette dernière est affichée sous la forme “2009-01-01T00:00:00Z”. Si un décalage horaire était appliqué, la valeur serait affichée avec la date “2008-12-31”, ce qui ne serait pas correct.

Normalisation de java.sql.Time

Comme pour java.sql.Date, les valeurs java.sql.Time sont normalisées et n'incluent pas la date. Cela signifie que l'environnement d'exécution d'eXtreme Scale ne stocke pas l'année, le mois ou le jour. L'heure est stockée en heure GMT à partir du 1er janvier 1970, ce qui est cohérent avec l'implémentation de java.sql.Time.

Par exemple, si le client met à jour une propriété java.sql.Time avec la valeur "2009-01-01T03:00:00", le service de données REST crée une instance java.sql.Time avec une valeur de 3*60*60*1000 millisecondes, soit 3 heures. Lorsque le service REST extrait la valeur, cette dernière est affichée sous la forme "1970-01-01:03:00:00Z".

Associations

Les associations définissent la relation entre deux entités homologues. Le service REST d'eXtreme Scale reflète les associations modélisées avec des entités définies à l'aide des entités annotées d'eXtreme Scale ou des entités définies à l'aide d'un fichier XML de descripteur d'entité.

Maintenance de l'association

Le service de données REST d'eXtreme Scale ne prend pas en charge les contraintes d'intégrité référentielles. Le client doit s'assurer que les références sont mises à jour lorsque des entités sont supprimées ou ajoutées. Si une entité cible d'une association est supprimée de la grille de données et que le lien entre l'entité source et l'entité cible n'est pas supprimé, le lien est rompu. Le service de données REST eXtreme Scale et l'API EntityManager tolère des liens et consigne les liens rompus sous forme d'avertissements CWPRJ1022W. Les associations rompues sont supprimées de la charge de la demande.

Utilisez une demande par lots pour regrouper les mises à jour d'association dans une même transaction afin d'éviter les liens rompus. Voir la section suivante pour plus de détails sur les demandes par lots.

L'élément ReferentialConstraint du modèle de données d'entité ADO.NET n'est pas utilisé par le service de données REST d'eXtreme Scale.

Multiplicité des associations

Les entités peuvent avoir des associations à plusieurs valeurs ou des associations à valeur unique. Les associations à plusieurs valeurs ou collections sont des associations one-to-many ou many-to-many. Les associations à valeur unique sont des associations one-to-one ou many-to-one.

Dans une grille de données partitionnée, tous les entités doivent avoir le même chemin d'association de clé à valeur unique vers une entité racine. Une autre section de cette rubrique explique comment définir une association de clés. L'entité racine étant utilisée pour partitionner l'entité, les associations many-to-many ne sont pas autorisées pour les grilles de données partitionnées. Pour un exemple de modélisation d'un schéma d'entité relationnelle pour une grille de données partitionnées, voir Evolutivité du modèle de données dans eXtreme Scale.

L'exemple suivant décrit comment les types d'association de l'API EntityManager, modélisés à l'aide de classes Java annotées, sont mappés au modèle de données d'entité ADO.NET :

@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>

Associations unidirectionnelles et bidirectionnelles

Les associations d'entités peuvent être unidirectionnelles ou bidirectionnelles. En spécifiant l'attribut "mappedBy" sur l'annotation @OneToOne, @OneToMany ou @ManyToMany ou l'attribut "mapped-by" sur la balise d'attribut XML one-to-one, one-to-many ou many-to-many, l'entité devient bidirectionnelle. Le protocole OData requiert actuellement que toutes les entités soient bidirectionnelles, afin de permettre aux clients de générer des chemins de navigation dans les deux sens. L'API EntityManager d'eXtreme Scale autorise la modélisation d'associations unidirectionnelles qui permettent d'économiser la mémoire et de simplifier la maintenance des associations. Si une association unidirectionnelle est utilisée, le client des services de données REST ne doit naviguer dans l'association qu'à l'aide de l'association définie.

Par exemple : Si une association unidirectionnelle many-to-one est définie entre Address et Country, l'URI n'est pas autorisé :

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

Associations clés

Des associations à valeur unique (one-to-one et many-to-one) peuvent également être incluses comme une clé d'entités ou partie intégrante de cette clé. Il s'agit d'une association clé.

Des associations de clés sont requises lorsque vous utilisez une grille de données partitionnées. L'association clé doit être définie pour toutes les entités enfant d'un schéma d'entités partitionné. Le protocole OData requiert que toutes les entités soient directement adressables. Cela signifie que la clé de l'entité enfant doit inclure la clé utilisée pour le partitionnement.

Dans l'exemple ci-après, Customer fait l'objet d'une association one-to-many avec Order. L'entité Customer représente l'entité racine et l'attribut customerId est utilisé pour partitionner l'entité. La commande a inclus le client dans son identité :

@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;
}

Lorsque le service de données REST génère le document EDMX pour ce modèle, les zones de la clé Customer sont automatiquement incluses dans l'entité Order :

<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>

Lorsqu'une entité est créée, la clé ne doit jamais être modifiée. Cela signifie que l'association clé entre une entité enfant et son parent doit être modifiée ; l'entité enfant doit être supprimée et recréée avec un autre parent. Dans une grille de données partitionnées, cela nécessite deux ensembles de modifications par lots différents, car le transfert impliquera probablement plusieurs.

Opérations en cascade

L'API EntityManager accepte les règles en cascade flexibles. Les associations peuvent être marquées de sorte à réaliser en cascade des opérations de persistance, de suppression, d'invalidation ou de fusion. De telles opérations de cascade peuvent se produire des deux côtés d'une association bidirectionnelle.

Le protocole OData n'autorise les opérations de suppression en cascade que d'un côté de l'association. L'annotation CascadeType.REMOVE ou l'attribut XML cascade-remove ne peut pas être défini des deux côtés d'une association bidirectionnelle one-to-one ou du côté "many" d'une association one-to-many. L'exemple suivant illustre une association bidirectionnelle Cascade.REMOVE valide :

@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;
}

L'association EDMX résultante se présente comme suit :

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