Arquivo de Propriedades do Serviço de Dados REST

Para configurar o serviço de dados REST, edite o arquivo de propriedades para o REST e defina o esquema de entidade necessário para uma grade de dados.

O arquivo de propriedades do serviço de dados REST é o arquivo de configuração principal para o serviço de dados REST do eXtreme Scale. Esse arquivo é um arquivo de propriedades Java pares de valores da chave. Por padrão, o tempo de execução do serviço de dados REST procura por um arquivo wxsRestService.properties nomeado corretamente no caminho de classe. O arquivo também pode ser definido explicitamente por meio do uso da propriedade de sistema: wxs.restservice.props.

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

Quando o serviço de dados REST é carregado, o arquivo de propriedades utilizado é exibido nos arquivos de log:

CWOBJ4004I: Os arquivos de propriedades do serviço de dados REST do eXtreme Scale foram carregados: [/usr/configs/RestService.properties]

O arquivo de propriedades do serviço de dados REST suporta as seguintes propriedades:

Tabela 1. Propriedades para o Serviço de Dados REST
Propriedade Descrição
catalogServiceEndPoints A lista requerida delimitada por vírgula de hosts e portas de um domínio do serviço de catálogo no formato: <host:port>. Isso é opcional se estiver usando o WebSphere Application Server integrado ao WebSphere eXtreme Scale para hospedar o serviço de dados REST. Consulte Iniciando um Serviço de Catálogo Independente para obter mais informações.

catalogServiceEndPoints=

server1:2809,server2:2809

objectGridNames Os nomes necessários das grades de dados para expor ao serviço REST. Pelo menos um nome de ObjectGrid é necessário. Separe nomes de ObjectGrid múltiplos utilizando uma vírgula:

ECommerceGrid,InventoryGrid

objectGridClientXML O nome opcional do arquivo XML de substituição de cliente do ObjectGrid. O nome especificado aqui será carregado do caminho de classe. O padrão é:

/META-INF/objectGridClient.xml.

ogClientPropertyFile O nome opcional do arquivo de propriedades do cliente do ObjectGrid. Este arquivo contém propriedades de segurança que são necessárias para ativar a segurança do cliente do ObjectGrid. Se o atributo "securityEnabled" for configurado no arquivo de propriedades, a segurança será ativada no cliente do ObjectGrid usado pelo serviço REST. O "credentialGeneratorProps" também deve ser configurado no arquivo de propriedades para um valor no formato "user:pass" ou um valor de {xor_encoded user:pass}
loginType O tipo de autenticação usado pelo Serviço REST quando a segurança do cliente do ObjectGrid for ativada. Se a segurança do cliente do ObjectGrid não for ativada, esta propriedade será ignorada.
Se a segurança do cliente do ObjectGrid for ativada e loginType for configurado para básico, o serviço REST irá:
  • Usar as credenciais especificadas na propriedade 'credentialGeneratorProps' do arquivo de propriedades do cliente do ObjectGrid para operações do ObjectGrid na inicialização do serviço.
  • Usar a autenticação HTTP BASIC para operações de sessões do ObjectGrid por pedido
Se a segurança do cliente do ObjectGrid for ativada e loginType for configurado para nenhum, o serviço REST irá:
  • Usar as credenciais especificadas na propriedade 'credentialGeneratorProps' do arquivo de propriedades do cliente do ObjectGrid para operações do ObjectGrid na inicialização do serviço.
  • Usar as credenciais especificadas na propriedade 'credentialGeneratorProps' do arquivo de propriedades do cliente do ObjectGrid para operações de sessões do ObjectGrid por pedido.
traceFile O nome opcional do arquivo para o qual redirecionar a saída de rastreio. O padrão é logs/trace.log.
traceSpec A especificação de rastreio opcional que o servidor de runtime do eXtreme Scale deve usar inicialmente. O padrão é *=all=disabled. Para rastrear o serviço de dados REST inteiro, use: ObjectGridRest*=all=enabled
verboseOutput Se configurado como true, os clientes do serviço de dados REST receberão informações de diagnóstico adicionais quando ocorrer uma falha. O padrão é false. Esse valor opcional deve ser configurado como false para ambientes de produção conforme informações sensíveis forem reveladas.
maxResultsPerCollection O número máximo opcional de resultados que será retornado em uma consulta. O valor padrão é unlimited. Qualquer número inteiro positivo é um valor válido.
wxsRestAccessRightsFile O nome opcional do arquivo de propriedades de direitos de acesso do serviço REST do eXtreme Scale que especifica os direitos de acesso para as operações de serviço e as entidades do ObjectGrid. Se esta propriedade for especificada, o serviço REST tentará carregar o arquivo a partir do caminho especificado e tentará também carregar o arquivo a partir de seu caminho de classe.

Configuração do WebSphere eXtreme Scale

O serviço de dados REST do eXtreme Scale interage com oeXtreme Scale usando a API EntityManager. Um esquema de entidade é definido para uma grade de dados do eXtreme Scale e os metadados para as entidades são automaticamente consumidos pelo serviço de dados REST. Consulte o Definindo um Esquema de Entidade para obter detalhes sobre como configurar um esquema de entidade.

Por exemplo, é possível definir uma entidade que representa uma Pessoa em uma grade de dados do eXtreme Scale da seguinte forma:
@Entity															
public class Person {
		@Id String taxId;
		String firstName;
		String lastName;
}
Dica: As anotações utilizadas aqui estão no pacote com.ibm.websphere.projector.annotations.

O serviço REST automaticamente cria um Modelo de Dados de Entidade ADO.NET para o documento Serviços de Dados (EDMX), que está disponível usando a URI $metadata:

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

Depois que a grade de dados for configurada e estiver em execução, configure e empacote um eXtreme Scale. Para obter detalhes sobre como configurar o pacote do cliente do serviço de dados REST do eXtreme Scale, consulte as informações de compactação e implementação no Instalando o Serviço de Dados REST.

Modelo de Entidade

As entidades do WebSphere eXtreme Scale são modeladas usando as anotações da entidade ou um arquivo descritor de metadados da entidade. Para obter mais detalhes sobre como configurar um esquema de entidade, consulte o Definindo um Esquema de Entidade. O serviço REST do eXtreme Scale usa os metadados de entidade para criar automaticamente um modelo EDMX para o serviço de dados.

Esta versão do serviço de dados REST do WebSphere eXtreme Scale tem as seguintes restrições de esquema:
  • Ao definir entidades em uma grade de dados particionada, todas as entidades deverão ter uma associação com valor único direta ou indireta com a entidade raiz (uma associação chave). O tempo de execução do cliente WCF Data Service deve ter capacidade de acessar cada entidade diretamente por meio de seu endereço canônico. Portanto, a chave da entidade raiz que é utilizada para o roteamento de partição (a raiz do esquema) deve fazer parte da chave na entidade-filha.

    Por exemplo:

    @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;
    }
  • Associações bidirecionais e unidirecionais são suportadas. Entretanto, as associações unidirecionais podem nem sempre funcionar a partir de um cliente Microsoft WCF Data Services, já que elas só podem ser navegadas em uma direção e a especificação da Microsoft requer que todas as associações sejam bidirecionais.
  • Restrições de referência não são suportadas. O tempo de execução do WebSphere eXtreme Scale não valida chaves entre entidades. As associações entre as entidades devem ser gerenciadas pelo cliente.
  • Tipos complexos não são suportados. A API EntityManager não suporta atributos integráveis. Todos os atributos devem ser do tipo simples (consulte os tipos de atributos simples listados abaixo). Os atributos de tipo não simples são tratados como um objeto binário a partir da perspectiva do cliente.
  • A herança de entidade não é suportada. A API EntityManager não suporta herança.
  • Recursos de Mídia e Links de Mídia não são suportados. O atributo HasStream de EntityType no Conceptual Schema Definition Language Document for Data Services nunca é utilizado.

Mapeamento entre Tipos de Dados EDM e Tipos de Dados Java

O protocolo OData define a seguinte lista de tipos Entity Data Model (EDM) em seu sistema de tipo abstrato. Os tópicos a seguir descrevem como o adaptador REST do eXtreme Scale escolhe o tipo EDM com base no tipo básico definido na entidade. Para obter detalhes sobre os tipos EDM, consulte: Biblioteca MSDN: Sistema de Tipo Abstrato.

Os tipos EDM a seguir estão disponíveis no 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

O tipo EDM: Edm.Guid não é suportado pelo serviço de dados REST do eXtreme Scale.

Mapeando Tipos Java para Tipos EDM

O serviço de dados REST do eXtreme Scale converte automaticamente os tipos de entidade básicos em tipos EDM. O mapeamento de tipo pode ser visto por meio da exibição do documento de metadados do Entity Data Model Extensions (EDMX) utilizando o URI $metadata. O tipo EDM é usado pelos clientes para ler e gravar dados no serviço de dados REST.
Tabela 2. Tipos Java Mapeados para Tipos EDM. A tabela mostra o mapeamento do tipo Java definido para uma entidade para o tipo de dado EDM. Com a recuperação de dados utilizando uma consulta, os dados serão representados com estes 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
Outros tipos Edm.Binary

Mapeando de Tipos EDM para Tipos Java

Para pedidos Update e Insert, a carga útil especifica os dados a serem atualizados ou inseridos no serviço de dados REST do eXtreme Scale. O serviço pode converter automaticamente tipos de dado compatíveis em tipos de dados definidos no documento EDMX. O serviço de dados REST converte as representações de cadeia codificadas em XML do valor no tipo correto utilizando o seguinte processo de duas etapas:

  1. Uma verificação de tipo é feita para garantir que o tipo EDM seja compatível com o tipo Java. Um tipo EDM é compatível com um tipo Java se os dados suportados pelo tipo EDM forem um subconjunto dos dados suportados pelo tipo Java. Por exemplo, o tipo Edm.int32 é compatível com um tipo Java long, mas o tipo Edm.int32 não é compatível com um tipo Java short.
  2. Será criado um objeto de tipo Java de destino que representa o valor de cadeia na carga útil.
Tabela 3. Tipo EDM compatível com o 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

Tipos Temporais de Mapeamento

O Java inclui cinco tipos temporais para armazenamento de data, hora ou ambas: java.util.Date, java.sql.Date, java.sql.Time, java.sql.Timestamp e java.util.Calendar. Todos esses tipos são expressos no modelo de dados da entidade como Edm.DateTime. O serviço de dados REST do eXtreme Scale converte e normaliza automaticamente os dados, dependendo do tipo Java. Este tópico descreve vários problemas dos quais os desenvolvedores devem estar cientes ao utilizarem qualquer tipo temporal.

Diferenças de fuso horário

No WCF Data Services, as descrições de valores de hora no tipo Edm.DateTime são sempre expressas utilizando o padrão Coordinated Universal Time (UTC), que é o nome internacionalmente reconhecido de Horário de Greenwich (GMT). O Coordinated Universal Time é a hora conforme medição a zero graus de longitude, o ponto de origem do UTC. O horário de verão não se aplica ao UTC.

Convertendo entre entidade e tipos EDM

Quando um cliente envia um pedido ao serviço de dados REST, a data e a hora são representadas como um horário do fuso horário GMT, como no exemplo a seguir:

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

O serviço de dados REST construirá a instância de tipo temporal Java apropriada e a inserirá na entidade na grade de dados.

Quando um cliente solicita uma propriedade que é um tipo temporal Java do serviço de dados REST do eXtreme Scale, o valor é sempre normalizado como uma valor do fuso horário GMT. Por exemplo, se uma entidade java.util.Date for construída da seguinte forma:

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

A data e a hora são representadas com o uso do fuso horário padrão do processo Java, pois Calendar.getInstance() criará um objeto Calendar com o fuso horário local. Se o fuso horário local for CST, a data, quando recuperada do serviço de dados REST, será a representação GMT da hora: "2000-03-01T03:30:30"

Normalização de java.sql.Date

Uma entidade do eXtreme Scale pode definir um atributo com tipo Java java.sql.Date. Esse tipo de dado não inclui a hora e é normalizado pelo serviço de dados REST. Isso significa que o tempo de execução do eXtreme Scale não armazena nenhuma informação sobre horas, minutos, segundos ou milissegundos no atributo java.sql.Date. Independentemente do deslocamento de fuso horário, a data é sempre representada como uma data local.

Por exemplo, se o cliente atualizar uma propriedade java.sql.Date com o valor “2009-01-01T03:00:00”, o serviço de dados REST, que está no fuso horário CST (-06:00), criará simplesmente uma instância java.sql.Date da qual a hora é configurada como “2009-01-01T00:00:00” do horário CST local. Não é feita nenhuma conversão de fuso horário para se criar o valor java.sql.Date. Quando o cliente do serviço REST recuperar o valor desse atributo, ele será exibido como “2009-01-01T00:00:00Z”. Se uma conversão de fuso horário fosse feita, o valor seria exibido como tendo a data de “2008-12-31”, que seria incorreta.

Normalização de java.sql.Time

Semelhantes ao java.sql.Date, os valores de java.sql.Time são normalizados e não incluem informações de data. Isso significa que o tempo de execução do eXtreme Scale não armazena o ano, mês ou dia. A hora é armazenada com o uso do horário GMT da época de 1 de janeiro de 1970, que está consistente com a implementação java.sql.Time.

Por exemplo, se o cliente atualizar uma propriedade java.sql.Time com o valor "2009-01-01T03:00:00", o serviço de dados REST criará uma instância java.sql.Time com os milissegundos configurados como 3*60*60*1000, o que é igual a 3 horas. Quando o serviço REST recuperar o valor, ele será exibido como "1970-01-01:03:00:00Z".

Associações

