Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Sunday, October 30, 2011

JOCU – The Alpha

I’ve been working on an OData reader in java for some time now, and I am ready to show people the first alpha.  There are some pieces missing, and I would prefer better ways of accessing some of the data.  But here it is.

The release only has the underived version of the JOCU project.  It allows for most of the functionality from the OData protocol (the main one missing is the data format, this uses XML data src as apposed to the json format).

Here is a code snipit I wrote that uses the API from the JAR library.

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import lkoutzas.jocu.shared.AbstractCatelogueData;
import lkoutzas.jocu.shared.AbstractEntity;
import lkoutzas.jocu.underived.ODataEntity;
import lkoutzas.jocu.underived.ODataLink;
import lkoutzas.jocu.underived.ODataRepository;


public class RunJOCUDemo {

public static void main(String[] args) {

System.out.println("Welcome to the demo of the JOCU odata reader!!");
System.out.print("Catelogues Start: ");
System.out.println(new Timestamp(System.currentTimeMillis()));

// create the odata repository
ODataRepository oData = new ODataRepository();
// set the URI for the location of the repository
oData.SetURI("http://services.odata.org/OData/OData.svc/");
// get oData Catelogue
List<AbstractEntity> categlogues = oData.FetchODataCatelogues();
System.out.print("End: ");
System.out.println(new Timestamp(System.currentTimeMillis()));
// dump out results to show it works...
System.out.println("Catelogues...");
for(int i=0;i<categlogues.size();i++)
{
AbstractEntity local = categlogues.get(i);
System.out.println(local.getAttribute("href"));
}
System.out.println();
System.out.print("Entities Start: ");
System.out.println(new Timestamp(System.currentTimeMillis()));
// create the odata repository
ODataRepository oData2 = new ODataRepository();
// set the URI for the location of the repository
oData2.SetURI("http://services.odata.org/OData/OData.svc/");
// set the catelogue for the oData repositpory
oData2.SetCatelogue("Categories");
// query or filter the data request (need to detail full list)
oData2.getQuery().top("2").select("ID,Name");
// get entities
AbstractCatelogueData entities = oData2.FetchEntities();
System.out.print("End: ");
System.out.println(new Timestamp(System.currentTimeMillis()));

System.out.println("entities...");
for(int i=0;i<entities.getEntities().size();i++)
{
ODataEntity local = (ODataEntity) entities.getEntities().get(i);
System.out.println(local.field("ID") + ": " + local.field("Name") + " links are: ");
for(int j=0;j< local.getLinks().size();j++)
{
ODataLink odataLink = local.getLinks().get(j);
System.out.println(odataLink.getTitle() + " - " + odataLink.getHref() + " ("+ odataLink.getRelationship()+")");
}
}
}

}


As you can see, the API is pretty easy to use and I think pretty good.  So, for the “bits not in the alpha”.


Firstly, there is a bug that will mean that XML structured elements (CDATA as an example) are not parsed correctly.  They get broken down into separate elements rather than a single blob.


Also, I would like to improve the manner that the data is being accessed.  It feels a bit clunky to me. I am not sure how I can improve it, but I would like to see what I can think of.


The last missing bit / bug is that the expanded entities within the querystring.  At the moment I think it would fail badly.  The API will allow it, but the data will likely either cause the call to fail or it will will be ignored.


Once these items are in the code, I am going to work on the derived version, which will allow strongly typed objects and (hopefully) reduce the size of the downloaded packet.


The link for the alpha is here.  Let me know your thoughts.

Sunday, March 6, 2011

JOCU – The Final Stretch

So, I have the basics of an XML parser completed, now I need to implement this to deliver what I am wanting, which is the Java OData Consuming Utility.  I am going to work on the loosely typed or underived version first, then I will implement the derived version.

Briefly, lets look at the functionality we can expect from the repository. 

string GetSource() / SetSource(string)
This will define what the source of the oData is.

bool GetMetadataRequired() / void SetMetadataRequired(bool)
This will set or get if the metadata is required for this repository

ODataEntities Fetch()
This will get the entities from the oData query

IODataQuery Filter(string)
Applies the filter URI convention to the source

IODataQuery SetEntityCollection(string)
This will define which collection that it is desired to get

IODataQuery GetEntity(string)
Gets a single entity from the collection

IODataQuery SetOrderBy(string)
Sets what the list is ordered by

IODataQuery Top(string)
Sets the number of entities that we want returned

IODataQuery Expand(string)
Sets which related entities to expand

IODataQuery Format(string)
Sets the format to return the data in (not used really for what I want, should I scrap it?)

IODataQuery Select(string)
Identifies which entity items to select, and related items

