Monday, December 14, 2009

Using JSON RESTfull Web Services in A Flex Application

Choice of JSON Library for Flex
After a few hours of googling, I have decided that the strongest candidate is the corelib library, which for ActionScript 3 is called as3corelib. It's hosted on Google code, although there are multiple references to it on Adobe website. However, none of these references pointed me to any trace of corelib on Adobe website. I wasn't able to figure out why. Leave a comment if you know the story behind.

It seems, that Flash Builder 4 comes with a HTTPService Wizard, which can import a JSON webservice, among other formats.

Limitations of Flash HttpService for RESTfull Webservices
The problem is that because FlashPlayer uses the browser for all networking operations, and Safari browser supports only Post and Get operations, HttpService doesn't support Put, Delete, Headers and Options operations. As a workaround, there is a library hosted on Google Code called RestHttpService, that can be used.

Using Eclipse IDE: Tips, Facts and Tricks

  • If a value gets stuck in Eclipse caches/preferences that doesn't make sense and you can't find a way to update to the new value using Eclipse GUI:
    • Search the workspace/.metadata folder for the obsolete value and correct it, esp. the .settings files. Don't touch binary files, unless you know what you're doing.
    • clean the Eclipse cache by starting exlipse, just once, with the first command line argument set to -clean
    • export preferences, switch to a new workspace and re-import the saved prefs.
    • reinstall Eclipse
    For more info see this great article.
  • The Project Delete doesn't delete any files from the project directory, not even from the .settings folder, unless you check the Delete files... checkbox. Question: is any information lost if I delete a project and then re-import it?
  • How to add a .jar file to classpath without using absolute paths? Follow these steps:

    • Go to Windows > Prefs > Java > Build Path > Claspath variable. Add a new variable pointing to the jar or to a folder, if there are many jars to add.
    • Go to Java Build Path of your project and click Add Variable. If you have specified a var pointing to a single jar, just select it and click OK. If you have created a var pointing to a folder, select it and click Extend. Then, select the jars you want to add (you can add them all in one step). Click OK.
  • How can I move project to another folder? For me this works:


    • Delete the project
    • Move the folder
    • Re-import the project
     

    Tuesday, December 8, 2009

    RESTfull Webservices Using Java with Introduction to JSON

    Introduction
    What are RESTfull or Rest web services and how can they be implemented in with Java? Also what is JSON and how to make a webservice that returns a JSON object?  This is what this blog is about. Specifically, first, about installing and running a sample RESTfull application available from Jersey project.

    What are RESTfull webservices? See this article. Or any other; there are many.

    Approach 1

    This approach uses one of the samples provided by the Jersey project and uses Maven to install the libraries. It's a bit heavy approach, but it works. Approach 2 below also uses Jersey, but is way lighter and simpler.


    Server Side
    I'm using Eclipse IDE with Glassfish Application Server. The steps for this configuration are:
    • Add Jersey and Jersey Documentation and Examples components to Glassfish using its admin console. Note, use GlassFish v3 Prelude version.  When I used GlassFish v3 Promoted Build, the Examples module was not showing in its Update Tool.
    • Restart the GF server.
    • Find the Jersey samples in GF_Home/glassfish/jersey folder.  Go into helloworld-webapp folder. You should see a .pom file there, that is used by maven. From that folder, run "mvn clean package" command. Install maven if needed.
    • Maven installs many files, and for me it ended with an error saying it can't read the glassfish-embedded-all-3.0-Prelude-Embedded-b10.jar file.  I have located this file in the maven repository (Documents and Settings/user/.m2/...) and found that it was broken.  I had to download it manually from internet (search by the file name).
    • Rerun the mvn command. It finished successfully and created a war file in the target directory.
    • Open GF console, and from Web Applications do a deploy. Point to the above war file and click OK. That did it.
    • Point your browser to http://localhost:8080/helloworld-webapp/helloworld. The string "Hello World" appeared.
    Analyzing the Sample
    After I had the sample running, I have exploded and analyzed the contents of the generated war file. The file had a class file implementing the resource plus two more short config files.

    sun-web.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" "http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
    <sun-web-app error-url="">
      <context-root>/helloworld-webapp</context-root>
      <class-loader delegate="true"/>
      <jsp-config>
        <property name="keepgenerated" value="true">
          <description>Keep a copy of the generated servlet class' java code.</description>
        </property>
      </jsp-config>
    </sun-web-app> 

    web.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
        <servlet>
            <servlet-name>Jersey Web Application</servlet-name>
            <servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
            <init-param>
                <param-name>com.sun.jersey.config.property.packages</param-name>
                <param-value>com.sun.jersey.samples.helloworld.resources</param-value>
            </init-param>
            <load-on-startup>1</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>Jersey Web Application</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    </web-app> 

    Approach 2
    Approach 1 worked OK, but I wasn't able to apply the sample to deploy an application of my own. And so I searched for a tutorial that uses Eclipse and possibly no Maven. I have run into this mini tutorial which worked great. I was able to drop this application into a Tomcat 6.0 and GlassFish 3 Prelude containers and it worked in both fine.
    Also, this example illustrates how the service can be implemented for different response formats, leaving to the requestor to decide which one to use.

    JSON
     JSON is simply a format, in a way an alternative to XML, that is especially useful for (de-)serializing objects, for example in order to send them over internet. The format is derived from JavaScript native format, but it became language neutral.  Here's a sample:
    {"name":"Alfred Alfredo","age":"47"}
    A nice and concise description of JSON syntax is on JSON website. To have your RESTfull webservice return a JSON object, download and add to the project jettison.jar that Jersey uses to create a JSON object. Now, for the sake of the demonstration, say that the webservice need to return a Person object:

    @XmlRootElement
    public class Person {
     public String name;
     public int age;
     
     public Person() {} // required by JAXB
     
     public Person(String name, int age) {
      this.name = name;
      this.age = age;
     }
    }

    Thanks to the annotations in this class, in order to return a JSON object we just need to define a method:

    @Path("/person")
    public class PersonResource {
      @GET  @Produces("application/json")
      public Person get() {
       return new Person("Alfred Alfredo",47);
      }
    }

    The JSON object as specified above, in the first part of this section will be returned. You can test it using a browser by pointing it to http://localhost:8080/jersey1/rest/person, where jersey1 is the context of my web app, rest is my servlet mapping and person is what I defined with @Path in my RESTful resource class.

    Tuesday, December 1, 2009

    Presenting Business Objects Reports in PDF Format Using Web Services

    Suppose you have a web application, whether of an RIA type or Web 1.0 type, that needs to present a report. One of the attractive options, is to have the report show in the browser as a PDF document. It seems an interesting option, because most users already have Adobe Acrobat Reader installed and are familiar with it. They usually know how to navigate through the document, print it or save it for emailing or just for later use.
    If your organization is also one of the many that use Business Objects (BO) as their standard reporting technology, the solution presented below may be for you.

    Since version XII, the Business Object Enterprise server is bundled and by default installs the web services module which allows to access reports via SOAP web services. Here's the solution:
    • The web application requests a report by calling the special reporting servlet, passing to it the report ID and required parameters.
    • The servlet uses web services to login to BO server and request the report, which then is returned to the client and displayed in a new browser tab or window in Acrobat Reader.
    The example below, shows the solution for the case when the client is a Flex application and the servlet is implemented in Java.

    Reporting Servlet
    The servlet consists of the following modules:
    • login module (login to BO server)
    • report parms module (requests a list of the parameters required by the report and prepares them)
    • report viewer module (configures the request to return the report in PDF format)
    • retrieve and deliver module (requests the report from BO server and sends it on its way back to the client)
    Login Module:
    
      SessionSoap session = new SessionSoapProxy("http://crystalbo:8080/dswsbobje/services/session");
      EnterpriseCredential credents = new EnterpriseCredential();
      credents.setLogin(businObjectsLoginName);
      credents.setPassword(businObjectsLoginPwd);
      SessionInfo si = session.login(credents);
      if( si == null ) { login failed... }
      // Instantiate Report Engine
      ReportEngineSoap rptEngine = new ReportEngineSoapProxy();
    

    Monday, November 16, 2009

    FlashPlayer and Flex Security Restrictions When Consuming a Webservice

    Here our system configuration (scenario):
    • Server A: hosts your Flex application
    • Server B: hosts a webservice consumed by your Flex application
     In order for your Flex application to be able to consume the webservice in above scenario, you have two options:
    • Place in the root of the application server on Server B a crossdomain.xml file specifying: allow-access-from-domain: server-A-domain, or
    • Use the Proxy service on Server A, which is part of LCDS and BlazeDS dataservices.

    Tuesday, November 10, 2009

    Google Voice: Can I Make Calls and Receive Them Without Using My Air-time Minutes?

    It's tricky, and I have wasted $55 by not understanding this. You always can make free calls to continental US if you place the call from the GV website. But, how about calling from you cell phone?

    Scenario: GV Account with GV Mobile Application
    If you:
    • open a Google Voice (GV) account and add you cell phone number to it
    • download to your mobile device a GV application (I'm using Android, G1)
    • make a call, or receive, a call selecting Google Voice for this, when asked,  
    The call will use your minutes! I have experienced this and it costed me. I know.

    Scenario: As Above with myFavs
    If you:
    • have myFavs or a similar service on your cell phone plan, and 
    • you add your GV number to your favs
    • receive a call or call you GV voice mail: your minutes won't be used
    • place call: your minutes will be used
    Scenario: As Above with A Twist
    If you add to your favs also the number that GV calls when you initiate a call, no minutes will be charged. However, for some reason, this number changes. So, this is not a robust solution.

    Saturday, October 31, 2009

    Why TDD Rather Than Traditional QA's Writing Tests

    First, I describe what is TDD. Then, I present a story that lead me to writing this article.  But if you don't care about stories, just skip to Conclusion and Resources


    What is TDD?
    I'll describe TDD not with my own words but with a few selected excerpts from this resource:
    • The practice of maintaining automated unit test suites has gained widespread acceptance over the past decade to the point where most developers today either engage in some amount of test writing or at least feel bad for not doing it.
    • To prevent regression, developers must provide a set of tests that exercise an application top-to-bottom and end-to-end (front-end to back-end), but anecdotal evidence suggests that even automated tests covering as little as 50% of the code can effectively guard against regression in many applications.
    • Competent developers either conform to a test-first discipline in which small test harnesses are built to exercise an API before the API itself is even implemented, or else employ a code-a-little-test-a-little (CALTAL) approach in which each unit of code developed is tested immediately after its compiled.
    • Most build systems, such as ant, provide direct support for running test suites as part of the application build process, and continuous integration systems, such as Cruise Control or Hudson, kick off such builds automatically each time code is committed to the team's version control system


    Situation
    Recently, I ran into project OpenSatNav. It's an open-source version of AndNav2, that is navigator application for Android OS based on OpenStreetMap. Great project, still pretty young, but dynamically expanding. I watched a few issues being fixed by the developers involved, and noticed that the process of findind a solution was a bit erratic. There were several attempts to guess a solution, and guesses were not perfect, but then there were a few better guesses.  Some NullPointException bugs cropped out after a few days and were fixed. Still, some issues were reported, but never reproduced, so by the token "it doesn't show the problem anymore, so let's close this issue", the issue has been closed. What was obvious to me, is that the solution is not necessarily correct. The testing was done manually and without even any systematic approach.

    Spring into Action
    It was obvious to me that what was definitely missing, was the automated testing, especially unit testing. I tried to step in and encourage unit testing. The idea of TDD, or any unit testing that I proposed several times was for the project team like a fairy tale about a bad wolf. But the developer team and the project lead were friendly and not exclusive.The lead-developer on this issue, responding to my requests, did include a well defined test-scenario with the fix code. I thought: it's not bad, I'll step in and write a unit or functional test for this fix. I have experience with TDD for Android, Java, GWT and Flex projects.

    Result
    It took me time (I have a full-time job and four children ages 4 - 19, plus, I took this as an opportunity to review the currently best practices for testing for Android OS), but finally I got to writing the test. And here's what I have found, which may be very well what also you experience is in this matter.  While writing a unit or a functional test for your own fix or new feature is a fun and a relatively straightforward activity, writing a test for a code written by someone else, is neither much fun nor simple. You end up reverse engineering the whole part of the system that surrounds the part where the fix was made.

    Conclusion
    Simple. Write your own tests. This, was for me always fun and an enlightening experience. And, I think, my design and coding have improved because of the tests I wrote. Tests for my own fixes.  Tests written immediately after I have written the code (CALTAL), or even just before I have written the code.

    Resources
    The following are useful for getting quickly to speed with TDD, esp. for Android OS development: