Securing web application deployed in Jetty

I wanted to figure out how to secure web application that is deployed in Jetty. Basic idea was i did create a UserServlet when user tries to access it he should be prompted for basic authentication and once user logs in check if he has admin role if yes then display "You have reached secure call" message, You can download the sample application from here This screen shot represents when user gets basic authentication prompt This is screen shot of screen that is displayed to the user after successful login I followed these steps to create the secured web application
  1. First i did create a UserServlet.java like this
    
    package com.webspherenotes.rest;
    import java.io.IOException;
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class UserServlet extends HttpServlet{
    
      @Override
      protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
        resp.setContentType("text/html");
        resp.getWriter().println("You have reached secure call");
      }
    
    }
    
    
    This servlet has only doGet() method and when it gets control it writes You have reached secure call message in the output
  2. Next i changed the web.xml to protect the UserServlet so that it looks like this
    
    <!DOCTYPE web-app PUBLIC
     "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
     "http://java.sun.com/dtd/web-app_2_3.dtd" >
    
    <web-app>
      <display-name>Archetype Created Web Application</display-name>
      <servlet>
        <servlet-name>User</servlet-name>
        <servlet-class>com.webspherenotes.rest.UserServlet</servlet-class>
      </servlet>
      <servlet-mapping>
        <servlet-name>User</servlet-name>
        <url-pattern>/user</url-pattern>
      </servlet-mapping>
    
      <security-constraint>
        <web-resource-collection>
          <web-resource-name>user</web-resource-name>
          <url-pattern>/user</url-pattern>
          <http-method>GET</http-method>
        </web-resource-collection>
        <auth-constraint>
          <role-name>ADMIN</role-name>
        </auth-constraint>
      </security-constraint>
    
      <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>Default</realm-name>
      </login-config>
    
      <security-role>
        <role-name>ADMIN</role-name>
      </security-role>
    </web-app>
    
    The security-constraint element says that protect GET calls to /user url and allow only those users who have ADMIN user right to access the servlet. The login-config element defines Default as realm name
  3. Next change the maven build file to configure maven-compiler-plugin so that it uses login service
    
    <build>
      <finalName>JettySecurity</finalName>
      <plugins>
        <plugin>
          <groupId>org.mortbay.jetty</groupId>
          <artifactId>jetty-maven-plugin</artifactId>
          <version>7.4.5.v20110725</version>
          <configuration>
            <scanIntervalSeconds>10</scanIntervalSeconds>
            <webAppConfig>
              <contextPath>/JettySecurity</contextPath>
            </webAppConfig>
            <loginServices>
              <loginService implementation="org.eclipse.jetty.security.HashLoginService">
                <name>Default</name>
                <config>${basedir}/src/main/resources/realm.properties</config>
              </loginService>
            </loginServices> 
            <connectors>
              <connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
                <port>9000</port>
                <maxIdleTime>60000</maxIdleTime>
              </connector>
            </connectors>
          </configuration>
        </plugin>
      </plugins>
    </build>
    
    The loginService element asks Jetty to use list of users and passwords from ${basedir}/src/main/resources/realm.properties file to authenticate users
  4. Next create realm.properties file which looks like this
    
    guest:guest
    admin:admin,ADMIN
    
    This file has only 2 users first is guest and second is admin the admin user has ADMIN role.
Now if you deploy the application by executing mvn jetty:run and then try accessing http://localhost:9000/JettySecurity/user URL you will get prompted for login. If you login as admin, admin then you should be able to access the UserServlet. But if you login as guest then you should see this error page

Using JPA in REST web application deployed in Jetty

