CUSTOMER AREA
Login: Password:
General Information
Services
Bluelemon Scenarios
Download Lemonade
Lemonade Tutorial
Lemonade Distilled
How to build a service
1. Hello World!
2. moAccount
3. moBank
4. moBank: PIN
5. moBank: Blue SMS
moBank enhanced
HOW TO BUILD A SERVICE

Mobile solutions are easy to build with Lemonade, as long as you follow some simple rules. This document presents the guidelines and explains how to design, plan and build Bluelemon services. All examples you will find in this tutorial and in the Lemonade downloadable package follow these rules.

If you are a software developer and are used to writing programs, remember that Bluelemon is less a programming language and more a platform for services assembly. Don't think of Bluelemon instructions and nodes as of methods, procedures and variables - think of them as of components that are glued together to create a service.

Lemonade was designed with visual editors and wizards in mind. The perfect Lemonade development environment should perform many of the steps described in this tutorial automatically, as steps in a wizard or round-trip engineering.
However, the current version of Lemonade does not include the wizards and editors. What is included is the engine that processes Bluelemon code and *.sns files, plus a framework web application to handle network calls from Bluelemon clients.

The lack of visual editors makes using Lemonade only a bit more complicated. If you gain just a little practice (playing with the examples is a good idea) and carefully follow the steps described below you will be able to build Lemonade mobile solutions quickly and efficiently.

A full-fledged, visual editing environment (probably implemented as a plugin for a popular Java IDE) is planned, but no delivery date is known yet. You can make Lemonade development run faster by providing feedback, so don't hesitate to let us know if you like Lemonade and would like to see it grow: lemonade@e-marson.com

OVERVIEW

The design phase of Lemonade service development can be split into three stages:

  • Create a functional diagram, which presents Bluelemon instructions that deliver the required functionality and the associations between them.
  • Create a location diagram, which assigns the resource comprising the service with nodes.
    Nodes identify a resource and provide a means of locating the resource. The node consists of two elements - name and location. There are four types of locations: permanent, session, network and package.
  • Create a deployment strategy: decide how the features will be accessed by the user's MIDlet.

After the "creative" you need to do some copying and pasting: you need to turn the three design artifacts into a web application scaffolding by creating skeletons of Sticks'n'Stones processes, declaring Spring beans and wiring and - if necessary - creating skeletons of Spring MVC Controllers for your business logic.
Ideally, this should happened automatically: you should be able to create the two diagrams and a deployment strategy, press one button and a wizard would create all the scaffolding code. Unfortunately, this release of Lemonade does not provide such a button, so you need to act the wizard's part yourself by following the strategy this document describes and use the provided file templates.

Once you have created Sticks'n'Stones processes and Java classes from templates, all you need to do is to fill in the "put your code here" placeholders.

FUNCTIONAL DIAGRAM

The functional diagram presents the logical workflow of the service, by showing Bluelemon instructions and associations between them.

This chapter covers:

BLUELEMON INSTRUCTIONS

According to Wikipedia, an instruction is "a form of communicated information that is both command and explanation for how an action, behavior, method, or task is to be begun, completed, conducted, or executed."

A Bluelemon instruction is simply a compiled fragment of Bluelemon source code. When a Bluelemon instruction is processed by the Bluelemon Runtime Environment (BRE), it makes the MIDlet perform some tasks. As was said in Lemonade Distilled, the only purpose of the MIDlet is to process Bluelemon instructions, byte by byte. Therefore any functionality of a Bluelemon service consists of some Bluelemon instructions and associations between them.

You should consult the Bluelemon API reference if you plan to write your own Bluelemon code.

This is an example of Bluelemon source code:

 <!-- create the form instance --->
 <blue:newInstance
    module="com/emarson/lemonade/bluelemon/midp1/Form"
    toVariable="form"/>


 <!-- set its title as 'Hello' --->
 <blue:call object="form" method="initialize">
   <blue:argument type="String" value="Hello"/>
 </blue:call>
 
 <!-- make it write 'Hello World!' --->
 <blue:call object="form" method="appendString">
   <blue:argument type="String" value="Hello World!"/>
 </blue:call>

 <!-- show the form on the screen of the device --->
 <blue:call manager="GeneralManager" method="setCurrent">
   <blue:argument type="variable" name="form"/>
 </blue:call>

Once compiled, this code produces a Bluelemon instruction (52 bytes, including the header) which displays a form saying "Hello World!".

All diagrams show Bluelemon instruction as boxes:

Every reasonable mobile solution will require more than one Bluelemon instruction. However, we said earlier that BRE only processes single Bluelemon instructions linearly.
To handle control flow in your mobile solution and run Bluelemon instructions in answer to user actions or other conditions, you need to define associations (you could also call them "links" or "transitions") between instructions.

This release of Lemonade environment has four kind of associations:

  1. in an ActionCommand
    ActionCommand is Bluelemon a wrapper for the MIDP Command class.
    The associated instruction is activated when the user picks one of the commands displayed on the phone screen (depending on the phone model, these could be assigned to soft buttons or gathered in a menu).

    <!-- some code before --->

    <!-- create the instance of CommandAction --->
    <blue:call manager="UtilsManager" 
               method="getActionCommand"
               toVariable="command">

      <blue:argument type="String" value="Continue" />
      <blue:argument type="byte"
                     value="ActionCommand.OK" />

      <blue:argument type="byte" value="0" />
      <blue:argument type="byteArr" 
                     contextKey="actionForContinue" />

    </blue:call>

    <!-- append it to the form --->
    <blue:call object="form" method="addCommand">
      <blue:argument type="variable" name="command" />
    </blue:call>

    <!-- some code after --->

  2. in a List
    You can associate Bluelemon instructions with a List object in two ways: you can assign a separate instruction for every item (see example below) or can assign a single instruction for all items.
    The associated instruction is activated when the user picks an item from the list.

    <!-- some code before --->

    <!-- create the list of type IMPLICIT --->
    <blue:call object="choiceFactory" method="createList"
               toVariable="list">

      <blue:argument type="byte" value="List.IMPLICIT"/>
    </blue:call>

    <!-- initialize it --->
    <blue:call object="list" method="initialize">
      <blue:argument type="String" value="title"/>
      <blue:argument type="dataset">
        <blue:descriptor>
          <blue:field type="String"/>
          <blue:field type="byteArr"/>
        </blue:descriptor>
        <blue:row>
          <blue:field value="Element 1"/>
          <blue:field contextKey="actionForElement1"/>
        </blue:row>
        <blue:row>
          <blue:field value="Element 2"/>
          <blue:field contextKey="actionForElement2"/>
        </blue:row>
      </blue:argument>
    </blue:call>

    <!-- some code after --->

  3. in a Timer
    When you initialize a Timer object, you provide an instruction to schedule.
    The instruction is activated according to the schedule by the Timer object itself.

    <!-- some code before --->

    <!-- create the instance of Timer --->
    <blue:newInstance
      module="com/emarson/lemonade/bluelemon/midp1/Timer"
      toVariable="timer"/>


    <!-- initialize it --->
    <blue:call object="timer" method="schedule">
      <blue:argument type="byteArr" 
                     contextKey="actionForTimer"/>

      <blue:argument type="byte" value="0"/>
      <blue:argument type="short" value="500"/>
    </blue:call>

    <!-- some code after --->

  4. direct call to another node
    One instruction can call the other directly.

    <!-- some code before --->

    <blue:call node="exampleNode" location="network">
      <blue:argument type="String" value="hi there"/>
    </blue:call>

    <!-- some code after --->

All diagrams show the associations using arrows:

EXAMPLE DIAGRAMS

These examples of functional diagrams show how instructions and associations form a service.

Example 1


Instruction A displays a form saying "Hello World!". It has an ActionCommand with the label "Exit" which is associated with instruction B. This closes the application when the command is activated by the user.

Example 2


Instruction A displays a form with two ActionCommand links: one closes the MIDlet, the other calls instruction B.

Instruction B displays an "implicit" list and creates and runs an instance of Timer object. Instructions C and D are associated with the list's two items and are activated when the user picks an element and presses "Select". Instruction E is associated with the timer and is activated by the timer.

Example 3


Instruction A displays a form where the user can enter the user id and password. Two commands are available, one closes the application and the other calls instruction B.

Instruction B has two associations, both of which can be activated when it is processed. It first directly calls C passing the user id and password as arguments and receiving an information if the input was correctly validated. If so, the instruction calls the server and receives either D or E as the response.

LOCATION DIAGRAM

The second step is to locate all resources used by the solution, i.e. define a unique mapping between resources and nodes. The diagram also show the associations between the nodes.

Nodes are a notion used in Bluelemon to call units which identify a resource and provide a mean of locating the resource. The node consists of two elements - name and location. There are four types of locations: permanent, session, network and package. A name must be unique within a given location.

Resources that need to be assigned to nodes are:

  • instructions from the functional diagram,
  • global variables used by those instruction,
  • network processes used in the solution.

This chapter covers:

STRATEGY FOR IMPLEMENTING ASSOCIATIONS

Two instructions that are associated in the functional diagram...

... can be located in one of the following ways:

  1. wrapping
    The associated instruction is placed inside the other.
    There is no "linking code" - the code of instruction B is simply copied and placed wherever it is "called" in the instruction A.
    Note that if B is called from multiple places, the code for it is duplicated so this option makes sense when instruction B is short. However, if B is only used once, wrapping is the simplest and most efficient way of calling it. This is similar to method inlining in traditional programming languages.
  2. "permanent" location
    Instruction B is placed in the permanent record store of MIDlet, in a node in the "permanent" location.
    The "linking code" calls the node B from "permanent" (call by reference).
    The code for instruction B is stored in one place and is always available available for calling.
  3. "session" location
    Instruction B is placed in the volatile memory of MIDlet, in a node in the "session" location.
    The "linking code" calls the node B from "session" (call by reference).
    Like above, the code is stored in one place rather than duplicated, but it is discarded when the application is closed.
  4. package location
    Both instructions or just B instruction is placed in a package named P. The package is stored in the permanent memory of MIDlet.
    The "linking code" calls the node B from "@P".
  5. network reference
    The code for instruction B is downloaded from the server.
    The "linking code" connects to server, downloads Bluelemon code returned by the server and processes it in the MIDlet.
    With this option, every call to B will involve a new network request. This introduces overhead but is very flexible. For example, you could dynamically generate the code for instruction B on the server by inserting database query results into it.

When you draw an association on the location diagram, you can indicate that you intend to provide custom "linking code" rather than rely on one of the standard implementations described above. You can show this on the diagram by drawing a dashed line between the custom "linking code" and the association arrow:

This example means that when instruction A refers to the associated instruction B (for example by calling it directly or assigning it to a ActionCommand), the instruction C should be used (inline) as the "linking code". This instruction replaces the standard invocation code.
For example, code B might be at a network location and the application designer wants to display a connection progress bar (the label for C might be "Display a connection progress bar and make a network call"). Another example might be a call to B in "permanent" location where instruction C would first check if code B is available at that location and if not - handle the error in a user-friendly way.
Instruction C only refers to the way an association is activate and is not related to the solution logic. Therefore it does not appear in the functional diagram.

EXAMPLE DIAGRAMS

Example 1

Four variants of a location diagrams for the functional diagram seen above:

Option 1


All instructions are located in one package "myP" and refer to each other.

Option 2


Instructions A, B and C are located in one package "myP" and refer to each other. Each of them contains (wraps) inlined instruction D.

Option 3


Instructions A, C and D are located in one package "myP". Instruction B is available from a network connection to a server.

Option 4


Instructions A and C are placed in the "permanent" location and instruction B is available server-side. They all refer to instruction D from the package "myP". When B is called by A, the standard "linking code" will be replaced by instruction E, which belongs to "mainPackage". Instruction refers to B because it invokes it (it replaces the standard invocation for B, so it must call invoke it internally) and to A because it provides a "Cancel" button that the user can activate to return to the previous screen.

Example 2

Two variants of a location diagrams for the functional diagram seen above:

Option 1


The diagram show a node N, which is at a "network" location. The instruction B refers to it. Depending on the authentication result, the server (Sticks'n'Stones process) responds with either instruction D or E.
The nodes "Image" and "Counter" are variables at a location "permanent". The first contains an image displayed by instruction A. The second counts successful login attempts and is used by instructions B and D.
This diagram places instruction A, B and C in package "examplePackage" and instruction F is inlined in the instructions that use it.

Option 2


This diagram is similar to Option 1, but this time instruction C is not a part of package "examplePackage" but is inlined in instruction B (wrapping). On the other hand, instruction F became a part of the package and is referred to by the other instructions rather than wrapped.

DEPLOYMENT STRATEGY

Once you have the functional diagram and location diagram, all you need to do is define a deployment strategy.

Deployment strategy defines:

  • installers, i.e. Bluelemon instructions, which are executed by Bluelemon Runtime Environment in the MIDlet, that prepare the solution for use,
  • url mappings, i.e. the assignment of installers to URLs within the web application and a definition of formats in which the installers will be delivered.

INSTALLERS

Installer is a Bluelemon instruction which consists of the following fragments:

  • name

    Name of the installer.

  • pre-install instruction
    An instruction that is executed before installation begins.
    It can, for example, remove unneeded packages or check available memory and, if necessary, abort the installation.
  • packages installation
    An instruction that installs the packages wrapped by this installer.
  • 'permanent' and 'session' updates
    An instruction that updates nodes in 'permanent' and 'session' locations.
  • post-install instruction
    An instruction that is executed when the instalation is complete.
    Usually, this will be executing one of the installed nodes or displaying an "Installation successful" message.

URL MAPPINGS

You define a URL mapping by associating installers with URLs within the web application and with mapping (the way an installer will be delivered).

Lemonade includes two kinds of mapping:

  • MIDlet

    The installer is placed as the 'res/s.blue' resource in a MIDlet, which is downloaded to the user's mobile phone.

    This type of mapping has the following parameters:

    • name

      Name of the mapping.

    • URL

      URL (within the web application) that is being mapped.

    • installer to use

      The installer that should be available at the URL.

    • package

      Directory with precompiled MIDlet classes and other MIDlet resources.

      Lemonade provides three directories with slightly different BRE MIDlet implementations:

      • midlet
        a version that works on all Java-capable phones,
      • logging-midlet
        like the above, but prints a lot of debugging information to the console,
      • bluesms-midlet
        a version for MIDP2 phones, that can receive Blue SMS Messages on port 4697.
    • MIDlet name

      Display name for the MIDlet.

    • MIDlet description

      Descriptive text for the MIDlet.

    • MIDlet version

      The version number for the MIDlet.

    • MIDlet vendor

      The name of MIDlet vendor (this should probably be your company's name).

  • instruction

    The installer will be sent to the requesting client as a Bluelemon instruction, without any wrapping.

    This type of mapping has the following parameters:

    • name

      Name of the mapping

    • URL

      URL (within the web application) that is being mapped.

    • installer to use

      The installer that should be available at the URL.

    • result type

      Specifies the result encoding. Available values are:

      • base64-decoded

        This encoding is required if the instruction will be read and executed by the MIDlet (network node calls).

      • base64-decoded-plain

        This encoding is useful for debugging when you want to display the instruction code in your web browser.

THE MAGIC BUTTON

In the perfect world (and hopefully in the next Lemonade release), you would create the two diagrams and deployment strategy and then you would press a button to automatically generate a complete web application, Sticks'n'Stones processes and Spring declarations. All that would be left to do would be to replace the placeholders in Bluelemon code and Java classes.

Unfortunately, this magic button does not yet exist.
This release of Lemonade does not include such a automated tool and you need to create all S'n'S processes, Spring declarations and Java class stubs yourself.

The remaining part of this document shows how to do this: how to turn the design into a scaffolding for concrete solution. If your goal is to get a general overview of Lemonade, you can jump to the solution examples right now.

STICKS'N'STONES

Sticks'n'Stones ( S'n'S in short) is a simple framework which is used in Lemonade to assemble Bluelemon code.

S'n'S is not limited to Bluelemon code. It is a general tool that evaluates processes, which can include decisions, loops and other building blocks. A process is defined in an XML document. The most important element in the document is "path" - a process execution path.

The "path" element can contain the following subelements:

  • action
    delegates processing to a Java class instance that has been registered as the handler for this action type
  • subprocess
    calls another S'n'S process and includes its output
  • decision
    conditional branch
  • doWhile, whileDo
    loops

A common misunderstanding among developers who are new to the Lemonade framework is confusing dependencies between S'n'S processes and between Bluelemon code and nodes.
You should remember that:

  • S'n'S processes are evaluated on the server side.
  • S'n'S processes can contain Bluelemon source code (in XML format) in an action element.
    However, the server only compiles the source code into Bluelemon instructions (byte code). The compiled code becomes the S'n'S process's output and is received by the MIDlet.
  • The MIDlet receives the compiled Bluelemon byte code and executes it byte by byte. The code is just a series of bytes.

EXAMPLE S'n'S PROCESS

The example below show a simple S'n'S process. Notice that it does not assemble any Bluelemon code.

<?xml version="1.0" encoding="UTF-8"?>
<process>

  <descriptor>
    <name>processName</name>
    <version>1.0</version>
    <description>A simple process</description>
    <vendor>E-MARSON</vendor>
  </descriptor>

  <arguments>
    <argument key="text" isRequired="true"/>
    <argument key="number">
      <defaultValue>9</defaultValue>
    </argument>
    <argument key="unnecessary" isRequired="false"/>
  </arguments>

  <path>

    <action name="change the text">
      <type>general/bcl</type>
      <definition>
        text = text + " #" + number;
      </definition>
    </action>
    
    <subprocess name="call the subprocess">
      <source>mySubprocess</source>
      <arguments>
        <argument key="what">text</argument>
      </arguments>
      <resultTo>actionForExit</resultTo>
    </subprocess>
    
    <action name="call another action">
      <type>myActionType</type>
      <definition do="something"/>
    </action>

    <finish name="done">
      <return>text</return>
    </finish>

  </path>

</process>

S'n'S AND BLUELEMON

As we said before, S'n'S is used in Lemonade to assemble Bluelemon code. The following Bluelemon-specific actions are used for this purpose:

  1. general/bluelemon/code
    The most common action type. Returns compiled Bluelemon code.
  2. general/bluelemon/package
    Returns Bluelemon code which, when executed in BRE, stores nodes in a new location in the MIDlet permanent memory.
  3. general/bluelemon/field
    Returns a compiled Bluelemon-type value.

The example below shows an S'n'S process that assembles a Bluelemon instruction that displays "Hello World!" on the phone screen. Remember: the process does not display that message, it only generates code that can be executed in the MIDlet.

<?xml version="1.0" encoding="UTF-8"?>
<process xmlns:blue="http://www.e-marson.com/bluelemon">

  <descriptor>
    <name>com/emarson/lemonade/bluelemon/1</name>
    <version>1.0</version>
    <description>'Hello World!' example</description>
    <vendor>E-MARSON</vendor>
  </descriptor>

  <arguments>
    <argument key="title" isRequired="true"/>
  </arguments>

  <path>
  
    <subprocess name="action for 'Exit'">
      <source>com/emarson/lemonade/Exit</source>
      <resultTo>actionForExit</resultTo>
    </subprocess>
 
    <action name="show screen with 'Hello World!' text">
      <type>general/bluelemon/code</type>
      <definition resultTo="bluelemonCode">

        <!-- create the form instance --->
        <blue:newInstance module="moduleName"
                          toVariable="form"/>

    
        <!-- set its title from the context --->
        <blue:call object="form" method="initialize">
          <blue:argument type="String" 
                         contextKey="title"/>

        </blue:call>
     
        <!-- make it write 'Hello World!' --->
        <blue:call object="form" method="appendString">
          <blue:argument type="String" 
                         value="Hello World!"/>

        </blue:call>
    
        <!-- show the form on the screen --->
        <blue:call manager="GeneralManager"
                   method="setCurrent">

          <blue:argument type="variable" name="form"/>
        </blue:call>

      </definition>
    </action>

    <finish name="return the result">
      <return>bluelemonCode</return>
    </finish>

  </path>

</process>

Notice the "contextKey" attribute in the call to "form" object's "initialize" method. This tells the Bluelemon compiler to use a value retrieved from the "title" variable in the S'n'S process context (here "title" is an argument passed when the process is called).

SPRING

This tutorial assumes that you are familiar with the Spring framework. If you are not, take a moment to look at the documentation available at www.springframework.org and learn more about this excellent framework.

Lemonade includes multiple Spring configuration files. The most important are:

  • bluelemon-standard-modules.xml
    definition of standard Bluelemon modules - used by the Bluelemon code compiler
  • controllers.xml
    Spring MVC controllers
  • sticksnstones.xml
    Sticks'n'Stones framework settings
  • url-mapping.xml
    URL mappings
  • views.xml
    Spring MVC views. definicje widoków

    Lemonade contains two View implementations:

    • com.emarson.sticksnstones.spring.SNSJarView

      A view that generates a MIDlet jar file.

    • com.emarson.sticksnstones.spring.SNSJarView

      A view that returns the result of an S'n'S process evaluation.

STEP BY STEP STRATEGY

The steps that should be performed automatically but, in this Lemonade release, need to be performed manually:

  1. Prepare .sns files for Bluelemon instructions

    For every instruction in functional diagram create an .sns file with a name that matches the instruction and the following content.
    Place this file in the S'n'S processes directory (the path can be configured in sticksnstones.xml) in a subdirectory whose name is infered from the location diagram.

  2. Prepare Bluelemon instructions for associations

    For every association between Bluelemon instructions, insert the "linking code" for the association in the "calling" .sns file.

    The linking code to use depends on the chosen association implementation strategy. The template provides linking code for all of the standard linking strategies. If the diagram shows a special association implementation strategy, use the indicated Bluelemon instruction as the linking code.

  3. Prepare the web application to handle "network" location nodes

    If the node at the "network" location, as defined by location diagram, is a simple Bluelemon instruction, skip this point - the default behaviour of the application will handle this properly.

    If the node is a network process where the server first performs some processing, where the the server chooses the Bluelemon instruction depending on some decisions or where the instruction is generated dynamically:

    1. declare a new MVC controller in controllers.xml - template,
    2. attach it to the URL infered from the node name by adding a new entry to url-mapping.xml - template,
    3. create a controller class that extends BluelemonCommandController - template.
  4. Prepare installers according to deployment strategy

    Do the following:

    1. create a subdirectory called 'deployment' in the solution's directory,
    2. for every package listed in 'package installation' section of installer definition create an .sns file with the name prefix "Package" according to the template,
    3. for every installer create an .sns file with the name prefix "Installer" according to the template.
  5. Prepare URL mappings according to deployment strategy

    If the mapping type is "instruction", skip it.

    If the mapping type is "midlet", do the following:

    1. declare a MIDlet view in views.xml - template,
    2. create a controller that backs this view - template,
    3. add a URL mapping the MIDlet jar - template; the matching .jad descriptor will automatically generated for each request.

Copyright 2008 E-MARSON Home   JavaPeople   JP Projects   About E-MARSON    Careers   Contact         Wersja polska