Associações definem o relacionamento entre duas entidades peer. O serviço REST do eXtreme Scale reflete as associações modeladas com entidades definidas com entidades anotadas do eXtreme Scale ou entidades definidas usando um arquivo XML descritor de entidade.

Manutenção de associação

O serviço de dados REST do eXtreme Scale não suporta restrições de integridade referencial. O cliente deve garantir que as referências sejam atualizadas quando entidades forem removidas ou incluídas. Se uma entidade de destino de uma associação for removida da grade de dados, mas o link entre a entidade de origem e de destino não for removido, o link será quebrado. O serviço de dados REST do eXtreme Scale e API de EntityManager tolera links quebrados e registra os links quebrados como avisos CWPRJ1022W.. As associações quebradas serão removidas da carga útil da solicitação.

Utilize um pedido em lote para agrupar atualizações de associação em uma única transação para evitar links quebrados. Consulte a seção a seguir para obter detalhes sobre as solicitações em lote.

O elemento ReferentialConstraint do Modelo de Dados de Entidade ADO.NET não é usado pelo serviço de dados REST do eXtreme Scale.

Multiplicidade de associação

Entidades podem ter associações com diversos valores ou associações com valor único. As associações com diversos valores, ou coletas, são associações um-para-muitos ou muitos-para-muitos. As associações com valor único são associações um-para-um ou muitos-para-um.

Em uma grade de dados particionada, todas as entidades devem ter um caminho de associação chave com valor único para uma entidade raiz. Outra seção deste tópico mostra como definir uma associação chave. Como a entidade raiz é usada para particionar a entidade, as associações muitos-para-muitos não são permitidas para grades particionadas. Para obter um exemplo de como modelar um esquema de entidade relacional para uma grade de dados particionados, consulte o Modelo de Dados Escalável no eXtreme Scale.

O exemplo a seguir descreve como os tipos de associação da API EntityManager, modelados com o uso de classes Java anotadas, são mapeados para o 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>

Associações bidirecionais e unidirecionais

As associações de entidades podem ser unidirecionais ou bidirecionais. Ao especificar o atributo "mappedBy" na anotação @OneToOne, @OneToMany ou @ManyToMany ou o atributo "mapped-by" na tag do atributo XML um-para-um, um-para-muitos ou muitos-para-muitos, a entidade se torna bidirecional. O protocolo OData requer atualmente que todas as entidades sejam bidirecionais, permitindo que clientes gerem caminhos de navegação em ambas as direções. A API EntityManager do eXtreme Scale permite modelar associações unidirecionais que podem salvar memória e simplificar a manutenção das associações. Se uma associação unidirecional for utilizada, o cliente de serviço de dados REST só deverá navegar por meio da associação utilizando a associação definida.

Por exemplo: Se uma associação muitos-para-um unidirecional for definida entre Address e Country, o seguinte URI não será permitido:

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

Associações chave

Associações com valor único (um-para-um e muitos-para-um) também podem ser incluídas como um todo ou como parte da chave de entidades. Isso é conhecido como associação chave.

As associações chave são necessárias quando uma grade de dados particionados é usada. A associação chave deve ser definida para todas as entidades-filhas em um esquema de entidade particionada. O protocolo OData requer que todas as entidades sejam diretamente endereçáveis. Isso significa que a chave na entidade-filha deve incluir a chave utilizada para o particionamento.

No exemplo a seguir, Customer tem uma associação um-para-muitos com Order. A entidade Customer é a entidade raiz e o atributo customerId é utilizado para particionar a entidade. Order incluiu Customer como parte de sua identidade:

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

Quando o serviço de dados REST gera o documento EDMX para esse modelo, os campos-chave Customer são automaticamente incluídos como parte da entidade 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>

Quando uma entidade for criada, a chave nunca deverá mudar. Isso significa que se a associação chave entre uma entidade-filha e seu pai tiver que mudar, a entidade-filha deverá ser removida e recriada com um pai diferente. Em uma grade de dados particionada, isso exigirá dois conjuntos de mudanças em lote diferentes, já que a mudança provavelmente envolverá mais de uma partição.

Operações em cascata

A API EntityManager permite uma política de cascata flexível. Associações podem ser marcadas para formar uma cascata das operações persist, remove, invalidate ou merge. Tais operações de cascata podem acontecer em um ou ambos os lados de uma associação bidirecional.

O protocolo OData só permite operações delete em cascata no lado um da associação. A anotação CascadeType.REMOVE ou o atributo XML cascade-remove não podem ser definidos em ambos os lados de uma associação bidirecional um-para-um ou no lado muitos de uma associação um-para-muitos. O exemplo a seguir ilustra uma associação bidirecional 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;
}

A associação EDMX resultante é semelhante à seguinte:

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