Creating a Hello World Service

With webOS 2.0, third party developers can now "roll their own" JavaScript services for access on Palm's public message bus. Besides powering the new Synergy APIs, JavaScript services strengthen webOS's support for background processing and add new capabilities such as low-level networking, filesystem access, and binary data processing.

The following five-step procedure shows the reader how to create and install a package containing a Hello World JavaScript service (com.palm.helloworld.service) and JavaScript application to access it on Palm's message bus. Currently, a service must be installed with an accompanying JavaScript app, though this can just be a stub.

Like all Hello World-type implementations, the intention is to strip the process down to a bare minimum, clearly showing what is involved and establishing a base for further development.

This procedure shows you how to do the following:

This article assumes that the reader has had some experience creating Mojo apps.

In this section:

Prerequisites

  • Your development PC should have the webOS 2.0 SDK installed.

  • If you are using a Palm device instead of the Palm Emulator, then:

    • The device should have webOS 2.0 or higher installed.

    • You should have a USB cord to connect the device to your devlopment PC.

    • The device should be charged and prepared.

    • You need a mechanism for logging into your device.

      The Tools section describes various mechanisms for doing this. Other options include using novaterm on the Mac. On my Windows PC, I used putty (installed with the PDK) to launch a shell and log in to the device. See the Tools section for more information on using these utilities.