I wanted to figure out how to use Hibernate JPA in a web application deployed in Jetty server, so i built this sample Contact REST service that uses JPA to perform CRUD operations on the CONTACT table and expose those operations using REST, you can download it from here I followed these steps to build the REST service.
  1. First i did create a Contact.java class which is a Entity class representing CONTACT table
    
    package com.webspherenotes.rest;
    
    import javax.persistence.Entity;
    import javax.persistence.Id;
    import javax.xml.bind.annotation.XmlRootElement;
    
    @Entity
    @XmlRootElement
    public class Contact {
     @Id
     private int contactId;
    
     private String firstName;
     private String lastName;
     private String email;
     
     public int getContactId() {
      return contactId;
     }
     public void setContactId(int contactId) {
      this.contactId = contactId;
     }
     public String getFirstName() {
      return firstName;
     }
     public void setFirstName(String firstName) {
      this.firstName = firstName;
     }
     public String getLastName() {
      return lastName;
     }
     public void setLastName(String lastName) {
      this.lastName = lastName;
     }
     public String getEmail() {
      return email;
     }
     public void setEmail(String email) {
      this.email = email;
     }
     
     @Override
     public String toString() {
      return "Contact [contactId=" + contactId + ", firstName=" + firstName
        + ", lastName=" + lastName + ", email=" + email + "]";
     }
    }
    
    The contactId field represents the primary key for contact table. The Contact class has Entity annotation that maps it to table in database.
  2. Then i did create peristence.xml file which acts as deployment descriptor for the JPA in the META-INF folder of the application like this
    
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.0"
     xmlns="http://java.sun.com/xml/ns/persistence" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
     http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
     <persistence-unit name="MyJPAJAXRS">
      <class>com.webspherenotes.rest.Contact</class>
      <properties>
       <property name="javax.persistence.jdbc.driver" 
       value="org.apache.derby.jdbc.ClientDriver" />
       <property name="javax.persistence.jdbc.url" 
       value="jdbc:derby://localhost:1527/C:/data/contact;create=true" />
       <property name="javax.persistence.jdbc.user" value="dbadmin" />
       <property name="javax.persistence.jdbc.password" value="dbadmin" />
      </properties>
     </persistence-unit>
    </persistence>
    
    The persistence.xml file is using JDBC driver properties for connecting to Apache Derby database.
  3. Create ContactApplication.java class which be the Application class for this REST application
    
    package com.webspherenotes.rest;
    javascript:void(0);
    import java.util.HashSet;
    import java.util.Set;
    
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Persistence;
    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    @ApplicationPath("rest")
    public class ContactApplication extends Application{
      Logger logger = LoggerFactory.getLogger(ContactApplication.class);
    
      @Override
      public Set<Object> getSingletons() {
        logger.debug("Entering ContactApplication.getSingletons()");
        EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("MyJPAJAXRS");
        ContactService contactService = new ContactService(entityManagerFactory);
        Set<Object> singletons = new HashSet<Object>();
        singletons.add(contactService);
        logger.debug("Exiting ContactApplication.getSingletons()");
        return singletons;
      }
    
    }
    
    The ContactApplication class overrides getSingletons() method so that it can create single instance of ContactService, which will be responsible for handling all the requests for ContactService. Since Jersey in not JEE 6 container i am responsible for creating object of EntityManagerFactory. After creating object of EntityManagerFactory i am injecting it into the ContactService class.
  4. The last step is to create ContactService.java, which exposes the REST operations
    
    package com.webspherenotes.rest;
    
    import java.util.List;
    
    import javax.persistence.EntityManager;
    import javax.persistence.EntityManagerFactory;
    import javax.persistence.Query;
    import javax.ws.rs.Consumes;
    import javax.ws.rs.DELETE;
    import javax.ws.rs.FormParam;
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.PUT;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.MediaType;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    @Path("/contact")
    public class ContactService {
    
      Logger logger = LoggerFactory.getLogger(ContactService.class);
      
      EntityManagerFactory entityManagerFactory;
      public ContactService(EntityManagerFactory entityManagerFactory){
        this.entityManagerFactory=entityManagerFactory;
      }
    
      @GET
      @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
      public List getContactList() {
        logger.debug("Entering ContactService.getContactList()");
    
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        Query q = entityManager.createQuery("SELECT x from Contact x");
        logger.debug("Exiting ContactService.getContactList()");
    
        return (List) q.getResultList();
      }
    
      @GET
      @Path("/{contactId}")
      @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
      public Contact getContact(@PathParam("contactId") int contactId) {
        logger.debug("Entering ContactService.getContact() contactId" + contactId);
    
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        Contact contact = entityManager.find(Contact.class, contactId);
        logger.debug("Exiting ContactService.getContact()" );
    
        return contact;
      }
      
      @POST
      @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
      @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
      public Contact insertContact(@FormParam("contactId") int contactId,
          @FormParam("firstName") String firstName,
          @FormParam("lastName") String lastName,
          @FormParam("email") String email) {
        logger.debug("Entering ContactService.insertContact()");
    
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        Contact contact = new Contact();
        contact.setContactId(contactId);
        contact.setFirstName(firstName);
        contact.setLastName(lastName);
        contact.setEmail(email);
        try{
        entityManager.getTransaction().begin();
        
        entityManager.persist(contact);
        entityManager.getTransaction().commit();
        }catch(Throwable t){
          if(entityManager.getTransaction().isActive())
            entityManager.getTransaction().rollback();
          contact = null;
        }finally{
          entityManager.close();
        }
        logger.debug("Exiting ContactService.insertContact()");
        return contact;
      }
    
    
      @PUT
      @Path("/{contactId}")
      @Produces({MediaType.APPLICATION_JSON,MediaType.APPLICATION_XML})
      @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
      public Contact updateContact(@PathParam("contactId") int contactId,
          @FormParam("firstName") String firstName,
          @FormParam("lastName") String lastName,
          @FormParam("email") String email) {
        logger.debug("Entering ContactService.update() contactId" + contactId);
    
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        Contact contact = new Contact();
        contact.setContactId(contactId);
        contact.setFirstName(firstName);
        contact.setLastName(lastName);
        contact.setEmail(email);
        try{
        entityManager.getTransaction().begin();
        entityManager.merge(contact);
        entityManager.getTransaction().commit();
        }catch(Throwable t){
          if(entityManager.getTransaction().isActive())
            entityManager.getTransaction().rollback();
          contact = null;
        }finally{
          entityManager.close();
        }
        logger.debug("Exiting ContactService.updateContact()");
    
        return contact;
      }
    
      @DELETE
      @Path("/{contactId}")
    
      public void deleteContact(@PathParam("contactId") int contactId) {
        logger.debug("Entering ContactService.deleteContact() contactId " + contactId);
        EntityManager entityManager = entityManagerFactory.createEntityManager();
        try{
          entityManager.getTransaction().begin();
          Contact contact = entityManager.find(Contact.class, contactId);
          logger.debug("remove contact " + contact);
          entityManager.remove(contact);
          logger.debug("After removing " + contact);
          entityManager.getTransaction().commit();
          }catch(Throwable t){
            if(entityManager.getTransaction().isActive())
              entityManager.getTransaction().rollback();
    
          }finally{
            entityManager.close();
          }
        logger.debug("Exiting ContactService.deleteContact()");
      }
    
    }
    
    The ContactService class exposes CRUD operations on the CONTACT table using REST

Using native alerts and cofirmations of mobile using Cordova

The PhoneGap/Cordova framework allows you to display native dialog box of the device, which allows you to use say custom title and better control on number of buttons on the dialog box. In addition to that it also allows you to beep or vibrate the device(Both beep and vibrate feature dont seem to work in the Android emulator). I wanted to try these features so i built this sample application, which allows you to play with different notifications. This is how the native alert box looks like This is how the native confirmation box looks like I followed these steps to build Android PhoneGap application
  1. I followed the instructions in Getting Started with Android to build application that points to index.html inside the application, i tried it once to make sure that it works
  2. Then i used the following index.html code
    
    <!DOCTYPE html>
    <html>
      <head>
        <title>Google Map Example</title>
      <meta name="viewport" content="width=device-width, 
      initialscale=1.0, user-scalable=no"></meta>
        <script type="text/javascript" charset="utf-8" 
    src="cordova-1.7.0.js"></script>
        <script type="text/javascript" charset="utf-8">
        function alertDismissed() {
            console.log("Inside alertDismissed");
        }
        function onConfirm(){
          console.log("Inside onConfirmation");
        }
        function showAlert() {
            navigator.notification.alert(
                'Sample native alert message',  
                alertDismissed,         
                'Sample native alert title',            
                'alert'                  
            );
        }
        function showConfirmation(){
          navigator.notification.confirm(
                  'Sample native confirmation',  
                  onConfirm,              
                  'Sample confirmation title',            
                  'Confirm'          
              );
        }
        function playBeep() {
            navigator.notification.beep(3);
        }
        function vibrate() {
            navigator.notification.vibrate(2000);
        }
        </script>
      </head>
      <body >
        <ul>
          <li><a href="#" onclick="alert('Browser alert'); 
    return false;">Show browser Alert</a></li>
          <li><a href="#" onclick="showConfirmation(); 
    return false;">Show Confirmation</a></li>
          <li><a href="#" onclick="showAlert(); 
    return false;">Show Alert</a></li>
          <li><a href="#" onclick="playBeep(); 
    return false;">Play Beep</a></li>
          <li><a href="#" onclick="vibrate(); 
    return false;">Vibrate</a></li>
        </ul>
         <p></p>
      </body>
    </html>
    
    The HTML of the page shows 5 different links each pointing to one JavaScript function. Each of the functions uses Phone Gap native feature to display native dialog boxes.

Google Map in PhoneGap/Cordova application

I wanted to figure out how to use Google Maps API in the Phone GAP application so i built this sample application that lets you enter address and it displays that address on the Map, you can download the sample application from here This is a screen shot of how my application looks like
This is how the index.html page for my application looks like

<!DOCTYPE html>
<html>
  <head>
    <title>Google Map Example</title>
 <style type="text/css">
      html { height: 100% }
      body { height: 100%; margin: 0; padding: 0 }
      #map_canvas { height: 100% }
    </style>
    <script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
    <script type="text/javascript" charset="utf-8" src="jquery.js"></script>
    <script src="http://maps.google.com/maps/api/js?sensor=true"></script>
    <script type="text/javascript" charset="utf-8">
    function displayCurrentLocation(){
     console.log("Entering displayCurrentLocation()");
  try{
   var currentLocationLatAndLong = new google.maps.LatLng(37.422006,-122.084095);
   var mapOptions ={
    zoom:8,
    center:currentLocationLatAndLong,
    mapTypeId: google.maps.MapTypeId.ROADMAP
   };
   var mapDiv = document.getElementById("map");
   map = new google.maps.Map(mapDiv,mapOptions);
  }catch(e){
   console.log("Error occured in ConsultantLocator.displayMap() " + e);
  }
     console.log("Exiting displayCurrentLocation()");
    }
    function addMarker(latLng,title,contentString){
  console.log("Entering addMarker()");
  var markerOptions = new google.maps.Marker({
    map: map,
    position: latLng,
    title:title,
    clickable:true
   });
  var marker = new google.maps.Marker(markerOptions);
  var infoWindowOptions = {
   content: contentString,
   position: latLng
  };
  var infoWindow = new google.maps.InfoWindow(infoWindowOptions);
  google.maps.event.addListener(marker, "click", function(){
   infoWindow.open(map);
  });
  console.log("Exiting addMarker()");
 }
    function getLatLangFromAddress(address){
     console.log("Entering getLatLangFromAddress()");
     var geocoder = new google.maps.Geocoder();
     geocoder.geocode( { 'address': address}, function(results, status) {

      if (status == google.maps.GeocoderStatus.OK) {
    var returnedValue =results[0].geometry.location;
       console.log("Address found is " + returnedValue);
       addMarker(returnedValue);
      }else{
       alert("Geocode was not successful for the following reason: " + status);
      }
        });
     console.log("Exiting getLatLangFromAddress()");
    }
    function addMarkerForAddress(){

     console.log("Entering addMarkerForAddress()");
     var address = $("#address").val();
     console.log($("#address"));
     var latLangForLocation = getLatLangFromAddress(address);
     console.log("Value returned by getLatLangFromAddress " +latLangForLocation);
     addMarker(latLangForLocation,address,address);
     console.log("Exiting addMarkerForAddress()");
    }
 document.addEventListener("deviceready", displayCurrentLocation, false);
    </script>
  </head>
  <body >
   <p>
    <input type="text" name="address" id="address" />
    <input type="button" id="getLocation" onclick="addMarkerForAddress()" value="Get Location"/>
   </p>
    <div id="map" style="width:100%; height:100%"></div>
  </body>
</html>
This application loads the google map during startup. When user enters address and clicks on get location it takes the address and uses it to find the latitude and longitude for that address and then users addMarker() method to display maker for that location

Using ripple mobile browser emulator for testing PhoneGap

One of the biggest pain point for testing PhoneGap application is deploying it on emulator and testing it, that process takes long time. So i started using the Ripple which is Google Chrome extension and it makes testing PhoneGap application really easy.
  1. Install Ripple extension in Chrome
  2. Start the Google Chrome browser with its access to local file system by executing chrome.exe -–allow-file-access-from-files
  3. Then Right click on the Ripple symbol and say Manage Google Extensions, on the next screen check Allow access to file URLs check box
  4. Now open index.html from the phoneGap application using file URL and enable Ripple for it
  5. Now you can test the geolocation application like this. With Ripple advantage is you can directly open the HTML in browser and then set geolocation directly using Ripple

