Archivo de propiedades del servicio de datos REST

Para configurar el servicio de datos REST, edite el archivo de propiedades para REST y defina el esquema de entidad necesario para una cuadrícula de datos.

El archivo de propiedades del servicio de datos REST es el archivo de configuración principal para el servicio de datos REST de eXtreme Scale. Este archivo es un archivo de propiedades Java con pares clave-valor. De forma predeterminada, el tiempo de ejecución del servidor de datos REST para un archivo wxsRestService.properties con el nombre correcto en la classpath. El archivo también se puede definir explícitamente utilizando la propiedad del sistema: wxs.restservice.props.

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

Cuando se carga el servicio de datos REST, el archivo de propiedades utilizado se muestra en los archivos de registro:

CWOBJ4004I: Los archivos de propiedades de servicio de datos REST de eXtreme Scale se han cargado: [/usr/configs/RestService.properties]

El archivo de propiedades del servicio de datos REST soporta las propiedades siguientes:

Tabla 1. Propiedades del servicio de datos REST
Propiedad Descripción
catalogServiceEndPoints Lista delimitada por comas necesaria de hosts y puertos de un dominio de servicio de catálogo en el formato: <host:puerto>. Es opcional si utiliza WebSphere Application Server integrado con WebSphere eXtreme Scale para alojar el servicio de datos REST. Si desea más información, consulte Inicio de un servicio de catálogo autónomo.

catalogServiceEndPoints=

server1:2809,server2:2809

objectGridNames Los nombres necesarios de las cuadrículas de datos que se deben exponer al servicio REST. Como mínimo, se necesita un nombre de ObjectGrid. Separe varios nombres de ObjectGrid utilizando comas:

ECommerceGrid,InventoryGrid

objectGridClientXML Nombre opcional del archivo XML de sustitución de cliente ObjectGrid. El nombre especificado aquí se cargará de la classpath. El valor predeterminado es:

/META-INF/objectGridClient.xml.

ogClientPropertyFile Nombre opcional del archivo de propiedades del ObjectGrid. Este archivo contiene propiedades de seguridad para habilitar la seguridad del cliente ObjectGrid. Si está establecido el atributo "securityEnabled" en el archivo de propiedades, se habilitará la seguridad en el cliente ObjectGrid que el servicio REST utiliza. "credentialGeneratorProps" se debe establecer también en el archivo de propiedades en el formato de "user:pass" o un valor de {xor_encoded user:pass}
loginType El servicio REST utiliza este tipo de autenticación cuando está habilitada la seguridad del cliente de ObjectGrid. Si no está habilitada la seguridad del cliente de ObjectGrid, se pasa por alto esta propiedad.
Si está habilitada la seguridad del cliente de ObjectGrid y loginType se establece en basic, el servicio REST:
  • Utilizará las credenciales especificadas en la propiedad 'credentialGeneratorProps' del archivo de propiedades del cliente de ObjectGrid para las operaciones de ObjectGrid en la inicialización del servicio.
  • Utilice la autenticación HTTP BASIC para las operaciones de sesión de ObjectGrid de solicitud de igual
Si está habilitada la seguridad de cliente de ObjectGrid y loginType se establece en none, el servicio REST:
  • Utilizará las credenciales especificadas en la propiedad 'credentialGeneratorProps' del archivo de propiedades del cliente de ObjectGrid para las operaciones de ObjectGrid en la inicialización del servicio.
  • Utilizará las credenciales especificadas en la propiedad 'credentialGeneratorProps' del archivo de propiedades del cliente de ObjectGrid para las operaciones de sesión de ObjectGrid de solicitud de igual.