To Create a Hello World Service

  1. Create a folder for your app and service.

    For example: C:\SampleService

  2. Create package, application and service subdirectories.

    You are going to need three subdirectories: one for the app, one for the service, and one for the package.

    Open a command prompt, go to C:, and generate your skeleton app that is going to call the service:

    C:\SampleService> palm-generate sampleservice.application
    
    
    Manually create the following two subdirectories:
    C:\SampleService\sampleservice.package
    C:\SampleService\sampleservice.service
    
    

    Currently, palm-generate is not set up to create these directories.

    You should now have a directory structure that looks like this:
    C:\SampleService\
              \sampleservice.application
              \sampleservice.package  
              \sampleservice.service
    
    

    Note that you are free to use whatever naming convention you like for your directories.

  3. Create or modify the following package and service sub-directory files:

    • \sampleservice.package\

      • packageinfo.json—Defines the package ID, app, services, icon, and template data for the service and app package.
    • \sampleservice.service\

      • sources.json—The equivalent to that for Mojo apps: it declares what source files should be loaded into the current service.

      • services.json—Defines what commands the service provides on Palm bus.

        The "public: true" property indicates that the service is accessible on the public bus. The default is false. Note that this is done on a per-command basis; you can choose to make some commands public and some not.

        The "activityTimeout" property determines how long, in seconds, the service remains running without being activated.

      • HelloCommandAssistant.js—Defines a single command assistant to execute the "hello" command.

        As with Mojo apps, each command consists of a controller and an assistant. The service framework provides the controller framework and manages common aspects of command execution. The service provides the assistant and manages specific aspects of command execution. The assistant is executed via the run method and returns an object containing a single reply property. This is constructed from the incoming name argument.

        Note that the assistant must return a Future, an object used for async processing that is part of Palm's Foundation libraries. See the Foundations documentation for more information.

        Note: The service ID must begin with the app ID and end in ".service". For example (this service):

        App ID : com.palm.helloworld Service ID : com.palm.helloworld.service

    File Contents
    packageinfo.json
    {
      "id": "com.palm.helloworld",
      "package_format_version": 2,
      "loc_name": "Palm Service Hello World Demo",
      "version": "1.0.0",
      "icon": "icon.png",
      "miniicon": "icon.png",
      "vendor": "Palm",
      "vendorurl": "palm.com",
      "app": "com.palm.helloworld",
      "services": ["com.palm.helloworld.service"]
    }
    
    services.json
    {
    "id": "com.palm.helloworld.service",
    "description": "Hello World Demo Service",
    "activityTimeout" : 30,
    "services": [{
        "name": "com.palm.helloworld.service",
        "description": "helloworld example",
        "commands": [{
            "name" : "hello",
            "assistant" : "HelloCommandAssistant",
            "public" : true
            }]
         }]
    }
    
    sources.json
    [{
        "library": {
            "name": "foundations",
            "version" : "1.0"
          }
    },
    {
        "source": "HelloCommandAssistant.js"
    }]
    
    HelloCommandAssistant.js
    var HelloCommandAssistant = function() {
    }
    
    HelloCommandAssistant.prototype.run = function(future) {
        console.log("***************Hello "+ this.controller.args.name);
        future.result = {reply: "Hello " + this.controller.args.name + "!"};
    }
    
  4. Create or modify the following application files.

    These files and their contents should be familiar to Mojo app developers.

    File Contents
    appinfo.json
    {
        "id": "com.palm.helloworld",
        "version": "1.0.0",
        "vendor": "Palm",
        "type": "web",
        "main": "index.html",
        "title": "Sample Service Call",
        "icon": "icon.png"
    }
    
    sources.json
    [
        {
            "source": "app/assistants/stage-assistant.js"
        },
        {
            "scenes": "main",
            "source": "app/assistants/main-assistant.js"
        }
    ]
    
    app\
        assistants\
            main-assistant.js
    
    function MainAssistant() {};
    
    MainAssistant.prototype.setup = function() {
        this.debugContainer = this.controller.get("debugOutput");
        this.logOutputNum = 0;
    };
    
    MainAssistant.prototype.activate = function(event) {
        var that = this;
        this.logInfo("Setup");
    
        // Call the Hello World service using standard Palm serviceRequest
        this.controller.serviceRequest("palm://com.palm.helloworld.service", {
            method: "hello",
            parameters: {"name": "World"},
            onSuccess:this.serviceSuccess.bind(this),
            onFailure:this.serviceFailure.bind(this)
        });
    };
    
    MainAssistant.prototype.serviceSuccess = function(successData){
        this.logInfo("Success Data: " + JSON.stringify(successData.reply));
    }
    MainAssistant.prototype.serviceFailure = function(failData){
        this.logInfo("Fail Data:" + JSON.stringify(failData));
    }
    
    MainAssistant.prototype.deactivate = function(event) {};
    
    MainAssistant.prototype.cleanup = function(event) {};
    
    MainAssistant.prototype.logInfo = function(logText) {
        this.debugContainer.innerHTML = (this.logOutputNum++) + ": " + logText + "
    " + this.debugContainer.innerHTML; };
    app\
        assistants\
            stage-assistant.js
    
    function StageAssistant() {
    }
    
    StageAssistant.prototype.setup = function() {
        this.controller.pushScene("main");
    }
    
    app\
        views\
            main\
                main-scene.html
    
    <div>
    Status:
    
    </div>
    <div id="debugOutput">
    </div>
    
  5. Package, install and launch the Hello World service.

    At a command line prompt, enter the following commands:

    c:\SampleService> palm-package sampleservice.application sampleservice.service sampleservice.package
    c:\SampleService> palm-install -r com.palm.helloworld
    c:\SampleService> palm-install com.palm.helloworld_1.0.0_all.ipk
    c:\SampleService> palm-launch com.palm.helloworld
    
    

    You should see the following screen on your device or emulator:

Debugging

To open a shell and log in to the device

  1. Open a command prompt.

  2. On Windows type:

    putty -P 10022 root@localhost
    
    
  3. On Mac OS X:

    ssh -p 10022 root@localhost
    
    
  4. Press "Enter" at the password prompt.

To open a shell and log in to the Emulator

  1. Open a command prompt.

  2. On Windows type:

    putty -P 5522 localhost
    
    
  3. On Mac OS X:

    ssh -p 5522 localhost
    
    
  4. Enter "root" at the login prompt.

  5. Press "Enter" at the password prompt.

To see your installed service on the device/emulator

  1. Open a device/emulator shell.

  2. Go to /media/cryptofs/apps/usr/palm/services and list ('ls') the files there.

    You should see an entry for com.palm.helloworld.service.

To invoke the service from a shell

You can use a 'luna-send' command to call your service:

/media/cryptofs/apps/usr/palm/services# luna-send -n 1  palm://com.palm.helloworld.service/hello '{"name":"world"}'

You should see the following response:

{"reply":"Hello world!","returnValue":true}

The framework automatically sets returnValue to true because a result was returned.

To manually start a service

You can use run-js-service to start your service:

/media/cryptofs/apps/usr/palm/services# run-js-service com.palm.helloworld.service

The "activityTimeout" field in "services.json" determines how long the service stays active without being called.

To monitor console messages in realtime

  • Open a shell and run:

    tail -f /var/log/messages
    
    

    The "-f" option causes tail to display the last 10 lines of messages and append new lines to the display as they are added.

  • To show output for just your app:

    tail -f /var/log/messages | grep <packageid>
    
    

Troubleshooting

You will see a screen similar to this:

if, in \sampleservice.service\services.json, you did not set the public flag to true. If false (the default), the service cannot be accessed on the public bus.