Using Geolocation API in Android Emulator

In the Getting address of the current location using GeoLocation API and Google MAP api entry i talked about how to use the GeoLocation API provided as part of HTML 5 to get the current address of the user. Now Phone Gap also provides support for geolocation which means it checks if the browser on the device has support for geolocation if yes it lets it work if not it will call the native API of the underlying browser to get the the location and return it to browser. I wanted to try that so i took the content of geolocation.html and copied it in the index.html file that my phonegap application for android is using, you can download that app from here I followed these steps to build Android PhoneGap application
  1. I followed the instructions in Getting Started with Android to build application that points to index.html inside the application, i tried it once to make sure that it works
  2. Then i copied the content of Geolocation.html in the index.html page
  3. Change the AndroidManifest.xml file to allow application to use the mock location
    
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.webspherenotes.phonegap"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk android:minSdkVersion="8" />
        <uses-permission android:name="android.permission.CAMERA" />
      <uses-permission android:name="android.permission.VIBRATE" />
      
      <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
      <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
      <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />
      <uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
     
     <uses-permission android:name="android.permission.READ_PHONE_STATE" />
      <uses-permission android:name="android.permission.INTERNET" />
      <uses-permission android:name="android.permission.RECEIVE_SMS" />
      <uses-permission android:name="android.permission.RECORD_AUDIO" />
      <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
      <uses-permission android:name="android.permission.READ_CONTACTS" />
      <uses-permission android:name="android.permission.WRITE_CONTACTS" />
      <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
      <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
      <uses-permission android:name="android.permission.GET_ACCOUNTS" />
      <uses-permission android:name="android.permission.BROADCAST_STICKY" />
        <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
            <activity
                android:name=".HelloPhoneGapActivity"
                android:label="@string/app_name" 
                android:configChanges="orientation|keyboardHidden" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    </manifest>
    
  4. The android emulator does not know how to find out current location of the user, so we have to setup mock location i.e. hard code a location for the user. For that you have two options either use the DDMS perspective in your Eclipse and after your emulator is started select it and enter value of longitude and latitude and click on send like this.
  5. Or open a Telnet session to the emulator by executing telnet localhost 5554 (you can get port number 5554 from the emulator window it would be in title bar) and then in the telnet window use geo fix -121.9754144 37.5669038 command to set the longitude and latitude like this
Now when i run this application in the Android emulator i can see it displaying the address for location that i sent to the emulator like this

Getting address of the current location using GeoLocation API and Google MAP api

The HTML 5 has concept of Geo Location that lets you read current address of the user, So if your using a mobile device it will give you current address using GPS but if your using normal Laptop or Desktop it still gives you current address with less accuracy. In my case it gives address of AT&T office which is my internet provider. I wanted to figure out how GeoLocation API's work so i build this sample application that displays my current address. You can download the Geolocation.html file from here This is how my Geolocation.html page looks like in browser
My Geolocation.html page has one Get Location button when you click on that button it will show you address of the current location. Now the address is not always accurate. Also i tested this code in Firefox 12.0 and Internet Explorer 9, the Geolocation code does not work in Chrome if your accessing the file directly from file system i mean using file:// URL. This is the source code for the Geolocation.html

<!DOCTYPE html>
<html>
  <head>
    <title>GeoLocation</title>
    <script src="http://maps.google.com/maps/api/js?sensor=true">
 </script>
    <script type="text/javascript" charset="utf-8">
   function getLocation(){
      console.log("Entering getLocation()");
      if(navigator.geolocation){
      navigator.geolocation.getCurrentPosition(
      displayCurrentLocation,
      displayError,
      { 
        maximumAge: 3000, 
        timeout: 5000, 
        enableHighAccuracy: true 
      });
    }else{
      console.log("Oops, no geolocation support");
    } 
      console.log("Exiting getLocation()");
    };
    function displayCurrentLocation(position){
      console.log("Entering displayCurrentLocation");
      var latitude = position.coords.latitude;
    var longitude = position.coords.longitude;
    console.log("Latitude " + latitude +" Longitude " + longitude);
    getAddressFromLatLang(latitude,longitude);
      console.log("Exiting displayCurrentLocation");
    }
   function  displayError(error){
    console.log("Entering ConsultantLocator.displayError()");
    var errorType = {
      0: "Unknown error",
      1: "Permission denied by user",
      2: "Position is not available",
      3: "Request time out"
    };
    var errorMessage = errorType[error.code];
    if(error.code == 0  || error.code == 2){
      errorMessage = errorMessage + "  " + error.message;
    }
    alert("Error Message " + errorMessage);
    console.log("Exiting ConsultantLocator.displayError()");
  }
    function getAddressFromLatLang(lat,lng){
      console.log("Entering getAddressFromLatLang()");
      var geocoder = new google.maps.Geocoder();
        var latLng = new google.maps.LatLng(lat, lng);
        geocoder.geocode( { 'latLng': latLng}, function(results, status) {
        console.log("After getting address");
        console.log(results);
        if (status == google.maps.GeocoderStatus.OK) {
          if (results[1]) {
            console.log(results[1]);
            alert(results[1].formatted_address);
          }
        }else{
          alert("Geocode was not successful 
    for the following reason: " + status);
        }
        });
      console.log("Entering getAddressFromLatLang()");
    }
    </script>
  </head>
  <body>
    <h1>Display the map here</h1>
    <input type="button" id="getLocation"
 onclick="getLocation()" value="Get Location"/>
    <div id="map"></div>
  </body>
</html>
When you click on Get Location button the control goes to getLocation() function which first checks if the browser supports GeoLocation API by checking navigator.geolocation object, if that object is not null that means browser supports GeoLocation and we ask browser for current location by calling navigator.geolocation.getCurrentPosition() with displayCurrentLocation() as a call back function if the current location lookup was successful. The browser calls displayCurrentLocation() function with current location using position object, which has longitude and latitude as properties. The latitude and longitude would have values like Latitude 37.5668988 Longitude -121.9753273, so we have to use the Google MAP API to get street address from the longitude and latitude values, for that we call getAddressFromLatLang function. Inside the getAddressFromLatLang() function i am creating object of google.maps.Geocoder and calling its geocode() method with latitude and longitude and it returns array of addresses for that location. Once i have the address i can print it using alert.

Using JQuery Mobile in PhoneGap/Cordova application

JQuery Mobile is one of the most popular Mobile UI frameworks, i wanted to figure out how to use it in Cordova application so i built a sample application that uses JQuery Mobile and also the Cordova device API to display device related properties in JQuery Mobile UI. You can download the sample application from here. I followed these steps to build this application
  1. I followed the instructions in Getting Started with Android to build application that points to index.html inside the application, i tried it once to make sure that it works
  2. I did download the jquery.mobile-1.1.0.zip from JQuery Mobile Download page
  3. I did unzip the jquery.mobile-1.1.0.zip in c:\software folder
  4. Next i copied the css, docs and js folder from C:\software\jquery.mobile-1.1.0\demos into assets/www folder of my web application.
  5. If your just starting with JQuery mobile or playing around then you can even directly point to the CDN URL of JQuery Mobile without actually downloading it in your application, in that case you can skip step 2 and 3. You can simply add these lines in your HTML page
    
    <link rel="stylesheet"
     href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />
    <script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
    <script
     src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>
    
  6. Next change your index.html page to look like this
    
    <!DOCTYPE html>
    <html>
    <head>
    <title>Device Properties Example</title>
    <script type="text/javascript" charset="utf-8" src="cordova-1.7.0.js"></script>
    <!--  
    <link rel="stylesheet"
     href="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.css" />
    <script src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
    <script
     src="http://code.jquery.com/mobile/1.1.0/jquery.mobile-1.1.0.min.js"></script>
    -->
    <link rel="stylesheet"  href="css/themes/default/jquery.mobile-1.1.0.css" />
    <script src="js/jquery.js"></script>
    <script src="js/jquery.mobile-1.1.0.js"></script>
    <script type="text/javascript" charset="utf-8">
     document.addEventListener("deviceready", onDeviceReady, false);
     function onDeviceReady() {
      console.log("Entering index.html.onDeviceReady");
      //var element = document.getElementById('deviceProperties');
      var html = "";
      html = html + "<li>" + 'Device Name: ' + device.name + "</li>";
      html = html + "<li>" + 'Device Cordova: ' + device.cordova + "</li>";
      html = html + "<li>" + 'Device Platform: ' + device.platform + "</li>";
      html = html + "<li>" + 'Device UUID: ' + device.uuid + "</li>";
      console.log(html);
    
      $("#deviceProperties").html(html);
      $("#deviceProperties").listview('refresh');
      console.log("Exiting index.html.onDeviceReady");
     } 
    </script>
    </head>
    <body>
    
     <div data-role="page" id="page1">
      <div data-theme="a" data-role="header">
       <h3>Hello JQuery Mobile</h3>
      </div>
      <div data-role="content">
       Device Properties
       <ul data-role="listview" data-inset="true" 
        id="deviceProperties">
    
       </ul>
      </div>
      <div data-theme="a" data-role="footer">
       <h3>Copyright stuff</h3>
      </div>
     </div>
     
    </body>
    </html>
    
    My application has one JQuery Mobile page whose content is defined using div with id equal to page1. The div with data-role equal to content defines the content of the page. By default it only has empty ul element, i am using onDeviceReady() JavaScript function to read device property and add them to the list.
This is screen shot of application once its loaded

Accessing external website from PhoneGap application

I wanted to create a PhoneGap application, which instead of pointing to a HTML page inside the application should open my blog site http://wpcertification.blogspot.com these are the steps that i followed to build the application, you can download it from here
  • I followed the instructions in Getting Started with Android to build application that points to index.html inside the application, i tried it once to make sure that it works
  • Then i changed the HelloCordovaActivity like this so that it points to http://wpcertification.blogspot.com
    
    package com.webspherenotes.cordova.sample;
    
    import org.apache.cordova.DroidGap;
    
    import android.app.Activity;
    import android.os.Bundle;
    
    public class HelloCordovaActivity extends DroidGap {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            super.loadUrl("http://wpcertification.blogspot.com");
        }
    }
    
    The onCreate() method is calling super.loadUrl("http://wpcertification.blogspot.com"); so that http://wpcertification.blogspot.com page is opened in the WebView as soon as application starts
  • The default configuration of the PhoneGap application disallows opening of any external URL so i had to change the cordova.xml like this to allow access to http://wpcertification.blogspot.com
    
    <?xml version="1.0" encoding="utf-8"?>
    
    <cordova>
     <!--  
     access elements control the Android whitelist.  
     Domains are assumed blocked unless set otherwise
      -->
    
        <access origin="http://127.0.0.1*"/> <!-- allow local pages -->
     
     
     <access origin="http://wpcertification.blogspot.com" />
     
     
     <!-- <access origin="https://example.com" /> 
     allow any secure requests to example.com -->
     <!-- <access origin="https://example.com" subdomains="true" /> 
     such as above, but including subdomains, such as www -->
     <!--  <access origin=".*"/>   
     Allow all domains, suggested development use only -->
    
        <log level="DEBUG"/>
        <preference name="classicRender" value="true" />
    </cordova>
    
    Take a look at XML comments in this file for syntax on how to allow access to external URLs
