Consuming openMDWS Services using EWD (Part 1)

Previous postings have provided an overview of openMDWS, in addition to creating and testing openMDWS services.  In this and the next posting I’m going to focus on the environment where they really come into their own: EWD.

EWD is a web application development framework that is optimised for Mumps and Caché systems, making it ideally suited for modernising VistA and making it available via desktop browsers and mobile devices.  Its high levels of automation and abstraction mean ultra-fast agile development (eg see Tony Shannon’s 10-day ClinUIP project) and its design-centred development paradigm means a clear separation of design and programming, with programming reduced to a minimum.  Coupled with openMDWS, the programming  task diminishes even further.  Furthermore, EWD’s built-in integration with and high-level abstraction of the very latest Javascript frameworks such as ExtJS and Sencha Touch means you can use all the very latest, leading-edge UI techniques  for both desktop and mobile users of VistA.

Since the back-end development of openMDWS services relies heavily on EWD, it’s hardly surprising that the front-end consumption of openMDWS services is also highly integrated and automated.

In this pair or articles about Consuming openMDWS services, I’m going to base my examples around the pre-built, pre-configured, ready-to-run VistA system known as the dEWDrop VM.  However, everything I’ll be explaining and demonstrating applies to any VistA implementation, running on either Caché or GT.M.  You just need to install and configure the latest build of EWD and you have everything you need.

The dEWDrop VM is a convenient platform for trying things out, and it’s a fixed, known configuration, making examples easy to describe in a way that will be guaranteed to run when you try them out.  If you’re running your own custom VistA/EWD implementation, you may need to amend aspects of the examples appropriately, mainly to cater for differences in how you’ve configured EWD.

Let’s start by writing a quick and simple test Mumps routine that we can run independently of EWD in the GT.M shell (Caché users can run the equivalent routine in a Cache Terminal session).  This example will invoke the pre-built openMDWS connect operation on the dEWDrop server, and allows us to easily see and examine how EWD’s interfacing to openMDWS works.

Create a text file named openMDWSTest.m in the /home/vista/p/ directory as follows:

openMDWSTest ; simple openMDWS Client Test
 ;
test1 ;
 s sessid=0 ; dummy EWD Session Id
 d setSessionValue^%zewdAPI("mdws.host","192.168.0.14",sessid)
 d setSessionValue^%zewdAPI("mdws.facade","EmrSvc",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)
 ;
 s nvps("sitelist")="dewdrop"
 s ok=$$request^%zewdMDWSClient("connect",.nvps,.results,sessid)
 QUIT
 ;

Now go into the GT.M shell and run this routine as follows:

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

MU-beta>d test1^openMDWSTest

It should come back very quickly with the MU-beta> prompt. Now take a look at the local symbol table to see what’s been returned. It should look similar to the following:

MU-beta>zwr
ok=""
results("DataSourceArray")=""
results("DataSourceArray","items")=""
results("DataSourceArray","items","DataSourceTO")=""
results("DataSourceArray","items","DataSourceTO","context")=""
results("DataSourceArray","items","DataSourceTO","description")=""
results("DataSourceArray","items","DataSourceTO","ewdToken")="wNagRAz3ouC1hx0gjYlucO5qA7SMFZ"
results("DataSourceArray","items","DataSourceTO","modality")="HIS"
results("DataSourceArray","items","DataSourceTO","port")=9100
results("DataSourceArray","items","DataSourceTO","protocol")="VISTA"
results("DataSourceArray","items","DataSourceTO","provider")="127.0.0.1"
results("DataSourceArray","items","DataSourceTO","siteId")=""
results("DataSourceArray","items","DataSourceTO","siteId","tag")="dewdrop"
results("DataSourceArray","items","DataSourceTO","siteId","text")="dEWDrop"
results("DataSourceArray","items","DataSourceTO","status")="active"
results("DataSourceArray","items","DataSourceTO","testSource")="false"
results("DataSourceArray","items","DataSourceTO","timeout")=0
results("DataSourceArray","items","DataSourceTO","vendor")=""
results("DataSourceArray","items","DataSourceTO","version")=""
results("DataSourceArray","items","DataSourceTO","welcomeMessage","#text",0)=111
results("DataSourceArray","items","DataSourceTO","welcomeMessage","#text",1)="WorldVistA EHR /VOE 1.0 "
results("DataSourceArray","items","DataSourceTO","welcomeMessage","#text",2)=" "
...etc
results("DataSourceArray","xmlns")="http://mdws.medora.va.gov/EmrSvc"_$C(1)_"attr"
results("DataSourceArray","xmlns:xsd")="http://www.w3.org/2001/XMLSchema"_$C(1)_"attr"
results("DataSourceArray","xmlns:xsi")="http://www.w3.org/2001/XMLSchema-instance"_$C(1)_"attr"
sessid=0

MU-beta>

Note: for clarity I’ve removed the multiple array nodes containing the welcomeMessage text.

