Proxy-Based Mobile Systems


When developing mobile Web services-based applications, a variety of different architectures are possible. A mobile systems architecture that is commonly used is a proxy-based one in which the mobile application communicates only with a proxy server. The proxy server in turn communicates with and manages the back-end resources, such as Web services.

Figure 10-6 depicts the block diagram architecture of a proxy-based mobile application. The mobile device is capable of running multiple applications. Each of these mobile applications presents a front-end user interface that presents information to users and captures user input. The application does only enough processing on the user input so that the proxy server can properly interpret the data. Different proxy servers may exist for different applications, or a single server may handle multiple applications. The role of the proxy server is to implement all required business logic to service the needs of the mobile application. The implementation of the business logic may include Web services or other distributed computing resources.

Figure 10-6. A proxy-based mobile Web services application.

graphics/10fig06.gif

Although each mobile application can directly interact with its proxy server, an intermediary messaging platform can be used to facilitate and manage communications. The messaging platform and the proxy server are the central locations in which to add paired services so that messages encoded on the mobile device are properly decoded by the proxy server (and vice versa). These paired services may include messaging protocols, compression algorithms, and security mechanisms. By locating these services in a distinct layer outside of the applications, both applications and the messaging platform can be more easily developed, maintained, and augmented.

Mobile Messaging Platform

We first discuss a simple Java implementation of a mobile messaging platform. The messaging platform has a component that runs locally on the mobile device (client-side) as well as a component that runs on the server. The client-side components consist of:

  • MobileMessagingPlatformServer.java

  • MobileMessagingPlatformThread.java

  • MobileServicesClient.java

While the server-side components consist of:

  • ServiceProxyGateway.java

  • InvokeService.java

Figure 10-7 illustrates the relationships between the various components of the mobile messaging platform as well as between the mobile messaging platform and each of the mobile applications.

Figure 10-7. The components of the mobile messaging platform.

graphics/10fig07.gif

We first discuss the components that run on the mobile device. What follows is the entire source code of MobileMessagingPlatformServer.java. This class listens for connections from applications running on the local device, and spawns a thread to handle the application requests.

 /*  * MobileMessagingPlatformServer.java  */ import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class MobileMessagingPlatformServer {    public MobileMessagingPlatformServer ()    {       serverStart ();    }    private void serverStart ()    {       try       { 

The messaging platform listens for connections from applications on port 20001. When a new connection is received, the MobileMessagingPlatformThread is instantiated and started.

      ServerSocket server = new ServerSocket ( 20001 );      while ( true )      {         Socket socketObj = server.accept ();         MobileMessagingPlatformThread mmpt =  new MobileMessagingPlatformThread  ( socketObj );          mmpt.start ();       }    }    catch ( IOException ioe )    {       System.out.println ( "IOException error: " +      ioe + "." );    } } 

The main method simply instantiates the MobileMessagingPlatformServer object.

    public static void main ( String args[] )    {       MobileMessagingPlatformServer mmps =   new MobileMessagingPlatformServer ();    } } 

What follows is the entire source code of MobileMessagingPlatformThread.java. This class parses the incoming messaging requests from each local application, analyzes and formats each request, and then forwards each request to the MobileServicesClient class for transmission to the proxy server.

 /*  * MobileMessagingPlatformThread.java  */ import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.Socket; import java.util.StringTokenizer; public class MobileMessagingPlatformThread extends Thread {    private Socket socket;    private BufferedReader streamIn;    private PrintWriter writeOut;    private String method = null;    private String rettype = null;    private String names = null;    private String types = null;    private String values = null;    private String servicename = null;    private String serviceclass = null;    public MobileMessagingPlatformThread ( Socket socket )    {       this.socket = socket; 

First, we prepare to read the incoming data as well as prepare to write data back to the local application through the socket connection.

       try       {          streamIn = new BufferedReader ( new InputStreamReader ( socket.getInputStream () ) );          writeOut = new PrintWriter ( socket.getOutputStream () , true );       }       catch ( IOException ioe )       {          System.out.println ( "IOException error - " +  ioe + "." );          try          {             socket.close ();          }          catch ( IOException e )          {             System.out.println ( "IOException error      while closing." );          }       }    }    public void run ()    {       char cb[] = new char[ 1 ];       String resultString = null;       MobileServicesClient mClient =   new MobileServicesClient ();       try       { 

Now, we read in the incoming data from the socket connection and convert it to a String. Next, the parseInMsg method is called on the entire String message to be parsed. As the message is parsed, each attribute name-value pair is written to the corresponding variable. After all of the variables have been updated, the MobileServicesClient object is called to actually transmit the data to the proxy server.

    while ( streamIn.read ( cb , 0 , 1 ) != -1 )          {             StringBuffer sb = new StringBuffer ( 16384 );             while ( cb[ 0 ] != '\0' )             {                sb.append ( cb[ 0 ] );                streamIn.read ( cb , 0 , 1 );             }             String msgIn = sb.toString ();             System.out.println ( "Server received message: "             + msgIn );             parseInMsg ( msgIn );             System.out.println ( "Parsed data as     follows:" );             System.out.println ( "servicename=" + servicename );             System.out.println ( "servicemethod=" + method );             System.out.println ( "rettype=" + rettype );             System.out.println ( "names=" + names );             System.out.println ( "types=" + types );             System.out.println ( "values=" + values );             resultString = mClient.invokeService ( servicename ,           serviceclass , method , rettype , names , types , values ).trim ();             System.out.println ( "Result is: " + resultString + "." );             writeOut.write ( resultString + "\0" );             writeOut.flush ();          }       }       catch ( IOException ioe )       {          System.out.println ( "IOException error." );       }    } 

The parseInMsg method parses the incoming message and writes each attribute name-value pair to its corresponding variable. Within the message sent from the local application, each name-value pair attribute, except for the last one, is followed by the delimiter "###".

The StringTokenizer object returns each delimited token, and the string representation of the token is stored in thisToken. The attribute name and value are extracted from each token by calculating the substring of each thisToken string object.

    private void parseInMsg ( String inStr )    {       StringTokenizer st = new StringTokenizer ( inStr , "###" , false );       String thisToken = null;       while ( st.hasMoreTokens () )       {          thisToken = st.nextToken ().toString ();          if ( thisToken.startsWith ( "servicename=" ) )          {             servicename = thisToken.substring ( 12 );          }          else if ( thisToken.startsWith ( "servicemethod=" ) )          {             method = thisToken.substring ( 7 );          }          else if ( thisToken.startsWith ( "rettype=" ) )          {             rettype = thisToken.substring ( 8 );          }          else if ( thisToken.startsWith ( "names=" ) )          {             names = thisToken.substring ( 6 );          }          else if ( thisToken.startsWith ( "types=" ) )          {             types = thisToken.substring ( 6 );          }          else if ( thisToken.startsWith ( "values=" ) )          {             values = thisToken.substring ( 7 );          }          else          {             System.out.println ( "Unknown parameter received." );          }       }    } } 

What follows is the entire source code of MobileServicesClient.java. This class consists of a single public method, which transmits the Web service call to the proxy server that will in fact invoke the Web service. The message that is transmitted to the proxy server is also formatted such that the proxy server can appropriately invoke the Web service and interpret the results.

The message is sent to the proxy server through a HTTP POST request. On the proxy server side, a J2EE Servlet receives and handles the request.

 /*  * MobileServicesClient.java  */ import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.lang.reflect.Method; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.StringTokenizer; public class MobileServicesClient {    public static String invokeService ( String serviceName ,                                         String serviceClass,                                         String method ,                                         String retType , String argNames , String argTypes , String argValues )    {       byte buf[] = new byte[ 2056 ];       int n;       String urlString;       StringBuffer sb = new StringBuffer ();       String resultStr = "";       Class classObj = null;       Class[] argTypeClasses;       Method methodObj = null;       Object obj = null; 

We first form the message that will be sent as part of our HTTP POST request to the proxy server. We append together all of the information such that the proxy server can itself invoke the appropriate Web service.

 sb.append ( "service =" ); sb.append ( URLEncoder.encode ( serviceName ) ); sb.append ( "&method=" ); sb.append ( URLEncoder.encode ( method ) ); sb.append ( "&rettype=" ); sb.append ( URLEncoder.encode ( retType ) ); sb.append ( "&names=" ); sb.append ( URLEncoder.encode ( argNames ) ); sb.append ( "&types=" ); sb.append ( URLEncoder.encode ( argTypes ) ); sb.append ( "&values=" ); sb.append ( URLEncoder.encode ( argValues ) ); String formData = sb.toString (); 

We then transmit our HTTP POST request to the proxy server located at:

 http://192.168.1.102:9090/ServiceProxyGateway/ServiceProxyGateway 

The data is transmitted as if it were HTML form data and is not encrypted for security.

       try       {          URL url = new URL ("http://192.168.1.102:9090/ ServiceProxyGateway/ServiceProxyGateway" );    HttpURLConnection urlcon = ( HttpURLConnection ) url.openConnection ();          urlcon.setRequestMethod ( "POST" );          urlcon.setRequestProperty ( "Content-type" , "application/x-www-form-urlencoded" );          urlcon.setDoOutput ( true );          urlcon.setDoInput ( true );          PrintWriter pout = new PrintWriter ( new OutputStreamWriter (               urlcon.getOutputStream () , "8859_1" ) ,   true );          pout.print ( formData );          pout.flush (); 

After the HTTP POST request has been sent, we wait for the response. The proxy server responds after it has actually invoked the desired Web service.

Once we receive the response from the proxy server, we concatenate together the response segments to form the entire response message, which is stored in the resultStr object. The resultStr object is returned as the result of invoking the Web service.

          InputStream in = urlcon.getInputStream ();          while ( ( n = in.read ( buf , 0 , buf.length ) ) != -1 )          {             resultStr = resultStr.concat (   new java.lang.String ( buf ).trim () );          }       }       catch ( MalformedURLException mue )       {          System.out.println ( mue );       }       catch ( IOException ioe )       {          System.out.println ( ioe );       }       return ( resultStr );    } } 

Next, we look at how to develop the proxy server. As we saw earlier, the Web service call is transmitted as a message from the actual mobile application to the mobile messaging platform, which then transmits it to the proxy server. In this mobile messaging platform, we use an HTTP POST request to send the message from the mobile messaging platform to the proxy server. Correspondingly, a J2EE Servlet is used on the proxy server side to receive and handle the HTTP POST request.

The proxy server is comprised of the J2EE Servlet ServiceProxyGateway as well as the helper class InvokeService that actually invokes the remote Web service. What follows is the entire source code of ServiceProxyGateway.java.

 /*  * ServiceProxyGateway.java  */ import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.util.StringTokenizer; public class ServiceProxyGateway extends HttpServlet {    private static final String CONTENT_TYPE = "text/html";    public void init ( ServletConfig config ) throws ServletException    {       super.init ( config );    }    /* Handle HTTP GETs and POSTs together */    public void doGet ( HttpServletRequest request , HttpServletResponse response )       throws ServletException , IOException    {       doPost ( request , response );    }    public void doPost ( HttpServletRequest request ,  HttpServletResponse response )      throws ServletException , IOException    {       String paramServiceURL;       String paramMethod;       String paramRetType;       String paramArgNames;       String paramArgTypes;       String paramArgValues; 

First we read the parameters of the HTTP POST request that was sent by the mobile messaging platform.

 paramServiceURL = request.getParameter ( "service" ); paramMethod = request.getParameter ( "method" ); paramRetType = request.getParameter ( "rettype" ); paramArgNames = request.getParameter ( "names" ); paramArgTypes = request.getParameter ( "types" ); paramArgValues = request.getParameter ( "values" ); 

Once we have read in all of the parameters of the POST request, we print them out to the console as a temporary log of the data that was received.

 System.out.println ( "Service Proxy Gateway." ); System.out.println ( "Received data:" ); System.out.println ( "    Service URL: " + paramServiceURL ); System.out.println ( "    Service Method: " + paramMethod ); System.out.println ( "    Method Return Type: " + paramRetType ); System.out.println ( "    Method Arg Names: " + paramArgNames ); System.out.println ( "    Method Arg Types: " + paramArgTypes ); System.out.println ( "    Method Arg Values: " + paramArgValues ); System.out.println ( " " ); 

Now that we have all of the parameters necessary to invoke the remote Web service, we instantiate a new InvokeService object, and set the various parameters in preparation for the Web service invocation using the object's setter methods.

 InvokeService callWS = new InvokeService (); callWS.setMethod ( paramMethod ); callWS.setReturnType ( paramRetType ); callWS.setWSURL ( paramServiceURL ); 

Since a Web service method invocation may have multiple arguments, we parse through each argument token and set its appropriate name, value, and type fields. A comma delimits each of the arguments, and StringTokenizer objects are used to extract each token from each of the overall strings.

       callWS.clearArgs ();       StringTokenizer tokenizerNames = new StringTokenizer ( paramArgNames , "," , false );       StringTokenizer tokenizerTypes = new StringTokenizer ( paramArgTypes , "," , false );       StringTokenizer tokenizerValues = new StringTokenizer ( paramArgValues , "," , false );       int k = 0;       while ( tokenizerNames.hasMoreTokens () )       {          String tokType = tokenizerTypes.nextToken ().trim ();          String tokName = tokenizerNames.nextToken ().trim ();          String tokVal = tokenizerValues.nextToken ().trim ();          callWS.setArgs ( k , tokType , tokName , tokVal );          k = k + 1;       } 

After the callWS object has been properly set, the invokeWSMethod method of the callWS object is called to invoke the actual Web service. CallRetObj is the object returned by the Web service invocation. The string representation of the CallRetObj is returned as the response of the Servlet to the HTTP POST request sent by the mobile messaging platform running on the mobile device.

       Object callRetObj = callWS.invokeWSMethod ();       String callRetObjString =   ( String ) callRetObj.toString ();       response.setContentType ( CONTENT_TYPE );       PrintWriter out = response.getWriter ();       out.println ( callRetObjString );    }    public void destroy ()    {    } } 

What follows is the entire source code of InvokeService.java. The InvokeService class invokes a Web service method using information about the Web service endpoint, method name, each of the method argument names, values, and types, as well as the method return type.

 /**  * InvokeService.java  */ import org.apache.axis.client.Call; import org.apache.axis.client.Service; import java.util.ArrayList; import java.util.List; public class InvokeService {    private static String targetWSURL = "";    private static String mMethodName = "";    private static Class mReturnType;    private static String lReturnType = "";    private static Object retObj;    private List lArgNames = new ArrayList ();    private List lArgTypes = new ArrayList ();    private List lArgValues = new ArrayList ();    public InvokeService ()    {    } 

The invokeWSMethod method is called to invoke a Web service method as specified using the setter methods.

    public Object invokeWSMethod ()    {       Object[] mArgValues =   new Object[ lArgValues.size () ];       try       {          Service service = new Service ();          Call call = ( Call ) service.createCall ();          call.setTargetEndpointAddress ( new java.net.URL     ( targetWSURL ) );          call.setOperationName ( mMethodName );          call.setProperty ( Call.NAMESPACE ,     "http:////tempuri.org//" );          retObj = call.invoke ( ( Object[] )       lArgValues.toArray ( mArgValues ) );       }       catch ( Exception e )       {          System.err.println ( e.toString () );       }       return ( retObj );    }    // The setWSURL method sets the desired Web service    //  endpoint location.    public void setWSURL ( String targetLocation )    {       targetWSURL = targetLocation;    }    // The setMethod method sets the desired Web service    //  method name.    public void setMethod ( String methodName )    {       mMethodName = methodName;    }    // The setReturnType method sets the desired Web    //  service's return type.    public void setReturnType ( String returnType )    {       lReturnType = returnType;       if ( ( lReturnType.compareToIgnoreCase         ( "integer" ) == 0 ) ||          ( lReturnType.compareToIgnoreCase ( "int" ) == 0 ))       {          mReturnType = int.class;       }       else if ( ( lReturnType.compareToIgnoreCase         ( "string" ) == 0 ) ||          ( lReturnType.compareToIgnoreCase ( "str" ) == 0 ))       {          mReturnType = String.class;       }       else       {          System.out.println ( "InvokeService:     Unsupported RetArgType received." );       }    }    // The clearArgs method clears all of the method    //  argument information: names, types, and values.    public void clearArgs ()    {       lArgNames.clear ();       lArgTypes.clear ();       lArgValues.clear ();    }    // The setArgs method sets the name, value, and    //  type of the kth argument of the desired Web    //  service method, where k equals argNum.    public void setArgs (int argNum ,          String argType ,         String argName ,         String argValue )    {       lArgNames.add ( argNum , argName );       if ( ( argType.compareToIgnoreCase ( "integer" )     == 0 ) ||          ( argType.compareToIgnoreCase ( "int" ) == 0 ))       {          lArgTypes.add ( argNum , int.class );          lArgValues.add ( argNum ,     new Integer (       Integer.parseInt ( argValue ) ) );       }       else if ( argType.compareToIgnoreCase   ( "string" ) == 0 )       {          lArgTypes.add ( argNum , String.class );          lArgValues.add ( argNum , argValue );       }       else if ( argType.compareToIgnoreCase   ( "boolean" ) == 0 )       {          lArgTypes.add ( argNum , boolean.class );          lArgValues.add ( argNum , argValue );       }       else       {          System.out.println ( "InvokeService:     Unsupported ArgType received." );       }    } } 

Now that we have seen how to develop the mobile messaging platform, we can build applications using any language or platform and simply pass messages to the messaging platform to invoke arbitrary Web services through the proxy server.

Flash ActionScript Mobile Application User Interface

As we discussed earlier, Macromedia Flash is a powerful platform for the development of user interfaces for mobile applications. Not only does Flash support complex graphics and interactions, it comes with a development environment as well as tools that facilitate graphical user interface development. As more and more mobile device manufacturers bundle the Flash player with their products, Flash represents a strong contender as the platform-of-choice for the development of user interfaces for Web services-based mobile applications.

Flash also supports scripting through its ActionScript language. Based on JavaScript, ActionScript provides a simple means to control different aspects of a Flash movie. For instance, based on user activity, such as a mouse click, different scenes within a Flash movie can be manipulated and shown. For example, in the mobile smart chess application shown in Figure 10-5, a mouse click over a cell that is occupied by a white chess piece results in the piece being relocated to the cell over which the mouse released. Mouse clicks over cells that are unoccupied or are occupied by black chess pieces are ignored, and the movie continues as is.

In this section, we look at the code required to invoke Web services from a Flash-based mobile application user interface. The code segment consists of the following four functions:

  • callWS: This function is called by the Flash-based user interface when the Web service is to be invoked.

  • sendMsg: This is a helper function that is internally called by the callWS function to send the Web service invocation message to the mobile messaging platform.

  • handleIncoming: This is a callback function that is automatically called when a message from the mobile messaging platform is received.

  • closeXmlSocket: This is a simple function that closes and terminates the communications channel between the Flash-based user interface and the mobile messaging platform.

The ActionScript source code in its entirety for these four functions follows:

 function callWS ( ) {   // If a communications channel to the mobile messaging   //  platform is already open, use it; otherwise, open   //  a new socket connection.   if (connectedToServer == 0)   {     objXMLSocket = new XMLSocket ();     objXMLSocket.onConnect = myOnConnect;     // Register the handleIncoming function as the     //  callback function for this socket     objXMLSocket.onXML = handleIncoming;     if ( !objXMLSocket.connect ( "localhost" , 20001 ))     {       // The communications socket could not be opened       trace ("Connection failed.")       connectedToServer = 0;     }   }   else   {     // The communications socket either already exists     //  or a new one was successfully created. Now we     //  can send the message to the mobile messaging     //  platform using the sendMsg function.     sendMsg( "http://192.168.1.102:9090/hpws/soap/               ChessMaster", "ChessMaster", "makeNextMove",               "String", "board", "String", boardStr );   } } function sendMsg ( servicename,                    serviceclass,                    method,                    rettype,                    names,                    types,                    values) {   // This function simply forms a message string consisting   //  of parameter name-value pairs delimited by "###"   strText = "servicename=" add servicename add "###" add             "service###"  add             "method=" add method add "###" add             "rettype=" add rettype add "###" add             "names=" add names add "###" add             "types=" add types add "###" add             "values=" add values;   // The message string is formed into a XML element   //  and sent to the mobile messaging platform   objXml = new XML ();   objElement = objXml.createTextNode ( strText );   objXML.appendChild ( objElement );   objXMLSocket.send ( objXML ); } function handleIncoming ( objXml ) {   // Acknowledge that a new message has been received   trace ( "Incoming message received." );   trace ( "String value is: " + objXML.toString () );   // Convert the incoming message to a string and call   //  the appropriate function to handle the message   makeComputersMove ( objXML.toString () ); } function closeXmlSocket ( ) {   // Close the communications socket   objXMLSocket.close(); } 

The mobile device-side console log information that is printed as a result of the Flash-based mobile chess application invoking the ChessMaster Web service using the mobile messaging platform is shown in Figure 10-8.

Figure 10-8. Device-side console log output for a Flash-based mobile chess application user interface invoking the ChessMaster Web service using the mobile messaging platform.
 Server received message: servicename=http:// 192.168.1.102:9090/hpws/soap/ ChessMaster###serviceclass=ChessMaster###method=makeNextMove# ##rettype=String###names=board###types=String###values=1:1:2: 1:3:1:4:1:5:1:6:1:7:1:8:1:1:2:2:3:3:3:4:2:5:6:6:2:7:2:8:2:1:8 :2:8:3:8:4:8:5:8:6:8:8:6:8:8:1:7:2:7:3:6:4:7:5:7:6:7:7:7:8:7: Parsed data as follows: servicename=http://192.168.1.102:9090/hpws/soap/ChessMaster serviceclass=ChessMaster method=makeNextMove rettype=String names=board types=String values=1:1:2:1:3:1:4:1:5:1:6:1:7:1:8:1:1:2:2:3:3:3:4:2:5:6:6: 2:7:2:8:2:1:8:2:8:3:8:4:8:5:8:6:8:8:6:8:8:1:7:2:7:3:6:4:7:5:7 :6:7:7:7:8:7: Result is: 3,6,3,5,. 

The information following the Server received message: label is the actual message received by the mobile messaging platform by the application user interface. The information following the Parsed data as follows: label is each of the parameter name-value pairs after they have been parsed and extracted by the mobile messaging platform. Finally, the information following the Result is: label is the string representation of the response received by the mobile messaging platform as a result of invoking the ChessMaster Web service.

Now that we have seen how to invoke a remote Web service from a mobile application using a mobile messaging platform, we next see how to invoke a Web service from a mobile application directly, without a messaging platform.

Invoking Web Services Directly Through a Proxy Server

If we do not want to use a messaging platform, we can directly invoke remote Web services by using the MobileServicesClient class from earlier in the chapter. TestServiceInvoke.java is a simple Java program that directly invokes the ChessMaster Web service without going through the mobile messaging platform.

 /*  * TestServiceInvoke.java  */ public class TestServiceInvoke {    public static void main ( String args[] )    {       MobileServicesClient mClient =   new MobileServicesClient ();       String servicename = "http://192.168.1.102:9090/hpws/         soap/ChessMaster";       String serviceclass = "ChessMaster";       String method = "makeNextMove";       String rettype = "String";       String names = "board";       String types = "String";       String values = "1:1:2:1:3:1:4:1:5:1:6:1:7:1:8:1:        1:2:2:3:3:3:4:2:5:6:6:2:7:2:8:2:        1:8:2:8:3:8:4:8:5:8:6:8:8:6:8:8:        1:7:2:7:3:6:4:7:5:7:6:7:7:7:8:7:";       String resultString = mClient.invokeService (         servicename ,                        serviceclass ,                               method ,         rettype ,         names ,         types ,         values ).trim ();       System.out.println ( "Result is: " + resultString );    } } 

Although the above Web service invocation is hard-coded to a particular Web service endpoint and input values, it can be used as a template and expanded for more dynamic Web service invocations from mobile applications.

Proxy server-based Web service invocations from mobile applications (with or without a mobile messaging platform) incur a variety of side effects some positive and some not so positive. In the remainder of this section, we discuss these side effects and provide guidance for best practices.

The first side effect of a proxy server-based Web service invocation model for mobile applications is that they are reasonably straightforward to develop if a non-mobile implementation already exists. For example, if the (non-mobile) Web application is built using J2EE servlets, the servlets can be easily modified to serve as the proxy server.

Presumably, each servlet of the original application was designed to accept input parameters, perform business logic (including invoking Web services) based on the input, and finally generate markup output. The existing application can be mobilized through the following steps:

  1. Develop an appropriate user interface for the mobile application.

  2. Based on user interaction with the user interface, develop business logic that runs on the mobile device and generates the appropriately formatted data to be transmitted to the servlet (proxy server) using HTTP POST.

  3. Modify each servlet such that instead of returning presentation-focused markup as its response, it returns data in a concise format.

  4. Augment the business logic running on the mobile device so that it can interpret the data returned by each servlet and update the user interface as appropriate.

By following these steps, a Web services-based application can be mobilized within a matter of days instead of months. Much of the development work is simply re-using existing and pre-tested business logic. Only the mobile application user interface and some business logic that runs on the mobile device must be developed and tested.

Techniques to support Web service invocation reliability and failover that are architected into the non-mobile application can be directly used by the mobilized application within a proxy server-based model. Techniques such as searching through an UDDI registry for alternate or more appropriate Web service endpoints can be implemented by the proxy server, instead of requiring that that business logic be implemented by the mobile application itself.

Moreover, within a typical enterprise environment, Web services-based applications utilize multiple Web services instead of just one. In this case, a proxy server-based invocation model effectively creates a single, coarse-grained interface to the multiple, underlying Web services. As illustrated in Figure 10-9, a proxy-based invocation model eliminates the individual Web service calls.

Figure 10-9. Proxy-based Web service invocations reduce wireless network usage.

graphics/10fig09.gif

Eliminating individual Web service calls in favor of an effective coarse-grained interface to multiple Web services has numerous benefits for mobile applications as well as for their users. These benefits include:

  • Usage costs: By reducing the number of individual Web service invocations and using a higher-level, more coarse-grained interface to multiple Web services a proxy server-based Web service model reduces network usage, and thus usage costs.

  • Latency: By reducing network usage, proxy server-based Web service invocations also potentially lower application latency by reducing the number of messages that must traverse over slower speed wireless networks. Additionally, since there may be lengthy delays between one Web service call and the next call, the connect/disconnect cycles required to access the wireless network increase latency.

  • Energy conservation: Since transmitting and receiving every bit of data using a wireless network consumes a fixed amount of energy, reducing the amount of wireless network usage has a corresponding reduction in energy consumption. Conserving the energy consumed by mobile applications increases the device's battery life.

These and other related benefits are advantageous for the mobile application itself, as well as for users of the application.

Although they are usually easier to develop and have a plethora of advantages, proxy-based Web service invocation models also suffer from a few shortcomings. The most important of these is that each application has a single point of failure, namely the proxy server. If the proxy server becomes unavailable or experiences a decrease in performance due to increased usage, each mobile application that relies on that proxy will suffer.

Additionally, the proxy server introduces an additional hop along the network that can increase the mobile application's latency. In some cases, the proxy server may be located further away on the network than the actual Web service endpoint. Depending on the relative speeds of the wireless and wireline networks, a direct Web service invocation may introduce less latency than a proxied invocation.

Many of these issues can be addressed or at least reduced by using clusters of servers that are geographically distributed throughout the network for the Web service invocation proxies. If any particular proxy server goes down or becomes slow, the other servers within the distributed cluster can handle proxy requests.

Now that we have seen the implementation of a proxy-based mobile Web services system, in the next section we describe the design of mobile applications that directly access Web services.



Developing Enterprise Web Services. An Architect's Guide
Developing Enterprise Web Services: An Architects Guide: An Architects Guide
ISBN: 0131401602
EAN: 2147483647
Year: 2003
Pages: 141

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net