traceFile Nombre opcional del archivo al que se debe redirigir la salida del rastreo. El valor predeterminado es logs/trace.log.
traceSpec Especificación de rastreo óptimo que el servidor de ejecución de eXtreme Scale debe utilizar inicialmente. El valor predeterminado es *=all=disabled. Para realizar el seguimiento del servicio de datos REST, utilice: ObjectGridRest*=all=enabled
verboseOutput Si se establece en true, los clientes del servicio de datos REST reciben información de diagnóstico adicional cuando se producen anomalías. El valor predeterminado es false. Este valor opcional se debe definir como false para los entornos de producción, ya que se puede revelar información sensible.
maxResultsPerCollection El número máximo opcional de resultados que se devolverán en una consulta. El valor predeterminado es unlimited. Cualquier entero positivo es un valor válido.
wxsRestAccessRightsFile El nombre opcional del archivo de propiedades de derechos de acceso del servicio REST de eXtreme Scale que especifica los derechos de acceso de las operaciones de servicio y las entidades ObjectGrid. Si se especifica esta propiedad el servicio REST intentará cargar el archivo de la vía de acceso especificada, si no intentará cargar el archivo desde su vía de acceso de clases.

Configuración de WebSphere eXtreme Scale

El servicio de datos REST de eXtreme Scale interactúa con eXtreme Scale mediante la API EntityManager. Se define un esquema de entidad para una cuadrícula de datos de eXtreme Scale y los metadatos para las entidades los consume automáticamente el servicio de datos REST. Consulte Definición de un esquema de entidad para obtener información sobre la configuración de un esquema de entidad.

Por ejemplo, puede definir una entidad que represente una persona en una cuadrícula de datos de eXtreme Scale de la forma siguiente:
@Entity															
public class Person {
		@Id String taxId;
	String firstName;
		String lastName;
}
Consejo: Las anotaciones utilizadas aquí están en el paquete com.ibm.websphere.projector.annotations.

El servicio REST crea automáticamente un documento de modelo de datos de entidad ADO.NET para servicios de datos (EDMX), que está disponible utilizando el URI $metadata:

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

Una vez que se ha configurado la cuadrícula de datos y está en ejecución, configure y empaquete un cliente de eXtreme Scale. Para obtener información detallada sobre cómo configurar el paquete de cliente de servicio de datos REST de eXtreme Scale, consulte la información sobre empaquetamiento y despliegue del apartado Instalación del servicio de datos REST.

Modelo de entidad

Las entidades de WebSphere eXtreme Scale se modelan utilizando las anotaciones de entidad o un archivo de descriptor de metadatos de entidad. Para obtener información sobre cómo configurar un esquema de entidad, consulte Definición de un esquema de entidad. El servicio REST de eXtreme Scale utiliza los metadatos de entidad para crear automáticamente un modelo EDMX para el servicio de datos.

Esta versión del servicio de datos REST de WebSphere eXtreme Scale tiene las siguientes restricciones de esquema:
  • Al definir entidades en una cuadrícula de datos particionada, todas las entidades deben tener una asociación de un solo valor directa o indirecta con la entidad raíz (una asociación de clave). El tiempo de ejecución de cliente del servicio de datos WCF debe poder acceder a cada entidad directamente mediante su dirección canónica. Por lo tanto, la clave de la entidad raíz utilizada para el direccionamiento de particiones (la raíz de esquema) debe formar parte de la clave en la entidad hijo.

    Por ejemplo:

    @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;
    }
  • Tanto las asociaciones bidireccionales como unidireccionales están soportadas. No obstante, es posible que las asociaciones unidireccionales no siempre funcionen desde un cliente de Microsoft WCF Data Services porque sólo se puede navegar por ellas en una dirección y la especificación de Microsoft requiere que todas las asociaciones sean bidireccionales.
  • Las restricciones referenciales no están soportadas. El tiempo de ejecución de WebSphere eXtreme Scale no valida las claves entre entidades. Las asociaciones entre entidades deben ser gestionadas por el cliente.
  • Los tipos complejos no están soportados. La API EntityManager no da soporte a atributos incorporados. Se espera que todos los atributos sean atributos de tipo simple (consulte la lista de tipos de atributos simples siguiente). Los atributos de tipo no simple se tratan como un objeto binario desde la perspectiva del cliente.
  • La herencia de entidades no está soportada. La API EntityManager no da soporte a la herencia.
  • Los recursos de medios y los enlaces de medios no están soportados. El atributo HasStream del EntityType del Documento de lenguaje de definición de esquemas conceptuales para servicios de datos nunca se utiliza.

Correlación entre tipos de datos EDM y tipos de datos Java

El protocolo OData define la lista siguiente de tipos de modelo de datos de entidad (EDM) en su sistema de tipos abstractos. Los temas siguientes describen cómo selecciona el adaptador REST de eXtreme Scale el tipo EDM basándose en el tipo básico definido en la entidad. Para obtener detalles sobre los tipos EDM, consulte MSDN Library: Abstract Type System (Biblioteca MSDN: sistema de tipo abstracto).

Los tipos de EDM siguientes están disponibles en 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

El tipo EDM: Edm.Guid no está soportado por el servicio de datos REST de eXtreme Scale

Correlación de tipos Java con tipos EDM

El servicio de datos REST de eXtreme Scale convierte automáticamente tipos de entidad básicos a tipos EDM. La correlación de tipo se puede ver visualizando el documento de metadatos de ampliaciones de modelo de datos de entidad (EDMX) utilizando el URI $metadata. El tipo EDM lo utilizan los clientes para leer y grabar datos en el servicio de datos REST.
Tabla 2. Tipos Java correlacionados con tipos EDM. La tabla siguiente muestra la correlación del tipo Java definido para una entidad con el tipo de datos EDM.Al recuperar datos utilizando una consulta, los datos se representarán con estos tipos:
Tipo Java Tipo 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
Otros tipos Edm.Binary

Correlación de tipos EDM con tipos Java

Para las solicitudes de actualización y las solicitudes de inserción, la carga útil especifica los datos que se deben actualizar o insertar en el servicio de datos REST de eXtreme Scale. El servicio puede convertir automáticamente tipos de datos compatibles a los tipos de datos definidos en el documento EDMX. El servicio de datos REST convierte las representaciones de serie codificadas en XML del valor en el tipo correcto utilizando el siguiente proceso de dos pasos:

  1. Se realiza una comprobación de tipo para asegurarse de que el tipo EDM se compatible con el tipo Java. Un tipo EDM es compatible con un tipo Java si los datos soportados por el tipo EDM son un subconjunto de los datos soportados por el tipo Java. Por ejemplo, el tipo Edm.int32 es compatible con un tipo long Java, pero el tipo Edm.int32 no es compatible con un tipo short Java.
  2. Se creará un objeto de tipo Java de destino que representa el valor de serie en la carga útil.
Tabla 3. Tipo EDM compatible con el tipo Java
Tipo EDM Tipo 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

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

Correlación de tipos temporales

Java incluye cinco tipos temporales para almacenar la fecha, la hora, o ambos: java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp y java.util.Calendar. Todos estos tipos se expresan en el modelo de datos de entidad como Edm.DateTime. El servicio de datos REST de eXtreme Scale convierte automáticamente y normaliza los datos en función del tipo Java. Este tema describe varias cuestiones que los desarrolladores deben tener en cuenta al utilizar cualquier tipo temporal.

Diferencias de huso horario

En WCF Data Services, las descripciones de valores de hora en el tipo Edm.DateTime siempre se expresa utilizando el estándar UTC (hora universal coordinada), que es el nombre internacionalmente reconocido la hora media de Greenwich (GMT). La hora universal coordinada es la hora medida a una longitud de cero grados, el punto de origen UTC. El horario de verano no es aplicable a la hora universal coordinada.

Conversión entre tipos de entidad y EDM

Cuando un cliente envía una solicitud al servicio de datos REST, la fecha y la hora se representan como una hora de huso horario GMT, como en el ejemplo siguiente:

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

