You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2017/11/23 13:18:22 UTC

[cxf] branch master updated: Adding the OData demo

This is an automated email from the ASF dual-hosted git repository.

sergeyb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/master by this push:
     new 03a9e8c  Adding the OData demo
03a9e8c is described below

commit 03a9e8ceacc115ddd1e458d44a198bdd58cf6b53
Author: Sergey Beryozkin <sb...@gmail.com>
AuthorDate: Thu Nov 23 13:18:08 2017 +0000

    Adding the OData demo
---
 .../main/release/samples/jax_rs/odata/README.txt   |  25 ++++
 .../src/main/release/samples/jax_rs/odata/pom.xml  |  91 ++++++++++++
 .../jax_rs/odata/src/main/config/KeyREADME.txt     |  19 +++
 .../odata/src/main/config/clientKeystore.jks       | Bin 0 -> 2039 bytes
 .../odata/src/main/config/serviceKeystore.jks      | Bin 0 -> 2039 bytes
 .../main/java/odata/server/DemoEdmProvider.java    | 152 +++++++++++++++++++++
 .../server/DemoEntityCollectionProcessor.java      | 149 ++++++++++++++++++++
 .../main/java/odata/server/JaxrsODataService.java  |  38 ++++++
 .../odata/src/main/java/odata/server/Server.java   |  50 +++++++
 distribution/src/main/release/samples/pom.xml      |   1 +
 10 files changed, 525 insertions(+)

