Java und das Open Data Protocol

Werbung
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Java und das Open Data Protocol
(OData)
Inhalt
Abstract ................................................................................................................................................... 3
Datenintegration über das Internet ........................................................................................................ 3
Befreiung der Daten aus „Datensilos“................................................................................................. 3
Das Open Data Protocol (OData)............................................................................................................. 5
Woher kommt das Open Data Protocol? ............................................................................................ 5
Was kann man mit OData machen? .................................................................................................... 5
Details von OData ................................................................................................................................ 6
Das OData Service-Dokument ............................................................................................................. 9
OData URI Konventionen .................................................................................................................. 10
Standardisierung von OData ................................................................................................................. 12
Java Implementierungen von OData ..................................................................................................... 12
Das Open Source Framework odata4j .............................................................................................. 13
Das SAP NetWeaver Gateway plug.in for Eclipse .............................................................................. 14
Zusammenfassung................................................................................................................................. 15
Weitere Informationen ......................................................................................................................... 16
Anhang: Quellkode der odata4j Beispiele ............................................................................................. 17
OData Consumer für Netflix mit odata4j .......................................................................................... 17
Einfacher OData Producer mit odata4j ............................................................................................. 20
1
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
2
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Abstract
Das Open Data Protocol (http://www.odata.org/), kurz OData genannt, ist eine Spezifikation von
Microsoft, welche ein Protokoll für die plattformübergreifende Integration von Daten definiert.
OData basiert auf REST und den Formaten JSON (JavaScript Object Notation) und AtomPub (Atom
Publishing Protocol). Es unterstützt die Abfrage und Änderung von Daten mit standardisierten
Internettechnologien. Außer für das Microsoft .NET Framework (3.5SP1 und 4.x) gibt es SDKs für
Java, JavaScript, Ruby, PHP und ObjectiveC. Microsoft Windows Azure erlaubt den Zugriff auf
relationale und nicht relationale Daten über OData. Auch IBM stellt bereits für die „WebSphere
eXtreme Scale” Plattform einen ODdata kompatiblen Daten-Service bereit, und SAP wird mit dem
Netweaver Gateway OData ebenfalls unterstützen. Der Vortrag gibt eine Einführung in das Open
Data Protocol und zeigt anhand von existierenden Anwendungen und Beispielen das Einsatzspektrum
dieser Technologie auf. Es wird weiterhin anhand zwei einfacher Beispiele gezeigt, wie man mit dem
Open Source Framework odata4j (http://code.google.com/p/odata4j/) einen Odata Consumer und
Producer mit Java implementieren kann.
Datenintegration über das Internet
Traditionelle Schnittstellen zur Integration von Daten in Applikationen sind im einfachsten Fall die I/O
Schnittstellen, welche das Betriebssystem zur Verfügung stellt. Für relationale Daten haben sich
Frameworks auf der Basis von ODBC, JDBC oder ADO.NET etabliert. Der Zugriff auf Daten, welche in
ERP, CRM oder anderen Geschäftsapplikationen liegen, geschieht über spezielle Adapter oder
Middleware. All diesen Schnittstellen ist gemeinsam, dass sie nur innerhalb des Intranets brauchbar
sind. Erst einige der sogenannten „NoSQL“ Datenbanken, wie z. B. Apache CouchDB, bieten
Schnittstellen auf der Basis von HTTP und sind damit auch über das Internet problemlos nutzbar.
Befreiung der Daten aus „Datensilos“
“There is a vast amount of data available today and data is now being collected and stored at a rate
never seen before. Much, if not most, of this data however is locked into specific applications or
formats and difficult to access or to integrate into new uses.” (siehe www.odata.org).
3
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Die hier zitierte Behauptung von der OData Homepage ist leider sehr zutreffend. Viele Daten, die für
die Öffentlichkeit oder bestimmte Gruppen von Leuten bzw. Unternehmen von großem (legalem)
Interesse oder Nutzen wären, sind in Datensilos eingeschlossen, die nur mit erheblichem Aufwand in
neue Applikationen, vor allem in die stark zunehmende Anzahl von Applikationen auf mobilen
Endgeräten, integriert werden können.
Für eine Datenintegration über das Internet sind, wie schon erklärt, die „traditionellen“
Datenintegrations-APIs ungeeignet.
Etabliert und bewährt hat sich im Internet dass http Protokoll. Http ist einfach aufgebaut und damit
auch gut zu implementieren, sodass es auf allen gängigen Applikationsentwicklungsplattformen
durch entsprechende Bibliotheken und Frameworks unterstützt wird. Die Adressierung und
Identifizierung von Ressourcen im Internet geschieht mit Hilfe von URIs, deren Syntax im RFC 3986
spezifiziert wurde.
Für den Datenzugriff (Datenintegration) über das Internet wäre also ein Mechanismus ideal, der auf
http in Verbindung mit URIs aufbaut und für die Abfrage und Manipulation von Daten ähnlich flexibel
ist, wie die Sprache SQL für relationale Datenbanken. Die hier beschriebenen Anforderungen werden
durch das Microsoft Open Data Protocol erfüllt, wie wir im Folgenden sehen werden.
4
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Das Open Data Protocol (OData)
Woher kommt das Open Data Protocol?
Das Open Data Protocol wurde als Microsoft internes Projekt gestartet, welches den Codenamen
„Astoria“ hatte. Daraus entstanden die ADO.NET Data Services und mit .NET 4.0 die WCF Data
Services. Es zeigte sich, dass die Architektur, das Protokoll und die Datenformate, welche den WCF
Data Services zugrunde liegen, sehr allgemein sind und in eine allgemeine Spezifikation gegossen
werden konnten, die eben als Open Data Protocol bezeichnet wurde und die auf einer eigene
Webseite www.odata.org veröffentlicht wurde. Diese Spezifikation ist unter dem Microsoft Open
Specification Promise freigegeben worden. Aktuell (August 2012) arbeitet ein OASIS Technical
Committee an der Normierung von OData (siehe https://www.oasisopen.org/committees/tc_home.php?wg_abbrev=odata).
Was kann man mit OData machen?
5
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
OData ermöglicht es unterschiedlichste Clients, wie PCs, Macs, Windows Phone, IPhone, IPad,
Android und Internet Browser in entsprechenden Backend-Systeme über das Internet zu integrieren.
Ebenso kann man Backend-Systeme selber über OData koppeln.
Details von OData
Die grundlegende Architektur von OData ist Rest, das Protokoll ist http, die Daten können in den
Formaten AtomPub oder JSON dargestellt werden. Die Metadaten werden durch einen XML Dialekt
beschrieben, der Conceptual Schema Definition Language (CSDL) heißt und der seinen Ursprung im
ADO.NET EntityFramework hat. Dazu mehr später.
Mit OData lassen sich also Schnittstellen zu Daten implementieren, den man die Eigenschaft
„RESTful“ zuschreiben kann. Lesen und Ändern der Daten geschieht mit den bekannten HTTP Verben.
Durch Verwendung von HTTP werden auch Caching und Proxys ausgenutzt. Die Daten werden als
Ressourcen betrachtet, die über eine einheitliche URL Syntax adressierbar sind. Die Repräsentation
der Daten kann im AtomPub oder im JSON Format durchgeführt werden.
6
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Das Datenmodell auf dem OData aufbaut, besteht aus Entitäten und den Assoziationen zwischen
ihnen. Die Entitäten sind Ressourcen, die Assoziationen werden durch Links (siehe CSDL) dargestellt.
Das Entity Data Model, kurz EDM, hat sehr große Ähnlichkeit mit dem Entity-Relationship-Modell von
Peter Chen, welches er 1976 veröffentlicht hat (siehe: http://de.wikipedia.org/wiki/EntityRelationship-Modell). Die Beschreibung dieses Datenmodells geschieht über die oben erwähnte
Conceptual Schema Definition Language (CSDL). CSDL wurde ursprünglich für das ADO.NET Entity
Framework entwickelt, um das konzeptionelle Datenmodell zu beschreiben. Das ADO.NET Entity
Framework ist ein Werkzeug zur objekt-relationales Abbildung (ORM), welches mit .NET 3.5
eingeführt wurde. Ein Beispiel für eine CSDL Beschreibung werde ich bei der Vorstellung der OData
Metadaten zeigen. Details zu CSDL findet man in der Dokumentation und Büchern zum ADO.NET
Entity Framework, sowie in der Spezifikation des Open Data Protocols.
Zum Ausführen von Lese- und Änderungsoperationen auf den Ressourcen werden die vier HTTP GET,
POST, PUT und DELETE benutzt. MIT GET werden Ressourcen abgefragt, mit POST werden neue
Ressourcen angelegt, mit PUT werden sie verändert und mit DELETE gelöscht. In anderer Reihenfolge
bezeichnet man dies auch als CRUD Operationen, also Create Read Update Delete.
Die Folie zeigt wie das EDM in OData aufgebaut ist. Es gibt einen „Entity Container“, welcher „Enttity
Sets“ enthält, die aus einzelnen Entitäten bestehen. Die Entitäten enthalten „Properties“ und
eventuell „Navigation Properties“, welche sie in Beziehung zu anderen Entitäten setzen.
7
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Die obige Folie zeigt den schematischen Aufbau eines AtomPub Services. Ein OData Services stellt ja
im Prinzip einen Atom-Pub Services dar. Die Folien assoziiert die AtomPub Elemente, mit den
entsprechenden Elementen des Entity Data Models. Die „Properties“ sind Erweiterungen an
AtomPub, welche OData eingeführt hat.
8
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Das OData Service-Dokument
Der Einstiegspunkt in einen OData Service ist das sogenannte Service-Dokument. Es stellt sozusagen
die Wurzel dar, von der man zu den einzelnen Entitäten (Ressourcen) verzweigen kann.
Das Service-Dokument ist im AtomPub Format. Auf der OData Web-Site gibt es einen Testservice,
dessen Service-Dokument über die URL http://services.odata.org/OData/OData.svc angesprochen
wird. Ruft man diese URL z. B. über den InternetExplorer auf, so wird das auf der Folie dargestellte
Service-Dokument zurückgegeben. Es besteht in diesem Fall aus einem Workspace mit dem Titel
„Default“, welcher drei Collections enthält Products, Categories und Suppliers. Das Dokument
entspricht der AtomPub Spezifikation RFC 5023 (http://bitworking.org/projects/atom/rfc5023.html):
IRI bedeutet hier Internationalized Resource Identifier.
Wer sich mit dem Microsoft SQL Server auskennt, wird hier die Beispieldatenbank „Northwind“
erkennen, die unter anderem die Tabellen Products, Categories und Suppliers enthält. Das ServiceDokument dient als Ausgangspunkt, um Informationen über die einzelnen „Products“, „Categories“
usw. zu bekommen. Dies geschieht über URIs, deren syntaktischer Aufbau auf der nächsten Folie
anhand von Beispielen erläutert wird. Die gesamte Northwind Datenbank ist über die URI
http://services.odata.org/Northwind/Northwind.svc/ erreichbar.
9
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
OData URI Konventionen
Damit man bestimmte Ressourcen über OData ansprechen kann sind Konventionen für die Syntax
des URI einzuhalten.
Ein URI für einen OData Service besteht aus drei Teilen:
1) Der „Service Root URI“, also dem Einstiegspunkt in den Service hier
http://services.odata.org/OData/OData.svc/
2) Dem „Resource path“ hier Products
3) Den „Query options“, in diesem Beispiel ein Filter für alle Produkte mit einem Preis kleine
als 3.5 $.
Beispiele für den Zugriff auf einzelne Entitäten und Mengen von Entitäten auf einzelnen Felder und
der Navigation entlang eines Links sind in der Tabelle in der Mitte der obigen Folie angegeben.




http://services.odata.org/OData/OData.svc/Products greift auf alle Produkte zu.
http://services.odata.org/OData/OData.svc/Products(3) greift auf das Produkt mit dem
Schlüssel 3 zu.
http://services.odata.org/OData/OData.svc/Products(3)/Price greift auf den Preis des
Produktes mit Schlüssel 3 zu
http://services.odata.org/OData/OData.svc/Categories(2)/Products zeigt alle Produkte an,
die zur Kategorie mit dem Schlüssel 2 gehören.
OData unterstützt nicht nur das XML Format AtomPub sondern auch noch Javascript Object Notation
(JSON). Das XML Format AtomPub ist voreingestellt. Unterstützt ein OData Service auch JSON, so
muss man dies über die Formatoption in dem URI spezifizieren, wie in den Beispielen auf der Folie zu
sehen, wenn man die Daten in diesem Format konsumieren möchte.
10
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Optional kann ein OData Service ein Metadatendokument zur Verfügung stellen. Die Beschreibung
der Daten im Metadatendokument geschieht über die XML Sprache Conceptual Schema Definition
Language (CSDL). CSDL definiert Microsoft Entity Data Model (EDM), welches zuerst im ADO.NET
Entity Framework genutzt wurde und welches auch das Datenmodell von OData ist. Zur Erinnerung
OData hat seinen Ursprung in den ADO.NET Data Services, die auf dem ADO.NET Entity Framework
aufbauten. Detaillierte Informationen zu CSDL findet man in der Dokumentation des Entity
Frameworks und auf der Webseite von OData. Die Abfrage der Metadaten geschieht durch Anhängen
von $metadata an den URI der Service-Root. Ein Beispiel für die Abfrage von Metadaten ist in der
Folie gezeigt.
Als Beispiel für ein Metadatendokument ist das des Services
http://services.odata.org/OData/OData.svc/ gezeigt. Das Metadatendokument wird z. B. von
Werkzeugen zur Generierung von Proxyklassen für den vereinfachten Zugriff auf OData-Services
benutzt z. B. in Visual Studio.
11
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Standardisierung von OData
Am 24.05.2012 hat Microsoft angekündigt (http://www.microsoft.com/enus/news/press/2012/may12/05-24ODataPR.aspx), dass zusammen mit den Firmen IBM, SAP, Citrix,
Progress Software und WSO2 (http://wso2.com/) bei OASIS (Organisation for the Advancement of
Structured Information Standards) ein Technical Committee zur Standardisierung von OData
gegründet wurde.
Java Implementierungen von OData
Die Tabelle auf dem Slide zeigt die Liste der aktuell verfügbaren OData SDKs.
Für alle gängigen mobilen Plattformen wie iPad, IPhone, Windows Phone 7 und Android gibt es
SDKs, um einfach OData-Services in entsprechende Applikationen zu integrieren.
Zur Implementierung von OData-Services gibt es SDKs für .NET 3.5 / 4.x, für Java, für PHP und Ruby.
Damit ist auch auf der Server Seite ein breites Spektrum an Applikationsplattformen abgedeckt.
Für Applikationsplattformen, für die es kein dediziertes OData SDK gibt, stellt die Integration von
OData Services kein allzu großes Problem dar, sofern entsprechende HTPP- und XML-Frameworks
(bzw. JSON-Frameworks) vorhanden sind.
12
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Das Open Source Framework odata4j
13
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Das SAP NetWeaver Gateway plug.in for Eclipse
14
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Zusammenfassung
Das Open Data Protocol nutzt im Internet etablierte und ausgereifte Architekturen, Protokolle,
Darstellungsformate und Softwaretechnologien. Aufgrund dieser Eigenschaften gibt es eine große
Anzahl von SDKs für die verschiedenen Applikationsplattformen. OData hat dadurch exzellente
Interoperabilitätseigenschaften und eignet sich damit sehr gut Datenintegration über das Internet.
Das Interesse von kommerziellen und öffentlichen Anbietern an OData ist groß, sodass es das
Potenzial hat das „ODBC“ des WWW werden.
15
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Weitere Informationen
•
INTRODUCING ODATA, DATA ACCESS FOR THE WEB, THE CLOUD, MOBILE DEVICES, AND
MORE by David Chappel
•
•
OData the silo buster
•
•
http://www.ibm.com/developerworks/websphere/downloads/xs_rest_service.html
Use OData to Execute RESTful CRUD Operations on Big Data in the Cloud
•
•
http://www.ibm.com/developerworks/data/library/techarticle/dm1205odata/index.html
WebSphere eXtreme Scale REST data service
•
•
http://www.osbf.eu/blog/tag/open-data-protocol/
Use OData with IBM DB2 and Informix
•
•
http://www.zdnet.com/blog/microsoft/why-microsofts-open-data-protocolmatters/12700
OData wird OASIS-Standard
•
•
http://scn.sap.com/people/john.patterson3/blog/2011/06/15/odata-the-silo-buster
Why Microsoft’s Open Data Protocol matters
•
•
http://msdn.microsoft.com/en-us/data/hh237663.aspx
http://acloudyplace.com/2011/12/use-odata-to-execute-restful-crud-operations-onbig-data-in-the-cloud/
Klaus Rohe, Plattformübergreifende Datenintegration mit dem Open Data Protocol,
javaSPEKTRUM 01/2011, Seite 30 - 33
•
http://www.sigsdatacom.de/fileadmin/user_upload/zeitschriften/js/2011/01/rohe_JS_01_11.pdf
16
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Anhang: Quellkode der odata4j Beispiele
Damit die folgenden Java Programme fehlerfrei kompiliert werden können, muss die
Umgebungsvariable CLASSPATH den vollständigen Pfad zu den folgenden jar-Dateien enthalten:


odata4j-0.6.0-core.jar, allgemein odata4j-x.y.z-core.jar
odata4j-0.6.0-bundle.jar, allgemein odata4j-x.y.z-bundle.jar
OData Consumer für Netflix mit odata4j
Datei BaseExample.java
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
import
org.core4j.Enumerable;
org.odata4j.consumer.ODataConsumer;
org.odata4j.core.OEntity;
org.odata4j.core.OProperty;
org.odata4j.edm.EdmAssociation;
org.odata4j.edm.EdmAssociationSet;
org.odata4j.edm.EdmComplexType;
org.odata4j.edm.EdmDataServices;
org.odata4j.edm.EdmEntityContainer;
org.odata4j.edm.EdmEntitySet;
org.odata4j.edm.EdmEntityType;
org.odata4j.edm.EdmFunctionImport;
org.odata4j.edm.EdmFunctionParameter;
org.odata4j.edm.EdmNavigationProperty;
org.odata4j.edm.EdmProperty;
org.odata4j.edm.EdmSchema;
org.odata4j.edm.EdmSimpleType;
public abstract class BaseExample {
protected static void report(String msg) {
System.out.println(msg);
}
protected static void report(String msg, Object... args) {
System.out.println(String.format(msg, args));
}
protected static void reportEntity(String caption, OEntity entity) {
report(caption);
for (OProperty<?> p : entity.getProperties()) {
Object v = p.getValue();
if (p.getType().equals(EdmSimpleType.BINARY) && v != null)
v = org.odata4j.repack.org.apache.commons.codec.binary.Base64
.encodeBase64String((byte[]) v).trim();
report(" %s: %s", p.getName(), v);
}
}
protected static int reportEntities(ODataConsumer c, String entitySetHref,
int limit) {
report("entitySetHref: " + entitySetHref);
Enumerable<OEntity> entities = c.getEntities(entitySetHref).execute()
.take(limit);
return reportEntities(entitySetHref, entities);
}
protected static int reportEntities(String entitySetHref,
Enumerable<OEntity> entities) {
int count = 0;
for (OEntity e : entities) {
reportEntity(entitySetHref + " entity" + count, e);
count++;
}
report("total count: %s \n\n", count);
return count;
}
private static void reportProperties(Iterable<EdmProperty> properties) {
for (EdmProperty property : properties) {
String p = String.format("Property Name=%s Type=%s Nullable=%s",
17
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
property.getName(), property.getType(),
property.isNullable());
if (property.getMaxLength() != null)
p = p + " MaxLength=" + property.getMaxLength();
if (property.getUnicode() != null)
p = p + " Unicode=" + property.getUnicode();
if (property.getFixedLength() != null)
p = p + " FixedLength=" + property.getFixedLength();
if (property.getStoreGeneratedPattern() != null)
p = p + " StoreGeneratedPattern="
+ property.getStoreGeneratedPattern();
if (property.getFcTargetPath() != null)
p = p + " TargetPath=" + property.getFcTargetPath();
if (property.getFcContentKind() != null)
p = p + " ContentKind=" + property.getFcContentKind();
if (property.getFcKeepInContent() != null)
p = p + " KeepInContent=" + property.getFcKeepInContent();
if (property.getFcContentKind() != null)
p = p + " EpmContentKind=" + property.getFcContentKind();
if (property.getFcEpmKeepInContent() != null)
p = p + " EpmKeepInContent=" + property.getFcEpmKeepInContent();
report("
" + p);
}
}
protected static void reportMetadata(EdmDataServices services) {
for (EdmSchema schema : services.getSchemas()) {
report("Schema Namespace=%s", schema.getNamespace());
for (EdmEntityType et : schema.getEntityTypes()) {
String ets = String
.format(" EntityType Name=%s", et.getName());
if (et.getHasStream() != null)
ets = ets + " HasStream=" + et.getHasStream();
report(ets);
for (String key : et.getKeys()) {
report("
Key PropertyRef Name=%s", key);
}
reportProperties(et.getDeclaredProperties());
for (EdmNavigationProperty np : et
.getDeclaredNavigationProperties()) {
report("
NavigationProperty Name=%s Relationship=%s
FromRole=%s ToRole=%s",
np.getName(), np.getRelationship()
.getFQNamespaceName(),
np.getFromRole()
.getRole(),
np.getToRole().getRole());
}
}
for (EdmComplexType ct : schema.getComplexTypes()) {
report(" ComplexType Name=%s", ct.getName());
reportProperties(ct.getProperties());
}
for (EdmAssociation assoc : schema.getAssociations()) {
report(" Association Name=%s", assoc.getName());
report("
End Role=%s Type=%s Multiplicity=%s", assoc
.getEnd1().getRole(), assoc.getEnd1().getType()
.getFullyQualifiedTypeName(), assoc.getEnd1()
.getMultiplicity());
report("
End Role=%s Type=%s Multiplicity=%s", assoc
.getEnd2().getRole(), assoc.getEnd2().getType()
.getFullyQualifiedTypeName(), assoc.getEnd2()
.getMultiplicity());
}
for (EdmEntityContainer ec : schema.getEntityContainers()) {
report(" EntityContainer Name=%s IsDefault=%s
LazyLoadingEnabled=%s",
ec.getName(), ec.isDefault(),
ec.getLazyLoadingEnabled());
18
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
for (EdmEntitySet ees : ec.getEntitySets()) {
report("
EntitySet Name=%s EntityType=%s",
ees.getName(), ees.getType()
.getFullyQualifiedTypeName());
}
for (EdmAssociationSet eas : ec.getAssociationSets()) {
report("
AssociationSet Name=%s Association=%s",
eas.getName(), eas.getAssociation()
.getFQNamespaceName());
report("
End Role=%s EntitySet=%s", eas.getEnd1()
.getRole().getRole(),
eas.getEnd1().getEntitySet()
.getName());
report("
End Role=%s EntitySet=%s", eas.getEnd2()
.getRole().getRole(),
eas.getEnd2().getEntitySet()
.getName());
}
for (EdmFunctionImport efi : ec.getFunctionImports()) {
report("
FunctionImport Name=%s EntitySet=%s
ReturnType=%s HttpMethod=%s",
efi.getName(), efi.getEntitySet() == null ?
null
: efi.getEntitySet().getName(),
efi
.getReturnType(),
efi.getHttpMethod());
for (EdmFunctionParameter efp : efi.getParameters()) {
report("
Parameter Name=%s Type=%s Mode=%s",
efp.getName(), efp.getType(),
efp.getMode());
}
}
}
}
}
}
Datei JerseyCltRuntimeFacade.java
import javax.ws.rs.ext.RuntimeDelegate;
import
import
import
import
org.odata4j.consumer.ODataConsumer;
org.odata4j.consumer.behaviors.BasicAuthenticationBehavior;
org.odata4j.jersey.consumer.ODataJerseyConsumer;
org.odata4j.jersey.consumer.ODataJerseyConsumer.Builder;
public class JerseyCltRuntimeFacade {
static {
// ensure that the correct JAX-RS implementation is loaded
RuntimeDelegate runtimeDelegate = new
com.sun.jersey.server.impl.provider.RuntimeDelegateImpl();
RuntimeDelegate.setInstance(runtimeDelegate);
}
public ODataConsumer create(String endpointUri) {
Builder builder = ODataJerseyConsumer.newBuilder(endpointUri);
return builder.build();
}
public ODataConsumer createUsingBasicAuth(String endpointUri, String user, String
password) {
ODataConsumer res = null;
try {
Builder builder = ODataJerseyConsumer.newBuilder(endpointUri);
builder.setClientBehaviors(new BasicAuthenticationBehavior(user,
password));
res = builder.build();
} catch (Exception e) {
System.err.printf("Error in JerseyRuntimeFacade.create(account, key):
%s", e.getMessage());
19
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
}
return res;
}
}
Datei NetflixODataClt.java
import java.util.List;
import org.odata4j.consumer.ODataConsumer;
import org.odata4j.core.OEntity;
import org.odata4j.core.OProperty;
public class NetflixODataClt extends BaseExample {
public static final String NETFLIX_URI = "http://odata.netflix.com/Catalog/";
public static void main(String[] args) {
NetflixODataClt odataclt = new NetflixODataClt();
odataclt.run(args);
}
private void run(String[] args) {
JerseyCltRuntimeFacade rtFacde = new JerseyCltRuntimeFacade();
ODataConsumer odc = rtFacde.create(NETFLIX_URI);
showMetadata(odc);
// locate the netflix id for Morgan Spurlock
int morganSpurlockId = odc.getEntities("People")
.filter("substringof('Spurlock', Name)").execute().first()
.getProperty("Id", Integer.class).getValue();
// lookup and print all titles he's acted in
List<OEntity> titlesActedIn = odc.getEntities("People")
.nav(morganSpurlockId, "TitlesActedIn").execute().toList();
for (OEntity title : titlesActedIn) {
for (OProperty<?> p : title.getProperties()) {
report("%s: %s", p.getName(), p.getValue());
}
report("====================================\n");
}
report("count: " + titlesActedIn.size());
}
private void showMetadata(ODataConsumer odc) {
report("========================= METADATA =========================\n");
reportMetadata(odc.getMetadata());
report("======================= END METADATA =======================\n");
}
}
Einfacher OData Producer mit odata4j
Datei Customer.java
public class Customer {
private int id;
private String name;
private double ordervalue;
public Customer() {
}
public Customer(int id, String name, double orderval) {
this.id = id;
this.name = name;
this.ordervalue = orderval;
}
public int getId() {
return id;
}
20
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
public String getName() {
return name;
}
public double getOrderValue() {
return ordervalue;
}
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setOrderValue(double ordeval) {
this.ordervalue = ordeval;
}
@Override
public String toString() {
return String.format("Customer[Id=%s,Name=%s,OrderValue=%f]", id, name,
ordervalue);
}
}
Datei JerseyServerRuntimeFacade.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.ws.rs.ext.RuntimeDelegate;
import
import
import
import
import
org.odata4j.core.Throwables;
org.odata4j.jersey.producer.server.JerseyServer;
org.odata4j.producer.resources.DefaultODataApplication;
org.odata4j.producer.resources.RootApplication;
org.odata4j.producer.server.ODataServer;
import com.sun.jersey.api.container.filter.LoggingFilter;
public class JerseyServerRuntimeFacade {
static {
// Ensure that the correct JAX-RS implementation is loaded
RuntimeDelegate runtimeDelegate = new
com.sun.jersey.server.impl.provider.RuntimeDelegateImpl();
RuntimeDelegate.setInstance(runtimeDelegate);
}
public void hostODataServer(String baseUri) {
try {
ODataServer server = new JerseyServer(baseUri,
DefaultODataApplication.class, RootApplication.class)
.addJerseyRequestFilter(LoggingFilter.class);
server.start();
System.out.println("Press any key to exit");
new BufferedReader(new InputStreamReader(System.in)).readLine();
server.stop();
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
}
21
Klaus Rohe, Microsoft Deutschland GmbH
28.08.2012
Datei SimpleODataServerExample.java
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.ws.rs.ext.RuntimeDelegate;
import
import
import
import
import
org.odata4j.core.Throwables;
org.odata4j.jersey.producer.server.JerseyServer;
org.odata4j.producer.resources.DefaultODataApplication;
org.odata4j.producer.resources.RootApplication;
org.odata4j.producer.server.ODataServer;
import com.sun.jersey.api.container.filter.LoggingFilter;
public class JerseyServerRuntimeFacade {
static {
// Ensure that the correct JAX-RS implementation is loaded
RuntimeDelegate runtimeDelegate = new
com.sun.jersey.server.impl.provider.RuntimeDelegateImpl();
RuntimeDelegate.setInstance(runtimeDelegate);
}
public void hostODataServer(String baseUri) {
try {
ODataServer server = new JerseyServer(baseUri,
DefaultODataApplication.class, RootApplication.class)
.addJerseyRequestFilter(LoggingFilter.class);
server.start();
System.out.println("Press any key to exit");
new BufferedReader(new InputStreamReader(System.in)).readLine();
server.stop();
} catch (IOException e) {
throw Throwables.propagate(e);
}
}
}
22
Herunterladen