Now the application is ready and when i launch it i can see my blog being opened like this

Setting up Android PhoneGap 1.7 development environment

Before few days i did blog about Setting up Android PhoneGap development environment in that case i had PhoneGap 1.6 working on Android 2.2. But then PhoneGap 1.7 came along and the Getting started document document talks about how to setup PhoneGap 1.7 which is now called Apache Cordova with Android 4.0.3. I followed the steps in the document and was able to get it working, one strange thing was after i said run as Android application it did not work as expected for first couple of times but after couple of times it started working, i am still trying to figure out what happened. I built this simple application that uses the device API to print device and Cordova related information. This is how my HTML looks like, you can download the source code for the application from here

<!DOCTYPE html>
<html>
  <head>
    <title>Device Properties Example</title>

    <script type="text/javascript" charset="utf-8" 
 src="cordova-1.7.0.js"></script>
    <script type="text/javascript" charset="utf-8">

    // Wait for Cordova to load
    //
    document.addEventListener("deviceready", onDeviceReady, false);

    // Cordova is ready
    //
    function onDeviceReady() {
        var element = document.getElementById('deviceProperties');

        element.innerHTML = 'Device Name: '     + device.name     + '<br />' + 
                            'Device Cordova: '  + device.cordova  + '<br />' + 
                            'Device Platform: ' + device.platform + '<br />' + 
                            'Device UUID: '     + device.uuid     + '<br />' + 
                            'Device Version: '  + device.version  + '<br />';
    }

    </script>
  </head>
  <body>
    <p id="deviceProperties">Loading device properties...</p>
  </body>
</html>
On the deviceready event i am reading different device properties and displaying them in the page. This is how the page looks like