From YiPs Wiki (i powered)

I5: REST 101 I 5 Call

(click to open)

Quick Page Table of Contents

Scanning…

REST 101

Introduction

In this case we replaced the PHP view and control elements of the previous 101 examples with a REST service and we keep the same RPG back-end SRVPGM model.

What is REST?

Roy Thomas Fielding coined the term Representational State Transfer (REST) in a 2000 doctoral dissertation http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm. Whew, smart people!

As a practical matter, what you really need to know is that REST style web services are designed in the same style as browser HTML pages, allowing REST client programs to “click/call” web page/service to page/service based on URL locations. In fact, your browser may have surfed into a REST service by accident and you will likely see a plain old XML document instead of a fancy web page. Like real estate, REST is all about location, location, location, and you can visit the REST location with your browser (and now you know what that goofy XML page you Googled by accident was all about).

Simply put, REST is an easy to understand technique that we can use to create natural HTTP-based web services that are very well behaved on the world wide web.

What is POX?

Nearly all successful REST web services use Plain Old XML (POX), to communicate data between the client and server. REST/POX is often described in casual conversation as “passing XML to/from the client” program. In fact REST/POX techniques are so natural, many “web” programmers have been doing REST/POX work without knowing these terms at all. Lately the term “Web 2.0″ is tossed about, but nearly always finds it’s programming home right back here at REST/POX. So, don’t be surprised if you catch yourself saying “Hey, I have been doing REST/POX for years”.

How does REST and SOAP compare?

We will assume you already have some knowledge of SOAP programming, but even if you don’t the following will give you a sound footing on the main differences with less “expert” exaggerated hype (although I am REST biased myself).

With SOAP programming it’s all about the verbs (methods):

With REST it’s all about the nouns (locations):

In REST, verbs are provided by HTTP protocol, GET, PUT, DELETE and POST, exactly the same verbs you typed into your HTML forms. In SOAP, method name verb(ology) is the playground of the OO kings and knaves alike and can be very creative such as ListOBigFolks getLargeFolksWithAtLeastOneBlueEye(height, weight)

In general, REST relies on “normal” good security via https for sensitive data and HTTP “reliability”. SOAP has many “plugins” offering a variety of middleware security and reliability services.

SOAP relies on a external description document named WSDL to describe all the service methods and objects passed to/from the client/server. WSDL also contains the location of the service (URI), so the client program is likely unaware of where it is getting it’s data (candy from a stranger). WSDL plays an active middleware role in coding/decoding client/server SOAP messages to/from program variables/classes. On the other hand, REST/POX the location is fixed by URL location and the XML “data” is essentially self describing (although the better sites offer a “keys to data” additional API XML documentation).

Practical REST services are dependent on HTTP locations, while SOAP services use HTTP as a “convenient” transport. Actually, SOAP-based services could “run” over FTP, telnet, etc., with a minor change to the WSDL description document (assuming the SOAP middleware handled the new transport).

In general most all languages can handle POX “XML parsing” in one way or another (PHP, Java, Ruby, Perl, RPG, etc.). SOAP requires additional middleware to dehydrate the data on the way to/from the server/client and then hydrate the data into language variables/classes to be used by the client/server. In some cases the SOAP contents will actually be a POX message, but that is really still SOAP transport, not REST.

Is REST or SOAP better?

After a point, any war of words between the REST and SOAP camps becomes increasingly academic, and well, boring. I find most soapbox dissertations on either side to be largely esoteric ramblings about SOAP objects uber alles vs. REST/POX simple XML for every web occasion. So, let me say that the service provider dictates the style of client programs, and the bigger the service provider the less we all argue.

How do I turn my *SRVPGM into a REST service?

Our MVC pattern followed in the previous DVD example, makes a switch to REST web services fairly straight forward. We really just need to replace the PHP view/control code with a web services POX front-end instead of a user HTML front-end.

However, we are going to need both a REST client and a REST server to demonstrated the whole client/server cycle.

How do I make a REST server using the i5 toolkit to my RPG SRVPGM?

The REST server in this example will feedback POX (XML) to the REST client program. Using our MVC methods creating the server looks nearly identical to all of the other browser based clients.

As you can see we have removed all MVC reference to HTML and replaced the view/control with rest server components. However, we are keeping the i5 model to our RPG SRVPGM to search for DVD data (cool right?).

<?php
define('APP_BASE_DIR', '');
include_once APP_BASE_DIR.'101Config.php';            /* Site:    site configuration         */
include_once APP_BASE_DIR.'101Connecti5.php';         /* Model:   i5 toolkit connect         */
include_once APP_BASE_DIR.'101RPGModel.php';          /* Model:   i5 toolkit call RPG SRVPGM */
include_once APP_BASE_DIR.'101RestServerView.php';    /* View:    plain old generated XML    */
include_once APP_BASE_DIR.'101RestServerControl.php'; /* Control: main "html" in / POX out   */
?>

We also changed include_once HTML control to REST server control. It looks much the same as the browser version, except we will output POX, instead of HTML.

<?php
// ------------------------
// Control: main
// ------------------------
post_mandatory 
( array 
  ( 'error', 'action', 'browsetype', 
    'browse_title', 'browse_actor', 
    'browse_category', 'limit_num'
  )
);
post_mandatory_array 
( array 
  ( 'selected_item', 'item' 
  ) 
);
if ($_POST ['browsetype']) 
{ if (! model_search 
        ( $_POST ['browsetype'], 
          $_POST ['browse_title'], 
          $_POST ['browse_actor'], 
          $_POST ['browse_category'], 
          $_POST ['limit_num'], 
          $search_item 
         ))
  { $_POST ['error'] = model_error ();
    echo POX_error($_POST ['error']);
  }
  else
  { echo POX_out($search_item);
  }
}
else
{ echo POX_error("no search data specified");
}
?>

