Thursday, November 10, 2011

Java One 2011 - Second Part

Hello everyone, It's been a month since JavaOne11 in San Francisco and I want to share with you some pictures about the event. On the left you can access some of the pictures I took during the event and around the city.

Day one was on Sunday Octuber 2nd 2011, I arrived quite late because I lost my flight from Orlando (MCO) to San Francisco (SFO). My original flight was a non-stop flight but  for a little problem with my bag at the airport I had to flight to Denver (DEN) and then to Reno (RNO) and then to San Francisco (SFO)... :-S
BTW, if you are planning to go to JavaOne12, try to take with you a non-checkable bag...

Anyway, I arrived at about 4pm and grabbed my badge and conference materials (water bottle, JavaOne bag, JavaOne alumni jacket, t-shirt, pen, etc). I lost the JUG's meetings but I could see the Duke's choice awards presented at the Mason Steet Café. Good food, drinks, music and networking for all!

Day two was Monday Octuber 3rd 2011, the day started with the JavaOne technical Keynote lots of information including Java SE (Java7 and Java8),  JavaFX (2.0), Java EE (cloud) and Java ME (embedded). Also, there was the Intel's Keynote presenting the performance of Java on Intel's machines. During the day, I attended several conferences including:
  • Choosing Your Java Web Framework: A Comparison
  • Java ME LWUIT 1.5
  • Instant Cloud: Just Add Java
At the end of the day, I had this LatinAmerica (LAD) Cocktail Reception so I started to walk to the address I was informed, the rain started and I couldn't avoid it... I arrived all wet and realized that the event had moved to another place, away from the place I was at... x-(
So, I missed the LAD Cocktail Reception and went to the OTN Night at Yerba Buena Gardens... again good food, drinks, music, nice show and fun with the OTN guys.

Day three was Tuesday Octuber 4th 2011, great free cappuccino at the Buzz House located at the Mason Street Café in my way to the Zone for a several amount of conferences during the day, including:
  • Java Strategy Keynote
  • What You Need for Building Cool Enterprise Applications with JSF
  • Java EE Web Security by Example
  • Building a Home Security System with Java
  • Top 10 Free Tools and Libraries for Building Better Java ME Applications
  • Web Services Security
  • Beginning Java EE 6 HOL (Hands on Lab)
From the list, the conferences I liked the most were: Java EE Web Security by Example and Top 10 Free Tools and Libraries for Building Better Java ME Applications.

This was a busy day, the hands on lab ended at 9pm, but not too late for a few free beers and some networking at the Buzz House. I met two other attendees while drinking my beer, one from Netherland and the other one from L.A. Surprisingly enough we found an Oracle Financial Services private party and we were able to go inside for more free beer, food, drinks and music YEAH!!!

Day Four was Wednesday Octuber 5th 2011, a day with not to many conferences (at least on my schedule) but perfect to go to visit the Demoground and some other places around the Zone, were you could find pinball games, tabletop games, grab some candies and hang out spaces. The conferences I attended that day were:
  • Refactoring Java EE 5 Code to Take Advantage of Java EE 6 Features
  • Project Coin in Action: Using New Java SE 7 Language Features in Real Code
  • Rethinking Best Practices with Java EE 6
I liked the Project Coin conference where I could see the new changes in the JDK 7 and was great source of information because I had the Java7 Event in Cali on November. The Demoground is a space where you can see demos about java technology: glassfish server, LWUIT, Java Card, etc. And is next to Java Exhibition Hall where you could get some answers from tech companies and also some souvenirs from them.

At the end of the day, we had the Oracle Appreciation Event featuring Sting and Tom Petty and the heartbreakers for great music, food, drinks... you know... great time! Oracle provided transportation to and from Treasure Island, where the event was run. I had to go back early, because my presentation was on the next day and I wanted to practice a little more...

Day Five was Thursday Octuber 6th 2011, my presentation day!! I was So nervous about it that I didn't attend any conference before my presentation. When I was practicing a little more, I heard about Steve Jobs death, so sad...
There were about 20-30 attendees at the conference room. The presentation went well, few questions at the end but people seemed to like it. I definitly will try it again for JavaOne12 and I will improve some things to ensure a better presentation.

At the end of the day we had this event called It's a Wrap at Yerba Buena Gardens and just like the other events we had good food, drinks, music and networking.

So, was it worth it to attend JavaOne11? YOU BET!! tons of information, directly from the people who is in front of the Java Technology wheel, good networking and great time!!
I think this year was better than the last one, although there are some things that can be improve for 2012 like the wireless network around the event.

I stayed an extra day in San Francisco in order to make some tourism around the city before going back home. Great city, small, easy for walking around, nice views around the bay, bring umbrella and jacket.

see ya!

Sunday, October 30, 2011

Java 7 Event Cali-Colombia

Hello all, I just came back from vacations and I just want to let you know that we are having a Java 7 event in Cali, Colombia, so if you are around, please come and join us. I will be speaking at the event presenting the Colombia Java Users Group and talking about Project Coin.

The information of the event is as follows:

LanguageSpanish
WhereIcesi University
Jefferson Smurfit room
Cali, Colombia
WhenNovember 1st 2011
4pm-6pm (GMT-5)

Links with more information (in spanish):

Colombia Java Users Group official web site
Icesi University, Computer Engineer FB page

See ya!


Friday, September 9, 2011

Java One 2011

Hello all,


On October 2–6, 2011, I'm going to be at JavaOne checking out the latest product and technology demos, meeting with fellow developers and industry experts, and learning about all things Java.

Better still, I'm going to be speaking at the event. Next is the information of my presentation:



Session ID: 24102
Session Title: Java ME and You: Discovering the Power of Mobile Masses' Inputs
Venue / Room: Parc 55 - Cyril Magnin I/II/III
Date and Time: 10/6/11, 12:30 - 13:30

"Nowadays people are connected to the network at all times via their mobile devices. This opens a huge number of possibilities for developing social network applications, because it enables you, as a developer, to create mobile applications that can deliver real-time information about anything. Imagine that your users act like sensors of a system: they send updates about the system and its behavior, and other users can benefit from it. In this session, you will discover how the users of a public transportation system in a developing country can access real-time information about the behavior of the system when this information is submitted by other users via their mobile devices with Java ME".

So I hope you can join me.

As always, JavaOne is the must-attend developer event of the year. I'm certainly going to be there, and I look forward to meeting you there, too.

High-level benefits of attending JavaOne
  • Improve your working knowledge and coding expertise
  • Choose from more than 400 sessions, including technical sessions, BOFs, keynotes, and hands-on labs
  • Learn from the world’s foremost Java experts
  • Follow in-depth technical tracks to focus on the Java technology that interests you most
  • Meet with fellow developers in formal and casual settings
  • Enjoy world-class networking and entertainment events


see ya soon!


Saturday, September 3, 2011

Google Static Maps API and JavaME

Whether you need a map for your location based application or just for fun, you can use the easiest way ever: Google Static Maps API. In this post, we are going to see how you can get a Map as an Image from a latitude and longitude point. The latitude and longitude can be obtained using Location API which we won't discuss in this post.

When writing this post, I realized there is some license restrictions in the use of Google Static Maps API in mobile Apps... I am posting it anyway just for research purposes, but I must warn you about this restriction:



Google Static Maps API Quick Review
This API lets you get an Image based on a URL and several parameters you can pass in to obtain a personalized map. You can play with the zoom, type of map, size of the image (width, height), markers at locations of the map, etc. There is a limit you have to keep in mind, the use of the API is subject to a query limit of 1000 unique (different) image requests per viewer per day, which is a lot of images... but if you need more, there is also a Premium license. For more information:


OK, what we do is the following:
  • Create a method that receives a latitude and longitude point and the size of the image as parameters.
  • Request the map image using the URL: http://maps.googleapis.com/maps/api/staticmap, and adding some parameters.
  • Create an Image object and return it, so we can show it on screen.

Hands on Lab
Following is the method we were talking about. It has parameters for the latitude and longitude, and also for the width and height of the image we are requesting. The latitude and longitude can be retrieved using Location API, and the width and height can be retrieved using the Canvas class.

public Image getMap(double lat, double lon, 
                                int width, int height) 
throws IOException 
{
    String url = "http://maps.google.com/maps/api/staticmap";
    url += "?zoom=15&size=" + width + "x" + height;
    url += "&maptype=roadmap";
    url += "&markers=color:red|label:A|" + lat + "," + lon;
    url += "&sensor=true";

    HttpConnection http = (HttpConnection) Connector.open(url);
    InputStream in = null;
    byte[] imgBytes = null;
    try {
        http.setRequestMethod(HttpConnection.GET);
        in = http.openInputStream();

        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] buffer = new byte[1024];
        int n = 0;
        while ((n = in.read(buffer)) != -1) {
            bos.write(buffer, 0, n);
        }
        imgBytes = bos.toByteArray();
    } finally {
        if (in != null) {
            in.close();
        }
        http.close();
    }
    Image img = Image.createImage(imgBytes, 0, imgBytes.length);

    return img;
}

As you may see, it is pretty simple to get the image of the map. The retrieving is pure HTTP request.
Next you can find an image retrieved by Google Static Maps from a location in my home town.


OK, you just saw how simply it would be if no restriction exists... What do you think about that restriction? It's kind of confusing, isn't it?

Anyway, we are going to need to find another way to show maps on our mobile apps.

see ya soon!

