Monday, May 29, 2017

How To Consuming WCF Data Service(OData) in Android/Java

WCF Data Service(previously known as ado.net Data Service) has been developed by Microsoft to support the Open Data Protocol(OData) . OData enables you to expose your data as resources that are addressable by URIs. This enables you to access and change data by using the semantics of representational state transfer (REST).

There are basically 2 libraries that support WCF Data Service for java and android i.e Restlet and OData4j.

However, Restlet being the popular one was not upto the mark for me. It invovles a lot time in setting up and is a lot slower. OData4j is comparatively new but it's much easier to use and even faster than Restlet.

As you have already guessed I would be showing how to use OData4j library to consume a WCF Data Service.

Step - 1 Download the latest OData4j library. At this point the latest version is 0.7. Extract it.

Step - 2 Click on the project> Select Properties> Java Build Path> Libraries Tab> Add External JARs > Navigate to your extracted folder and select odata4j-0.7.0-clientbundle from the bundles sub-folder. Now, on the Order and Export Tab checkmark your imported library.

The service that I would be using is a svc service from Odata.org itself http://services.odata.org/Northwind/Northwind.svc/.
It will look something like this:


Step - 3 Create a new Project or use your existing and design the layout for your web service consuming activity.

layout-wcf_example.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical" >

 <Button
 android:id="@+id/mybtn"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:text="Call WCF" />

 <ListView
 android:id="@+id/mylistview"
 android:layout_width="match_parent"
 android:layout_height="wrap_content" >
 </ListView>
 
</LinearLayout>
 
 

Now decide which property to extract from which table. You can view data from a table by apending the table name at the of the URL. This is what is displayed when we append Categories at the end of our URL i.e http://services.odata.org/Northwind/Northwind.svc/Categories.

Note: If you are not able to view the xml and seeing AtomPub format instead you can turn off feed reading for your browser. In Internet Explorer, Go To Tools> Internet Options > Content Tab> Feeds and Web Slices> Settings and then uncheck "Turn on feed reading view". Restart Internet Explorer.

For this example, we will extract the CategorID and CategoryName.

So here is the much-awaited code:

 ODataConsumer c = ODataJerseyConsumer
                    .create("http://services.odata.org/Northwind/Northwind.svc");
            List<OEntity>  listEntities = c.getEntities("Categories").execute().toList();
            System.out.println("Size - " + listEntities.size());
            if (listEntities.size() > 0) {
                for (OEntity entity : listEntities) {
                    categories.add(entity.getProperty("CategoryID").getValue()
                            .toString()
                            + " - "
                            + entity.getProperty("CategoryName").getValue()
                                    .toString());
                }
 
 

We are creating a ODataConsumer object with our service URL. Then we are specifying our entity from which we want to extract the data. Finally, looped all the entries we receive and extracted the required values and added them to ArrayList. You can perform all OData query functions and filter expressions .
You can also retrieve more information about a Property. H
ere are some sample queries:
? List listEntities = c.getEntities("Categories").expand("Products").top(5).execute().toList();
? System.out.println(""+entity.getProperty("CategoryName").getType ().getFullyQualifiedTypeName());

Here's the whole java class:
WCFExample.java

import java.util.ArrayList;
import java.util.List;

import org.odata4j.consumer.ODataConsumer;
import org.odata4j.core.OEntity;
import org.odata4j.jersey.consumer.ODataJerseyConsumer;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;

public class WCFExample extends Activity {
Button call;
ListView list;
ArrayList categories;
ArrayAdapter adapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate (savedInstanceState);
setContentView(R.layout.wcf_example);
setTitle("WCF Example");

call = (Button) findViewById (R.id.mybtn);
list = (ListView) findViewById(R.id.mylistview);
categories = new ArrayList();

call.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto- generated method stub
new callService().execute();
        }
    });
}

 public class callService extends AsyncTask<Void, Void, ArrayList<String>> {

  @Override
  protected ArrayList<String> doInBackground(Void... params) {
  // TODO Auto-generated method stub

  ODataConsumer c = ODataJerseyConsumer.create("http://services.odata.org/Northwind/Northwind.svc");

  List<OEntity> listEntities = c.getEntities("Categories").execute().toList();

  System.out.println("Size - " + listEntities.size());

  if (listEntities.size() > 0) {
      for (OEntity entity : listEntities) {
          categories.add(entity.getProperty("CategoryID").getValue()
          .toString()
          + " - "
          + entity.getProperty("CategoryName").getValue()
          .toString());
          }
      }
  return categories;
  }

  @Override
  protected void onPostExecute(ArrayList<String> result) {
  // TODO Auto-generated method stub
  super.onPostExecute(result);

  adapter = new ArrayAdapter<String>(WCFExample.this,
  android.R.layout.simple_list_item_1, result);
  list.setAdapter(adapter);
  }
 }
}

I have just created a list to show the output and used a AsyncTask to perform the functions but you can choose to create a new thread or a new service but never use UI thread. Don't forget to Register your Activity in your Manifest file and also add the following permission:

<uses-permission android:name="android.permission.INTERNET" />

You have any problem you can comment.
Also see the second part: Write Functions through WCF Data Service(OData) in Android

No comments:

Post a Comment