Manipulating data of OData v4 services with Olingo

In a previous post, we saw how to access data of OData v4 services with Olingo (see https://templth.wordpress.com/2014/12/03/accessing-odata-v4-service-with-olingo/). We will focus now on how to manipulate these data.

We dont remind here how to configure Olingo in the project and to get an instance of the client. Please refer to the previous post for more details.

In a first time, we will describe how to implement requests to add, update or delete elements. We tackle then how to build the content to provide when adding or updating elements.

For this post, we use the demo OData v4 service provided by the platform services.odata.org. This service provides read / write accesses.

Implementing CUD operations

In this section, we will describe how to add, update and delete data with Olingo. This is commonly named CUD (Create Update Delete operations). We dont focus on the way to create an instance of the class ODataEntity. We tackle this aspect later according to what we want to do.

We way to create and execute requests to update elements on OData v4 services follows the same style than for retrieve requests. The OData client of Olingo is used to get the right request factory, the CUDRequestFactory one. Using the latter we can the request kind for our processing.

If we want to add an element, it corresponds to a ODataEntityCreateRequest one. The URI to use for the request is the one of the element type. For example, if we want to a product, we simply need to use the entity set segment Products in the case of our service.

After executing the request, we can check that the element is successfully created using the status code of the response. Its the case with an HTTP code 201 (Created).

Following code describes how to create an element:

String serviceRoot = "http://services.odata.org/V4/OData/(S(li4s4wcplcgyiy3uvuog1lxl))/OData.svc";
URI productsUri = client.newURIBuilder(serviceRoot)
                  .appendEntitySetSegment("Products").build();

ODataEntity product = (...)

ODataEntityCreateRequest<ODataEntity> req = client.getCUDRequestFactory()
                  .getEntityCreateRequest(productsUri, product);

ODataEntityCreateResponse<ODataEntity> res = req.execute();

if (res.getStatusCode()==201) {
    // Created
}

For updates and deletions, we are now at the level of a particular element. This means that we need to add a key segment with the identifier of the element in the URI.

If we want to update an element, we need to use a request of type ODataEntityUpdateRequest. In this context, we have two update modes:

  • Full updates (replace mode): the element is updated with all the provided content. This replaces the existing content of the element. The mode UpdateType.REPLACE is used in this case.
  • Partial updates (patch mode): only the specified content in the request will be updated in the existing element. Other parts of the element remains the same. This is based under the hood on the HTTP method PATCH. The mode UpdateType.PATCH is used in this case.

After executing the request, we can check that the element is successfully updated using the status code of the response. Its the case with an HTTP code 204 (No Content).

Following code describes how to partially update an element:

String serviceRoot = "http://localhost:8080/V4/OData/(S(li4s4wcplcgyiy3uvuog1lxl))/OData.svc";
URI productsUri = client.newURIBuilder(serviceRoot)
                   .appendEntitySetSegment("Products")
                   .appendKeySegment(1000).build();

ODataEntity productUpdates = (...)

ODataEntityUpdateRequest<ODataEntity> req = client
                   .getCUDRequestFactory().getEntityUpdateRequest(productsUri,
                                      UpdateType.PATCH, productUpdates);

ODataEntityUpdateResponse<ODataEntity> res = req.execute();

if (res.getStatusCode()==204) {
    // Updated
}

Deleting elements simply corresponds to execute a request of type ODataEntityDeleteRequest.

After executing the request, we can check that the element is successfully deleted using the status code of the response. Its the case with an HTTP code 204 (No Content).

Following code describes how to delete an element:

String serviceRoot = "http://localhost:8080/V4/OData/(S(li4s4wcplcgyiy3uvuog1lxl))/OData.svc";
URI productsUri = client.newURIBuilder(serviceRoot)
                    .appendEntitySetSegment("Products")
                    .appendKeySegment(1000).build();

ODataDeleteResponse deleteRes = client.getCUDRequestFactory()
                    .getDeleteRequest(productsUri).execute();

if (deleteRes.getStatusCode()==204) {
    // Deleted
}

Now we saw how to execute the different requests, we will focus on the way to create elements involved in such requests.

Initializing elements

Within Olingo client support, entities correspond to exchanged data. They are received when retrieving data but can also be created to send data to the service. The key element is the interface ODataEntity. Olingo provides an object factory with the class ODataObjectFactory that allows to create them with its method newEntity.

Following code describes how to create an empty entity:

ODataEntity product = client.getObjectFactory().newEntity(
    new FullQualifiedName("ODataDemo", "Product"));

You can wonder what to specify for the qualified name It depends on the service you use. We need to refer to metadata provided by the target service. For more details, have a look at the section .

Now the entity is created, lets populate it with properties. The object factory used previously also provides methods to create properties and initialize their values.

In the following code, we focus on the creation of primitive properties of several types (integer, string, date, double):

// ID (Edm.Int32)
product.getProperties().add(
    client.getObjectFactory().newPrimitiveProperty(
       "ID",
       client.getObjectFactory().newPrimitiveValueBuilder()
           .buildInt32(1000)
));

// Name (Edm.String)
product.getProperties().add(
    client.getObjectFactory().newPrimitiveProperty(
        "Name",
        client.getObjectFactory().newPrimitiveValueBuilder()
            .buildString("Product name")
));

// ReleaseDate (Edm.DateTimeOffset)
product.getProperties().add(
    client.getObjectFactory().newPrimitiveProperty(
        "ReleaseDate",
        client.getObjectFactory().newPrimitiveValueBuilder()
            .setType(EdmPrimitiveTypeKind.DateTimeOffset)
            .setValue(Calendar.getInstance()).build()
));

// Rating (Edm.Int16)
product.getProperties().add(
    client.getObjectFactory().newPrimitiveProperty(
        "Rating",
        client.getObjectFactory().newPrimitiveValueBuilder()
            .buildInt32(2)
));

// Price (Edm.Double)
product.getProperties().add(
    client.getObjectFactory().newPrimitiveProperty(
        "Price",
        client.getObjectFactory().newPrimitiveValueBuilder()
            .buildDouble(4.5)
));

Using complex properties on elements

Some entities can also use complex properties in addition to primitive properties. For our service, its the case of the entity type PersonDetail with the property Address.

In this case, we need to create a complex value with the method newComplexValue of the object factory. This returns an instance of type ODataComplexValue. We can add then primitive properties in the way than described in the previous section. The last step is to create the complex property itself based on a name and the complex value using the method newComplexProperty of the object factory.

Following code describes how to create a complex value and set it for the complex property:

ODataEntity personDetails = client.getObjectFactory().newEntity(
    new FullQualifiedName("ODataDemo", "PersonDetail"));

// PersonID (Edm.Int32)
personDetails.getProperties().add(
    client.getObjectFactory().newPrimitiveProperty(
        "PersonID",
        client.getObjectFactory().newPrimitiveValueBuilder()
        .buildInt32(1000)
));

(...)

// Address (Complex)
ODataComplexValue<ODataProperty> address =
    client.getObjectFactory().newComplexValue("ODataDemo.Address");
// Street (Edm.String)
address.add(client.getObjectFactory().newPrimitiveProperty("Street",
    client.getObjectFactory().newPrimitiveValueBuilder().buildString("street")));
(...)
// Country (Edm.String)
address.add(client.getObjectFactory().newPrimitiveProperty("Country",
    client.getObjectFactory().newPrimitiveValueBuilder().buildString("country")));

personDetails.getProperties().add(
    client.getObjectFactory().newComplexProperty("Address", address));

In the real world, data are linked together. Its also the case with OData entities. In an upcoming post, we will describe how to manage these links.

This entry was posted in Java, Olingo, REST and tagged , , , . Bookmark the permalink.

3 Responses to Manipulating data of OData v4 services with Olingo

  1. Pingback: Updating data links of OData v4 services with Olingo | Sandbox for the Web stack

  2. Luis says:

    I need to send and save an instance of an object of a class, the server is developed to receive the object.
    it is possible to send the object as a parameter?

  3. Andy says:

    Can you give an example of Deep Insert using Olingo?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s