Note: We are accepting HTML “GET” or “POST” request ($_POST vars) just like the HTML versions for this demonstration instead of a POX-based REST client request. Although simple, there are a number of REST production sites like this example.

How can SimpleXML help my REST Server?

The “view” we return to our REST clients will be POX (XML), so we have removed the MVC HTML view and added a rest server include_once.

SimpleXML provides ideal “simple” ways to construct well formed XML without all the mess of string concatenation.

<?php
function POX_out($search_item)
{ $simple = new SimpleXMLElement('<result></result>');
  foreach($search_item as $it)
  { $dvd = $simple->addChild("dvd");
    $dvd->addChild("PROD_ID",$it[0]); 
    $dvd->addChild("TITLE",$it[1]); 
    $dvd->addChild("ACTOR",$it[2]);
    $dvd->addChild("PRICE",$it[3]);  
  }
  return $simple->asXml();
}

We added a POX error return to client if something goes wrong.

function POX_error($error)
{ $simple = new SimpleXMLElement('<result></result>');
  $dvd = $simple->addChild("dvd");
  $dvd->addChild("ERROR",$error);
  return $simple->asXml();
}

Note: You may have noticed the “new” and “→” operator. So we have introduced a bit of “class” OO into our largely procedural model, but I think you will agree that XML with all the nested XML nodes really simplifies using SimpleXML objects. This is one PHP class structure well worth the time to learn.

How I do make a client to call a REST service?

Using our MVC pattern we can easily switch out a one of the other models (i5, ibm_db2, etc.), and replaced it with a rest client model that will “GET” data from the REST server above.

Just like previous examples the browser will see HTML forms for search and list, completely unaware that we have actually called across the web to get the data from a REST server (cool). In fact, we just change to the REST client model, and leave all the other HTML control/view code “as is” (are you a MVC believer yet?).

<?php
define('APP_BASE_DIR', '');
$RESTSERVER = "/qiwikiCode/101RPGRestServer.php";
include_once APP_BASE_DIR.'101Config.php';            /* Site:    site configuration         */
include_once APP_BASE_DIR.'101ConnectRest.php';       /* Model:   REST connect               */
include_once APP_BASE_DIR.'101RestClientModel.php';   /* Model:   REST client                */
include_once APP_BASE_DIR.'101HtmlView.php';          /* View:    plain old generated html   */
include_once APP_BASE_DIR.'101HtmlControl.php';       /* Control: main loop html forms       */
?>

The first thing we need to do is figure out our REST URL (location). For compare purposes we will stuff this code in the model_connect, even though it is more model_where (artistic license).

The connect code should produce a URL “base” to call our REST service on this same box. The varying “parameters” passed to the REST service will be added to the URL “base” in the REST client model code.

Example:
http://myi5:89/qiwikiCode/101RPGRestServer.php
-- append --
?browsetype=actor&browse_actor=Ch&limit_num=4 
<?php
// ---------------------
// Model: connect
// ---------------------
function model_connect() 
{ global $MODEL, $RESTSERVER;
  $service = "http://".$_SERVER["SERVER_NAME"];
  if (isset($_SERVER["SERVER_PORT"]))
  { $service .= ":".$_SERVER["SERVER_PORT"];
  }
  $service .= $RESTSERVER;
  $MODEL ['conn'] =  $service; 
  return True;
}
function model_error_rest($error = "") 
{ model_error($error);
}
?>

“Normally” the REST service is at a “well known” address (i.e. http://yahoo.com/REST/Service), but we will take the liberty to steal information from the PHP superglobals to calculate the URL and stuff it into $MODEL [‘conn’].

After the figuring out the initial web domain of the REST service in model_connect, we need to append the specific request “GET” parameters to the REST service.

Example:
http://myi5:89/qiwikiCode/101RPGRestServer.php
-- append --
?browsetype=actor&browse_actor=Ch&limit_num=4 
<?php
function model_search($browsetype, $browse_title, $browse_actor, $browse_category, $limit_num, &$items) 
{ global $MODEL, $categories;
  if (!model_connect ()) 
  { False;
  }
  $link_id = $MODEL ['conn'];  
  $items = array ( );
  switch($browsetype)
  { case 'title':
      $link_id .= "?browsetype=title&browse_title=$browse_title";
      break;
    case 'actor':
      $link_id .= "?browsetype=actor&browse_actor=$browse_actor";
      break;
    case 'category':
      $link_id .= "?browsetype=category&browse_category=$browse_category";
      break;
    default:
      break;
  }
  $link_id .= "&limit_num=$limit_num";

How can simplexml_load_file call a REST service?

We now have a fully formed URL with parameters to call our REST service.

http://myi5:89/qiwikiCode/101RPGRestServer.php?browsetype=actor&browse_actor=Ch&limit_num=4 

W can use PHP APIs to “GET” data from the REST service. In this case, simplexml_load_file(“URL”) really makes getting the POX (XML) for our REST server easy.

  // get the REST XML document
  $xml = simplexml_load_file($link_id);
  if (!$xml)
  { model_error("simplexml_load_file($link_id) failed");
    return False;
  }

Followed by a simple parse of the POX (XML) data using SimplXML, to return the array of search items found.

  // parse the xml
  foreach($xml as $row)
  { if (isset($row->ERROR))
    { model_error($row->ERROR);
      return False;
    }
    array_push
      ( $items,
        array
        ( $row->PROD_ID, 
          $row->TITLE, 
          $row->ACTOR, 
          $row->PRICE
        )
      );
  }
  return True;
}
?>

Done!

Retrieved from http://youngiprofessionals.com/wiki/index.php/I5/REST101I5Call
Page last modified on January 10, 2013, at 01:38 PM EST