Stage 1

Enabling Google Android to consume SOA oriented store business services.

Week 1

The following has taken place between the 25th of April and May 3rd 2009

Tuscany Markmail

First contact with tuscany markmail [1] and quick review of mentor’s posts related to the projet as far as development and bugs issuing are concerned.

Alternate development environment

I used to perform developments on a dual boot with the project’s data synchronized at both sides with a subersion repository. In case one of the OSes messed up, i can still keep on track with coding while fixing the issue.

Performed tasks:

  • Format the existing rusted ubuntu hardy
  • Download and install of Ubuntu Jaunty
  • Installation of needed dev tools (java, subversion, android sdk 1.5, eclipse ganymede + plugins (Android Developer tools, Sublipse), maven.
  • SVN checkout of the java tuscany repository
  • Maven built started but started but not terminated yet

Tuscany Android Patch

Investigation on how to get the shopping cart service consumed from android using the atom binding.
Fact: Android don’t provide yet any implementation of the Atom publishing protocol specifiations. With Luciano, we agreed couple of weeks ago (even before GSOC09 results to go for the Apahe Abdera project [2].

Plan: (Recquire mentor’s validation)

  • Import needed Abdera’s jars to the Android project.
  • Follow instrutions in [3] to implement the shopping cart items posting via the Atom publishing protocol in order to retrieve later the shopping cart total using JSON.
  • Week 2

    Continuous efforts on cart’s item posting via an atom binding (04-05-09 / 10-05-09)

    - I created a package structure like the one done for json: services.atom.abdera.AtomAbdera. This class implements a post item method, which will build an atom entry from the Item object it receives as arguments and post it to an URI. The post will be made via an “AbderaClient” object.
    Butttttttttttttt as Abdera uses J2SE’s apache http client, while it’s already natively supported on Android ==> Conflicting packages and classes names

    Alternative to Abdera

    How?: Parse the atom as xml and post it to the Cart servlet using android native classes only.

    HttpPost httpost = new HttpPost(ServiceURI);
            HttpResponse response;
            List<NameValuePair> atomelyItem=new ArrayList<NameValuePair>();
            atomelyItem.add(new BasicNameValuePair("content","<entry xmlns='http://www.w3.org/2005/Atom'>" +
             "<title>item</title>" +
             "<content type='text/xml'>" +
              "<Item xmlns='http://services/'>" +
              "<name xmlns=''>" + item.getName()+ "</name>" +
             "<price xmlns=''>" +item.getPrice()+"</price>" +
              "</Item></content></entry>"));
            try {
                httpost.setEntity(new UrlEncodedFormEntity(atomelyItem, HTTP.UTF_8));
                response = client.execute(httpost);
                Log.e("Atom entry post", response.getStatusLine().toString());
            } catch (UnsupportedEncodingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Log.e("TUSC","enti");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                Log.e("TUSC","resp");
            }

    This was fine, but the http response returned INTERNAL_SERVER_ERROR. I was running it from android sdk v1.1. The web store also returned a null pointer exception, i lost after migrating to android 1.5. Even the TabActivity was bugging under Android 1.5. I then tried to create a simple android project, with a single activity, and perform the (xml)atom post. Still have the INTERNAL_SERVOR_ERROR, but no sign of the null pointer exception. To reproduce it, i created a quick test.html with the following content:

    <form method="post" action="http://lkster:8080/ShoppingCart/Cart">
    <input type="hidden" value="<entry xmlns='http://www.w3.org/2005/Atom'><title>item</title><content type='text/xml'><Item xmlns='http://services/'><name xmlns=''>Orange</name><price xmlns=''>$35</price></Item></content></entry>" name="entry">
    <input type="submit" value="go!">
    </form>

    And after hitting the go! button it now prints in the browser the exception:

    HTTP ERROR: 500
    INTERNAL_SERVER_ERROR
    RequestURI=/ShoppingCart/Cart
    Caused by:
    java.lang.NullPointerException
        at org.apache.tuscany.sca.binding.atom.provider
    .AtomBindingListenerServlet.doPost(AtomBindingListenerServlet.java:604)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
        at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:487)
        at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:362)
        at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:181)
        at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:726)
        at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:139)
        at org.mortbay.jetty.Server.handle(Server.java:324)
        at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:505)
        at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:842)
        at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:648)
        at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:211)
        at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:380)
        at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:395)
        at org.apache.tuscany.sca.core.work.Work.run(Work.java:63)
        at org.apache.tuscany.sca.core.work.ThreadPoolWorkManager$
    DecoratingWork.run(ThreadPoolWorkManager.java:215)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at java.lang.Thread.run(Unknown Source)
    Powered by Jetty://

    How to solve it? No idea yet!! I then got back to the ‘challengeful’ solution: Abdera!!

    Port Abdera onto Android?

    I converted Abdera sources (abdera-core, abdera-i18n, abdera-client) to android project in order to resolve missing imports and their dependecies, of course after removing jdk references. After digging docjar [4] (very interesting for open source java classes implementation), and tweaking some classes (commenting some methods in order to reduce the list of classes to import), i ended up with the following list:

    com.sun.activation.registries
    .LogSupport.java
    .MailcapFile.java
    .MailcapParseException.java
    .MailcapTokenizer.java
    java.awt.datatransfer
    .DataFlavor.java
    .MimeType.java
    .MimeTypeParameterList.java
    .MimeTypeParseException.java
    .Transferable.java
    .UnsupportedFlavorException.java
    javax.activation
    .ActivationDataFlavor.java
    .CommandInfo.java
    .CommandMap.java
    .DataContentHandler.java
    .DataContentHandlerFactory.java
    .DataHandler.java
    .DataSource.java
    .MailcapCommandMap.java
    .MimeType.java
    .MimeTypeParameterList.java
    .MimeTypeParseException.java
    .SecuritySupport.java
    .UnsupportedDataTypeException.java
    .URLDataSource.java
    javax.xml.namespace
    .QName.java
    javax.xml.transform
    .Result.java
    .Source.java
    javax.xml.transform.stream
    .StreamResult.java
    .StreamSource.java
    org.apache.commons.codec
    .BinaryDecoder.java
    .BinaryEncoder.java
    .Decoder.java
    .DecoderException.java
    .Encoder.java
    .EncoderException.java
    .StringDecoder.java
    .StringEncoder.java
    org.apache.commons.codec.binary
    .Base64.java
    .Hex.java
    org.apache.commons.codec.net
    .BCodec.java
    .QCodec.java
    .QuotedPrintableCodec.java
    .RFC1522Codec.java
    .StringEncodings.java

    Happy to have resolved the dependencies, i attached the sources and at the build i got a “gbish”:

    [2009-05-08 16:10:54 - abdera-core]
    trouble processing "java/awt/datatransfer/DataFlavor$1.class":
    [2009-05-08 16:10:54 - abdera-core]
    Attempt to include a core VM class in something other than a core library.
    It is likely that you have attempted to include the core library from a desktop
    virtual machine into an application, which will most assuredly not work. If
    you really intend to build a core library -- which is only appropriate as
    part of creating a full virtual machine binary, as opposed to compiling an
    application -- then use the "--core-library" option to suppress this error
    message. If you go ahead and use "--core-library" but are in fact building
    an application, then please be aware that your build will still fail at some
    point; you will simply be denied the pleasure of reading this helpful error
    message.
    [2009-05-08 16:10:54 - abdera-core] 1 error; aborting
    [2009-05-08 16:10:54 - abdera-core] Conversion to Dalvik format failed with error 1
    [2009-05-08 16:11:04 - abdera-core]

    It seems like oscar encountered this too last year. I read some of his posts on mail-archive, and the solution seems to be a rebuilt of android.jar

    Android.jar rebuilt

    I then decided to perform a rebuilt of android.jar with the classes listed above. After all, that could be a training for the host-android part of the project, on which i’ll surely have to perform such tasks. How to perform the build? I’ve recently heard of google releasing android’s sources, and I went to [5], and guess what? Building android sources under windows is not yet supported!! A chance i set up my jaunty dev environment last week. Well, i followed carefully the steps quoted on the page. After getting the sources via “repo sync”, i then created the directory android-sources/dalvik/libcore/abdera_dependencies for the classes i listed above. I then launch a make on android sources at the top level, and was hopefully waiting for an android.jar to appear in the “out directory”. Instead i got nothing like that after hours of build.
    By the same time, i’ve been hopefully searching for android.jar sources, and i got two zips:
    - android-1.5-cupcake-src.zip from [6]
    - androidsrc from [7]
    I’ve tried to create a simple java project with each of them, but even before removing jdk references, eclipse was already trying to rebuild the workspace, process that take more than hours, and still at 1% with increasingly number of errors (i stopped the massacre at about 20000 errors). I guess, i should now get back to Tuscany’s community to ask for help. I think they already have performed this before!

    Issues to be resolved:

    • How to perform a rebuilt of android.jar?
    • how to resolve the NullPointerException above?
    • I’ve “accidentally” been on [8], and i suspect i’ll have to deal with. Can someone brief me on it please? Thx.

    Nextly

    Next week, i’ll be focusing more on the host-android part.

    Week 3

    The following has taken place between the 11th and the 17th of May 2009
    All services are now consumed…

    Android Store progress

    Services side:

    I’ve finally found a way posting and parsing the atom feeds exchanged between the android client and the web store using android’s native DefaultHttpClient, http client methods (HttpPost, HttpGet, HttpDelete), and the SAX API. The atom feed is then considered like a simple XML stream.
    The following methods have been implemented for the ShoppingCartProxy class:

    • addItem()
    • clearCartContent()
    • getItems()
    • removeItem()

    And a new package named services.atom.xml has been created with the following classes:

    • AtomXML wth the following static methods:
      • getItems()
      • performDelete()
      • postItem()
    • CartItemHandler which is used to parse the atom feed.
    • UI side

      I spent couple of days tweaking android to create a custom layout for the catalog and the shopping cart’s ListViews in vain. In fact, i was trying to make it look like what’s on the picture below so that only the buttons will be clickable. I finally ends with nothing, and i think, i’m finally going to make each ListView row directly clickable, but with a small imageview at its right side (red cross for the shopping cart, and green plus for the catalog). I guess it’ll look on that way a little bit prettier than now.


      custom_layout

      Porting Tuscany’s module onto android

      I’ve been quickly briefed on the retrotranslator, and his feature of converting Tuscany’s module to get working on android. Sounds very amazing how it may automatically handles apis android doesn’t support natively, and am already looking forward getting deeper into it. Well, how does it work? Is there any location for the source code? I guess i’ll have to learn a lot from Oscar about that!!
      Seems like another alternative will be to rewrite each of the extensions, or should i say adapt each module’s source code to the android platform and limit non supported API imports. In that case, it will be interesting to build a priority list of the extensions to be ported, and after importing each one, implementing a use case to illustrate it or an adaptation of any existing use case already provided for desktop environment.
      I’ll be analyzing both ways till the end of May, and according to the constraints i’ll choose with the community’s help a way dealing with all this.

      Week 4

      The following has taken place between the 18th and the 23rd of May 2009
      Final fixes to UI

      Rewriting the catalog Activity

      At launch: The catalog items are retrieved using Android’s Native JSON RPC binding to the Catalog Service.


      catalog
      fig#1

      While the shopping cart’s tab may look :
      Either like (see below) if the shopping cart is currently empty at the server side
      shop_emptyfig#2
      Or like (see fig#3) if in another session or from another client, items have been added to the shopping cart. HttpGet is used there to receive the shopping cart content via an atom binding to the ShoppingCart Service, and the SAX parser helps parsing the received feed.

      After clicking on an item in the catalog list, it’ll be added in the shopping cart list with an associated key generated by the server. Items are encoded in xml and sent via HttpPOST using again an atom binding to the ShoppingCart Service. Consequently, the entity to be sent has its contentType set to atom/xml as Android doesn’t support Atom yet. As on the webstore, items can be added as many times as the user desires it. Below is the result of five consecutives clicks on different items.
      shop_full
      fig#3

      You should also notice that the shopping cart total has been calculated. This is the result of the “Total” service invocation via JSON RPC.

      Let’s now try to remove the second occurrence of “Apple”. Clicking on an occurrence from the shopping cart send an HttpDelete request to the ShoppingCartService. The shopping cart’s list is automatically refreshed, and now looks like this:
      shop_del
      fig#4

      Finally, the erase cart button is used to delete all items from the shopping cart. After clicking on it, the user is requested a confirmation, before the server side deletion is proceeded. And after performing the delete, the shopping cart tab looks like in #fig2

      shop_erase
      fig#5

      Todo List for next week

      • Run sample calculator on android and build an issues list
      • Test the 2 known ways resolving the issues:
        • Use the retranslator [9]
        • Rewrite needed stuffs

      Code Hosting

      Thought about projet repository creation at Google Code Hosting (unless ASF provide another way doing this)
      Projet name: tuscanystoreandroidgsoc09

      References

      [1]: http://tuscany.markmail.org/
      [2]: http://abdera.apache.org
      [3]: http://cwiki.apache.org/ABDERA/client.html
      [4]: http://www.docjar.com/
      [5]: http://source.android.com/download
      [6]: http://blog.marvinware.com/
      [7]: http://androidforums.com/android-developers/1045-source-code-android-jar.html
      [8]: http://svn.apache.org/repos/asf/tuscany/sandbox/mobile-android/retrotranslator_readme
      [9]: http://retranslator.sourceforge.net