References:

Google Static Maps API. [online].
Available on Internet: http://code.google.com/intl/en/apis/maps/documentation/staticmaps/
[accessed on August 20 2011].

Developing Location Based Services: Introducing the Location API for J2ME. 2009. MobiForge [online].
Available on Internet: http://mobiforge.com/developing/story/developing-location-based-services-introducing-location-api-j2me
[accessed on August 20 2011].

Mini App With Location API and Google Maps in Java ME. 2009. Nokia [online].
Available on Internet: http://www.developer.nokia.com/Community/Wiki/Mini_App_With_Location_API_and_Google_Maps_in_Java_ME
[accessed on September 02 2011].

Google Maps API Family. FAQ. Google [online].
Available on Internet: http://code.google.com/intl/en/apis/maps/faq.html#mapsformobile
[accessed on September 02 2011].

Monday, July 25, 2011

READ_WRITE XML in Java Me

Last month (june-2011) I needed to write a mobile application that could read and write xml documents (using JavaMe, of course). As it was the very first time I needed to do something like that, I had to do some research and what I found is that there are plenty lot of sites, documentation and libraries to do it.

XML Quick Review
As you may know, XML is a markup language (eXtensible Markup Language), it's made of tags, just like html, but in XML the tags are defined by you and they have the meaning you want. It was created to be the standar in data interchange between platforms and it has succeded. Microsoft Office uses it, RSS uses it, ATOM uses it, XHTML uses it, SOAP uses it, and so on... For more information about XML, you can visit the following link:


Remember from my previous posts that JSON was created for the same purpose: data interchange between platforms. They both has their pros as we shall see in a minute...

XML vs JSON
Both them are standards for data interchange. I met XML long before JSON, but it wasn't until I learned about web services that I realized its great value! defining data structures that could be used in any platform...wow!

Recently I met JSON and at first I was like "Why another data interchange standard? isn't XML already enough?" Anyway, after reading and using it I kind of like it.

XML JSON
  • Tags make it easy to read the data.
  • Libraries make it easy for creation/maintenance.
  • Popularity, it is supported by other standards (i.e.XHTML).
  • Mature. It was created in the late 90's.
  • No tags, meaning lighter files.
  • There are also libraries for JSON.
  • Lighter to process
  • Gaining ground in Web technologies.
  • For more pros/cons check this post:


    In my opinion, for comunication between servers and mobile clients, I'd prefer using JSON because is lighter than XML. Nevertheless, you should be aware of using both.

    XML Parsers and JavaMe
    As mentioned before, there are plenty lot of libraries to work with XML in JavaMe. A XML parser is a software that is able to read, process and output XML data and it behaves in any of the following:
    • Reads the entire document and creates an in memory representation of it.
    • Push notifications to listeners when reading the entire document.
    • Pulls information from the document as the application requests it, like an Iterator.

    As you may suppose, the third type, Pull parsers, are better for use in JavaMe.

    READ_WRITE XML in Java Me
    In this post we are going to use KXML2 library in order to make use of XML in a sample mobile application. KXML2 is a pull XML parser with a small footprint, ideal for JavaMe. You may download the library or consult the API from the following URL:


    The sample application will create Client objects and will save them in a XML file. Also, the application will read a XML file in order to import some configurations like number of clients to create and the name of the file where the data is going to be exported.

    READ
    Let’s begin. The following XML document, is the configuration file I was talking about:

      
    <?xml version='1.0' encoding='UTF-8' ?>
    <!--Information for runtime-->
    <conf>
     <numClients>3</numClients>
     <fileName>clients.xml</fileName>
    </conf>
    

    As you may see, it has the properties needed at runtime. The next class, is where we are going to load these properties at runtime:

      
    public class Conf {
    
      /** Number of clients that we will create*/
      private int numClients = 0;
      /** Constant name of the number of clients tag*/
      private static final String ATT_NUM_CLIENTS = "numClients";
      /** Name of the XML where the clients are going to be 
          serialized*/
      private String fileName = "";
      /** Constant name of the file name tag*/
      private static final String ATT_FILE_NAME = "fileName";
    
      /**
       * Returns the configuration object for the XML Document 
       * represented by the parser passed as a parameter
       * @param parser KXMLParser of the configuration XML Document
       * @return Configuration object mapped from the KXMLParser
       */
      public static Conf loadFromXml(KXmlParser parser) {
        Conf conf = new Conf();
        try {
          //this will tell us which type of info we are reading 
          //from the XML document
          int eventType = parser.getEventType();
    
          //do it until the end of the file
          while (eventType != XmlPullParser.END_DOCUMENT) {
            //we are only interested in the start tags
            if (eventType == XmlPullParser.START_TAG) {
              //if the start tag is for the number of clients...
              if (parser.getName().equals(ATT_NUM_CLIENTS)) {
                //obtain the text for this property
                conf.setNumberOfClients(
                     Integer.parseInt(parser.nextText()));
              }
              //otherwise, if the start tag is form the file name...
              else if (parser.getName().equals(ATT_FILE_NAME)) {
                //obtain the text for this property
                conf.setNameOfFile(parser.nextText());
              }
            }
            //move to the next info
            eventType = parser.next();
          }
        } catch (Exception ex) {
          ex.printStackTrace();
        }
    
        return conf;
      }
    
      //getters and setters...
    }
    

    The interesting part of this class is the method +loadFromXml(KXmlParser parser):Conf, which is the method that maps the properties of the XML configuration file with the attributes of the Conf class. The constants defined in this class, are the names of the tags used in the XML document.
    Also you can notice how to obtain information from the XML Document through the KXMLParser. If you need another example about gathering information from the XML Parser, you can check this URL:


    Please note that the KXMLParser that we are using in the Conf class, implements the XmlPullParser interface described in the last URL.

    WRITE
    Now let’s take a look at the Client class, where we are going to write our clients information to a XML Document. In this class, we are going to use the following elements:
    • Comments: It’s easy to add comments. Every element in the XML tree extends from the class org.kxml2.kdom.Node, and have this method to add a child:

    Node.addChild(int, int, java.lang.Object):void

    So, for adding a comment to the XML Document, you do:

     
    Document doc = new Document();
    doc.addChild(0,Node.COMMENT, "This is a XML Comment");
    


    • Document Encoding: Very useful when needing i18n for your application. You can achieve this using the org.kxml2.kdom.Document class:

    Document doc = new Document();
    doc.setEncoding("UTF-8");
    


    • XML Element and its value: The org.kxml2.kdom.Node class has a special method to create Elements. After you create an Element you can sets its value adding a child of type TEXT. At the end, don’t forget to add the Element as a child of the Document or as a child of another Element:

    //creates a XML Document
    Document doc = new Document();
    //Creates a XML Element
    Element elem = doc.createElement(null, “NameOfTheElement”);
    //Sets the value of the Element
    elem.addChild(0, Node.TEXT, “ValueOfTheElement”);
    //Adds the Element to the XML Document at the specified index
    doc.addChild(0, Node.ELEMENT, elem);
    


    • Formatting: The library doesn’t format the output of the XML Document by default, so you have to add some formatting as TEXT nodes that can make human readable the XML output .

    Document doc = new Document();
    //adds a new line to the output        
    doc.addChild(0, Node.TEXT, "\n");
    //this comment will appear as a new line in the output of this XML Document
    doc.addChild(1,Node.COMMENT, "This XML is for One Client");
    //adds a new line an a tab space to the output
    doc.addChild(2, Node.TEXT, "\n\t");
    //creates an empty element
    Element elem = doc.createElement(null, “NameOfTheElement”);
    //The element will appear as a new line and with a tab space in the output of this XML Document
    doc.addChild(3, Node.ELEMENT, elemClient);
    

    Do not repeat indexes at the addChild method of a node or you will overwrite added children.

    Following is the Client class:

    import java.util.Vector;
    import org.kxml2.kdom.*;
    
    public class Client {
        /** Constant name of the client tag*/
        private static final String ATT_CLIENT = "Client";
        /** Constant name of the clients tag*/
        private static final String ATT_CLIENTS = "List";
        /** Name of the client*/
        private String name;
        /** Constant name of the attribute name*/
        private static final String ATT_NAME = "name";
        /** Last name of the client*/
        private String lastName;
        /** Constant name of the attribute last name*/
        private static final String ATT_LAST_NAME = "lastName";
        /** Identification of the client*/
        private String id;
        /** Constant name of the attribute id*/
        private static final String ATT_ID = "id";
    
        /**
         * Allows to get the XML Document from the Client passed 
         * as parameter
         * @param client Client object to convert to XML
         * @return XML Document of the Client passed as parameter
         */
        public static Document toXML(Client client) {
            Document doc = new Document();
            doc.setEncoding("UTF-8");
            
            doc.addChild(0, Node.TEXT, "\n");
            doc.addChild(1,Node.COMMENT, 
                         "This XML is for One Client");
    
            Element elemClient = toXMLElement(doc, client);
            doc.addChild(2, Node.TEXT, "\n\t");
            doc.addChild(3, Node.ELEMENT, elemClient);
            
            return doc;
        }
    
        /**
         * This method should be used by this class only, 
         * that's why it is private.
         * Allows to get a XML Element from the Client passed 
         * as parameter
         * @param client Client Object to convert to XML Element
         * @return XML Element representation of the Client passed 
         * as parameter
         */
        private static Element toXMLElement(Document doc
                                          , Client client) {
            Element elem = doc.createElement(null, ATT_CLIENT);
    
            Element elemId = elem.createElement(null, ATT_ID);
            //check if the attribute is set
            if(client.getId() != null 
               && !client.getId().trim().equals(""))
            {
              elemId.addChild(0, Node.TEXT, client.getId());
            }
    
            Element elemName = elem.createElement(null, ATT_NAME);
            //check if the attribute is set
            if(client.getName() != null 
               && !client.getName().trim().equals(""))
            {
              elemName.addChild(0, Node.TEXT, client.getName());
            }
    
            Element elemLastName = 
                   elem.createElement(null, ATT_LAST_NAME);
            //check if the attribute is set
            if(client.getLastName() != null 
               && !client.getLastName().trim().equals(""))
            {
              elemLastName.addChild(0, Node.TEXT
                                   ,client.getLastName());
            }
    
            //add the elements to the Client Element
            elem.addChild(0, Node.TEXT, "\n\t\t");
            elem.addChild(1, Node.ELEMENT, elemId);
            elem.addChild(2, Node.TEXT, "\n\t\t");
            elem.addChild(3, Node.ELEMENT, elemName);
            elem.addChild(4, Node.TEXT, "\n\t\t");
            elem.addChild(5, Node.ELEMENT, elemLastName);
            elem.addChild(6, Node.TEXT, "\n\t");
    
            return elem;
        }
    
        /**
         * Allows to get a XML Document from a Vector of Clients
         * @param clients Vector of clients to convert to XML
         * @return XML Document of the Vector of clients
         */    
        public static Document toXMLs(Vector clients) {
            Document doc = new Document();
            doc.setEncoding("UTF-8");
    
            doc.addChild(0, Node.TEXT, "\n");
            doc.addChild(1,Node.COMMENT
                        ,"This XML is for a list of Clients");
            doc.addChild(2, Node.TEXT, "\n");
            //creates the root ekement and adds it to the document
            Element root = doc.createElement(null, ATT_CLIENTS);
            doc.addChild(3,Node.ELEMENT, root);
            doc.addChild(4, Node.TEXT, "\n");
    
            int j = 0;
            for (int i = 0; i < clients.size(); i++, j+=2) {
                Client client = (Client) clients.elementAt(i);
                //ask for the XML Element for each client
                Element elemClient = toXMLElement(doc, client);
                root.addChild(j, Node.TEXT, "\n\t");
                root.addChild(j+1, Node.ELEMENT, elemClient);
            }
            root.addChild(j, Node.TEXT, "\n");
            return doc;
        }
        
        //getters and setters...
    }
    

    The class has a few attributes to manage information of a client, it also has constants with the name of the XML tag names where the information is going to be added. The static methods, are helpers to obtain the XML Document of a client or from a Vector of clients. You may notice the addition of TEXT nodes with the values “\n\t...”, what we are doing is adding format (“\n” = New Line, “\t” = Tab space) to the output of the XML document as we will see later.

    The MIDlet that we are going to use in order to test the previous classes is a simple MIDlet without any UI. It first will load the properties from the XML file using the FileConnection API and KXML2, and then it will create as many clients as the numClients property says. At the end, we will write the cliens information to a XML file using FileConnection API and KXML2 (again). The MIDlet uses a conf.xml file located at one of the root file system of the device. Remember from our previous post some useful methods when working with FileConnection API.

    //imports...
    
    public class KxmlMidlet extends MIDlet {
    
      public void startApp() {
        //obtain the roots for the FileConnection API
        Vector roots = getRoots();
    
        Vector vClients = new Vector();
        Conf conf = loadXML("file:///" + 
                            roots.firstElement().toString() + 
                            "conf.xml");
    
        //create as many clients as the property says
        Client client = null;
        for (int i = 0; i < conf.getNumberOfClients(); i++) {
          client = new Client();
          client.setId("" + (i+1));
          client.setName("Name for Client " + client.getId());
          client.setLastName(
               "Last Name for Client " + client.getId());
    
          vClients.addElement(client);
        }
    
        //if there are created clienst, write them to a XML File
        if (vClients.size() > 0) {
          Document doc = Client.toXMLs(vClients);
          saveOnDevice("file:///" + 
                        roots.firstElement().toString() + 
                        conf.getNameOfFile(), doc);
        }
      }
    
      
      /**
       * Loads the configuration file located at the specified 
       * location
       * @param path location where the configuration file is at
       * @return Conf object with the configurations
       */
      private Conf loadXML(String path) {
        Conf conf = new Conf();
    
        KXmlParser parser = null;
        InputStream in = null;
        FileConnection file = null;
        try {
          //Access to the file
          file = (FileConnection) Connector.open(path);
          //Checks whether the file exist
          if (!file.exists()) {
            return conf;
          }
    
          in = file.openInputStream();
    
          parser = new KXmlParser();
          //the second parameter is the encoding.
          //Try to use a encoding
          //in order to avoid special characters issues.
          //For example in order to use á,é,í...Ñ... try ISO8859_1
          //You can also try the general one: UTF-8, 
          //but it wont work with á,é...
          parser.setInput(in, "UTF-8");
          //calls the helper method of the Conf class
          conf = Conf.loadFromXml(parser);
    
        } catch (Exception ex) {
          ex.printStackTrace();
        } finally {
    
          if (in != null) {
            try {
              in.close();
            } catch (Exception ex) {
            }
          }
          if (file != null) {
            try {
              file.close();
            } catch (Exception ex) {
            }
          }
        }
    
        return conf;
      }
    
     
      /**
       * Saves the XML Document in the file system of the device
       * @param name Path to file to be created
       * @param doc XML Document to be saved
       */
      public void saveOnDevice(final String name, 
                               final Document doc) {
        //starts a new Thread in order to avoid blocks
        new Thread(new Runnable() {
    
          public void run() {
            //used for writing the XML
            XmlSerializer serializer = null;
    
            FileConnection file = null;
            OutputStreamWriter out = null;
            try {
              file = (FileConnection) Connector.open(name);
              //checks whether the file exist or not
              if (!file.isDirectory() && !file.exists()) {
                file.create();
              }
    
              out = new OutputStreamWriter(file.openOutputStream());
              serializer = new KXmlSerializer();
              serializer.setOutput(out);
              doc.write(serializer);
              out.flush();
              out.close();
    
            } catch (Exception ex) {
              ex.printStackTrace();
            } finally {
              if (out != null) {
                try {
                  out.close();
                } catch (Exception ex) {
                }
              }
              if (file != null) {
                try {
                  file.close();
                } catch (Exception ex) {
                }
              }
            }
          }
        }).start();
      }
    
      /**
       * Asks for the list of drivers where files can be stored
       * @return Vector of Strings representing the name of
       * the drivers where files can be stored
       */
      private Vector getRoots() {
        Vector vRoots = new Vector();
    
        if (checkFileSupport()) {
          Enumeration drivers = FileSystemRegistry.listRoots();
          while (drivers.hasMoreElements()) {
            vRoots.addElement((String) drivers.nextElement());
          }
        }
        return vRoots;
      }
    

    So, after running the MIDlet, we will find a XML file in the file system of the device, with the name specifid by the nameOfFile property and with the information of our clients in XML. Remember from our previous post where is javame saving my files?, if you dont know where to find the XML file that we are talking about.

    Next is the output of this file:

    <?xml version='1.0' encoding='UTF-8' ?>
    <!--This XML is for a list of Clients-->
    <List>
     <Client>
      <id>1</id>
      <name>Name for Client 1</name>
      <lastName>Last Name for Client 1</lastName>
     </Client>
     <Client>
      <id>2</id>
      <name>Name for Client 2</name>
      <lastName>Last Name for Client 2</lastName>
     </Client>
     <Client>
      <id>3</id>
      <name>Name for Client 3</name>
      <lastName>Last Name for Client 3</lastName>
     </Client>
    </List>

    You may notice it is human readable, because we added formatting texts during the XML Document creation.

    Here is another file, without using formatting text:

    <?xml version='1.0' encoding='UTF-8' ?><!--This XML is for a list of Clients--><List><Client><id>1</id><name>Name for Client 1</name><lastName>Last Name for Client 1</lastName></Client><Client><id>2</id><name>Name for Client 2</name><lastName>Last Name for Client 2</lastName></Client><Client><id>3</id><name>Name for Client 3</name><lastName>Last Name for Client 3</lastName></Client></List>
    

    So it’s up to you if you need formatting or not.

    KXML2 is working on a newer version of the library, you should check its website in order to be updated with the latest version available.
    I liked using KXML2, and I think it is very useful when your device doesn’t have any embedded API to work with XML. Some new devices nowadays come with an API to work with XML and Web Services called JSR172. In a future post we will remake this clients example using the features provided by JSR172.

    OK, quite a large post, but I hope it can help you to work with XML on your mobile applications.

    see ya soon!

    References:

    KXML. [online].
    Available on Internet: http://kxml.sourceforge.net/kxml2/
    [accessed on June 12 2011].

    XML Pull Parsing. March 2005. XML Pull .org [online].
    Available on Internet: http://www.xmlpull.org/
    [accessed on June 12 2011].

    KXML: A Great Find for XML Parsing in J2ME. April 2003. DevX.com [online].
    Available on Internet: http://www.devx.com/xml/Article/11773
    [accessed on June 12 2011].

    Monday, July 11, 2011

    JavaMe Tips: FileConnection API useful methods

    Hello all. Today I'm going to show you two very useful methods when working with the FileConnection API for JavaMe. This methods along with others not described in this post, can help you a lot:

      
      //inside a class...
    
      /**
       * Checks whether the device has support for the 
       * FileConnection API
       * @return true if and only if the device supports the API
       * false otherwise
       */
      private boolean checkFileSupport() {
        if (System.getProperty(
           "microedition.io.file.FileConnection.version") != null)
        {
          return true;
        }
        return false;
      }
    

    The last method tells you whether the device has support for the FileConnection API. Pretty handy when the application is developed for a wide range of mobile devices.
    Next, we'll see a method that returns all the possible drives where the files can be stored in the mobile device.

      
       //inside a class...
    
      /**
       * Asks for the list of drivers where files can be stored
       * @return Vector of Strings representing the name of
       * the drives where files can be stored
       */
      private Vector getRoots() {
        Vector vRoots = new Vector();
    
        if (checkFileSupport()) {
          Enumeration drivers = FileSystemRegistry.listRoots();
          while (drivers.hasMoreElements()) {
            vRoots.addElement((String) drivers.nextElement());
          }
        }
        return vRoots;
      }
    

    Imagine your application takes snapshots, and you want to ask the user where to store them... with the help of the last method  and a List, you can show to the user all the possible "hard drives" where he/she can save their pictures.

    see ya soon!

    References:

    Getting Started with the FileConnection APIs. December 2004. Oracle [online].
    Available on Internet: http://developers.sun.com/mobility/apis/articles/fileconnection/
    [accessed on February 26 2011].

    Working with the Java ME FileConnection API on Physical Devices. March 2007. Java.net[online].
    Available on Internet: http://today.java.net/article/2007/03/27/working-java-me-fileconnection-api-physical-devices
    [accessed on February 26 2011].

    Sunday, May 1, 2011

    Web Component Developer Certification


    Hi again, it's been a while since my last post. I just got certified as Oracle Certified Web Component Developer for J2EE 5 (OCPJWCD, also known as SCWCD), that's the reason why I've been away for the last month. I want to share some tips about passing the exam:

    Exam Name: Oracle Certified Web Component Developer for J2EE 5
    Exam Code: 310-083
    Number of Questions: 69
    Score to pass: 70%
    Preparation Time: 4 months (about 6 hours/week)
    Test Site: Prometric
    Date: 5/11/2011

    Why Certified?
    There are many benefits about being certified, you can validate your knowledge, improve your work efficiency and even ask for a better income... I've been working with java for Web for about 3 years already and I thought this certification was going to be easy, but it wasn't. During my preparation I realized that there are several functionalities I wasn't aware of. Now that I'm certified I feel really good and confident about the technology and I'm even going to start studying for the web services certification. Anyway, the reason why I took the certification was to improve my knowledge about the java technology and aspire for a better income.

    Why JEE 5 instead of JEE 6?
    That was a really tough desicion, because a new version of the exam had arrived with the all new JEE 6... so I thought that taking the JEE 5 exam was like learning old technology. 
    To make my decition I had to validate which technology my clients were using. I realized that none of my clients were using JEE 6, but they do have several inhouse web applications in JEE 5. It's not like they aren't getting in JEE 6 ever, but at short term JEE 5 would give me more job opportunities. Perhaps, next year I will update my certification to JEE 6, I think I'm going to let the market lead me.

    Preparation
    I've had previous experience with Java for Web, therefore I thought that studying for this certification was piece of cake... but the truth is that many of the underlying processes and the servlet container's responsabilities were unknown to me. I used this really great book, if you are looking for a good book to take the exam and learn, I truly recommend this one:


    It has a lot of pages, believe me I know... but the reading is so easy and it has so many graphics and good sense of humor that made my reading very pleasent. As a regular employee I had to study at nights and weekends that's why I used to study 6 hours per week and it took me about 3 months and a half to finish the reading and exercises. After reading the book I started to prepare myself with mock exams. I was able to find some for free (check the links at the end) but I decided to buy some. 

    For my previous certifications exams I used "whizlabs", it has a nice web interface so you can access it everywhere if you have internet connection and it gives you 1 test exam and 5 mock exams to validate your knowledge, also the reporting tool is pretty good. During that week I googled some other mock exams and then I found "enthuware". Checking the forums I realized that enthuware was as good as whizlabs, it wasn't a Web interface but it gives you 8 mock exams,  so I decided to give it a chance, also because whizlabs was USD75 and enthuware was USD20 at that time... I'm not getting in the discussion about which one is better, I have used both and I like both, it's just that enthuware was at a better price at that moment.

    During the exam
    You have 180 minutes to finish the exam, it took me about 90 minutes to finish it. I think my preparation was really good, I'm glad I chose enthuware because the UI interface was very similar to the real exam and some of the questions were similar too. My score was 88% which is very good. Something I wasn't prepare for was JSTL, the exam had about 5-10 questions about it, fortunately my job experience helped me there.

    Useful Links
    http://education.oracle.com/pls/web_prod-plq-dad/db_pages.getpage?page_id=322
    http://www.coderanch.com/how-to/java/ScwcdLinks
    http://www.enthuware.com/index.php/mockexams/sunjavacertifications/scwcd-questions
    http://www.whizlabs.com/scwcd/scwcd.html


    I hope those of you who are thinking about taking the exam may find this post useful, from now on I will keep posting about JavaMe and I'm going to start posting about Java for Web too.


    bye.

    Tuesday, March 15, 2011

    JavaMe Tips: Where is FileConnection API writing my files when using Emulator?

    Last weekend when working on a FileConnection API request I realized that I didn't know where in my PC were the emulator saving the files I was creating, so I made a little research...

    I know there are different kind of emulators, some of them have their own way to simulate the behavior of the sd cards from mounting a user directory to the use of default directories in user's profile.

    The Emulators I was using were WTK 2.5.2 and JavaMe sdk 3.0 and I was working on Netbeans 6.9.1 and here is what I found.

    For WTK 2.5.2:
    Try looking in 

    <Documents and settings>/<UserName>/j2mewtk/2.5.2/appdb/<TempDir>/filesystem

    Where <TempDir> is a temporal directory that is created to hold all the files in runtime. Be careful, everytime you close the emulator the dirs are deleted, so make any validation you need before closing your emulator.

    For JavaMe sdk 3.0:
    Try looking in

    <DocumentsAndSettings>/<UserName>/javame-sdk/3.0/work/<EmNum>/appdb/filesystem

    Where <EmNum> is a number representing the Emulator you are using, for example, DefaultCldcPhone1 emulator is number 6.

    see ya soon!

    References:

    How to test file reading/writing and web server app in emulator? 2008. Forum.Nokia [online].
    Available on Internet: http://discussion.forum.nokia.com/forum/showthread.php?143733-How-to-test-file-reading-writing-and-web-server-app-in-emulator
    [accessed on March 13 2011].

    Monday, March 14, 2011

    Canvas ScreenShot in JavaMe

    Due to the previous posts about image encoding and image's bytes, I found an interesting question about how to get a screenshot of a canvas in JavaMe and it turns out to be very simple. Just remember, once you get the mutable (changeable) Image you should encode it in some format (i.e. PNG, JPEG, etc...).

    The following is a regular canvas class which paints a smily:

      
    //imports...
    public class MyCanvas extends Canvas {
        
        /**
         * Creates a mutable image representing a screenshot of the
         * canvas
         * @return Screenshot as a mutable image
         */
        public Image getScreenShot() {
          Image screenshot = Image.createImage(getWidth(), 
                             getHeight());
          Graphics g = screenshot.getGraphics();
          paint(g);
          return screenshot;
        }
    
        /**
         * Painting method
         * @param g Graphic object to which the painting is done
         */
        public void paint(Graphics g) {
          //change to black an paint the whole background
          g.setColor(0x000000);
          g.fillRect(0, 0, getWidth(), getHeight());
    
          //change to yellow
          g.setColor(0xFFFF00);
          //left|top position of the face so it seems centered
          int xCenter = (getWidth() - 80) / 2;
          int yCenter = (getHeight() - 80) / 2;
          //draw the face
          g.fillArc(xCenter, yCenter, 80, 80, 0, 360);
          //change to black color
          g.setColor(0x000000);
          //left eye
          g.fillArc(xCenter + 20, yCenter + 20, 10, 15, 0, 360);
          //right eye
          g.fillArc(xCenter + 50, yCenter + 20, 10, 15, 0, 360);
          //smile
          g.fillArc(xCenter + 15, yCenter + 50, 50, 10, 180, 180);
    
        }
      }
    

    Notice that the +getScreenShot():Image method is creating a mutable image of the same width and height of the canvas. It also gets the Graphic object from that image so that the paint method can draw the smily on it.

    What to do with the screenshot? As I told you before, it's up to you. You can convert it to bytes, save it using RMS or FileConnection API, send it over the network...etc. But whatever you choose to do, remember to encode it using PNG or JPEG encoders, otherwise your end user may not be able to see or manipulate the image.

    see ya soon!

    References:

    A minimal PNG encoder for J2ME. 2009. [online].
    Available on Internet: http://www.chrfr.de/software/midp_png.html
    [accessed on March 12 2011].

    J2ME Screenshot of a Canvas. March 2010. Forum.Nokia [online].
    Available on Internet: http://discussion.forum.nokia.com/forum/showthread.php?191207-J2ME-Screenshot-of-a-Canvas
    [accessed on March 12 2011].

    PNG Encoding in Java ME. March 2010. Forum.Nokia [online].
    Available on Internet: http://wiki.forum.nokia.com/index.php/PNG_Encoding_in_Java_ME
    [accessed on March 12 2011].

    Saturday, March 12, 2011

    Convert image to byte array (byte[]) in JavaMe II

    The Convert image to byte array (byte[]) in JavaMe post  showed how you can read an image from your jar file or from the sd card of your device and convert it to a byte array. Those images are called immutable (non-changeable) and when we read them we are reading bytes in some format (png, jpeg..) but, what happens when we are creating mutable (changeable) images in memory and we want to get their bytes?

    For example, what if you can create a snapshot from what a canvas is showing? or what if you create an application that reads an image and apply some effects like blur, resizing, etc.?

    You have to be very careful in these situations because you could, some how, get the bytes from the mutable image, but you certanly need to encode them (format them in png or jpeg...) in order to show them in your application or to write them to a file so the user can see it.

    So in this post we are going to use a very simple PNG encoder. You can get more information about it using the following link:


    There are some other encoders that also use compression and formats like bmp, jpeg, etc. but for this post we are just showing you an example with PNG as it is the MIDP's standard image format. Download the PNG class and add it to your project so you can use it.

    In this example we are going to create a mutable image and then we are going to use some methods to get the image's bytes and finally we are going to encode those bytes using the PNG Encoder. The image is very simple, just a smily.



      
       //inside a midlet...
    
       /**
       * Creates a mutable (changeable) Image with a smily.
       * @return Image mutable image with a smile face on it
       */
      public Image createImage() {
        Image img = Image.createImage(100, 100);
        //Get the graphics so you can paint the image
        Graphics g = img.getGraphics();
        //change to black an paint the whole background
        g.setColor(0x000000);
        g.fillRect(0, 0, 100, 100);
    
        //change to yellow
        g.setColor(0xFFFF00);
        //left|top position of the face so it seems centered
        int xCenter = (img.getWidth() - 80) / 2;
        int yCenter = (img.getHeight() - 80) / 2;
        //draw the face
        g.fillArc(xCenter, yCenter, 80, 80, 0, 360);
        //change to black color
        g.setColor(0x000000);
        //left eye
        g.fillArc(xCenter + 20, yCenter + 20, 10, 15, 0, 360);
        //right eye
        g.fillArc(xCenter + 50, yCenter + 20, 10, 15, 0, 360);
        //smile...well kind of
        g.fillArc(xCenter + 15, yCenter + 50, 50, 10, 180, 180);
    
        return img;
      }
    

    OK, with the last piece of code you created a mutable image (changeable) but, in what format is it? PNG? JPEG? none? That's correct you don't know, so that's why you have to encode it. The PNG encoder that we are using in this post has a method called: +toPNG(int,int,byte[],byte[],byte[],byte[]):byte[]
    That's the method we are going to use in order to get our image's bytes in PNG format. But before using it, we need to get the params we are going to send. The first ints are the width and height of the image, the byte arrays are in order: alpha, red, green and... blue.

    The width and height are pretty straightforward: +getWidth():int and +getHeight():int from the Image object, but to get the byte arrays you will need to do some binary operations:

      
       //inside a midlet...
    
      /**
       * Gets the channels of the image passed as parameter.
       * @param img Image
       * @return matrix of byte array representing the channels:
       * [0] --> alpha channel
       * [1] --> red channel
       * [2] --> green channel
       * [3] --> blue channel
       */
      public byte[][] convertIntArrayToByteArrays(Image img) {
        int[] pixels = new int[img.getWidth() * img.getHeight()];
        img.getRGB(pixels, 0, img.getWidth(), 0, 0, img.getWidth(), 
                   img.getHeight());
        
        // separate channels
        byte[] red = new byte[pixels.length];
        byte[] green = new byte[pixels.length];
        byte[] blue = new byte[pixels.length];
        byte[] alpha = new byte[pixels.length];
    
        for (int i = 0; i < pixels.length; i++) {
          int argb = pixels[i];
          //binary operations to separate the channels
          //alpha is the left most byte of the int (0xAARRGGBB)
          alpha[i] = (byte) (argb >> 24);
          red[i] = (byte) (argb >> 16);
          green[i] = (byte) (argb >> 8);
          blue[i] = (byte) (argb);
        }
    
        return new byte[][]{alpha, red, green, blue};
      }
    

    Don't you worry if you don't understand immediatly the above code, just imagine a pixel as the following int 0xAARRGGBB, where AA = alpha channel, RR = red channel, GG = green channel and BB = blue channel, so if you want to separate the alpha channel byte you need to move it to the right, that's the binary operator >> doing... and remember 1 byte = 8 bits so in order to move AA (1 byte = 8 bits) to BB you have to move it 3 times or 24 bits and when you have it in the right most byte, you can cast it to byte and then you have separated the alpha channel, got it?

    Finally we need to invoke +toPNG(int,int,byte[],byte[],byte[],byte[]):byte[]  method in order to get our bytes encoded as PNG format and that's it. What to do with the encoded bytes is up to you... send them over the network, write them to a file using FileConnection API, etc. You can also check my previous posts if you need more documentation.

    see ya soon!


    References:

    A minimal PNG encoder for J2ME. 2009. [online].
    Available on Internet: http://www.chrfr.de/software/midp_png.html
    [accessed on March 12 2011].

    J2ME Screenshot of a Canvas. March 2010. Forum.Nokia [online].
    Available on Internet: http://discussion.forum.nokia.com/forum/showthread.php?191207-J2ME-Screenshot-of-a-Canvas
    [accessed on March 12 2011].

    PNG Encoding in Java ME. March 2010. Forum.Nokia [online].
    Available on Internet: http://wiki.forum.nokia.com/index.php/PNG_Encoding_in_Java_ME
    [accessed on March 12 2011].

    Saturday, February 26, 2011

    Convert image to byte array (byte[]) in JavaMe

    Last post showed you how to take a picture using the device's camera and then send it to a servlet in Base64 format. But sometimes, you just need to send a picture that is either inside the application or in your memory card (sd card, etc.).

    So in this post, we are going to convert images inside the application to byte arrays so you can use the methods showed in the last post in order to send thouse images to the servlet. Also, we will see how to get byte arrays from a file with the help of the FileConnection API, but we are not getting in details with this API. I will share some links that make a great work for getting started with it.

    The following method takes a String as parameter and looks inside the application to get the bytes:

      
         //inside MIDlet class...
    
       /**
       * Reads the local image resource and returns an
       * array of bytes representing the image
       * @param imgPath path to the image inside the app
       * @return array of bytes representing the image
       */
      public byte[] loadFromApp(String imgPath) {
    
        byte[] imgBytes = null;
        ByteArrayOutputStream baos = null;
        InputStream in = null;
        try {
    
          baos = new ByteArrayOutputStream();
          //this image is inside my mobile application
          in = this.getClass().getResourceAsStream(imgPath);
          byte[] buffer = new byte[1024];
          int n = 0;
          while ((n = in.read(buffer)) != -1) {
            baos.write(buffer, 0, n);
          }
    
          imgBytes = baos.toByteArray();
    
        } catch (Exception ex) {
          ex.printStackTrace();
        } finally {
          //whatever happends close the streams
          if (baos != null) {
            try {
              baos.close();
            } catch (Exception ex) {
            }
          }
          if (in != null) {
            try {
              in.close();
            } catch (Exception ex) {
            }
          }
        }
    
        return imgBytes;
      }
    

    So you see it's pretty straightforward, just get the resource as a stream and start passing the bytes from one stream to another, at the end the ByteArrayOutputStream let you get the byte array.

    But, what if you just want to send a picture you just take and is saved in your memory card (sd card, micro sd card...etc.)? well you have to access the file with the help of the FileConnection API. Here are some great links to help you get started with this API:

    For getting started right from oracle:

    For some considerations when using the API in real devices:

    OK, after you understand how the API works and can access the files, you can use the following method to get the byte arrays of the files. You will realize that this method is very similar to the previous one:

      
         //inside MIDlet class...
    
       /**
       * Reads the image and returns an array of bytes
       * @param imgPath Path to the image inside the Device or
       * the memory card
       * @return array of bytes representing the image
       */
      public byte[] loadFromDevice(String imgPath) {
    
        byte[] imgBytes = null;
        ByteArrayOutputStream baos = null;
        InputStream in = null;
        FileConnection file = null;
        try {
          //Access to the file
          file = (FileConnection) Connector.open(imgPath);
          //Checks whether the file exist
          if (!file.exists()) {
            return new byte[0];
          }
          baos = new ByteArrayOutputStream();
          in = file.openInputStream();
          byte[] buffer = new byte[1024];
          int n = 0;
          while ((n = in.read(buffer)) != -1) {
            baos.write(buffer, 0, n);
          }
    
          imgBytes = baos.toByteArray();
    
        } catch (Exception ex) {
          ex.printStackTrace();
        } finally {
          //whatever happends close the streams
          if (baos != null) {
            try {
              baos.close();
            } catch (Exception ex) {
            }
          }
          if (in != null) {
            try {
              in.close();
            } catch (Exception ex) {
            }
          }
          if (file != null) {
            try {
              file.close();
            } catch (Exception ex) {
            }
          }
        }
    
        return imgBytes;
      }
    

    There's one important thing to keep in mind with this API... not all devices implement it, so you should check if the device supports it before using it. The following method lets you check the availability of the API:

      
         //inside MIDlet class...
    
      /**
       * Checks whether the device has support for
       * the FileConnection API
       * @return true if and only if the device
       * supports the API false otherwise
       */
      private boolean checkFileSupport() {
        if (System.getProperty
           ("microedition.io.file.FileConnection.version") != null) {
          return true;
        }
    
        return false;
      }
    

    I hope you can use this methods in your applications and start sharing some images!

    see ya soon!


    References:

    Getting Started with the FileConnection APIs. December 2004. Oracle [online].
    Available on Internet: http://developers.sun.com/mobility/apis/articles/fileconnection/
    [accessed on February 26 2011].

    Working with the Java ME FileConnection API on Physical Devices. March 2007. Java.net[online].
    Available on Internet: http://today.java.net/article/2007/03/27/working-java-me-fileconnection-api-physical-devices
    [accessed on February 26 2011].

    Saturday, February 12, 2011

    Taking a picture - Base64 encoding in JavaMe

    It's been a while since my last post, January was a busy month, but here I am again.

    In this post, we are going to do something really interesting: taking a snapshot with the phone's camera and send it to the server in Base64 format.

    You should read the post about Base64 in JavaMe (J2ME) if you haven't:


    Taking the snapshot is quite easy, you just have to be careful about blocking calls. The real problem happens when uploading the image to the server. I tried several scenarios using Glassfish 3.0.1 and Tomcat 6.0.32 and none of the scenarios worked on both servers... It was very frustrating becasue the code seems to be OK, but works for Glassfish or for Tomcat but not both.

    Let's start with the general code, assume the following is inside the MIDlet class:

      
         //inside MIDlet class...
    
         /** Commands to control the application flow*/
         private Command commandShoot = null;
         private Command commandExit = null;
         private Command commandSend = null;
         private Command commandBack = null;
         private Display display = null;
    
         /** flags to indicate whether the phone 
          *  supports png or jpeg encoding for snapshots
          */
         private boolean png = false;
         private boolean jpeg = false;
    
         /** Canvas where the video is going to be played*/
         private VideoCanvas videoCanvas = null;
    
         /** Canvas where the snapshot is going to be shown*/
         private ImageCanvas imgCanvas = null;
    
    
         public void startApp() {
            display = Display.getDisplay(this);
    
            commandExit = new Command("Exit", Command.EXIT, 0);
            commandShoot = new Command("Shoot", Command.SCREEN, 0);
            commandSend = new Command("Send", Command.SCREEN, 0);
            commandBack = new Command("Back", Command.BACK, 0);
    
            //Verifies if the application can use the camera
            //and encoding
            if (checkCameraSupport() && 
                checkSnapShotEncodingSupport()) {
    
                //this is the canvas where the video will render
                videoCanvas = new VideoCanvas(this);
                videoCanvas.addCommand(commandExit);
                videoCanvas.addCommand(commandShoot);
                videoCanvas.setCommandListener(this);
    
                display.setCurrent(videoCanvas);
            } else {
                System.out.println("NO camera support");
            }
        }
    
        /**
         * Checks whether the phone has camera support
         * @return true if and only if the phone has camera
         * support
         */
        private boolean checkCameraSupport() {
            String propValue = System.getProperty
                               ("supports.video.capture");
            return (propValue != null) && propValue.equals("true");
        }
        
        /**
         * Checks if the phone has png or jpeg support.
         * @return true if and only if the phone supports
         * png or jpeg encoding
         */
        private boolean checkSnapShotEncodingSupport() {
            String encodings = System.getProperty
                               ("video.snapshot.encodings");
            png = (encodings != null) 
                  && (encodings.indexOf("png") != -1);
    
            jpeg = (encodings != null) 
                   && (encodings.indexOf("jpeg") != -1);
    
            return png || jpeg;
        }
    

    The previous methods tell you if the phone has camera support and if it can encode snapshots in either png or jpeg format. The +startApp():void method, starts the application, checks for the camera support and starts the canvas where the video will render.

    Next is the method that actually encodes an array of bytes. Later we will show how to pass the Image as a byte array to this method in order to get the Image in Base64 format:

      
         //inside MIDlet class...
    
        /**
         * Encodes an array of bytes
         * @param imgBytes Array of bytes to encode
         * @return String representing the Base64 format of
         * the array parameter
         */
        public String encodeImage(byte[] imgBytes) {
            byte[] coded = Base64.encode(imgBytes);
            return new String(coded);
        }
    

    As we saw in the Base64 encode-decode in JavaMe (J2ME) Post, the previous method encodes using the bouncy castle library.

    The following methods goes inside the MIDlet class as well, they are responsible of starting the canvas that takes the snapshot and passing the snapshot to another canvas in order to show it to the user:

      
        //inside MIDlet...
    
        /**
         * Starts the Video Canvas to take the snapshot
         */
        public void snapShot() {
    
            if (png) {
                videoCanvas.startSnapShot("png");
            } else if (jpeg) {
                videoCanvas.startSnapShot("jpeg");
            } else {
                videoCanvas.startSnapShot(null);
            }
        }
    
        /**
         * Shows the snapshot in a Canvas
         * @param bytes Array of bytes representing the
         * snapshot
         */
        public void showSnapShot(byte[] bytes) {
            if (bytes != null) {
    
                imgCanvas = new ImageCanvas(bytes);
                imgCanvas.addCommand(commandSend);
                imgCanvas.addCommand(commandBack);
                imgCanvas.setCommandListener(this);
    
                display.setCurrent(imgCanvas);
            }
        }
    

    OK, that's pretty much the general code for the MIDlet, let's see what happens within the VideoCanvas class. The next code should be inside the constructor, it starts the video player:

            
        //inside VideoCanvas class...
    
        /* Application MIDlet**/
        ImageCaptureMidlet midlet = null;
    
        /** Control for the video*/
        VideoControl videoControl = null;
    
        public VideoCanvas(ImageCaptureMidlet mid) {
            midlet = mid;
            Player player = null;
    
            try {
                player = Manager.createPlayer("capture://video");
                player.realize();
                videoControl = (VideoControl) player.getControl
                               ("VideoControl");
                videoControl.initDisplayMode
                           (VideoControl.USE_DIRECT_VIDEO, this);
                videoControl.setDisplayFullScreen(true);
                videoControl.setVisible(true);
    
                player.start();
    
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    

    So, when the canvas is created it starts the player and the video starts playing inside the canvas. When the MIDlet invokes the +snapShot():void method, the following piece of code is executed inside the VideoCanvas class:

        //inside VideoCanvas class...
    
        /**
         * Starts a thread to take the snapshot. 
         * Some devices will take the snapshot without 
         * the need of a thread, but some others 
         * doesn't (including my emulator). 
         * So start a new Thread...
         * @param encoding String representing the encoding
         * to use when taking the snapshot
         */
        public void startSnapShot(final String encoding) {
            new Thread(new Runnable() {
    
                public void run() {
                    try {
                        byte[] rawBytes = null;
                        if (encoding != null) {
                            //take the snapshot using the encoding
                            rawBytes = videoControl.getSnapshot
                                       ("encoding=" + encoding);
    
                        } else {
                            //take the snapshot using the best
                            //possible encoding. 
                            //Implementation dependent
                            rawBytes = videoControl.getSnapshot
                                       (null);
                        }
                        //ask the midlet to show the snapshot
                        midlet.showSnapShot(rawBytes);
                    } catch (MediaException ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();
        }
    

    You may notice that the method starts a new Thread. That's because not all devices will take the snapshot right away, some times it takes a little bit to start the camera and take the sanpshot. That's why, we have started a new Thread. Also, check that +VideoControl.getSnapshot(String):byte[] method can receive a null parameter, indicating that let the implementation decide which is the best encoding possible to take the snapshot. Finally, when the snapshot is taken, the method asks the application MIDlet to show it.

    We have previously seen the +showSnapShot(byte[]):void method in the MIDlet class, so let's take care about the ImageCanvas class where the snapshot is shown:

        //inside ImageCanvas class...
    
        /** Snapshot to render*/
        private Image image = null;
    
        /** bytes of the snapshot*/
        private byte[] imageBytes = null;
    
        public ImageCanvas(byte[] bytes) {
            imageBytes = bytes;
    
            //creates an Image using the byte array 
            image = Image.createImage(imageBytes, 0, 
                                      imageBytes.length);
        }
    
        public void paint(Graphics g) {
            int width = getWidth();
            int height = getHeight();
            g.setColor(0x000000);
            g.fillRect(0, 0, width, height);
    
            //render the snapshot
            g.drawImage(image, getWidth() / 2, getHeight() / 2, 
                        Graphics.HCENTER | Graphics.VCENTER);
        }
    
        //Getters and Setters...
    
    

    OK, up until now we have seen how to take a snapshot and render it on a Canvas. That's the general code we were talking about at the beginning of this post. Now let's see how to send the snapshot to the server. Here we are going to present two scenarios, one for Glassfish server and another for the Tomcat server.

    Glassfish Server:
    The following method is the method inside the MIDlet that sends the snapshot to a servlet deployed on Glassfish server 3.0.1:

        //inside MIDlet class
    
        /**
         * Sends the snapshot to the server
         */
        public void send() {
            new Thread(new Runnable() {
    
                public void run() {
    
                    String imageEncoded = 
                       encodeImage(imgCanvas.
                                   getImageBytes());                
    
                    String format = png ? "png" : jpeg?"jpeg":"";
                    
                    //This is my servlet’s URL
                    String URL = 
                               "http://localhost:8080/" + 
                               "Base64ExampleServlet_v2/" +
                               "ImageServlet";
    
                    HttpConnection http = null;
                    OutputStream os = null;
                    DataOutputStream dout = null;
                    try {
                        //Open HttpConnection using POST
                        http = (HttpConnection) Connector.open(URL);
                        http.setRequestMethod(HttpConnection.POST);
                        //Content-Type is must to pass parameters 
                        //in POST Request
                        http.setRequestProperty(
                             "Content-Type", 
                             "application/x-www-form-urlencoded");
                       
                        os = http.openOutputStream();
    
                        ByteArrayOutputStream bout = new 
                                           ByteArrayOutputStream();
                        dout = new DataOutputStream(bout);
                        dout.writeUTF(imageEncoded);
                        dout.writeUTF(format);
                        os.write(bout.toByteArray());
                        
                        os.flush();  
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    } 
                    //whatever happens, close the streams 
                    //and connections
                    finally {
                        if (os != null) {
                            try {
                                os.close();
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                        if (dout != null) {
                            try {
                                dout.close();
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                        if (http != null) {
                            try {
                                http.close();
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                    }
                }
            }).start();
        }
    

    As you can see, the method calls the encoding method passing the snapshot as a byte array, then it starts a HttpConnection to the servlet deployed on Glassfish server. It opens the OutputStream and writes the image as Base64 format and it also writes the encoding (format) used. On the server side, you should read the stream the same way you wrote it, taht is, first read the image in Base64 format and then the encoding used (format).

    Tomcat Server:
    The following method is the method inside the MIDlet that sends the snapshot to a servlet deployed on Tomcat server 6.0.32:

        //inside MIDlet class
    
        /**
         * Sends the snapshot to the server
         */
        public void send() {
            new Thread(new Runnable() {
    
                public void run() {
    
                    String imageEncoded = 
                       encodeImage(imgCanvas.
                                   getImageBytes());                
    
                    String format = png ? "png" : jpeg?"jpeg":"";
                    
                    //This is my servlet’s URL
                    String URL = 
                               "http://localhost:8080/" + 
                               "Base64ExampleServlet_v2/" +
                               "ImageServlet";
    
                    HttpConnection http = null;
                    OutputStream os = null;
                    try {
                        //Open HttpConnection using POST
                        http = (HttpConnection) Connector.open(URL);
                        http.setRequestMethod(HttpConnection.POST);
                        //Content-Type is must to pass parameters 
                        //in POST Request
                        http.setRequestProperty(
                             "Content-Type", 
                             "application/x-www-form-urlencoded");
                       
                        os = http.openOutputStream();
    
                        //IMPORTANT, when writing Base64 format
                        //there are chars like '+' that  
                        //must be replaced when sending.
                        imageEncoded = 
                            imageEncoded.replace('+', '-');
                        StringBuffer params = new StringBuffer();
                        params.append("image" + "=" + imageEncoded);
                        params.append("&" + 
                                      "format" + "=" + format);
                        System.out.println(params.toString());
                        os = http.openOutputStream();
                        os.write(params.toString().getBytes());
                        
                        os.flush();  
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    } 
                    //whatever happens, close the streams 
                    //and connections
                    finally {
                        if (os != null) {
                            try {
                                os.close();
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                        if (http != null) {
                            try {
                                http.close();
                            } catch (IOException ex) {
                                ex.printStackTrace();
                            }
                        }
                    }
                }
            }).start();
        }
    

    This method differs from the Glassfish method in the way it writes the parameters. Tomcat's method writes the parameters as a key/value pair. Notice one important point, the Base64 format uses chars like '+', chars that may be confused in the HTTP protocol, because they can be translated as a space char. So before sending the image in Base64, replace the '+' chars with '-' chars, but when receiving in the servlet (server side), convert the chars back before writing the image to the disk. This is only needed in the Tomcat's method.

    Wow, loooooong post... Again, my advise is be careful when deciding which method to use in which server. Sometimes the code you wrote may be well written but for some reasons it won't work on the server... so you have to try another way to write your code until it works.

    That's it for now, hope this helps you to write applications that use the device's camera.

    see ya soon!


    References:

    Taking Pictures with MMAPI. 2011. Oracle [online].
    Available on Internet: http://developers.sun.com/mobility/midp/articles/picture/
    [accessed on February 01 2011].

    Java Tips - Capturing Video on J2ME devices. 2011. Java Tips [online].
    Available on Internet: http://www.java-tips.org/java-me-tips/midp/capturing-video-on-j2me-devices.html
    [accessed on February 01 2011].

    J2ME Sample Codes: Image Capturing in J2ME. 2011. J2ME Sample Codes [online].
    Available on Internet: http://j2mesamples.blogspot.com/2009/06/image-capturing-in-j2me.html
    [accessed on February 01 2011].

    Embedded Interaction - Working with J2ME - Picture transmission over HTTP. 2011. Embedded Interaction [online].
    Available on Internet: http://www.hcilab.org/documents/tutorials/PictureTransmissionOverHTTP/index.html
    [accessed on February 01 2011].

    Base64. 2010. Wikipedia [online].
    Available on Internet: http://en.wikipedia.org/wiki/Base64
    [accessed on December 28 2010].

    The Legion of the Bouncy Castle. bouncycastle.org [online].
    Available on Internet: http://www.bouncycastle.org/
    [accessed on December 28 2010].

    Sunday, January 9, 2011

    Servlet-GSON vs JSONME-JavaME III

    This is the third post about JSON and JavaME. In previous releases: first we introduced JSON for JavaMe (J2ME), then we improved the example by adding compression/decompression support. Now, we are going to introduce Base64 format support for sending images in our JSON example.
    Although this is not a best practice, because you should send the image's URL  instead of sending the image itself in the JSON String, sometimes you just need to do exactly that.

    Requirements:

    Servlet-GSON vs JSONME-JavaME: Contains the original classes. More info:
    http://www.java-n-me.com/2010/11/servlet-gson-vs-jsonme-javame.html

    Servlet-GSON vs JSONME-JavaME II: Second part of the saga. Adds compression/decompression support. More info:
    http://www.java-n-me.com/2010/12/servlet-gson-vs-jsonme-javame-ii.html

    Base64 encode-decode in JavaMe: Explains how to use Base64 format in JavaMe (J2ME). More info:
    http://www.java-n-me.com/2010/12/base64-encode-decode-in-javame.html


    You should check the previous requirements if you haven't, because in this post we use some of the classes defined there.

    The image we are going to send is in PNG format:



    OK, let's begin, first we are going to show you the changes in some of the original classes. As usual, let's start with the server side:

    import java.awt.Image;
    public class Client {

       /** Name of the client*/
        private String name;

        /** Last name of the client*/
        private String lastName;

        /** Identification of the client*/
        private String id;

        /** Photo of the client*/
        private transient Image photo;


        /** Photo of the client in Base 64 format*/
        private  String photoBase64;


        //Getters and Setters...
    }

    Our Client class has now two new attributes for the photograph of the client. The java.awt.Image attribute binds to the photograph of the client directly. The String attribute photoBase64 contains the Base64 format of the photograph that is going to be sent in the JSON String. Notice that the attribute photo is marked as transient, meaning that GSON won't use this attribute in the JSON String.

    Following is the servlet class which will create a client with a photograph, will get the JSON String representation of the client and his photograph and will compress the data before sending the response to the mobile client. The servlet uses the GSON API, the java.util.zip.GZIPOutputStream and the JSE sun.misc.BASE64Encoder class:


    import com.google.gson.Gson;
    import java.io.*;
    import java.net.URL;
    import java.util.Vector;
    import java.util.zip.GZIPOutputStream;
    import javax.servlet.ServletException;
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.*;
    import javax.swing.ImageIcon;
    import model.Client;
    import sun.misc.BASE64Encoder;

    public class ClientsServlet extends HttpServlet {
       ...

        /**
         * Handles the HTTP <code>POST</code> method.
         * @param request servlet request
         * @param response servlet response
         * @throws ServletException if a servlet-specific error occurs
         * @throws IOException if an I/O error occurs
         */
        protected void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
            //sets the type of response and the charset used
            //Be careful, in your mobile client, read the response using the same charset
            //if sending the response as text. If you sent it as binary data,
            //there is no problem
            response.setContentType("application/json; charset=UTF-8");

            //create some clients and add them to the vector
            Vector vClients = new Vector();

            //used to convert Image to Base64 format
            BASE64Encoder encoder = new BASE64Encoder();

            Client clientOne = new Client();
            clientOne.setName("Alexis");
            clientOne.setLastName("López Ñ");
            clientOne.setId("123456");
            clientOne.setPhoto(new ImageIcon("images/duke.png").getImage());
            //get the image bytes. Read it as an URL
            byte[] imgBytes =
              getImageBytes("http://localhost:8080/GSON_Servlet/images/duke.png");
            String imageCoded = encoder.encode(imgBytes);
            clientOne.setPhotoBase64(imageCoded);

            //... add more clients...
          
            vClients
               .add(clientOne);

            //convert the clients vector to JSON using GSON, very Easy
            Gson gson = new Gson();
            String jsonOutput = gson.toJson(vClients);

            System.out.println("*****JSON STRING TO RESPONSE*****");
            System.out.println(jsonOutput);
            System.out.println("*********************************");

            System.out.println("Length of String in bytes = "
                                        + jsonOutput.getBytes().length);
            //compress de data
            byte[] compressed = compress(jsonOutput);
            System.out.println("Length of compressed bytes = "
                                        + compressed.length);

            //send the binary response
            ServletOutputStream out = response.getOutputStream();
            out.write(compressed, 0, compressed.length);
            out.flush();
            out.close();
        }
        ...
    }

    The servlet uses two important methods. One is the +compress(String):byte[] that we have analized in the previous post of this saga. The other one is the +getImageBytes(String):byte[] which is shown next:

    /** * Returns the binary representation of the image passed as an URL * @param imgURL URL String of the image * @return array of binary data representing the image * @throws IOException */ public static byte[] getImageBytes(String imgURL) throws IOException { URL imgUrl = new URL(imgURL); ByteArrayOutputStream bout = new ByteArrayOutputStream(); InputStream in = imgUrl.openStream(); int i = 0; while ((i = in.read()) != -1) { bout.write(i); } in.close(); bout.close(); byte[] bytes = bout.toByteArray(); return bytes; }

    The last method reads the image from the URL and gets its binary representation. One important thing to keep in mind, is that you should use PNG Images as it is the default format for JavaMe (J2ME) MIDP applications, not doing so may arise exceptions on the mobile client when parsing the Image data. When the servlet is run and it receives a POST request, the following message is shown on the console output:

    INFO: *****JSON STRING TO RESPONSE***** 9/01/2011 06:11:23 PM INFO: [{"name":"Alexis","lastName":"López Ñ","id":"123456","photoBase64":"iVBORw0KGgoAAAANSUhEUgAAAP8AAADICAMAAAAQqcftAAAAAXNSR0IArs4c6QAAAwBQTFRFDAAA\r\nCgQKGAAAEAgMGAAIGAAQGAgIGAgQEBAIABAQCBAQEBAQEBAYEBgQEBgYECEYGAgYGBAIGBAQGBAY\r\nGBgIGBgQGBgYGBghGCEYIQAAIQAIIQAQIQgQIQgYIRAQIRAYKQAMKQgQKQAYIRAhIRgQIRgYIRgh\r\nISEYMQAILgUVNwQSQgAYKRAUKRgYKSEYPA0YISEhKRAhKRghKRgpMRQhMRgpPQghPRQhKSEhKSkh\r\nISEpKSYrMSUlNi4pOScvOzU1SBwpRkI9WgYgbBk1RkJKTkdHVkhNVFJMUlJaWlRUXlhaZVtdb2Fk\r\ncWxne2lwf3h5yBUsqDBU1Bcx0SRJ3BU53xs53yJK4TJjin5"
    ... not all data shown ... "}] INFO: *********************************



    INFO: Length of String in bytes = 17425
    INFO: Length of compressed bytes = 12890

    As you can see, the JSON representation of the client now has the photograph in Base64 format in order to send the image data to the mobile client as part of the JSON String. Also notice that there is some compression in the response to the client.

    On the mobile client side, there are also changes in the Client class:

    import java.util.Vector;
    import javax.microedition.lcdui.Image;
    import org.bouncycastle.util.encoders.Base64;
    import org.json.me.JSONArray;
    import org.json.me.JSONException;
    import org.json.me.JSONObject;

    public class Client {


        /** Name of the client*/
        private String name;

        /** Constant name of the attribute name*/
        private static final String ATT_NAME = "name";

        /** Last name of the client*/
        private String lastName;

        /** Constant name of the attribute last name*/
        private static final String ATT_LAST_NAME = "lastName";

        /** Identification of the client*/
        private String id;

        /** Constant name of the attribute id*/
        private static final String ATT_ID = "id";

        /** Photo of the client*/
        private  Image photo;

        /** Photo of the client in Base 64 format*/
        private  String photoBase64;


         /** Constant name of the attribute photoBase64*/
        private static final String ATT_PHOTO_BASE_64 = "photoBase64";

        //Getters and Setters...

        /**
         * This method should be used by this class only, that's why it is private.
         * Allows to get a JSONObject from the Client passed as parameter
         * @param client Client Object to convert to JSONObject
         * @return JSONObject representation of the Client passed as parameter
         */
        private static JSONObject toJSONObject(Client client) {
            JSONObject json = new JSONObject();
            try {
                json.put(ATT_NAME, client.getName());
                json.put(ATT_LAST_NAME, client.getLastName());
                json.put(ATT_ID, client.getId());
                //only if the client has a photo associated send it as JSON
                if(client.getPhotoBase64() != null)
                {
                    json.put(ATT_PHOTO_BASE_64, client.getPhotoBase64());
                }
            } catch (JSONException ex) {
                ex.printStackTrace();
            }
            return json;
        }

        /**
         * Allows to get a Client Object from a JSON String
         * @param jsonText JSON String to convert to a Client Object
         * @return Client Object created from the String passed as parameter
         */
        public static Client fromJSON(String jsonText) {
            Client client = new Client();
            try {
                JSONObject json = new JSONObject(jsonText);

                //check if the JSON text comes with the attribue Name
                if (json.has(ATT_NAME)) {
                    //asign the String value of the attribute name to the client
                    client.setName(json.getString(ATT_NAME));
                }

                //check if the JSON text comes with the attribue last name
                if (json.has(ATT_LAST_NAME)) {
                    client.setLastName(json.getString(ATT_LAST_NAME));
                }

                //check if the JSON text comes with the attribue id
                if (json.has(ATT_ID)) {
                    client.setId(json.getString(ATT_ID));
                }

                 //check if the JSON text comes with the attribue photo
                if (json.has(ATT_PHOTO_BASE_64)) {
                    client.setPhotoBase64(json.getString(ATT_PHOTO_BASE_64));


                    //once the photo in base 64 format has been read,
                    //convert it to an Image. IMPORTANT: PNG image format or
                    //you may get an Exception
                    byte[] decoded = Base64.decode(client.getPhotoBase64());
                    Image img = Image.createImage(decoded, 0, decoded.length);
                    client.setPhoto(img);
                }
            } catch (JSONException ex) {
                ex.printStackTrace();
            }
            return client;
        }
    }

    You can find the changes in bold. The important changes are the adition of the attributes for managing the photograph and the modification of the methods for parsing the JSON String to and from an Object. Notice the use of the org.bouncycastle.util.encoders.Base64 class to decode the Base64 format data of the photograph. You can find the original source code of the Client class (mobile client side) in the first post of this saga.

    Next is the MIDlet that runs the code:

    import com.tinyline.util.GZIPInputStream;
    import java.io.*;
    import java.util.Vector;
    import javax.microedition.io.*;
    import javax.microedition.lcdui.Display;
    import javax.microedition.lcdui.Form;
    import javax.microedition.midlet.*;


    public class JSONMIDlet extends MIDlet {


        private Form f = null;


        public JSONMIDlet() {
            //form for the photos
            f = new Form("Photo testing");
        }


        public void pauseApp() {
        }


        public void destroyApp(boolean unconditional) {
            notifyDestroyed();
        }


        public void startApp() {
            try {
                //ask for the clients
                Vector clients = getClients();


                //show information of the clients
                System.out.println("*****CLIENT INFORMATION*****");
                for (int i = 0; i < clients.size(); i++) {
                    Client cl = (Client) clients.elementAt(i);


                    System.out.println("Client " + (i + 1) 
                                                    + " name = " + cl.getName());
                    System.out.println("Client " + (i + 1) 
                                                    + " last name = " + cl.getLastName());
                    System.out.println("Client " + (i + 1) 
                                                    + " ID = " + cl.getId());
                    System.out.println("Client " + (i + 1) 
                                                    + " Photo Base64 = " + cl.getPhotoBase64());
                    System.out.println("");


                    //if the client has a photo, append it to the form
                    if (cl.getPhoto() != null) {
                        f.append(cl.getPhoto());
                    }
                }




                Display dsp = Display.getDisplay(this);
                dsp.setCurrent(f);




            } catch (IOException ex) {
                //manage the exception
                ex.printStackTrace();
            }
        }


    ...//other methods


    }

    The method +getClients():Vector has not changed and can be found in the last post of this saga (as there is compression/decompression support). Finally the emulator shows the following:


    Well, that's it for today. Quite a large post, I hope I was clear enaugh, but if you have any questions do not hesitate to contact me.

    see ya soon!


    References:

    TinyLine Utils. 2010. TinyLine [online].
    Available on Internet: http://www.tinyline.com/utils/index.html
    [accessed on December 11 2010].

    Using JavaScript Object Notation (JSON) in Java ME for Data Interchange. Agosto 2008. Oracle [online].
    Available on Internet: http://java.sun.com/developer/technicalArticles/javame/json-me/
    [accessed on October the 26th 2010].

    meapplicationdevelopers: Subversion. 2007. Oracle [online].
    Available on Internet: https://meapplicationdevelopers.dev.java.net/source/browse/meapplicationdevelopers/demobox/mobileajax/lib/json/
    [accessed on October the 27th 2010].

    The Legion of the Bouncy Castle. bouncycastle.org [online].
    Available on Internet: http://www.bouncycastle.org/
    [accessed on December 28 2010].