diff --git a/distribution/src/main/release/samples/jax_rs/odata/README.txt b/distribution/src/main/release/samples/jax_rs/odata/README.txt
new file mode 100644
index 0000000..7338e5b
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/odata/README.txt
@@ -0,0 +1,25 @@
+JAX-RS OData Demo 
+=================
+
+This demo shows a CXF JAX-RS service interposing over Apache Olingo based OData 4 service.
+
+Credits. 
+
+This demo was built by copying some of the files and the code described at
+
+https://olingo.apache.org/doc/odata4/tutorials/read/tutorial_read.html 
+
+After bulding the demo and starting it with "mvn -Pserver", do
+
+1. curl -H "application/json" http://localhost:9000/DemoService/DemoService.svc/Products
+
+It will return the OData model describing the products
+
+2. curl -H "application/json" http://localhost:9000/DemoService/DemoService.svc/$metadata
+
+It will return the OData model describing the products metadata
+
+3. curl -H "application/json" http://localhost:9000/DemoService/DemoService.svc
+
+It will return the OData service metadata 
+
diff --git a/distribution/src/main/release/samples/jax_rs/odata/pom.xml b/distribution/src/main/release/samples/jax_rs/odata/pom.xml
new file mode 100644
index 0000000..d3b89ce
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/odata/pom.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0"?>
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one
+  or more contributor license agreements. See the NOTICE file
+  distributed with this work for additional information
+  regarding copyright ownership. The ASF licenses this file
+  to you under the Apache License, Version 2.0 (the
+  "License"); you may not use this file except in compliance
+  with the License. You may obtain a copy of the License at
+ 
+  http://www.apache.org/licenses/LICENSE-2.0
+ 
+  Unless required by applicable law or agreed to in writing,
+  software distributed under the License is distributed on an
+  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+  KIND, either express or implied. See the License for the
+  specific language governing permissions and limitations
+  under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>jax_rs_odata</artifactId>
+    <name>JAX-RS OData</name>
+    <description>JAX-RS OData</description>
+    <parent>
+        <groupId>org.apache.cxf.samples</groupId>
+        <artifactId>cxf-samples</artifactId>
+        <version>3.2.2-SNAPSHOT</version>
+        <relativePath>../..</relativePath>
+    </parent>
+    <properties>
+        <olingo.version>4.5.3</olingo.version>
+    </properties>
+    <profiles>
+        <profile>
+            <id>server</id>
+            <build>
+                <defaultGoal>test</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <phase>test</phase>
+                                <goals>
+                                    <goal>java</goal>
+                                </goals>
+                                <configuration>
+                                    <mainClass>odata.server.Server</mainClass>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-frontend-jaxrs</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.cxf</groupId>
+            <artifactId>cxf-rt-transports-http-jetty</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+         <groupId>org.apache.olingo</groupId>
+         <artifactId>odata-commons-api</artifactId>
+         <version>4.4.0</version>
+        </dependency>
+        <dependency>
+         <groupId>org.apache.olingo</groupId>
+         <artifactId>odata-commons-core</artifactId>
+         <version>4.4.0</version>
+        </dependency>
+        <dependency>
+         <groupId>org.apache.olingo</groupId>
+         <artifactId>odata-server-api</artifactId>
+         <version>4.4.0</version>
+        </dependency>
+        <dependency>
+         <groupId>org.apache.olingo</groupId>
+         <artifactId>odata-server-core</artifactId>
+         <version>4.4.0</version>
+        </dependency> 
+    </dependencies>
+</project>
diff --git a/distribution/src/main/release/samples/jax_rs/odata/src/main/config/KeyREADME.txt b/distribution/src/main/release/samples/jax_rs/odata/src/main/config/KeyREADME.txt
new file mode 100644
index 0000000..9b55d5a
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/odata/src/main/config/KeyREADME.txt
@@ -0,0 +1,19 @@
+# The below scripts show the commands used to generate the self-signed keys for this sample.
+# If you use the below script to create your own keys be sure to change the passwords used here
+# DO NOT USE THE SUPPLIED KEYS IN PRODUCTION--everyone has them!!
+# For production recommended to use keys signed by a third-party certificate authority (CA)
+
+# Create the combination keystore/truststore for the client and service.
+# Note you can create separate keystores/truststores for both if desired
+keytool -genkeypair -validity 730 -alias myservicekey -keystore serviceKeystore.jks -dname "cn=localhost" -keypass skpass -storepass sspass
+keytool -genkeypair -validity 730 -alias myclientkey -keystore clientKeystore.jks -keypass ckpass -storepass cspass
+
+# Place server public cert in client key/truststore
+keytool -export -rfc -keystore serviceKeystore.jks -alias myservicekey -file MyService.cer -storepass sspass
+keytool -import -noprompt -trustcacerts -file MyService.cer -alias myservicekey -keystore clientKeystore.jks -storepass cspass
+
+# Place client public cert in service key/truststore
+# Note this needs to be done only if you're requiring client authentication
+# as configured in resources/ServerConfig.xml
+keytool -export -rfc -keystore clientKeystore.jks -alias myclientkey -file MyClient.cer -storepass cspass
+keytool -import -noprompt -trustcacerts -file MyClient.cer -alias myclientkey -keystore serviceKeystore.jks -storepass sspass
diff --git a/distribution/src/main/release/samples/jax_rs/odata/src/main/config/clientKeystore.jks b/distribution/src/main/release/samples/jax_rs/odata/src/main/config/clientKeystore.jks
new file mode 100644
index 0000000..89dbb3d
Binary files /dev/null and b/distribution/src/main/release/samples/jax_rs/odata/src/main/config/clientKeystore.jks differ
diff --git a/distribution/src/main/release/samples/jax_rs/odata/src/main/config/serviceKeystore.jks b/distribution/src/main/release/samples/jax_rs/odata/src/main/config/serviceKeystore.jks
new file mode 100644
index 0000000..cdbe48a
Binary files /dev/null and b/distribution/src/main/release/samples/jax_rs/odata/src/main/config/serviceKeystore.jks differ
diff --git a/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/DemoEdmProvider.java b/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/DemoEdmProvider.java
new file mode 100644
index 0000000..41d20b3
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/DemoEdmProvider.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package odata.server;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind;
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider;
+import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer;
+import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainerInfo;
+import org.apache.olingo.commons.api.edm.provider.CsdlEntitySet;
+import org.apache.olingo.commons.api.edm.provider.CsdlEntityType;
+import org.apache.olingo.commons.api.edm.provider.CsdlProperty;
+import org.apache.olingo.commons.api.edm.provider.CsdlPropertyRef;
+import org.apache.olingo.commons.api.edm.provider.CsdlSchema;
+
+/**
+ * this class is supposed to declare the metadata of the OData service
+ * it is invoked by the Olingo framework e.g. when the metadata document of the service is invoked
+ * e.g. http://localhost:8080/ExampleService1/ExampleService1.svc/$metadata
+ */
+public class DemoEdmProvider extends CsdlAbstractEdmProvider {
+
+  // Service Namespace
+  public static final String NAMESPACE = "OData.Demo";
+
+  // EDM Container
+  public static final String CONTAINER_NAME = "Container";
+  public static final FullQualifiedName CONTAINER = new FullQualifiedName(NAMESPACE, CONTAINER_NAME);
+
+  // Entity Types Names
+  public static final String ET_PRODUCT_NAME = "Product";
+  public static final FullQualifiedName ET_PRODUCT_FQN = new FullQualifiedName(NAMESPACE, ET_PRODUCT_NAME);
+
+  // Entity Set Names
+  public static final String ES_PRODUCTS_NAME = "Products";
+
+
+  @Override
+  public List<CsdlSchema> getSchemas() {
+
+    // create Schema
+    CsdlSchema schema = new CsdlSchema();
+    schema.setNamespace(NAMESPACE);
+
+    // add EntityTypes
+    List<CsdlEntityType> entityTypes = new ArrayList<CsdlEntityType>();
+    entityTypes.add(getEntityType(ET_PRODUCT_FQN));
+    schema.setEntityTypes(entityTypes);
+
+    // add EntityContainer
+    schema.setEntityContainer(getEntityContainer());
+
+    // finally
+    List<CsdlSchema> schemas = new ArrayList<CsdlSchema>();
+    schemas.add(schema);
+
+    return schemas;
+  }
+
+
+  @Override
+  public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) {
+
+    // this method is called for one of the EntityTypes that are configured in the Schema
+    if(entityTypeName.equals(ET_PRODUCT_FQN)){
+
+      //create EntityType properties
+      CsdlProperty id = new CsdlProperty().setName("ID").setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName());
+      CsdlProperty name = new CsdlProperty().setName("Name").setType(EdmPrimitiveTypeKind.String.getFullQualifiedName());
+      CsdlProperty  description = new CsdlProperty().setName("Description").setType(EdmPrimitiveTypeKind.String.getFullQualifiedName());
+
+      // create CsdlPropertyRef for Key element
+      CsdlPropertyRef propertyRef = new CsdlPropertyRef();
+      propertyRef.setName("ID");
+
+      // configure EntityType
+      CsdlEntityType entityType = new CsdlEntityType();
+      entityType.setName(ET_PRODUCT_NAME);
+      entityType.setProperties(Arrays.asList(id, name , description));
+      entityType.setKey(Collections.singletonList(propertyRef));
+
+      return entityType;
+    }
+
+    return null;
+  }
+
+  @Override
+  public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) {
+
+    if(entityContainer.equals(CONTAINER)){
+      if(entitySetName.equals(ES_PRODUCTS_NAME)){
+        CsdlEntitySet entitySet = new CsdlEntitySet();
+        entitySet.setName(ES_PRODUCTS_NAME);
+        entitySet.setType(ET_PRODUCT_FQN);
+
+        return entitySet;
+      }
+    }
+
+    return null;
+  }
+
+  @Override
+  public CsdlEntityContainer getEntityContainer() {
+
+    // create EntitySets
+    List<CsdlEntitySet> entitySets = new ArrayList<CsdlEntitySet>();
+    entitySets.add(getEntitySet(CONTAINER, ES_PRODUCTS_NAME));
+
+    // create EntityContainer
+    CsdlEntityContainer entityContainer = new CsdlEntityContainer();
+    entityContainer.setName(CONTAINER_NAME);
+    entityContainer.setEntitySets(entitySets);
+
+    return entityContainer;
+  }
+
+  @Override
+  public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) {
+
+    // This method is invoked when displaying the service document at e.g. http://localhost:8080/DemoService/DemoService.svc
+    if(entityContainerName == null || entityContainerName.equals(CONTAINER)){
+      CsdlEntityContainerInfo entityContainerInfo = new CsdlEntityContainerInfo();
+      entityContainerInfo.setContainerName(CONTAINER);
+      return entityContainerInfo;
+    }
+
+    return null;
+  }
+}
\ No newline at end of file
diff --git a/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/DemoEntityCollectionProcessor.java b/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/DemoEntityCollectionProcessor.java
new file mode 100644
index 0000000..8c3c8f0
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/DemoEntityCollectionProcessor.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package odata.server;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import org.apache.olingo.commons.api.data.ContextURL;
+import org.apache.olingo.commons.api.data.Entity;
+import org.apache.olingo.commons.api.data.EntityCollection;
+import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.data.ValueType;
+import org.apache.olingo.commons.api.edm.EdmEntitySet;
+import org.apache.olingo.commons.api.edm.EdmEntityType;
+import org.apache.olingo.commons.api.ex.ODataRuntimeException;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataRequest;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.processor.EntityCollectionProcessor;
+import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions;
+import org.apache.olingo.server.api.serializer.ODataSerializer;
+import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.api.serializer.SerializerResult;
+import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.UriResourceEntitySet;
+
+/**
+ * This class is invoked by the Olingo framework when the the OData service is invoked order to display a list/collection of data (entities).
+ * This is the case if an EntitySet is requested by the user.
+ * Such an example URL would be:
+ * http://localhost:8080/ExampleService1/ExampleService1.svc/Products
+ */
+public class DemoEntityCollectionProcessor implements EntityCollectionProcessor {
+
+  private OData odata;
+  private ServiceMetadata serviceMetadata;
+
+  // our processor is initialized with the OData context object
+  public void init(OData odata, ServiceMetadata serviceMetadata) {
+    this.odata = odata;
+    this.serviceMetadata = serviceMetadata;
+  }
+
+
+  // the only method that is declared in the EntityCollectionProcessor interface
+  // this method is called, when the user fires a request to an EntitySet
+  // in our example, the URL would be:
+  // http://localhost:8080/ExampleService1/ExampleServlet1.svc/Products
+  public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, SerializerException {
+
+    // 1st we have retrieve the requested EntitySet from the uriInfo object (representation of the parsed service URI)
+    List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
+    UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); // in our example, the first segment is the EntitySet
+    EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();
+
+    // 2nd: fetch the data from backend for this requested EntitySetName // it has to be delivered as EntitySet object
+    EntityCollection entitySet = getData(edmEntitySet);
+
+    // 3rd: create a serializer based on the requested format (json)
+    ODataSerializer serializer = odata.createSerializer(responseFormat);
+    
+    // 4th: Now serialize the content: transform from the EntitySet object to InputStream
+    EdmEntityType edmEntityType = edmEntitySet.getEntityType();
+    ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).build();
+
+    final String id = request.getRawBaseUri() + "/" + edmEntitySet.getName();
+    EntityCollectionSerializerOptions opts =
+        EntityCollectionSerializerOptions.with().id(id).contextURL(contextUrl).build();
+    SerializerResult serializedContent = serializer.entityCollection(serviceMetadata, edmEntityType, entitySet, opts);
+
+    // Finally: configure the response object: set the body, headers and status code
+    response.setContent(serializedContent.getContent());
+    response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+    response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());
+  }
+
+
+  /**
+   * Helper method for providing some sample data
+   * @param edmEntitySet for which the data is requested
+   * @return data of requested entity set
+   */
+  private EntityCollection getData(EdmEntitySet edmEntitySet){
+
+    EntityCollection productsCollection = new EntityCollection();
+    // check for which EdmEntitySet the data is requested
+    if(DemoEdmProvider.ES_PRODUCTS_NAME.equals(edmEntitySet.getName())) {
+      List<Entity> productList = productsCollection.getEntities();
+
+      // add some sample product entities
+      final Entity e1 = new Entity()
+          .addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 1))
+          .addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Notebook Basic 15"))
+          .addProperty(new Property(null, "Description", ValueType.PRIMITIVE,
+              "Notebook Basic, 1.7GHz - 15 XGA - 1024MB DDR2 SDRAM - 40GB"));
+      e1.setId(createId("Products", 1));
+      productList.add(e1);
+
+      final Entity e2 = new Entity()
+          .addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 2))
+          .addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "1UMTS PDA"))
+          .addProperty(new Property(null, "Description", ValueType.PRIMITIVE,
+              "Ultrafast 3G UMTS/HSDPA Pocket PC, supports GSM network"));
+      e2.setId(createId("Products", 1));
+      productList.add(e2);
+
+      final Entity e3 = new Entity()
+          .addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 3))
+          .addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Ergo Screen"))
+          .addProperty(new Property(null, "Description", ValueType.PRIMITIVE,
+              "19 Optimum Resolution 1024 x 768 @ 85Hz, resolution 1280 x 960"));
+      e3.setId(createId("Products", 1));
+      productList.add(e3);
+    }
+
+    return productsCollection;
+  }
+  
+  private URI createId(String entitySetName, Object id) {
+    try {
+      return new URI(entitySetName + "(" + String.valueOf(id) + ")");
+    } catch (URISyntaxException e) {
+      throw new ODataRuntimeException("Unable to create id for entity: " + entitySetName, e);
+    }
+  }
+}
\ No newline at end of file
diff --git a/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/JaxrsODataService.java b/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/JaxrsODataService.java
new file mode 100644
index 0000000..d645c73
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/JaxrsODataService.java
@@ -0,0 +1,38 @@
+package odata.server;
+
+import java.util.ArrayList;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+
+import org.apache.olingo.commons.api.edmx.EdmxReference;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataHttpHandler;
+import org.apache.olingo.server.api.ServiceMetadata;
+
+@Path("/DemoService.svc")
+public class JaxrsODataService {
+
+    @GET
+    @Path("{id:.*}")
+    public Response service(@Context HttpServletRequest req, @Context HttpServletResponse resp) {
+
+        String requestMapping = req.getContextPath() + req.getServletPath() + "/DemoService.svc";
+        req.setAttribute("requestMapping", requestMapping);
+        // create odata handler and configure it with EdmProvider and Processor
+        OData odata = OData.newInstance();
+        ServiceMetadata edm = odata.createServiceMetadata(new DemoEdmProvider(),
+                                                          new ArrayList<EdmxReference>());
+        ODataHttpHandler handler = odata.createHandler(edm);
+        handler.register(new DemoEntityCollectionProcessor());
+
+        // let the handler do the work
+        handler.process(req, resp);
+        return Response.ok().build();
+    }
+    
+}
diff --git a/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/Server.java b/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/Server.java
new file mode 100644
index 0000000..f10d6c3
--- /dev/null
+++ b/distribution/src/main/release/samples/jax_rs/odata/src/main/java/odata/server/Server.java
@@ -0,0 +1,50 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package odata.server;
+
+import java.util.Collections;
+
+import org.apache.cxf.ext.logging.LoggingFeature;
+import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
+import org.apache.cxf.jaxrs.lifecycle.SingletonResourceProvider;
+
+public class Server {
+
+    
+    protected Server() throws Exception {
+        JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean();
+        sf.setResourceClasses(JaxrsODataService.class);
+        sf.setResourceProvider(JaxrsODataService.class,
+            new SingletonResourceProvider(new JaxrsODataService()));
+        sf.setFeatures(Collections.singletonList(new LoggingFeature()));
+        sf.setAddress("http://localhost:9000/DemoService");
+
+        sf.create();
+    }
+
+    public static void main(String args[]) throws Exception {
+        new Server();
+        System.out.println("Server ready...");
+
+        Thread.sleep(5 * 600000 * 1000);
+        System.out.println("Server exiting");
+        System.exit(0);
+    }
+}
diff --git a/distribution/src/main/release/samples/pom.xml b/distribution/src/main/release/samples/pom.xml
index afd3180..88983d6 100644
--- a/distribution/src/main/release/samples/pom.xml
+++ b/distribution/src/main/release/samples/pom.xml
@@ -67,6 +67,7 @@
         <module>jax_rs/description_swagger2_spring</module>
         <module>jax_rs/basic_oidc</module>
         <module>jax_rs/big_query</module>
+        <module>jax_rs/odata</module>
         <module>callback</module>
         <module>wsdl_first_pure_xml</module>
         <module>jaxws_dispatch_provider</module>

-- 
To stop receiving notification emails like this one, please contact
['"commits@cxf.apache.org" <co...@cxf.apache.org>'].