Creating multi page application in WorkLight

WorkLight allows you to create multi-page application, i wanted to try this feature, so i changed the Contact Search application that i created in Using BusyIndicator common control entry, so that, when executes a search for contact, it returns list of contact names, user can click on one of the contact name to go to the Contact Details page and that page has button that allows user to go back to Summary page. This is how my summary page looks like
When you click on the arrow button next to any user name it takes you to the Details page for that contact which looks like this
You can click on the Summary button on the Details page to go back to the Contact Summary page. I followed these steps to create this sample application
  1. First i changed the main or landing page of my app to mark the div where the new page should be inserted, i did that by setting value of id element to pagePort like this
    
    !DOCTYPE html>
    <html>
    <head>
    ....
    </head>
    <body onload="WL.Client.init({showLogger:true})" id="content"
      style="display: none">
    
      <div data-role="page" id="page1">
        <div data-theme="a" data-role="header">
          <h3>Contact DB App</h3>
        </div>
        <div data-role="content" id="pagePort" >
          <div data-role="fieldcontain">
            <fieldset data-role="controlgroup">
              <label for="textinput1"> First Name </label> <input
                id="contactName" placeholder="" value="" type="text" />
            </fieldset>
          </div>
          <a data-role="button" data-transition="fade"
            href="javascript:getContact()" id="searchContact"> Search
            Contact </a>
          <ul data-role="listview" data-inset="true" data-filter="true"
            id="displayContact">
          </ul>
        </div>
        <div data-theme="a" data-role="footer">
          <h3>Copyright stuff</h3>
        </div>
      </div>
      <script src="js/HelloDatabase.js"></script>
      <script src="js/messages.js"></script>
      <script src="js/auth.js"></script>
    </body>
    </html>
    
  2. Then i did create this new contactDetail.html page in the same directory as that of my first/landing page
    
    <div data-role="content" id="mainContent">
      <div data-role="fieldcontain">
        <fieldset data-role="controlgroup">
          <label for="firstName"> First Name </label> 
          <input id="firstName" placeholder="" value="" type="text" readonly="readonly" />
          <label for="lastName"> Last Name </label> 
          <input id="lastName" placeholder="" value="" type="text" readonly="readonly"/>
          <label for="email"> Email </label> 
          <input id="email" placeholder="" value="" type="text" readonly="readonly"/>
          
          <a data-role="button" data-transition="fade"
            href="javascript:showSummary()" id="searchContact"> Summary </a>
        </fieldset>
      </div>
    </div>
    
    The Details page shows the form with contact details and it has a Summary button that allows user to go back to the summary page, when you click on that button it will pass control to showSummary() method
  3. I had to make changes to my main JavaScript function to make it look like this
    
    var busyIndicator;
    function wlCommonInit() {
      busyIndicator = new WL.BusyIndicator('page1');
    }
    
    function getContact() {
      console.log("Entering getContact() REST service based version");
      var contactName = $('contactName').getValue();
      var invocationData = {
        adapter : "ContactWSService",
        procedure : "searchContact",
        parameters : [ contactName ]
      }
      var options = {
        onSuccess : loadContactSuccess,
        onFailure : loadContactFailure
      }
      busyIndicator.show();
      WL.Client.invokeProcedure(invocationData, options);
    }
    
    function loadContactSuccess(result) {
      console.log("Inside loadContactSuccess " + result);
      var html = '';
      try {
        if (result.status == 200) {
          var contactList = result.invocationResult.Envelope.Body.searchContactResponse.contactList;
          var i = 0;
          for (i = 0; i < contactList.length; i++) {
            var currentContact = contactList[i];
            html = html + '<li><a href="javascript:showContactDetail('
                + currentContact.contactId + ')">'
                + currentContact.firstName + ' '
                + currentContact.lastName + '</a></li>';
          }
        }
        jq("#displayContact").html(html);
        jq("#displayContact").listview('refresh');
        busyIndicator.hide();
      } catch (e) {
        busyIndicator.hide();
      }
    }
    function showContactDetail(contactId) {
      console.log("Show Contact Detail is clicked " + contactId);
      WL.Page.load("contactDetail.html", {
        onComplete : function() {
          console.log("After fragment is loadded ");
          jq('#mainContent').trigger("create");
          getContactDetails(contactId);
        },
        onUnload : function() {
          console.log("After fragment is unloadded ");
        }
      });
    }
    
    function showSummary() {
      WL.Page.load("contactSummary.html", {
        onComplete : function() {
          console.log("After fragment is loadded ");
          jq('#mainContent').trigger("create");
          
        },
        onUnload : function() {
          console.log("After fragment is unloadded ");
        }
      }); 
    }
    
    function getContactDetails(contactId) {
      console.log("Entering getContactDetails()");
      var invocationData = {
        adapter : "ContactWSService",
        procedure : "getContact",
        parameters : [ contactId ]
      }
      var options = {
        onSuccess : getContactDetailsSuccess,
        onFailure : getContactDetailsFailure
      }
      busyIndicator.show();
      WL.Client.invokeProcedure(invocationData, options);
    }
    
    function getContactDetailsSuccess(result) {
      console.log("Entering getContactDetailsSuccess");
      try {
        if (result.status == 200) {
          var displayContact = result.invocationResult.Envelope.Body.getContactResponse.contact;
          $('firstName').value=displayContact.firstName;
          $('lastName').value=displayContact.lastName;
          $('email').value=displayContact.email;
        }
        busyIndicator.hide();
      } catch (e) {
        busyIndicator.hide();
      }
    }
    function getContactDetailsFailure(result) {
      console.log("Entering getContactDetailsFailure");
    }
    
    I had to make quite a few changes in my JavaScript they are as follows
    • loadContactSuccess: The loadContactSuccess method gets called when you execute search and it gets back the result, this method generates one row each for the result. I changed this method so that when it was generating the list i did attach getContactDetails(contactId) method to each row
    • showContactDetail: The showContactDetail method will get called when user clicks on any of the user name, when that happens i am calling WL.Page.load("contactDetails.html" method which replaces the markup inside the page with contactDetail.html, this method also calls the getContactDetails which calls SOAP service with contactId to get details of the contact.
    • showSummary: The showSummary method will be called when user clicks on the Summary button on the details page, it again calls WL.Page.load("contactSummary.html" to replace the markup in the current page with the contact details

Forcing jQuery Mobile to re-evaluate styles/theme on dynamically inserted content

Today i was trying to build a JQuery Mobile application that has multiple pages. When user clicks on the page switch button i take the markup on the new page and insert it in the old page. One problem that i noticed is when you insert HTML into a page and that HTML has jQuery UI widgets then those widgets do not get evaluated, instead jQuery Displays them without any styles. You can solve this problem by calling the $('changedDiv').trigger("create") method with value of the div equal to id where the new markup got inserted


<div id='changedDiv'>
//Insert jQuery widgets here
</div>

Using WL.SimpleDialog() to display error

I wanted to figure out how to use WL.SimpleDialog() so i used it to change the contact application that i developed in Using BusyIndicator common control so that if there is JavaScript Exception during searching of contact it displays that error in Dialog Box like this
This is how my JavaScript looks like after the changes

var busyIndicator;
function wlCommonInit(){
  busyIndicator = new WL.BusyIndicator('page1');
}
function getContact(){
  console.log("Entering getContact() REST service based version");
  var contactName = $('contactName').getValue();
  var invocationData = {
      adapter:"ContactWSService",
      procedure:"searchContact",
      parameters:[contactName]
  }
  var options ={
      onSuccess:loadContactSuccess,
      onFailure:loadContactFailure
  }
  busyIndicator.show();
  WL.Client.invokeProcedure(invocationData, options);
}

function loadContactSuccess(result){
  console.log("Inside loadContactSuccess " + result);
  var html = '';
  try{
  if(result.status == 200){
    var contactList = result.invocationResult.Envelope.Body.
 searchContactResponse.contactList;
    var i = 0;
    for(i =0 ; i < contactList.length ; i++){
      var currentContact = contactList[i];
      html =  html + '<li><a href="#">'+currentContact.firstName 
   +' ' +currentContact.lastName +'</a></li>';
    }   
  }
  jq("#displayContact").html(html);
  jq("#displayContact").listview('refresh');
  busyIndicator.hide();
  }catch(e){
    busyIndicator.hide();
    displayError(e.toString());
  }
}

function loadContactFailure(result){
  console.log("Inside loadContactError " + result);
  busyIndicator.hide();
  displayError(result);
}

function displayError(errorString) {
  var dialogTitle = "Error";
  WL.SimpleDialog.show(dialogTitle, errorString, [ {
    text : 'OK',
    handler : simpleDialogButton1Click
  }
  ]);
}
function simpleDialogButton1Click() {
}

First i did create a displayError() method that takes error message as input and displays it in Modal dialog that has only one button. The simpleDialogButton1Click() would get called when user clicks on OK in the Error dialog but it does not do anything. The displayError() method is getting called from the exception handler class as well as the loadContactFailure() class.

Using BusyIndicator common control

I wanted to try using the BusyIndicator so i decided to change the Contact Search application that i developed in Using JQuery Mobile in WorkLight application entry, so that as soon as user clicks on Search Contact it starts showing the busy indicator and that indicator stays still the results are updated. I made following changes in my JavaScript file.


var busyIndicator;
function wlCommonInit(){
  busyIndicator = new WL.BusyIndicator('page1');
}
function getContact(){
  var contactName = $('contactName').getValue();
  var invocationData = {
      adapter:"ContactWSService",
      procedure:"searchContact",
      parameters:[contactName]
  }
  var options ={
      onSuccess:loadContactSuccess,
      onFailure:loadContactFailure
  }
  busyIndicator.show();
  
  WL.Client.invokeProcedure(invocationData, options);
}

function loadContactSuccess(result){
  console.log("Inside loadContactSuccess " + result);
  var html = '';
  try{
  if(result.status == 200){
    var contactList = result.invocationResult.Envelope.Body.searchContactResponse.contactList;
    var i = 0;
    for(i =0 ; i < contactList.length ; i++){
      var currentContact = contactList[i];
      html =  html + '<li><a href="#">'+currentContact.firstName +' ' 
   +currentContact.lastName +'</a></li>';
    }   
  }
  jq("#displayContact").html(html);
  jq("#displayContact").listview('refresh');
  
  busyIndicator.hide();
  
  }catch(e){
    busyIndicator.hide();
  }
}

function loadContactFailure(result){
  console.log("Inside loadContactError " + result);
  busyIndicator.hide();
}
First i had to create object of WL.BusyIndicator with value of page1 as input, page1 is the value of id attribute on enclosing div in my page. Without that i was getting JavaScript initialization error. Then the getContact() which is responsible for initiating the contact search call invokes the show() method to start the BusyIndicator. I am calling the hide() method of BusyIndicator in the loadContactSuccess() method which is a callback method that gets called once the results are ready and the UI is updated.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport"
  content="width=device-width, initial-scale=1.0, maximum-scale=1.0, 
  minimum-scale=1.0, user-scalable=0" />
<title>HelloDatabase</title>
<link rel="shortcut icon" href="images/favicon.png" />
<link rel="apple-touch-icon" href="images/apple-touch-icon.png" />
<link rel="stylesheet" href="css/reset.css" />
<link rel="stylesheet" href="css/HelloDatabase.css" />
<link rel="stylesheet" href="css/jquery.mobile-1.0.min.css" />
<script src="js/jquery-1.7.1.min.js"></script>
<script>
  var jq = jQuery.noConflict();
</script>

<script src="js/jquery.mobile-1.0.min.js"></script>
</head>
<body onload="WL.Client.init({showLogger:true})" id="content" style="display: none">
  <div data-role="page" id="page1">
    <div data-theme="a" data-role="header">
      <h3>Contact DB App</h3>
    </div>
    <div data-role="content">
      <div data-role="fieldcontain">
                    <fieldset data-role="controlgroup">
                        <label for="textinput1">
                           First Name
                        </label>
                        <input id="contactName" placeholder="" value="" type="text" />
                    </fieldset>
                </div>
                <a data-role="button" data-transition="fade" 
    href="javascript:getContact()" id="searchContact">
                    Search Contact
                </a>
      <ul data-role="listview" data-inset="true" data-filter="true" id="displayContact">
      </ul>
    </div>
    <div data-theme="a" data-role="footer">
      <h3>Copyright stuff</h3>
    </div>
  </div>
  <script src="js/HelloDatabase.js"></script>
  <script src="js/messages.js"></script>
  <script src="js/auth.js"></script>
</body>
</html>

WorkLight SOAP Service debugging

I ran into few issues while working on Accessing SOAP service from the WorkLight app blog entry and these are the solutions to those problems First problem was i had to build the SOAP request in JavaScript manually for use in the HTTP Adapter class and since this code runs on server i was not able to debug it, and i was not sure what message is getting built. So i used the WL.Logger.debug("SOAP Request " + searchContactRequest) call in my Adapter code and then when i hit the adapter it did write this log statement in \Worklight\server\log\server\server.log directory like this 2012-03-29 15:40:30,469 DEBUG [developer] (pool-7-thread-2:0ad7210e-9ed8-4c58-9b38-853d1918131b) SOAP Request <soapenv:Envelope xmlns:q0="http://webspherenotes.com" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soapenv:Header> </soapenv:Header> <soapenv:Body> <q0:searchContact> <arg0>at</arg0> </q0:searchContact> </soapenv:Body> </soapenv:Envelope> The worklight server does take care of writing the response of the SOAP request into the same log file, so having log enabled for com.srndpt.adapters helps Also note that the WorkLight server takes care of converting the SOAP XML response into JSON This is the response of my SOAP Service <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> - <S:Body> - <ns2:searchContactResponse xmlns:ns2="http://webspherenotes.com"> - <contactList> <contactId>1</contactId> <email>sdpatil@gmail.com</email> <firstName>Sunil</firstName> <lastName>Patil</lastName> </contactList> - <contactList> <contactId>2</contactId> <email>patil.jiyas@gmail.com</email> <firstName>Jiya</firstName> <lastName>Patil</lastName> </contactList> - <contactList> <contactId>3</contactId> <email>patil.navyas@gmail.com</email> <firstName>Navya</firstName> <lastName>Patil</lastName> </contactList> </ns2:searchContactResponse> </S:Body> </S:Envelope> The WorkLight server takes that response and converts it into JSON object and sticks it into Result element like this {"responseID":"10","statusCode":200,"errors":[],"isSuccessful":true,"statusReason":"OK","Envelope":{"Body":{"searchContactResponse":{"ns2":"http://webspherenotes.com","contactList":[{"lastName":"Patil","contactId":"1","email":"sdpatil@gmail.com","firstName":"Sunil"},{"lastName":"Patil","contactId":"2","email":"patil.jiyas@gmail.com","firstName":"Jiya"},{"lastName":"Patil","contactId":"3","email":"patil.navyas@gmail.com","firstName":"Navya"}]}},"S":"http://schemas.xmlsoap.org/soap/envelope/"},"warnings":[],"info":[]}

Accessing SOAP service from the WorkLight app

In the Using JQuery Mobile in WorkLight application entry i built a WorkLight application that takes contact last name as input and uses it to search for contact by using WorkLight SQL adapter, i wanted to check if i can achieve same functionality by using SOAP service so these are the steps that i used
  1. First i did build a simple JAXWS service that takes last name of the contact as input parameter and returns list of contacts with matching last name, you can download the service that i used from here
  2. Next i used the WorkLight studio to create a HTTP Adapter, i used ContactWSService as name for that adapter
  3. After creating the adapter i change the ContactWSService-impl.js that was generated to look like this
    
    function searchContact(lastName) {
     var searchContactRequest = '<soapenv:Envelope '+  
       'xmlns:q0="http://webspherenotes.com" '+  
       'xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" '+  
       'xmlns:xsd="http://www.w3.org/2001/XMLSchema" '+  
       'xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> '+  
       '<soapenv:Header> '+  
       '</soapenv:Header> '+  
      '<soapenv:Body> '+ 
      '<q0:searchContact> '+
       '<arg0>'+lastName+'</arg0> '+
       '</q0:searchContact> '+
       '</soapenv:Body> '+  
     '</soapenv:Envelope> ';
     WL.Logger.debug("SOAP Request " + searchContactRequest);
     var input = {
         method : 'post',
         returnedContentType : 'xml',
         path : '/ManageContactWS/contactws',
         body:{
          content: searchContactRequest.toString(),
          contentType: 'text/xml; charset=utf-8'
         }
     };
     return WL.Server.invokeHttp(input);
    }
    
    In order to make a SOAP request call you will have to create the SOAP message first, i used the Eclipse Web Services Explorer tool to first test my SOAP service and then copied the XML SOAP message that it used for request into my JavaScript file. Once i have the SOAP message in String format i used it to make HTTP POST call
  4. Next i had to change the ContactWSService.xml the deployment descriptor for my adapter to declare searchContact procedure, after changes the file looks like this
    
    <?xml version="1.0" encoding="UTF-8"?>
    <wl:adapter name="ContactWSService"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:wl="http://www.worklight.com/integration"
      xmlns:http="http://www.worklight.com/integration/http">
    
      <displayName>ContactWSService</displayName>
      <description>ContactWSService</description>
      <connectivity>
        <connectionPolicy xsi:type="http:HTTPConnectionPolicyType">
          <protocol>http</protocol>
          <domain>localhost</domain>
          <port>9000</port>      
        </connectionPolicy>
        <loadConstraints maxConcurrentConnectionsPerNode="2" />
      </connectivity>
      <procedure name="searchContact"/>
    </wl:adapter>
    
  5. The last change was in the WorkLight application code where i make the adapter call and parse the returned results so that i can display them, This is how my .js file looks like
    
    function getContact(){
     console.log("Entering getContact() REST service based version");
     var contactName = $('contactName').getValue();
     var invocationData = {
       adapter:"ContactWSService",
       procedure:"searchContact",
       parameters:[contactName]
     }
     var options ={
       onSuccess:loadContactSuccess,
       onFailure:loadContactFailure
     }
     WL.Client.invokeProcedure(invocationData, options);
    }
    
    function loadContactSuccess(result){
     console.log("Inside loadContactSuccess " + result);
     var html = '';
     if(result.status == 200){
      var contactList = result.invocationResult.Envelope.Body.searchContactResponse.contactList;
      var i = 0;
      for(i =0 ; i < contactList.length ; i++){
       var currentContact = contactList[i];
       html =  html + '
  6. '+currentContact.firstName +' ' +currentContact.lastName +'
  7. '; } } jq("#displayContact").html(html); jq("#displayContact").listview('refresh'); } function loadContactFailure(result){ console.log("Inside loadContactError " + result); }
    Important Note: By default the JAXWS wraps the return value in XML element named return and the WorkLight server simply uses the same name while converting the XML result into JSON object, but that makes accessing the return element difficult in the client javascript because return is the JavaScript keyword and you can not use it in your code. So to get around this problem i had to change my sample web service and use JAXWS annotation to customize name of the return element to contactList

Developing JAXWS Service for deployment in GlassFish/JEE 5 compliant container

In the newer version of JEE you can use annotations for creating Web Service, i wanted to try this feature so i did create this simple JAX WS service that takes name/part of the name of contact as input and return list of contacts with same last name. You can download the JAXWS service from here First i did create a ContactWS.java class that looks like this

import java.util.List;

import javax.jws.*;
@WebService(name="ContactWS", serviceName="ContactWS", 
targetNamespace="http://webspherenotes.com")
public class ContactWS {
  
  @WebMethod(operationName="searchContact")
  @WebResult(name="contactList",partName="contactList")
  public List searchContact(String lastName) {
    ContactDAO contactDAO = new ContactDAOImpl();
    return contactDAO.searchContact(lastName);
  }

}
The ContactWS class implements web service. The next step is to declare this class as servlet in web.xml like this


<web-app xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
  version="2.5">

  <display-name>Contact Web Service</display-name>

  <servlet>
    <servlet-name>ContactWS</servlet-name>
    <servlet-class>com.webspherenotes.ws.ContactWS</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>ContactWS</servlet-name>
    <url-pattern>/contactws/*</url-pattern>
  </servlet-mapping>

<
Once the application is deployed in the GlassFish server you can access it by going to http://localhost:9000/ManageContactWS/contactws

WorkLight HTTP Adapter returning XML

In the Invoking REST service from WorkLight entry i blogged about how to make a REST call that returns XML from WorkLight application using HTTP adapter. One thing that i noticed during that is even though my REST service returns XML WorkLight converts it into JSON for me and the generated JSON follows the same structure as that of the XML. This is how my XML response of the REST service looks like
The WorkLight server converts it into JSON and return's JSON that looks like this

Invoking REST service from WorkLight

In the Using JQuery Mobile in WorkLight application entry i blogged about how to create a simple Contact Search application that takes user's last name as parameter and searches all the contacts with that name displays to the user. In that example i used the WorkLight SQL adapter for making query, but i already have my own REST service that can do same thing and i wanted to use it.
This service takes part of last name as query parameter and returns all the contacts that match the name in XML format. I wanted to use this service in my WorkLight application, so that i could use the Http Adapter so i followed these steps
  1. First i did create a ContactRESTService adapter
  2. Then i changed the ContactRESTService-impl.js like this
    
    
    function getContactList() {
      var input = {
          method : 'get',
          returnedContentType : 'xml',
          path : '/ManageContact/rest/contact'
      };
      return WL.Server.invokeHttp(input);
    }
    
    function searchContact(lastName){
      var input = {
            method : 'get',
            returnedContentType : 'xml',
            path : '/ManageContact/rest/contact/search?lastName='+lastName
        };
        return WL.Server.invokeHttp(input);
    }
    
    
    function getStoriesFiltered(){
    }
    
    My adapter has 2 methods first is getContactList() that returns all the contacts in the database by calling /ManageContact/rest/contact URL and it does not take any parameter. The searchContact() takes lastName as parameter and makes GET call to '/ManageContact/rest/contact/search?lastName='+lastName URL.
  3. I also had to change the ContactRESTService.xml so that my adapter descriptor looks like this
    
    <?xml version="1.0" encoding="UTF-8"?>
    <wl:adapter name="ContactRESTService"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      xmlns:wl="http://www.worklight.com/integration"
      xmlns:http="http://www.worklight.com/integration/http">
    
      <displayName>ContactRESTService</displayName>
      <description>ContactRESTService</description>
      <connectivity>
        <connectionPolicy xsi:type="http:HTTPConnectionPolicyType">
          <protocol>http</protocol>
          <domain>localhost</domain>
          <port>9000</port>      
        </connectionPolicy>
        <loadConstraints maxConcurrentConnectionsPerNode="2" />
      </connectivity>
      <procedure name="getContactList"/>
      <procedure name="searchContact"/>
      <procedure name="getStoriesFiltered"/>
    </wl:adapter>
    
  4. After that i had to make couple of my minor change in my WorkLight application so that it would use the HTTP adapter instead of the SQL adapter, This is how my JavaScript that makes call to the adapter looks like
    
    function getContact(){
     console.log("Entering getContact() REST service based version");
     var contactName = $('contactName').getValue();
     var invocationData = {
       adapter:"ContactRESTService",
       procedure:"searchContact", 
       parameters:[contactName]
     }
     var options ={
       onSuccess:loadContactSuccess,
       onFailure:loadContactFailure
     }
     WL.Client.invokeProcedure(invocationData, options);
    }
    
    function loadContactSuccess(result){
     console.log("Inside loadContactSuccess " + result);
     var html = '';
     
     if(result.invocationResult.isSuccessful){
      var contactList = result.invocationResult.contacts.contact;
      var i = 0;
      for(i =0 ; i < contactList.length ; i++){
       var currentContact = contactList[i];
       html =  html + '<li><a href="#">'+currentContact.firstName +' ' 
    +currentContact.lastName +'</a></li>';
      }   
     }
     
     jq("#displayContact").html(html);
     jq("#displayContact").listview('refresh');
    }
    
    function loadContactFailure(result){
     console.log("Inside loadContactError " + result);
    }
    
    First the getContact() which makes call to the HttpAdapter had to changed to use the name of the ContactRESTService as adapter and searchContact as procedure name. Then i had to change the loadContactSuccess() method the part which reads the search results. Worklight makes sure that i get results in JSON format with little bit different structure.

WorkLight resources directory

You might have noticed that when you make changes in any HTML or JavaScript file in the WorkLight Studio those changes do not get reflected right away instead you will have to Right Click on the Project and say Run -< Build All and Deploy. It seems that when you click on Build and Deploy the Studio generates the files required for WorkLight and for every Environment in the Worklight\server\widget-resources directory like this
My HelloWorkLight project supports ipad and iphone environment so every time i click on the Build All and Deploy, WorkLight studio creates relevant directories under Worklight\server\widget-resources directory one is HelloWorlight-common-*, HelloWorkLight-ipad-*,HelloWorkLight-iphone-* the * represents a integer that worklight keeps incrementing. WorkLight studio copies all the application related files in these folders, if you make a change directly in of these files those changes get reflected right away but then you will not have those changes in your project and you those changes wont get picked after next deployment. If you open the files in these directories you will notice that WorkLight adds quite a few elements to it. For example this is my html file

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, 
  maximum-scale=1.0, minimum-scale=1.0, user-scalable=0" />
        <title>HelloWorklight</title>
        <link rel="shortcut icon" href="images/favicon.png" />
        <link rel="apple-touch-icon" href="images/apple-touch-icon.png" />
        <link rel="stylesheet" href="css/reset.css" />
        <link rel="stylesheet" href="css/HelloWorklight.css" />        
    </head>
    <body onload="WL.Client.init({})" id="content" style='display: none'>
    <div id="AppBody">
      <div id="header">
        <div id="ReloadButton" onclick="reload();"></div>
        <h1>Basic Development</h1>
      </div>
      <div id="wrapper">
        <label for="actions">Display: </label>
        <select id="actions" onchange="displayInfo();">
          <option value="appEnvironment" selected="selected">Application Environment</option>
          <option value="language">Language</option>
        </select>
        <div id="info"></div>
      </div>
      <div id="worklight" onclick="loadWebPage();"></div>
    </div>

        <script src="js/HelloWorklight.js"></script>
        <script src="js/messages.js"></script>
        <script src="js/auth.js"></script>
    </body>
</html>
After deploy the same file gets changed to

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0, 
  maximum-scale=1.0, minimum-scale=1.0, user-scalable=0" />
        <title>HelloWorklight</title>
        <link rel="shortcut icon" href="images/favicon.png" />
        <link rel="apple-touch-icon" href="images/apple-touch-icon.png" />
        <link rel="stylesheet" href="css/reset.css" />
        <link rel="stylesheet" href="css/HelloWorklight.css" />        
    <link rel="stylesheet" href="wlclient/css/wlclient.css" />
    <link rel="stylesheet" href="xilinus/css/default.css" />
    <link rel="stylesheet" href="xilinus/css/alphacube.css" />
    <link rel="stylesheet" href="xilinus/css/debug.css" />
    <script type="text/javascript">
        // Define WL namespace. 
        var WL = WL ? WL : {};
        
        /** 
         * WLClient configuration variables.
         * Values are injected by the deployer that packs the gadget.
         */
        WL.StaticAppProps = {
          "APP_DISPLAY_NAME": "HelloWorklight",
          "APP_LOGIN_TYPE": "never",
          "APP_SERVICES_URL": "/apps/services/",
          "APP_VERSION": "1.0",
          "ENVIRONMENT": "preview",
          "HEIGHT": 460,
          "IID": 0,
          "LOGIN_DISPLAY_TYPE": "popup",
          "LOGIN_POPUP_HEIGHT": 610,
          "LOGIN_POPUP_WIDTH": 920,
          "LOGIN_REALM": null,
          "PREVIEW_ENVIRONMENT": "common",
          "TIMESTAMP": "192.168.94.131 on 2012-03-28 at 17:00:00",
          "WIDTH": 320,
          "WORKLIGHT_ROOT_URL": "/apps/services/api/HelloWorklight/common/0/"
    };
    </script>
    <script src="common/js/prototype.js"></script>
    <script src="common/js/containerCommunicationAPI.js"></script>
    <script src="common/js/base.js"></script>
    <script src="wlclient/js/messages.js"></script>
    <script src="common/js/wlcommon.js"></script>
    <script src="common/js/busy.js"></script>
    <script src="xilinus/js/window.js"></script>
    <script src="xilinus/js/debug.js"></script>
    <script src="wlclient/js/worklight.js"></script>
    <script src="wlclient/js/gadgetCommunicationAPI.js"></script>
    <script src="wlclient/js/wlclient.js"></script>
    <script src="wlclient/js/wlfragments.js"></script>
    <script src="wlclient/js/encryptedcache.js"></script>
    <script src="wlclient/js/blockTEA.js"></script>

  </head>
    <body onload="WL.Client.init({})" id="content" style='display: none'>
    <div id="AppBody">
      <div id="header">
        <div id="ReloadButton" onclick="reload();"></div>
        <h1>Basic Development</h1>
      </div>
      <div id="wrapper">
        <label for="actions">Display: </label>
        <select id="actions" onchange="displayInfo();">
          <option value="appEnvironment" selected="selected">Application Environment</option>
          <option value="language">Language</option>
        </select>
        <div id="info"></div>
      </div>
      <div id="worklight" onclick="loadWebPage();"></div>
    </div>

        <script src="js/HelloWorklight.js"></script>
        <script src="js/messages.js"></script>
        <script src="js/auth.js"></script>
    </body>
</html>