What we’ve done in this example is we’ve  invoked EWD’s openMDWS client function, asking it to run the connect operation.  What got returned was a local array named results which has been automatically mapped from the XML response that was delivered by the openMDWS connect operation.

This demonstrates the bi-directional XML to/from Mumps local array mapping that EWD automatically provides.  We first saw this in the previous article that described the creation of openMDWS operations, where the XML to be returned by the operation was described in terms of a local array whose subscripts corresponded to the XML tag hierarchy.

We now see the exact opposite happening: EWD’s openMDWS client automatically maps the XML response document that it received back into a corresponding Mumps local array again: it should be identical to the array that the openMDWS operation developer originally defined.

EWD therefore removes the need for any XML document handling: the parsing is all carried out automatically for you and all that’s needed is simple Mumps coding to traverse and manipulate a local array: all simple, standard stuff for any Mumps developer.

[By the way, you can also run EWD’s openMDWS client against pukka VA MDWS operations (using their HTTP GET interface), and you’ll get back the response in a Mumps local array, mapped from the MDWS XML response.]

Lets look in a bit more detail at the test routine, in particular those initial lines where we set up a number of EWD Session variables:

 s sessid=0 ; dummy EWD Session Id
 d setSessionValue^%zewdAPI("mdws.host","192.168.0.14",sessid)
 d setSessionValue^%zewdAPI("mdws.facade","EmrSvc",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)

Normally we’d be working within an EWD application, and what we’re doing is simulating an EWD Session (using a notional SessionID of 0).  [Note: EWD will automatically clear down this session in due course, so don’t worry too much about it]

EWD requires a number of specifically-named Session variables to be instantiated before its openMDWS client interface can be invoked:

mdws.host: This is the domain name/IP address of the system whose MDWS/openMDWS operations we wish to invoke. Change this appropriately to the domain name or IP address assigned to your dEWDrop (or VistA) server.

mdws.version: If you wish to invoke openMDWS operations, the value is “openMDWS“. If you wish to use VA MDWS services, please contact me for now (the interface is already working but not currently officially released)

mdws.path: If mdws.version is “openMDWS“, then EWD needs to know how to construct the URL that it uses to invoke the openMDWS services. This will depend on how EWD is configured on the openMDWS server. On a dEWDrop server, the path is /vista/, but it on other servers it is often /ewd/.

mdws.sslProxyPort: dEWDrop servers are pre-configured to prevent HTTP access in the clear. Only HTTPS/SSL access is allowed. GT.M cannot interface directly via SSL, so it has to make use of an SSL proxy (eg stunnel, Delegate). dEWDrop servers are pre-configured with an SSL proxy (actually implemented via Apache). The mdws.sslProxyPort Session variable specifies the TCP port via which GT.M communicates with the SSL Proxy. In the case of dEWDrop, you should specify port 89.  If your VistA server is configured to allow HTTP access in the clear, you can dispense with this variable (however, you really should consider tightening up security, particularly if it’s a production server!)

mdws.facade: this specifies the facade to which the openMDWS/MDWS operation you wish to invoke belongs

vista.host: use this to specify the domain name/IP address of the server on which you’re running the EWD openMDWS Client. This Session variable is used by EWD to determine whether or not the openMDWS operations you’re invoking are on a remote server or not: EWD simply compares the value of vista.host with mdws.host. If they are the same, EWD will automatically invoke the openMDWS web service wrapper function directly, effectively bypassing the HTTP and XML processing overheads. In our example, even though we’re running the example entirely on the same dEWDrop server, we’ve deliberately forced EWD to make an HTTP call to the openMDWS service as if it was a remote server. If you set the value of vista.host to be the same as mdws.host (eg 192.168.0.14 in our example), then you’ll actually see no difference in how the example runs (except that it will be quicker) – the returned results array will be identical, even though the HTTP/XML mechanism has been bypassed. Try firing up two instances of dEWDrop servers and run the example on one of them, but access the openMDWS connect operation from the other.

With that information in place, we can now invoke EWD’s openMDWS web service client function:

openMDWSTest ; simple openMDWS Client Test

 s nvps("sitelist")="dewdrop"
 s ok=$$request^%zewdMDWSClient("connect",.nvps,.results,sessid)

The only argument you vary is the operation value, in this case “connect“. The nvps local array allows us to define the inputs for the operation: in our example there is only one – sitelist – on an openMDWS system this is a somewhat notional parameter and currently really just there for compatibility with the MDWS connect operation.

Otherwise, always specify the arguments for EWD’s openMDWS client function as per the example above. The sessid argument specifies the EWD Session ID, and the reference to the results array allows us to get back the XML-mapped array from the web service response.

So, now we’ve been able to see how EWD’s openMDWS client works, we’re ready to try it out in an actual EWD application.  Part 2 of this article will delve into this in detail.

 

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

%d bloggers like this: