Programming for Mobility


In this section, we extend the application to support mobile access. As we saw in Chapter 10, supporting mobile access to an application can be accomplished by using either a proxy-based architecture or communicating with the individual Web services directly from the mobile application.

For existing enterprise applications, a proxy-based mobile solution is usually easier to develop. Minimally, the application view or presentation layer is simply mobilized and migrated to the mobile device. The remainder of the application, including the business logic and Web service invocations, remains on the server. This server then acts as a proxy between the mobile application and the remote Web services.

Figure 13-40 depicts the architecture that will mobilize the application.

Figure 13-40. Mobilizing the application by using a proxy-based architecture.

graphics/13fig16.gif

The MobileServlet proxy interprets the data from the mobile application, MobileClient-Application, and in turn invokes the appropriate Web services that implement the required business logic to handle the requests. The proxy combines information from the Web services, as well as other business logic implemented by the proxy itself, and responds to the mobile request in a format acceptable to the mobile device and application. It is important to note that this is not a browser-based solution, but instead uses a mobile application that communicates with the Servlet using HTTP.

Figure 13-41 shows a screenshot of the mobile user interface of the MobileClientApplication. The user interface is simple and allows the user to enter the desired part number and quantities from both Vendors A and B. When the user depresses the FINDIT button, it submits the data to the MobileServlet as HTTP POST form data. The message returned by the MobileServlet is displayed within the rectangular textarea widget.

Figure 13-41. Mobile user interface of the MobileClientApplication.

graphics/13fig17.jpg

The source code of the MobileClientApplication is listed in Figure 13-42. The application basically consists of two major sections. The first section builds the entire graphical user interface by appropriately placing textboxes and labels throughout the frame widget. The widget is sized to fit within a personal digital assistant (PDA) device. The second section is comprised of the goButtonActionPerformed method, and implements the business logic that exchanges messages to the MobileServlet based on the data input by the user into the form fields.

Figure 13-42. MobileClientApplication source code.
 import java.awt.*; import java.awt.event.ActionEvent; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; public class MobileClientApplication extends Frame {    // The graphical user interface widget variable    //  definitions    TextField vendorAPartNumberTextField;    Label vendorAPartNumberLabel;    TextField vendorAQuantityTextField;    Label vendorAQuantityLabel;    // The vendorBPartNumberTextField,    //  vendorBPartNumberLabel, vendorBQuantityTextField,    //  vendorBQuantityLabel have been removed for brevity    // The button that the user presses after entering    //  all of the requested information    Button goButton;    // The textfield where the results from the Web    //  service invocation are displayed    TextArea resultsTextField;    public MobileClientApplication ()    {    }    // Build the graphical user interface    public void createTextEntry ()    {       vendorAPartNumberLabel = new Label ();       vendorAPartNumberLabel.setForeground ( Color.black );       vendorAPartNumberLabel.setBackground ( Color.white );       vendorAPartNumberLabel.setText("Vendor A Part No.: " );       vendorAPartNumberLabel.setLocation ( 5 , 30 );       vendorAPartNumberLabel.setBounds ( 5 , 30 , 100 , 20 );       vendorAPartNumberLabel.setFont ( new java.awt.Font                                      ( "Dialog" , 1 , 12 ) );       vendorAPartNumberTextField = new TextField ();       vendorAPartNumberTextField.setColumns ( 4 );       vendorAPartNumberTextField.setForeground(Color.black );       vendorAPartNumberTextField.setBackground(Color.white );       vendorAPartNumberTextField.setText ( "111" );       vendorAPartNumberTextField.setColumns ( 15 );       vendorAPartNumberTextField.setLocation ( 135 , 30 );       vendorAPartNumberTextField.setBounds ( 135 , 30 , 100 ,                                              20 );       vendorAPartNumberTextField.setFont ( new java.awt.Font                                      ( "Dialog" , 1 , 12 ) );       vendorAQuantityLabel = new Label ();       vendorAQuantityLabel.setForeground ( Color.black );       vendorAQuantityLabel.setBackground ( Color.white );       vendorAQuantityLabel.setText ( "Vendor A Qty: " );       vendorAQuantityLabel.setLocation ( 5 , 60 );       vendorAQuantityLabel.setBounds ( 5 , 60 , 100 , 20 );       vendorAQuantityLabel.setFont ( new java.awt.Font                                     ( "Dialog" , 1 , 12 ) );       vendorAQuantityTextField = new TextField ();       vendorAQuantityTextField.setColumns ( 2 );       vendorAQuantityTextField.setForeground ( Color.black );       vendorAQuantityTextField.setBackground ( Color.white );       vendorAQuantityTextField.setText ( "33" );       vendorAQuantityTextField.setLocation ( 135 , 60 );       vendorAQuantityTextField.setBounds ( 135 , 60 , 100 ,                                            20 );       vendorAQuantityTextField.setFont ( new java.awt.Font                                      ( "Dialog" , 1 , 12 ) );       // The vendorBPartNumberTextField,       //  vendorBPartNumberLabel, vendorBQuantityTextField,       //  vendorBQuantityLabel have been removed for brevity       resultsTextField = new TextArea ( "" , 20 , 5 ,                        TextArea.SCROLLBARS_HORIZONTAL_ONLY );       resultsTextField.setEditable ( false );       resultsTextField.setForeground ( Color.red );       resultsTextField.setBackground ( Color.white );       resultsTextField.setLocation ( 05 , 160 );       resultsTextField.setBounds ( 05 , 160 , 230 , 70 );       resultsTextField.setFont ( new java.awt.Font                                     ( "Dialog" , 1 , 12 ) );       goButton = new Button ();       goButton.setBackground ( Color.black );       goButton.setForeground ( Color.black );       goButton.setFont ( new java.awt.Font ( "Dialog" , 1 ,                                               12 ) );       goButton.setForeground ( SystemColor.activeCaptionText );       goButton.setLabel ( "FIND IT" );       goButton.setLocation ( 125 , 250 );       goButton.setBounds ( 125 , 250 , 110 , 30 );       goButton.addActionListener ( new         java.awt.event.ActionListener ()       {          public void actionPerformed ( ActionEvent e )          {             goButtonActionPerformed ( e );          }       } );       this.add ( vendorAPartNumberLabel , "North" );       this.add ( vendorAPartNumberTextField , "North" );       this.add ( vendorAQuantityLabel , "North" );       this.add ( vendorAQuantityTextField , "North" );       // The vendorBPartNumberTextField,       //  vendorBPartNumberLabel, vendorBQuantityTextField,       //  vendorBQuantityLabel have been removed for brevity       this.add ( resultsTextField , "North" );       this.add ( goButton , "North" );    }    // Close the user interface window and exit if the    //  user so chooses    public boolean handleEvent ( Event evt )    {       if ( evt.id == Event.WINDOW_DESTROY )       {          System.exit ( 0 );       }       return super.handleEvent ( evt );    }    // This method is called when the user presses the    //  goButton (pressed after the user enters all of    //  the requested information.    void goButtonActionPerformed ( ActionEvent e )    {       byte buf[] = new byte[ 4012 ];       int n;       String confirmStr = "";       StringBuffer sb = new StringBuffer ();       sb.append ( URLEncoder.encode ( "vapn" ) + "=" );       sb.append ( URLEncoder.encode (                   vendorAPartNumberTextField.getText () ) );       sb.append ( "&" + URLEncoder.encode ( "vaq" ) + "=" );       sb.append ( URLEncoder.encode (                   vendorAQuantityTextField.getText () ) );       // The information for vbpn and vbq (read from       //  vendorBPartNumberTextField and       //  vendorBQuantityTextField)       //  have been removed for brevity       String formData = sb.toString ();       try       {          URL url = new URL (                 "http://localhost:8080/meps/MobileServlet");          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 ();          InputStream in = urlcon.getInputStream ();          while((n = in.read(buf , 0 , buf.length)) != -1 )          {             confirmStr =                   confirmStr.concat (new String(buf ,0 , n));          }          if ( confirmStr != null )          {             resultsTextField.setText ( confirmStr );          }       }       catch ( MalformedURLException err )       {          System.out.println ( err );       }       catch ( IOException err2 )       {          System.out.println ( err2 );       }    }    public static void main ( String args[] ) throws Exception    {       MobileClientApplication window =                            new MobileClientApplication ();       window.setTitle ( "Mobile Enterprise Procurement" );       window.setLayout ( null );       window.setBackground ( Color.white );       window.createTextEntry ();       window.pack ();       window.resize ( 250 , 320 );       window.show ();    } } 

The source code for the MobileServlet is listed in Figure 13-43. The MobileServlet serves as a proxy between the MobileApplicationClient and the back-end server-side business logic, as was implemented by the TransactionalClient class.

Figure 13-43. MobileServlet source code.
 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; public class MobileServlet extends HttpServlet {    private static final String CONTENT_TYPE = "text/html";    static String paramVendorAPartNumber;    static String paramVendorAQuantity;    static String paramVendorBPartNumber;    static String paramVendorBQuantity;    String resultString = "empty";    public void init ( ServletConfig config )                                  throws ServletException    {       super.init ( config );    }    // Forward the doGet to the doPost    public void doGet ( HttpServletRequest request ,                        HttpServletResponse response )                        throws ServletException , IOException    {       doPost ( request , response );    }    // Service the HTTP POST request    public void doPost ( HttpServletRequest request ,                         HttpServletResponse response )                         throws ServletException , IOException    {       boolean serviceConfirm;       boolean formReady = true;       paramVendorAPartNumber = request.getParameter("vapn");       paramVendorAQuantity = request.getParameter ("vaq");       paramVendorBPartNumber = request.getParameter ("vbpn");       paramVendorBQuantity = request.getParameter ("vbq");       response.setContentType ( CONTENT_TYPE );       PrintWriter out = response.getWriter ();       // All of the fields must be filled in,       // otherwise, print a message to fill everything in.       // This is done by setting formReady to false       if ( ( paramVendorAPartNumber == null ) ||          ( paramVendorAQuantity == null ) ||          ( paramVendorBPartNumber == null ) ||          ( paramVendorBQuantity == null ) )       {          formReady = false;       }       else       {          if ((paramVendorAPartNumber.trim ().length () == 0 )          || ( paramVendorAQuantity.trim ().length () == 0 )          || ( paramVendorBPartNumber.trim ().length () == 0 )          || ( paramVendorBQuantity.trim ().length () == 0 ) )          {             formReady = false;          }       }       if ( !formReady )       {          // If the form is not ready, then return a message          //  to completely fill-in the required fields.          resultString = "Please complete the above form!";       }       else       {          // If the form is ready, then we simply have to          //  invoke the transactionalClient which implements          //  the business logic for completing the          //  transaction. The message returned by the          //  TransactionalClient is returned to the mobile          //  application.          resultString = invokeTransactionalClient                           (paramVendorAPartNumber,                            paramVendorBPartNumber,                            paramVendorAQuantity,                            paramVendorBQuantity);       }       out.println (resultString);    }    public void destroy ()    {    }    private static String invokeTransactionalClient (vapn,                                           vbpn, vaq, vbq)    {       String returnString = "return sting from ITC";       // The body of the TransactionalClient class       //  goes here. The only changes are (1) instead       //  of outputting messages to the console, the       //  the messages should be returned as part of       //  the method's return value, and (2) the hard-       //  coded Vendor A and B part number and quantities       //  must be set based on the vapn, vbpn, vaq, and       //  vbq variables.       return ( returnString );    } } 

The MobileServlet is a standard J2EE Servlet that accepts messages from the MobileClientApplication as HTTP POST form parameters. These parameters are read and parsed by the MobileServlet to ascertain that all of the required fields have been filled in by the user. If some of the form fields are empty, a message to completely fill in all of the form fields is returned to the MobileClientApplication which, in turn, displays it for the user.

If all of the form fields are properly filled in, then the MobileServlet invokes the invokeTransactionalClient method. This method is basically a replica of the TransactionalClient class from Figure 13-38, and has not been shown for the sake of brevity. The only changes between the implementation of the TransactionalClient and the invokeTransactionalClient are as follows:

  1. Messages must be output not to the system console, but instead must be returned as part of the method's return value. For example, the System.out.println's within the TransactionalClient class that output user messages must simply be returned as the return value of the invokeTransactionalClient method.

  2. The Vendor A and B part numbers and quantities that are hardcoded in the TransactionalClient class must be set based on the vapn, vbpn, vaq, and vbq variables. That is, the following two lines must be replaced as shown:

     int  orderA = vas.placeOrder(101, 2);        int  orderB = vbs.orderComponent(45,  888); 

    with

     int  orderA = vas.placeOrder(vapn, vaq);        int  orderB = vbs.orderComponent(vbq,  vbpn); 

With these simple changes, our mobilization of the TransactionalClient is complete.



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