A continuación, el servicio de datos REST construirá la instancia de tipo temporal Java correspondiente y la insertará en la entidad en la cuadrícula de datos.

Cuando un cliente solicita una propiedad que es un tipo temporal Java del servicio de datos REST de eXtreme Scale, el valor siempre se normaliza como un valor de huso horario GMT. Por ejemplo, si una entidad java.util.Date se construye tal como se indica a continuación:

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

La fecha y la hora se representan utilizando el huso horario predeterminado del proceso Java porque Calendar.getInstance() creará un objeto Calendar con el huso horario local. Si el huso horario local es CST, entonces la fecha, cuando se recupere del servicio de datos REST, será la representación GMT de la hora: "2000-03-01T03:30:30"

Normalización de java.sql.Date

Una entidad de eXtreme Scale puede definir un atributo con el tipo Java java.sql.Date. Este tipo de datos no incluye la hora y el servicio de datos REST lo normaliza. Esto significa que el tiempo de ejecución de eXtreme Scale no almacena ninguna información de horas, minutos, segundos o milisegundos en el atributo java.sql.Date. Independientemente del desplazamiento de huso horario, la fecha siempre se representa como una fecha local.

Por ejemplo, si el cliente actualiza una propiedad java.sql.Date con el valor “2009-01-01T03:00:00”, el servicio de datos REST, que está en el huso horario CST (-06:00), creará simplemente una instancia de java.sql.Date cuya hora se define como “2009-01-01T00:00:00” de la hora CST local. No se realiza ninguna conversión de huso horario para crear el valor de java.sql.Date. Cuando el cliente del servicio REST recupere el valor de este atributo, se mostrará como “2009-01-01T00:00:00Z”. Si se realizase una conversión de huso horario, el valor se mostraría como si tuviese la fecha "2008-12-31", lo que sería incorrecto.

Normalización de java.sql.Time

De forma similar a java.sql.Date, los valores de java.sql.Time se normalizan y no incluyen la información de la fecha. Esto significa que el tiempo de ejecución de eXtreme Scale no almacena el año, el mes ni el día. La hora se almacena utilizando la hora media de Greenwich a partir del 1 de enero de 1970, lo que es coherente con la implementación de java.sql.Time.

Por ejemplo, si el cliente actualiza una propiedad java.sql.Time con el valor "2009-01-01T03:00:00", el servicio de datos REST creará una instancia de java.sql.Time con el valor de milisegundos definido como 3*60*60*1000, que equivale a 3 horas. Cuando el servicio REST recupere el valor, se mostrará como "1970-01-01:03:00:00Z".

Asociaciones

Las asociaciones definen la relación entre dos entidades iguales. El servicio REST de eXtreme Scale refleja las asociaciones modeladas con entidades definidas con entidades anotadas de eXtreme Scale o entidades definidas mediante un archivo XML descriptor de entidad.

Mantenimiento de asociaciones

El servicio de datos REST de eXtreme Scale no soporta las restricciones de integridad referencial. El cliente debe asegurarse de que las referencias se actualicen cuando se eliminen o añadan entidades. Si una entidad de destino de una asociación se elimina de la cuadrícula de datos, pero el enlace entre la entidad de origen y de destino no se elimina, el enlace se romperá. El servicio de datos REST de eXtreme Scale y la API EntityManager toleran enlaces rotos y los registran como avisos CWPRJ1022W. Las asociaciones rotas se eliminarán de la carga útil de la solicitud.

Utilice una solicitud por lotes para agrupar actualizaciones de asociaciones en una sola transacción para evitar enlaces rotos. Consulte la sección siguiente para obtener detalles sobre las solicitudes por lotes.

El servicio de datos REST de eXtreme Scale no utiliza el elemento ReferentialConstraint del modelo de datos de entidad ADO.NET.

Multiplicidad de asociaciones

Las entidades pueden tener asociaciones con varios valores o asociaciones con un solo valor. Las asociaciones con varios valores, o colecciones, son asociaciones "de uno a muchos" o "de muchos a muchos". Las asociaciones con un solo valor son o asociaciones "de uno a uno" o "de muchos a uno".

En una cuadrícula de datos particionada, todas las entidades deben tener una única vía de acceso de asociación de clave de un solo valor a la entidad raíz. En otro apartado de este tema se muestra cómo definir una asociación de claves. Dado que la entidad raíz se utiliza para particionar la entidad, no se permiten asociaciones de muchos a muchos para cuadrículas de datos particionadas. Para ver un ejemplo sobre cómo modelar un esquema de entidad relacional para una cuadrícula de datos particionada, consulte Modelo de datos escalable de eXtreme Scale.

El ejemplo siguiente describe cómo los tipos de asociación de la API EntityManager, modelados utilizando clases Java anotadas, se correlacionan con el modelo de datos de entidad 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>

Asociaciones bidireccionales y unidireccionales

Las asociaciones de entidades pueden ser unidireccionales o bidireccionales. Especificando el atributo "mappedBy" en la anotación @OneToOne, @OneToMany o @ManyToMany o el atributo "mapped-by" en la etiqueta XML one-to-one, one-to-many o many-to-many, la entidad se vuelve bidireccional. El protocolo OData requiere actualmente que todas las entidades sean bidireccionales, que permiten a los clientes generar vías de acceso de navegación en ambas direcciones. La API EntityManager de eXtreme Scale permite modelar asociaciones unidireccionales que pueden ahorrar memoria y simplificar el mantenimiento de las asociaciones. Si se utiliza una asociación unidireccional, el cliente del servicio de datos REST sólo debe navegar por la asociación utilizando la asociación definida.

Por ejemplo: Si se define una asociación unidireccional de muchos a uno entre Address y Country, no se permite el URI siguiente:

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

Asociaciones de clave

También se pueden incluir asociaciones de un solo valor (de uno a uno y de muchos a uno) como toda la clave de entidades o parte de ella. Esto se conoce como asociación de clave.

Se requieren asociaciones de clave al utilizar una cuadrícula de datos particionada. La asociación de clave se debe definir para todas las entidades hijo en un esquema de entidad particionada. El protocolo OData requiere que todas las entidades sean directamente direccionables. Esto significa que la clave de la entidad hijo debe incluir la clave utilizada para el particionamiento.

En el ejemplo siguiente, Customer tiene una asociación de uno a muchos con Order. La entidad Customer es la entidad raíz y el atributo customerId se utiliza para particionar la entidad. Order tiene incluido Customer como parte de su identidad:

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

Cuando el servicio de datos REST genera el documento EDMX para este modelo, los campos de clave de Customer se incluyen automáticamente incluidos como parte de la entidad 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>

Cuando se crea una entidad, la clave nunca debe cambiar. Esto significa que si la asociación de clave entre una entidad hijo y su padre debe cambiar, la entidad hijo se debe eliminar y se debe volver a crear con un padre diferente. En una cuadrícula de datos particionada, esto requerirá dos conjuntos de cambios por lotes distintos ya que el traslado probablemente implicará más de una partición.

Operaciones en cascada

La API EntityManager permite una política de cascada flexible. Las asociaciones se pueden marcar para realizar una operación de persistencia, eliminación, invalidación o fusión en cascada. Estas operaciones en cascada pueden realizarse en uno o ambos lados de una asociación bidireccional.

El protocolo OData sólo permite operaciones de supresión en el lado único de la asociación. La anotación CascadeType.REMOVE o el atributo XML cascade-remove no se pueden definir a ambos lados de una asociación bidireccional de uno a uno ni en el múltiple de una asociación de uno a muchos. El ejemplo siguiente ilustra una asociación bidireccional Cascade.REMOVE válida:

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

La asociación resultante debe ser tal como se indica a continuación:

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