Consuming openMDWS Services using EWD (Part 2)

In this second part of my two-part article, I’m going to go through in detail how to build an EWD application that consumes openMDWS services.

Although I’ll be posting here all the source code that makes up the example application, you can download it all from the EWD Github site.  If you download it, copy the contents into a new EWD Application directory named omDemo.  Amongst the EWD source page files, you’ll find a GT.M routine file that I’ve included named openMDWSDemo.m.  This contains the onBeforeRender methods for the omDemo application.  You should move this to the appropriate directory for your EWD script routine files: on a dEWDrop server, copy it to /home/vista/p/.  Note that you’ll need to edit some of the configuration details in the openMDWSDemo.m routine file before you try running it.  This will be described below.

So the first thing we must do is to create a new EWD Application directory for our new application.  We’re going to call it omDemo (an abbreviation of openMDWSDemo).  On a dEWDrop server, we therefore must create the directory /home/vista/www/ewd/omDemo.

Our example application is going to make use of the ExtJS Javascript framework.  EWD already integrates this framework and exposes its widgets etc as EWD Custom Tags.  The dEWDrop VM comes with ExtJS (and Sencha Touch 2) pre-installed, so we can start using it straight away.  If you’re trying out this example on a custom VistA server, you’ll need to install ExtJS: see the relevant chapter in the EWD/ExtJS Reference Guide.

We’ll first create our EWD Application’s First Page (by convention named index.ewd) which will be as follows:

<ext4:container rootPath="/vista/ext-4" isFirstPage="true" onBeforeRender="initialise^openMDWSDemo">

  <ext4:viewPort layout="border">
    <ext4:panel region="north" id="northPanel" title="OpenMDWS Demo: <?= #vista.systemId ?>" autoheight="true" border="false" margins="0 0 5 0">
      <ext4:toolbar dock="top">
        <ext4:button text="Get Clinics" id="getClinicsBtn" hidden="true" nextPage="getClinics" addTo="westPanel" />
      </ext4:toolbar>
    </ext4:panel>
    <ext4:panel region="west" id="westPanel" collapsible="true" title="" width="200" autoheight="true" />
    <ext4:panel region="center" height="100%" id="centerPanel" />
  </ext4:viewPort>

  <ext4:modalwindow title="EWD/MDWS Scheduler Demo" id="loginPanel" height="200" width="400" layout="fit" autoShow="true">
    <ext4:formPanel bodyPadding="10">
      <ext4:fieldset title="Login to VA System <?= #vista.systemId ?>">
        <ext4:textfield id="accessCode" inputType="password" fieldLabel="Access Code" allowBlank="false" value="" />
        <ext4:textfield id="verifyCode" inputType="password" fieldLabel="Verify Code" allowBlank="false" value="" />
      </ext4:fieldset>
     <ext4:button text="Quick Login" handler="function() {Ext.getCmp('accessCode').setValue('worldvista6');Ext.getCmp('verifyCode').setValue('$#happy7');}" />
     <ext4:submitbutton text="Submit" nextPage="login" />
    </ext4:formPanel>
  </ext4:modalwindow>

</ext4:container>

I’m not going to explain in detail the use of ExtJS Custom Tags in EWD: all that is documented in the EWD/ExtJS Reference Guide.

However, in summary, what this set of EWD Custom Tags defines is an ExtJS 3-panel layout (North, West and Center) that will be used for the main application, but it overlays this with a modal panel containing a login form. Save this page as index.ewd in the omDemo application directory. Then compile it. If you’re using dEWDrop, do the following (first check that you’re in the /home/vista/ path):

vista@dEWDrop:~$ pwd
/home/vista
vista@dEWDrop:~$ mumps -dir

MU-beta>d compileAll^%zewdAPI("omDemo")
/home/vista/www/ewd/omDemo/ewdAjaxError.ewd
/home/vista/www/ewd/omDemo/ewdAjaxErrorRedirect.ewd
/home/vista/www/ewd/omDemo/ewdErrorRedirect.ewd
/home/vista/www/ewd/omDemo/index.ewd

MU-beta>

Before we can run the index page in a browser, we first need to define the onBeforeRender method that is specified in the main container tag, ie:

<ext4:container rootPath="/vista/ext-4" isFirstPage="true" onBeforeRender="initialise^openMDWSDemo">

What we’ll do in this method is to set up the openMDWS EWD Session variables that define the openMDWS environment we want to invoke: we saw these in the example in the first part of this posting. So we need to create the openMDWSDemo Mumps routine. If we’re using a dEWDrop server, we’ll do this by creating a file named openMDWSDemo.m in the /home/vista/p/ directory. The routine should initially contain the following:

openMDWSDemo ; EWD/openMDWS demo: scripts
 ;
initialise(sessid)
 ;
 d setSessionValue^%zewdAPI("vista.systemId","Robs dEWDrop Server",sessid)
 d setSessionValue^%zewdAPI("mdws.host","192.168.1.120",sessid)
 d setSessionValue^%zewdAPI("mdws.facade","SchedulingSvc",sessid)
 d setSessionValue^%zewdAPI("mdws.version","openMDWS",sessid)
 d setSessionValue^%zewdAPI("mdws.path","/vista/",sessid) 
 d setSessionValue^%zewdAPI("vista.host","localhost",sessid)
 d setSessionValue^%zewdAPI("vista.sslProxyPort","89",sessid)
 QUIT ""
 ;

You’ll probably need to change the mdws.host value from 192.168.1.120 to the one assigned to your dEWDrop (or other VistA) server.

The Session variable vista.systemId is used for display purposes in the ExtJS layout in index.ewd, ie:

  <ext4:panel region="north" id="northPanel" title="OpenMDWS Demo: <?= #vista.systemId ?>" autoheight="true" border="false" margins="0 0 5 0">

  and:

  <ext4:fieldset title="Login to VA System <?= #vista.systemId ?>">

Once we’ve saved the openMDWSDemo routine, we’re ready to try running the application in a browser.  On a dEWDrop server, the URL you use is:

  https://[domainName/IP Address]/vista/omDemo/index.ewd

  eg if the dEWDrop server has been allocated an IP address of 192.168.1.120:

  https://192.168.1.120/vista/omDemo/index.ewd

The first time you do this, you’ll probably get a warning about the SSL certificate, eg:

 
 
 
 
 
 
 
 
 
 
 
 
 

Don’t worry about this – it’s because the dEWDrop server has a self-certified SSL certificate.  Just click the Proceed Anyway button.  You should now see the greyed out ExtJS layout, overlaid with the VistA login form:

 
 
 
 
 
 
 
 
 
 
 
 
 

I’ve added a handy speed-up feature for testing which, of course, shouldn’t be present in a production application: if you click the button in the login form that is named Quick Login, it automatically inserts the dEWDrop default Access Code and Verify Code into the form fields.  We’ve not yet added the mechanism for handling the user’s login, so don’t click the Submit button yet.

If you look in the index.ewd source page file, you’ll see what the Submit button is going to do when it is clicked:

  <ext4:submitbutton text="Submit" nextPage="login" />

This is EWD-shorthand for specifying that when the button is clicked, a request will be made for an EWD page named login.ewd.  This will be what’s known as an EWD fragment – not a complete page of HTML, but just a fragment of markup and/or Javascript.  The login.ewd fragment will need to do two things:

– validate the submitted Access Code and Verify Code.  If invalid, it must return appropriate error messages.  This task will be the responsibility of the fragment’s onBeforeRender method;

– if valid, remove the modal login form panel, and bring the main ExtJS layout into focus.

We’ll also make it add the logged in user’s name to the top of the page, and add a button to the top toolbar:

So let’s write the login.ewd page:

<ext4:fragment onBeforeRender="login^openMDWSDemo">

  <ext4:js at="top">
    Ext.getCmp("loginPanel").destroy();
    Ext.getCmp("getClinicsBtn").show();
    Ext.getCmp("northPanel").setTitle("Welcome <?= #vista.name ?>");
  </ext4:js>

</ext4:fragment>

We’ll also add the onBeforeRender method (login) to the openMDWSDemo.m routine file:

login(sessid)
 ;
 n data,nvps,ok,results,vaSystem
 ;
 s vaSystem=$$getSessionValue^%zewdAPI("vista.systemId",sessid)
 ;
 s nvps("sitelist")=vaSystem
 s ok=$$request^%zewdMDWSClient("connect",.nvps,.results,sessid)
 i '$$isConnected^%zewdMDWSClient(.results) QUIT "Unable to connect to VA system "_vaSystem_": "_$$getFaultMessage^%zewdMDWSClient(.results)
 ;
 s nvps("username")=$$getSessionValue^%zewdAPI("accessCode",sessid)
 s nvps("pwd")=$$getSessionValue^%zewdAPI("verifyCode",sessid)
 s nvps("context")=""
 s ok=$$request^%zewdMDWSClient("login",.nvps,.results,sessid)
 i '$$isLoggedIn^%zewdMDWSClient(.results) QUIT $$getFaultMessage^%zewdMDWSClient(.results)
 s ok=$$getLoginData^%zewdMDWSClient(.results,.data)
 ;
 d setSessionValue^%zewdAPI("vista.DUZ",data("DUZ"),sessid)
 d setSessionValue^%zewdAPI("vista.name",data("name"),sessid)
 d setSessionValue^%zewdAPI("vista.SSN",data("SSN"),sessid)
 ;
 QUIT ""

I’ve highlighted two lines that you should recognise from the standalone example I described in the first part of this article: we’re making calls to the openMDWS operations named connect and login.  You’ll also see that I’m using some handy convenience functions that EWD provides for use with openMDWS:

isConnected() this allows us to determine whether or not the connect operation was successful

getFaultMessage(): this returns the message returned in an openMDWS XML Fault response

isLoggedIn(): this allows us to determine whether or not the login operation was successful

getLoginDate(): this extracts some of the key data from the login operations results array into a simpler data array

Finally, if everything is successful, the login() method saves some information into the EWD Session.  You’ll see that vista.name is used in the login fragment’s Javascript which updates the title at the top of the page, ie:

Ext.getCmp("northPanel").setTitle("Welcome <?= #vista.name ?>");

Save all the files we’ve created and edited, recompile the omDemo EWD application and we can now re-run the application and try logging in.  Use the Quick Login button and click the Submit button: you should now see the following:

 
 
 
 
 
 
 
 
 
 
 
 
 

If you see this, then EWD has successfully invoked the connect and login openMDWS services!

You’ll now see that a button labelled Get Clinics has appeared in the top left of the page.  You can’t click it yet as we haven’t defined how it will work.  We originally defined this button in index.ewd:

  <ext4:button text="Get Clinics" id="getClinicsBtn" hidden="true" nextPage="getClinics" addTo="westPanel" />

This is telling EWD that when the button is clicked, it should make a request for the EWD fragment named getClinics.ewd, and its contents should be added to the ExtJS panel whose id is westPanel.

Let’s build this part out to show how we can use another openMDWS operation, in this case getClinics.  This operation is already built-in to EWD’s openMDWS implementation, but its core function and its web service wrapper were examined in detail in the earlier posting titled The openMDWS Cookbook.

So we’ll first create the EWD fragment named getClinics.ewd:

<ext4:fragment onBeforeRender="getClinics^openMDWSDemo">
  <ext4:treepanel border="0" id="clinicTree" autoheight="true" width="205" sessionName="vista_clinics" nextPage="confirmClinic" addTo="centerPanel" replacePreviousPage="true" expandedTree="true" />
</ext4:fragment>

This fragment is going to get the list of clinics on the VistA server (by invoking the openMDWS getClinics operation),  It’s then going to present them as an ExtJS tree menu (defined using the <ext4:treepanel> Custom Tag).

We’ll define the getClinics() onBeforeRender method by adding the following to the openMDWSDemo.m routine file:

getClinics(sessid)
 n nvps,ok
 s nvps("target")=""
 s ok=$$request^%zewdMDWSClient("getClinics",.nvps,.results,sessid)
 i $$isFault^%zewdMDWSClient(.results) QUIT $$getFaultMessage^%zewdMDWSClient(.results)
 s ok=$$getClinicData^%zewdMDWSClient(.results,.clinic)
 d mergeArrayToSession^%zewdAPI(.clinic,"vista.clinics",sessid)
 QUIT ""
 ;

You’ll see in the code above (shown in bold)  that it makes an openMDWS request for the getClinics operation. I’m then using a convenience function (getClinicData) that maps the XML results array into another local array that maps directly onto the EWD Session Array structure needed to define an ExtJS tree menu. For clarity, here’s what this function actually does:

getClinicData(results,data)
 n count,i,id,name
 ;
 k data
 s count=$$getValue($g(results("TaggedHospitalLocationArray","count")))
 f i=1:1:count d
 . s id=$$getValue($g(results("TaggedHospitalLocationArray","locations","HospitalLocationTO",i,"id")))
 . s name=$$getValue($g(results("TaggedHospitalLocationArray","locations","HospitalLocationTO",i,"name")))
 . s data(i,"nvp")="clinicNo="_i
 . s data(i,"text")=name
 . s data(i,"clinicId")=id
 QUIT ""
 ;

Save these files, recompile the omDemo application and then try re-running it in the browser. Login and now click the Get Clinics button and you should see the following:

 
 
 
 
 
 
 
 
 
 
 
 
 

Just one last step. The ExtJS tree menu has been told to fetch another EWD fragment named confirmClinic.ewd whenever any clinic in the menu is clicked. The contents of confirmClinic.ewd will be added into the ExtJS layout’s center panel and will replace anything that is currently in that panel.  Here’s the <ext4:treepanel> tag from getClinics.ewd with this behaviour highlighted in bold:

  <ext4:treepanel border="0" id="clinicTree" autoheight="true" width="205" sessionName="vista_clinics" nextPage="confirmClinic" addTo="centerPanel" replacePreviousPage="true" expandedTree="true" />

The EWD fragment confirmClinic.ewd looks like this:

<ext4:fragment onBeforeRender="getSelectedClinic^openMDWSDemo">
  <ext4:panel border="0" id="clinic" html="Clinic selected: <?= #clinicName ?>" />
</ext4:fragment>

and its onBeforeRender method needs to be added to openMDWSDemo.m:

getSelectedClinic(sessid)
 ;
 n clinicName,clinicNo,clinics
 ;
 s clinicNo=$$getRequestValue^%zewdAPI("clinicNo",sessid)
 d mergeArrayFromSession^%zewdAPI(.clinics,"vista.clinics",sessid)
 s clinicName=$g(clinics(clinicNo,"text"))
 d setSessionValue^%zewdAPI("clinicName",clinicName,sessid)
 QUIT ""
 ;

Save the files and recompile the application and re-run it. This time, when the list of clinics appears, try clicking on some of them. Each time you do so, the one you selected should appear in the center panel, eg:

 
 
 
 
 
 
 
 
 
 
 
 
 

That’s it! We now have a fully-functioning EWD desktop application that is using openMDWS services and visualising the data they return using the sophisticated UI capabilities of ExtJS.

You’ll have hopefully noticed how little we had to define: ie how few tags were required to define the pages/fragments, and how little back-end code was required in the onBeforeRender methods.

One last thing you can try is to edit the initialise() method in openMDWSDemo.m and set the value of vista.host to be the same as mdws.host. Recompile the EWD application and try it again. It should run identically, but perhaps you’ll notice that it’s snappier: that will be because it’s now bypassing the HTTP/XML requests and invoking the web service functions directly.  Once again, just a very small change by you and EWD does all the rest of the optimisation for you automatically.

So hopefully this example confirms that EWD and openMDWS makes it incredibly quick and easy to modernise VistA!

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s