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:
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á:
Se a
segurança do cliente do ObjectGrid for ativada e loginType for configurado para
nenhum, o serviço REST irá:
|
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. |
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.
@Entity
public class Person {
@Id String taxId;
String firstName;
String lastName;
}
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.
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.
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;
}
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:
O tipo EDM: Edm.Guid não é suportado pelo serviço de dados REST do eXtreme Scale.
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 |
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:
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 |
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 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>