Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member182638
Active Contributor

Following on from Part 1  (Build your first Mobile web app using jQuery Mobile and ABAP - Part 1) and Part 2  (Build your first Mobile web app using jQuery Mobile and ABAP - Part 2), we finally explore a basic UPDATE scenario for our Mobile web app using jQuery Mobile and ABAP BSP. 

Firstly I should acknowledge my good colleague Abhinav Tayal (below) with whom I collaborated to produce this final part of the blog series.    Abhinav previously worked with SAP Labs developing BSP applications and so I appreciated his thoughts and guidance on the server-side processing to bring this final part of the blog series to completion.

OK, in Part 2 we built 3 HCM employee self-service display scenarios (display Org details, Address details, Absence bookings) for our Smartphone / Tablet using jQuery Mobile and BSP ABAP.  If you followed the steps you should have accomplished this within an hour or two.  We ended up with a functioning Mobile Web App and appreciated the power that a lightweight framework such as jQuery Mobile (along with HTML5/CSS3) could bring to the UI.  And did you notice we didn't need to write a single line of Javascript?  The jQuery Mobile framework did the heavy lifting in this respect.

In this part we will need to add a little Javascript.  We will deal with that when we extend the view layout.  

To begin with however we will commence with extending the model class with a method to be able to update your Address ...  

MODEL

Extend the model class ZCL_MOBILE_DEMO_MODEL that you created in Part 2 as follows ...

  • Add a new Public instance method SET_ADDRESS
  • Add the following parameter declarations to this method ...

 

  • Now insert the following logic for this method (note that this is simplified somewhat for the purpose of the exercise and would ordinarily include additional error handling) ... 

METHOD set_address.

  DATA: lock_return TYPE bapireturn1,

        bapi_return TYPE bapireturn1.

* Lock the employee record

  CALL FUNCTION 'BAPI_EMPLOYEE_ENQUEUE'

    EXPORTING

      number = address_data-pernr

    IMPORTING

      return = lock_return.

  IF lock_return IS NOT INITIAL.

    message = 'Cannot lock employee record - please try again later'.

    RETURN.

  ENDIF.

* Execute the address change

  CALL FUNCTION 'BAPI_ADDRESSEMP_CHANGE'

    EXPORTING

      employeenumber         = address_data-pernr

      subtype                = address_data-subty

      objectid               = address_data-objps

      lockindicator          = address_data-sprps

      validitybegin          = address_data-begda

      validityend            = address_data-endda

      recordnumber           = address_data-seqnr

*     CONAME                 =

      streetandhouseno       = address_data-stras

*     SCNDADDRESSLINE        =

      city                   = address_data-ort01

*     DISTRICT               =

      postalcodecity         = address_data-pstlz

      state                  = address_data-state

*     COUNTRY                =

*     TELEPHONENUMBER        =

*     NOCOMMIT               =

    IMPORTING

      return                 = bapi_return.

* Capture the return message

  if bapi_return is initial.

    m_address_data = address_data.

    message = ''.

  else.

    message = bapi_return.

    return.

  endif.

* Unlock the employee record

  CALL FUNCTION 'BAPI_EMPLOYEE_DEQUEUE'

  EXPORTING

    number        = address_data-pernr.

ENDMETHOD.

  • A few comments about this method ... it calls a standard BAPI to execute the address change.  If a BAPI return is received, the return message is propogated back to the caller of the method, otherwise the M_ADDRESS_DATA attribute for the model class is updated with the new address.
  • Save and activate the changes 

CONTROLLER

Extend the BSP controller class ZCL_MOBILE_DEMO_CONTROLLER as follows ...

  • Add a new instance method PROCESS_INPUT.
  • Add the following parameter declaration to this method ...

  • Now insert the following logic for this method (once again this is simplified somewhat for the purpose of the exercise and would ordinarily include additional error handling) ...

METHOD process_input.

* Data declaration

  DATA: l_view TYPE REF TO if_bsp_page,

        ls_field  TYPE ihttpnvp,

        new_address TYPE BAPIP0006.

* Refresh model if necessary

  IF m_mobile_model IS NOT BOUND.

    do_init( ).

  ENDIF.

* Initialise new_address to be the same as the existing address

  new_address = m_mobile_model->m_address_data.

* Street

  READ TABLE lt_fields WITH KEY name = 'street' INTO ls_field.

  IF sy-subrc = 0.

    new_address-stras = ls_field-value.

  ENDIF.

* City

  READ TABLE lt_fields WITH KEY name = 'city' INTO ls_field.

  IF sy-subrc = 0.

    new_address-ort01 = ls_field-value.

  ENDIF.

* State

  READ TABLE lt_fields WITH KEY name = 'state' INTO ls_field.

  IF sy-subrc = 0.

    new_address-state =  ls_field-value.

  ENDIF.

* Postcode

  READ TABLE lt_fields WITH KEY name = 'postcode' INTO ls_field.

  IF sy-subrc = 0.

    new_address-pstlz = ls_field-value.

  ENDIF.

  CALL METHOD m_mobile_model->set_address

    EXPORTING

      address_data = new_address

    RECEIVING

      message      = m_message.

  l_view = create_view( view_name = 'message.xml').

*   Set the message

  l_view->set_attribute( name = 'lv_message' value = m_message ).

*   Call the view

  call_view( l_view ).

ENDMETHOD.

  • The PROCESS_INPUT method performs the task of extracting the address fields from the HTTP POST (which will be declared later below) and then executing the SET_ADDRESS method that we declared against the model class.  The return message is then passed to a new view 'message.xml' (which we will define shortly) and the view is called and returned back as the HTTP response.
  • Of course in reality you would architect a method such as PROCESS_INPUT to handle multiple possible scenarios to allow this approach to scale.
  • We need to update the DO_REQUEST method which we implemented in Part 2 so that it now executes PROCESS_INPUT when input form fields are detected

METHOD do_request.

.... where we previously had ...

  ELSE.

* Process input fields

* Ignore this at this stage for Part 2 of the blog

  ENDIF.

.... change this to ...

  ELSE.

* Process input fields

    process_input( lt_fields ).

  ENDIF.

  • Note that this approach deviates from the standard call to DISPATCH_INPUT which is an existing provided method for input processing.  We could have alternatively chosen to re-implement this method instead of creating a separate one.
  • Save and activate the changes.

VIEW

Now hopefully in the controller class method PROCESS_INPUT you noticed we are calling a new view 'message.xml'.  We now need to declare this as follows for the BSP Application ZMOBILE_DEMO ...

  • Right click on the BSP application ZMOBILE_DEMO and select to create a Page.  Enter the page name as 'message.xml', enter a description, and select the page type as View.
  • For the page, select the tab Page Attributes and enter the following attributes ...

  • For the page, select the tab Layout and overwrite the default HTML with the following ...

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

<return>

  <% if lv_message is initial. %>

  <result>0</result>

  <message>Record updated successfully</message>

  <% else. %>

  <result>1</result>

  <message><%= lv_message %></message>

  <% endif. %>

</return>

Finally, we need to enrich the original view layout for 'main.htm' with some Javascript.  I made the decision to hijack the form submission when a user presses the 'Save' button for the Address Update page using jQuery and to submit the data explicitly via an Ajax call to the ABAP server.  In this case the call is made directly back to the BSP application controller and handled there (via DO_REQUEST and subsequently PROCESS_INPUT), however the call could just as readily have been made to an alternate web service, such as (for instance) the future Gateway product which is released in 2011 (although the calls would need to be framed around REST principles).

  • Maintain the layout for the original view 'main.htm' which we created in Part 2, and insert the Javascript specified below (note that best practice in reality is to code the Javascript into a separate file and reference it from the HTML, but for simplicity of the blog I have declared it as inline Javascript here) ...

<!DOCTYPE html>

<html>

<head>

  <title>Mobile Demo</title>

  <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.css"></link>

  <script src="http://code.jquery.com/jquery-1.4.4.min.js"></script>

  <script src="http://code.jquery.com/mobile/1.0a2/jquery.mobile-1.0a2.min.js"></script>

  <!-- New script declaration for Part 3 below ... -->

  <script type="text/javascript">

  // Event registration

  $(function() {

      // Register event for handling submit of address updates

      $('#address_update').submit(function() {

          // Compile data to send to SAP server

          var dataString = '&street=' + $("input#street").val() +

                           '&city=' + $("input#city").val() +

                           '&state=' + $("input#state").val() +

                           '&postcode=' + $("input#postcode").val();

          // Initiate page loading animation

          $.mobile.pageLoading();

          // Perform posting to SAP server

          $.ajax({

              type: "POST",

              url: "mobilemain.do",

              data: dataString,

              success: function(xml){

                           // Disable page loading animation

                           $.mobile.pageLoading(false);

                           // Process return page

                           // Evaluate the return code from the return xml

                           if ($(xml).find("result").text() == "0") {

                             // If successful update the relevant address in the HTML DOM

                             $('#display_street').text($("input#street").val());

                             $('#display_city').text($("input#city").val());

                             $('#display_state').text($("input#state").val());

                             $('#display_postcode').text($("input#postcode").val());

                           }

                           // Extract the return message text from the return xml

                           var msg = ($(xml).find("message").text());

                           // Set the return message

                           $('#return_message').text(msg);

                           // Popup the message dialog

                           $.mobile.changePage("#message", "pop");

                           // Return to the employee address page

                           $.mobile.changePage("#emp_address", "slide");

                        } // Return message

          }); // Ajax posting

      }); // Submit handler

  }); // Event registration

  </script>

</head>

.... etc etc.

  • I have tried to comment the Javascript to help you understand it better.  In basic terms, we use a jQuery (not jQuery Mobile) API to register an event listener for the Address Update submit event.  When this event fires, jQuery funnels it into our Javascript function.  The function firstly formats the raw data to send to the server, initiates the animation (so the user sees that server communication is occurring), and initiates a HTTP POST to the BSP application.  The response received is captured and the page loader animation is terminated.  At this stage we hope to have an XML return page in the Javascript variable 'xml'.  We evaluate this page for a result code.  If it is 0 (success) then we update the address values in our HTML DOM accordingly.  Finally we extract the return message, insert that into the HTML DOM for the Message 'dialog' (I referred to that briefly in Part 2) and execute a page transition to display the message dialog.
  • The end result is that we successfully execute a basic UPDATE scenario using Ajax against our ABAP server.  If you test this, you can use transaction PA20 and evaluate infotype 0006 to see that the address record was indeed updated in the system.

Execute your BSP application.  If you are able to visualise it using a browser such as Safari (avoid Internet Explorer because the user experience is very poor) or even better a Smartphone such as an iPhone or Android, it should behave something like this YouTube video ...


ARCHITECTURAL THOUGHTS

In reality there are a multitude of architectural design approaches that could be used to execute the UPDATE scenario, and the one described in this blog is simplistic and would need additional work to enable it to scale for multiple scenarios.  Nonetheless I have this working and have decided to document it rather than waiting to build the perfect architecture.

In my discussions with Abhinav some of the concerns we toyed with included ...

  • How much information to return in the response page.  At the moment the solution documented here is very basic and minimalist, but you could choose to also return the HTML fragment for the area you have updated and when receiving this in Javascript you update the HTML DOM accordingly.  This would alleviate the need for the manual Javascript updates that are being made to update the address values in our HTML DOM.
  • On the Javascript side the solution here manually encodes values relating to address.  You would want to abstract this in some manner such that the Javascript function can be called more generically without having to duplicate it for each scenario. That's my next task ...

CONCLUSION

Notwithstanding that the solution we have built would need additional work to make it deployable (as indicated throughout the blog I have simplified it here, removing error handling etc), you can see that with a relatively small quantity of ABAP, HTML and Javascript, you can build a fully functional Mobile web app from your ABAP server.  It took only a couple of days to build this solution which includes 3 scenarios (and documented here it should take you less than a couple of hours to do the same).  Think about how many you could build in a couple of weeks, and the value that this could bring to your organisation.

Here are some possibilities (all of which are very achievable - I already have pursued some of these ...)

  • Other Employee Self Service functions such as display leave balances (quotas), book absences (leave), display bank accounts etc.
  • Manager Self Service functions, such as displaying leave bookings of subordinates (eg. to find out who is booked to be absent today) etc.
  • Workflow listing and approvals.
  • Customer lookup, opportunities and activities details.
  • Asset maintenance functions.
  • etc. etc.

There are also additional HTML5 FEATURES that you could incorporate to extend this solution, to improve the offline capability of the web application.   Some of these include the offline database storage capabilities of HTML5, as well as the cache manifest concept which permits web pages to be stored locally on the client and accessed when there is no network connection.  In fact it was leveraging these features which helped SAP Mentor Matt Harding and Alisdair Templeton to win the Las Vegas TechEd 2010 Demo Jam prize this year.

Hopefully you have found this blog series to have been somewhat useful.  It documents my experience investigating the world of mobile web app development (in an SAP context), after having explored native and hybrid iPhone application development.  Certainly I was surprised with how quickly the web app was able to be constructed.  I hope you can take this, build upon it, and share your experiences with the community also.  Please feel free to comment below on how you went ...

PS:  If you enjoyed this blog series please see my john.moy3/blog/2011/01/17/extend-your-sap-jquery-mobile-web-app-with-html5-concepts-and-native-device-features--part-1 blog series where I explore a more advanced architectural style with jQuery Mobile and extend it with HTML5/CSS3 and native device features.

36 Comments
Labels in this area