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 :
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 :
Si la sécurité du client ObjectGrid est activée et que loginType a la valeur none, le service de données REST :
|
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. |
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é.
@Entity
public class Person {
@Id String taxId;
String firstName;
String lastName;
}
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.
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.
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;
}
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 :
Le type EDM Edm.Guid n'est pas pris en charge par le service de données REST d'eXtreme Scale.
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 |
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 :
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 |
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".
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>