IODataQuery InlineCount(string)
Sets the inline count property on the data source

IODataQuery CustomURIElement(string)
Sets a custom element to the query that is sent to the OData source

string GetMetadata(string)
This will get the OData collection metadata entry

And, from the point of view of the entity we have the following:

string Get(string)
Gets the value of the key passed though

string GetMetadata(string)
Gets the metadata value for the key passed though

Most of this is derived from the OData URI conventions, with some basic access functions thrown in.  I think that this is all I need to implement, but to be honest I’m not sure.  I have a feeling I will be uncovering more than I expect as I start to tackle the implementation of the repository access, but I need to start somewhere, and this is the best place.  I am aiming to finish this off in the next month or so, but as I am doing this in my spare time to have some fun we shall see what happens.

Saturday, January 8, 2011

Running a single test with JUnit and Eclipse

So, I had a slight problem with using TDD in Eclipse.  Not a problem as such, more an obstacle that I needed to overcome.  What I wanted to do was to write a test, get that working, then re-run all the tests, check that the changes to the code hadn’t caused another error to correct, then move on to the next test.  I found a few odds and ends about how this could be done, but nothing seemed to work.

After some looking and seeing I was able to get this working.  Here’s how I did it.  For this example, I am using JUnit 4 and Eclipse 3.6.1 (Helios).  Please note, to see the images more clearly just click on the image.

Firstly, go to Run –> Run Configurations

Then, right click the JUnit node in the tree and select New

Enter the name for the run configuration (I have called mine XMLSourceRepository_GetTokensTest)

Select the Method that you would like to test (default is all methods).

Now, I have Android JUnit and Eclipse JUnit launchers, so down the bottom I need to press the hyperlink and the following dialogue box appears. Select the Use Configuration specific settings and then Eclipse JUnit Launcher.

And your done.  Press the run button to run the test, and now it is in your run and debug button menus

So there you have it.  Using JUnit and Eclipse Helios (3.6.1) I have been able to select a single test to run without the overhead of other tests being run as well.

Now, to me, this is rather complex and time consuming if you write a test, change the run configurations to add or alter an existing configuration, make a few changes to change the code, then have to do the whole process again.  It would be easier be able to do this via the source or a test list of some kind.  I am not saying that this isn’t possible, but I couldn’t get it to work.  If you know how to do that, please let me know so that I can correct this post with the easier way of managing tests!

Sunday, January 2, 2011

Java Open Data Protocol API

Recently, I have played with Open Data Protocol (OData) using Java and I am not entirely happy with the API’s that I have had to use.  So, in true developer style I am going to attempt to write my own.  Have called it JOCU (Java OData Consuming Utility). I figure that by doing this I will learn the OData Protocol, touch up on my Java coding, practice TDD and JUnit, and maybe play with GIT or some other source control.

Open Data Protocol

Now for some understanding.  The Open Data Protocol was put together by various organisations to surface data in a consistent way that was manageable cross platform.  It allows for updating and retrieving of data to the data store via the URI conventions.  I wont go into it in detail cause I am likely to get it wrong, and that isn't the idea of this post.  For more information, go to http://www.odata.org/.

So, on with the show… my first hurtle

I have started the API and have already come across something worth noting down.  I had written a function to get the source code for a file, called GetSource.  The original code is below:

public String GetSource(String URIForSource) throws  MalformedURLException, IOException  {

URL url = new URL(URIForSource);
HttpURLConnection URLConn = (HttpURLConnection)url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(URLConn.getInputStream()));

String str;
String result = "";
while ((str = in.readLine()) != null)
result = result + str;
in.close();
return result;
}

Now for HTML files and for static XML files this is fine.  However, when you use this for an OData source, it dies (returns a 400 Bad Request error).  I then thought that there was something wrong with my URL so I copied it into a browser and it worked!  I was left with the question: why would the URL work in a browser yet not in code?  After some investigating, I found that I needed to identify the types of responses that I would accept.  As a result, I added one line to my code and came up with the below:

public String GetSource(String URIForSource) throws  MalformedURLException, IOException  {

URL url = new URL(URIForSource);
HttpURLConnection URLConn = (HttpURLConnection)url.openConnection();
URLConn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
BufferedReader in = new BufferedReader(new InputStreamReader(URLConn.getInputStream()));

String str;
String result = "";
while ((str = in.readLine()) != null)
result = result + str;
in.close();
return result;
}

As you can see in line 5, I set the connection to accept xml, along with other types that I needn’t go into.  As a result, the code is now working perfectly (under what tests I have written to date that is).


Next is to manage the tokens that the XML returns.