Monday 22 July 2019

Olingo: OData: Read information about product continued


To make the code more readable and extendible, lets refactor the code in previous post.

I refactored the code from previous post by adding below classes.
Product.java: Model class represents product information.
ProductUtil.java: Return the product specific details OData service
EntityUtil.java: Return the entity specific details to OData service. Entity can be product, customer or any other thing.

Total project structure looks like below.


Find the below working application.

Product.java
package com.app.model;

public class Product {
 private int id;
 private String name;
 private String description;
 private double price;

 public Product(int id, String name, String description, double price){
  this.id = id;
  this.name = name;
  this.description = description;
  this.price = price;
 }

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getDescription() {
  return description;
 }

 public void setDescription(String description) {
  this.description = description;
 }

 public double getPrice() {
  return price;
 }

 public void setPrice(double price) {
  this.price = price;
 }

}


DemoEdmProvider.java
package com.app.service;

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;
import org.apache.olingo.commons.api.ex.ODataException;

/**
 * Class to provide OData services. Edm stands for Entity Data Model.
 * 
 * @author Krishna
 *
 */
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 CsdlEntityContainer getEntityContainer() throws ODataException {
  // 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) throws ODataException {
  // 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;
 }

 @Override
 public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) throws ODataException {
  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 CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException {
  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());
   CsdlProperty price = new CsdlProperty().setName("Price")
     .setType(EdmPrimitiveTypeKind.Double.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, price));
   entityType.setKey(Collections.singletonList(propertyRef));

   return entityType;
  }

  return null;
 }

 @Override
 public List<CsdlSchema> getSchemas() throws ODataException {
  // 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;
 }

}


DemoEntityCollectionProcessor.java
package com.app.service;

import java.util.List;

import org.apache.olingo.commons.api.data.ContextURL;
import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.edm.EdmEntitySet;
import org.apache.olingo.commons.api.edm.EdmEntityType;
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.ODataLibraryException;
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.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;

import com.app.util.EntityUtil;

public class DemoEntityCollectionProcessor implements EntityCollectionProcessor {
 private OData odata;
 private ServiceMetadata serviceMetadata;

 public void init(OData odata, ServiceMetadata serviceMetadata) {
  this.odata = odata;
  this.serviceMetadata = serviceMetadata;
 }

 public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo,
   ContentType responseFormat) throws ODataApplicationException, ODataLibraryException {

  List<UriResource> resourcePaths = uriInfo.getUriResourceParts();
  UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0);
  EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet();

  EntityCollection entitySet = EntityUtil.getData(edmEntitySet);

  ODataSerializer serializer = odata.createSerializer(responseFormat);

  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);

  response.setContent(serializedContent.getContent());
  response.setStatusCode(HttpStatusCode.OK.getStatusCode());
  response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString());

 }

}


DemoServlet.java
package com.app.servlet;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.olingo.server.api.OData;
import org.apache.olingo.server.api.ODataHttpHandler;
import org.apache.olingo.server.api.ServiceMetadata;
import org.apache.olingo.server.api.edmx.EdmxReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.app.service.DemoEdmProvider;
import com.app.service.DemoEntityCollectionProcessor;

public class DemoServlet extends HttpServlet {

 private static final long serialVersionUID = 1L;
 private static final Logger LOG = LoggerFactory.getLogger(DemoServlet.class);

 @Override
 protected void service(final HttpServletRequest req, final HttpServletResponse resp)
   throws ServletException, IOException {

  try {
   OData odata = OData.newInstance();
   
   ServiceMetadata edm = odata.createServiceMetadata(new DemoEdmProvider(), new ArrayList<EdmxReference>());
   
   ODataHttpHandler handler = odata.createHandler(edm);
   handler.register(new DemoEntityCollectionProcessor());
   
   handler.process(req, resp);

  } catch (RuntimeException e) {
   LOG.error("Server Error occurred in ExampleServlet", e);
   throw new ServletException(e);
  }
 }
}


EntityUtil.java
package com.app.util;

import org.apache.olingo.commons.api.data.EntityCollection;
import org.apache.olingo.commons.api.edm.EdmEntitySet;

import com.app.service.DemoEdmProvider;

/**
 * Responsible to perform CRUD operations on entities.
 * 
 * @author Krishna
 *
 */
public class EntityUtil {

 public static EntityCollection getData(EdmEntitySet edmEntitySet) {
  if (DemoEdmProvider.ES_PRODUCTS_NAME.equals(edmEntitySet.getName())) {
   return ProductUtil.getProductsData();
  }

  return null;
 }
}


ProductUtil.java
package com.app.util;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

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.ex.ODataRuntimeException;

import com.app.model.Product;

public class ProductUtil {
 private static List<Product> products = new ArrayList<>();

 static {
  Product prod1 = new Product(1, "Washing Machine by AVC", "Good for morth east countries", 876544);
  Product prod2 = new Product(2, "XYZ Camera", "Catch pics while travelling", 965987);

  products.add(prod1);
  products.add(prod2);
 }

 private static Entity getProductEntity(final Product product) {
  Entity entity = new Entity().addProperty(new Property(null, "ID", ValueType.PRIMITIVE, product.getId()))
    .addProperty(new Property(null, "Name", ValueType.PRIMITIVE, product.getName()))
    .addProperty(new Property(null, "Description", ValueType.PRIMITIVE, product.getDescription()))
    .addProperty(new Property(null, "Price", ValueType.PRIMITIVE, product.getPrice()));
  entity.setId(createId("Products", product.getId()));
  return entity;
 }

 public static EntityCollection getProductsData() {
  EntityCollection dataToSend = new EntityCollection();
  List<Entity> productList = dataToSend.getEntities();

  for (Product prod : products) {
   productList.add(getProductEntity(prod));
  }

  return dataToSend;
 }

 private static URI createId(final String entitySetName, final Object id) {
  try {
   return new URI(entitySetName + "(" + String.valueOf(id) + ")");
  } catch (URISyntaxException e) {
   throw new ODataRuntimeException("Unable to create id for entity: " + entitySetName, e);
  }
 }
}


web.xml
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
 <display-name>Archetype Created Web Application</display-name>


 <servlet>
  <servlet-name>DemoServlet</servlet-name>
  <servlet-class>com.app.servlet.DemoServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>DemoServlet</servlet-name>
  <url-pattern>/DemoService.svc/*</url-pattern>
 </servlet-mapping>

</web-app>


index.jsp
<html>
<body>
 <h2>Hello World!</h2>
</body>
</html>

Run the application on server.

Hit below url.


You can see below messages in browser.

<?xml version="1.0" encoding="UTF-8"?>
<a:feed xmlns:a="http://www.w3.org/2005/Atom" xmlns:d="http://docs.oasis-open.org/odata/ns/data" xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" m:context="$metadata#Products">
   <a:id>http://localhost:8080/olingoDemo_refactored//DemoService.svc/Products</a:id>
   <a:entry>
      <a:id>Products(1)</a:id>
      <a:title />
      <a:summary />
      <a:updated>2018-12-07T09:08:25Z</a:updated>
      <a:author>
         <a:name />
      </a:author>
      <a:link rel="edit" href="Products(1)" />
      <a:category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#OData.Demo.Product" />
      <a:content type="application/xml">
         <m:properties>
            <d:ID m:type="Int32">1</d:ID>
            <d:Name>Washing Machine by AVC</d:Name>
            <d:Description>Good for morth east countries</d:Description>
            <d:Price m:type="Double">876544.0</d:Price>
         </m:properties>
      </a:content>
   </a:entry>
   <a:entry>
      <a:id>Products(2)</a:id>
      <a:title />
      <a:summary />
      <a:updated>2018-12-07T09:08:25Z</a:updated>
      <a:author>
         <a:name />
      </a:author>
      <a:link rel="edit" href="Products(2)" />
      <a:category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#OData.Demo.Product" />
      <a:content type="application/xml">
         <m:properties>
            <d:ID m:type="Int32">2</d:ID>
            <d:Name>XYZ Camera</d:Name>
            <d:Description>Catch pics while travelling</d:Description>
            <d:Price m:type="Double">965987.0</d:Price>
         </m:properties>
      </a:content>
   </a:entry>
</a:feed>



Previous                                                    Next                                                    Home

No comments:

Post a Comment