Академический Документы
Профессиональный Документы
Культура Документы
on IBM i
Presented by
Scott Klement
http://www.scottklement.com
2012-2014, Scott Klement
Our Agenda
Agenda for this session:
1. Introduction
What's a web service?
Why web services?
Types
2. Setting up Apache
Configuring an HTTP server
Tell HTTP server to call an RPG pgm
3. Coding web services
REST with XML
REST with JSON
4. SOAP with IBMs IWS.
2
REST vs SOAP
REST: Web service where the URL identifies a resource to work with.
Input/output documents may be in any format. (Most commonly XML
or JSON)
Often, all input is within the URL
Technically, the HTTP method should be the verb (type of action to
take), but many web services do not use this approach, and still refer
to themselves as REST
Much simpler/runs faster than SOAP.
SOAP: XML-based web service where document format is standardized
Input/output documents are always XML in SOAP format
The verb (or action to perform) is given in a separate soap-action
keyword.
An accompanying WSDL document describes the SOAP details,
including networking details and schema
Much more complex than REST
Many more tools are available (vs REST) which can make SOAP
easier to code than REST.
8
Sign-in
Click Internet Configurations (if IBM i 6.1 or higher)
Click IBM Web Administration for i"
9
I recommend using a
number in the 8000
range, if possible.
In this example, I
picked port 8001
10
11
12
Server Root
13
Document Root
14
15
Access Log
16
17
Summary Screen
18
20
Just add the preceding code to an already working Apache instance on IBM i.
ScriptAlias tells apache that you want to run a program.
If URL starts with /cust, Apache will CALL PGM(RESTFUL/CUSTINFO)
Our REST web service can be run from any IP address (Allow from all).
http://ibmi.example.com/cust/495
Alternate Recipe
The last slide shows how to make /cust always do a call restful/custinfo.
But, perhaps youd rather not have to key a separate Apache configuration for
each restful web service you want to run? There are pros and cons to this:
Dont have to stop/start server to add
new service.
http://ibmi.example.com/rest/custinfo/495
22
23
24
RESTful Example
Easier way to think of REST
all input is in URL
output has no standard can be anything (but usually is XML or JSON)
Output
Input
For example, you might have a web service that takes a customer number as
input, and returns that customer's address.
GET http://i.scottklement.com:8001/cust/495
-orGET http://i.scottklement.com:8001/cust/495?op=retrieve
<result>
<cust id="495">
<name>ANCO FOODS</name>
<street>1100 N.W. 33RD STREET</street>
<city>POMPANO BEACH</city>
<state>FL</state>
<postal>33064-2121</postal>
</cust>
</result>
25
To accomplish this, I'm going to use 3 different APIs (all provided by IBM)
QtmhRdStin reads standard input
getenv retrieves an environment variable.
QtmhWrStout writes data to standard output.
26
IF
K DISK
D getenv
D
var
PR
D QtmhWrStout
D
DtaVar
D
DtaVarLen
D
ErrorCode
PR
D err
D
bytesProv
D
bytesAvail
ds
D xml
D
inp
pr
5000a
5000a
D
D
D
D
C
s
s
s
x'0d25'
10i 0
5000a
varying
5000a
CRLF
pos
uri
data
*
*
extproc('getenv')
value options(*string)
extproc('QtmhWrStout')
65535a
options(*varsize)
10I 0 const
8000A
options(*varsize)
qualified
10i 0 inz(0)
10i 0 inz(0)
varying
varying const
27
REQUEST_URI will
contain
http://x.com/cust/495
Custno is everything
after /cust/ in the URL
28
30
HTTPAPI REQTYPE(*GET)
URL('http://as400.klements.com/cust/520')
DEBUG('/tmp/restdebug.txt')
DOWNLOAD('/tmp/resttest.xml')
If successful, the output from the web service will now be in the DOWNLOAD
file, shown above as /tmp/resttest.xml . Use the IBM i DSPF command
to view it on green-screen:
DSPF STMF('/tmp/resttest.xml')
HTTPAPI supports both GET and POST methods, and PUT & DELETE are
planned for the future. Plus, the DEBUG file can provide extra debugging
information when something is wrong.
DSPF STMF('/tmp/restdebug.xml')
31
This web service is designed to return a list of invoices for a given customer
number, within a given date range.
495 = customer number
20100901 = start date (in year, month, date format)
20100930 = end date (in year, month, date format)
The web service will scan for the slashes, get the parameter info from the
URL, and build a JSON document that matches the criteria.
33
Introducing JSON
JSON = JavaScript Object Notation
JSON is used for the types of applications as XML would be. However, JSON
has one big advantage over XML: Its natively understood by Javascript. This
means that web applications using JSON are easier to write, and run faster
than those using XML.
JSON is used to describe data structures in Javascript. Including complex
situations with data structures and arrays nested inside each other.
ds
qualified
dim(2)
4p 0
25a
[
{
"custno": 1000,
"name": "ACME, Inc",
},
{
"custno": 2000,
"name": "Industrial Supply Limited",
}
]
<list>
<cust>
<custno>1000</custno>
<name>Acme, Inc</name>
</cust>
<cust>
<custno>2000</custno>
<name>Industrial Supply Limited</name>
</cust>
</list>
35
Preferred by Javascript
These days, almost all web applications are written in Javascript frameworks,
and in Javascript, JSON is much faster and easier to work with than XML.
Assuming a variable named data contains the Javascript from the last slide,
this is all thats needed to parse/read the contents of the JSON document:
var list = eval( "(" + data + ")" );
for (x=0; x<list.length; x++) {
y = list[x].custno;
z = list[x].name;
}
36
"success": false,
"errmsg": "Put Error Message Here"
}
{ "success": true,
"errmsg": "",
"list": [{
"invno": "xyz",
"date": "2012-01-23",
"name": "Acme Industries, Inc.",
"amount": 123.45,
"weight": 123.45,
},
{ same fields again },
{ same fields again },
{ etc }
]}
37
D
D
D
D
CRLF
data
uri
cust
sdate
edate
custpos
sdatepos
edatepos
jsonName
jsonDate
C
s
s
s
s
s
s
s
s
s
s
5000a
5000a
4s
8s
8s
10i
10i
10i
25a
10a
x'0d25'
varying
varying
0
0
0
0
0
0
D row
D
inv
D
date
D
name
D
amount
D
weight
ds
qualified
5a
8s 0
25a
9p 2
9p 1
38
39
Each time I call QtmhWrStout(), it adds more data on to the end of what Ive
already sent.
This part is just the start of the JSON document.
Subsequent calls will write rows of data, and they will be added on to the
end.
Finally, well call QtmhWrStout one last time to end the JSON document.
41
42
43
44
If you wrote a reusable program, and wanted everyone to use it, how would
you explain it?
Which server is it on?
Which network protocol should you call it with?
What parameters does it accept? (Sequence, data types, etc)
Would you use?
Documentation in MS Word? Or PDF? Or a wiki somewhere?
Maybe you'd teach other programmers in person? (like me!)
Comments in the code?
Expect the caller to read the code??!
46
WSDL Files
Web Services Description Language (WSDL)
pronounced "WHIZ-dull"
Standardized way of documenting a web service.
A type (schema? flavor?) of XML
Can be generated by a tool from your parameter list!
Can be read by a computer program to make your service easy to call
Almost always used with SOAP. Occasionally also used with POX or REST.
What it does
What routines it offers (like procedures in a service program)
Where the service is located (domain name or IP address)
Protocol to use
Structure of input/output messages (parameters)
Schema (make sure youve got it all right!)
47
WSDL Skeleton
<definitions>
<types>
definition of types........
</types>
<message>
definition of a message....
</message>
<portType>
definition of a port.......
</portType>
<binding>
definition of a binding....
</binding>
<service>
a logical grouping of ports...
</service>
</definitions>
SOAP
SOAP = Simple Object Access Protocol
SOAP is an XML language that describes the parameters that you pass to the
programs that you call. When calling a Web service, there are two SOAP
documents -- an input document that you send to the program you're calling, and
an output document that gets sent back to you.
"Simple" is a relative term!
Not as simple as RPG parameter lists.
Not as simple as REST
Simpler than CORBA.
49
SOAP Skeleton
Here's the skeleton of a SOAP message:
<soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope"
soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding" >
<soap:Header>
(optional) contains header info, like payment info or authentication info
(crypto key, userid/password, etc)
</soap:Header>
<soap:Body>
. . .
Contains the parameter info. (Varies by application.)
. . .
<soap:Fault>
(optional) error info.
</soap:Fault>
. . .
</soap:Body>
</soap:Envelope>
50
Input Message
<soapenv:Envelope>
<soapenv:Body>
<xsd:getcust>
<xsd:args0>
<xsd:CUSTNO>495</xsd:CUSTNO>
</xsd:args0>
</xsd:getcust>
</soapenv:Body>
</soapenv:Envelope>
Output Message
I've removed the namespace information to keep this example clear and simple. (In a
real program, namespaces would be included.)
<soapenv:Envelope>
<soapenv:Body>
<ns:getcustResponse>
<ns:return>
<ns:CITY>POMPANO BEACH</ns:CITY>
<ns:NAME>ACME INC</ns:NAME>
<ns:POSTAL>33064-2121</ns:POSTAL>
<ns:STATE>FL</ns:STATE>
<ns:STREET>123 MAIN STREET</ns:STREET>
</ns:return>
</ns:getcustResponse>
</soapenv:Body>
</soapenv:Envelope>
51
52
H PGMINFO(*PCML:*MODULE)
53
SOAP GETCUST (1 of 2)
H DFTACTGRP(*NO) ACTGRP('SOAP') PGMINFO(*PCML: *MODULE)
FCUSTFILE
D CUST
D
D GETCUST
D
CustNo
D
Name
D
Street
D
City
D
State
D
Postal
D GETCUST
D
CustNo
D
Name
D
Street
D
City
D
State
D
Postal
IF
K DISK
PREFIX('CUST.')
E DS
qualified
extname(CUSTFILE)
PR
ExtPgm('GETCUST')
like(Cust.Custno)
like(Cust.Name)
like(Cust.Street)
like(Cust.City)
like(Cust.State)
like(Cust.Postal)
PI
like(Cust.Custno)
like(Cust.Name)
like(Cust.Street)
like(Cust.City)
like(Cust.State)
like(Cust.Postal)
54
SOAP GETCUST (2 of 2)
/free
chain CustNo CUSTFILE;
This API is equivalent
if not %found;
to the CL
msgdta = 'Customer not found.';
SNDPGMMSG
command, and
QMHSNDPM( 'CPF9897': 'QCPFMSG
*LIBL'
: msgdta: %len(msgdta): '*ESCAPE' causes my program
to end with an
: '*PGMBDY': 1: MsgKey: err );
exception ("halt")
else;
Custno = Cust.Custno;
Name
= Cust.name;
Street = Cust.Street;
City
= Cust.City;
When there are no
State = Cust.State;
errors, I simply return
my output via the
Postal = Cust.Postal;
parameter list. IWS
endif;
takes care of the XML
*inlr = *on;
for me!
/end-free
55
56
57
58
Click next
60
61
62
63
Here you configure the exact library list that you want
your RPG program to run under.
Use the Add/Remove/Up/Down buttons to add/remove
libraries, and change their order.
65
67
When you see this box (with the "green light" balls) it
means your service is active!
68
69
Step 2:
Paste in URL to WSDL
(from the "View Service
Definition" link) into the
Initial WSDL blank.
70
Step 4:
Enter the customer number
into the SOAP message for
the input parms.
71
72
73
74
ds
D SOAPINV
D
CustNo
D
strDate
D
endDate
D
rtnCount
D
rtnList
D SOAPINV
D
CustNo
D
strDate
D
endDate
D
rtnCount
D
rtnList
PR
qualified inz
5a
8s 0
25a
9p 2
9p 1
4p
8p
8p
10i
ExtPgm('SOAPINV')
0 const
0 const
0 const
0
likeds(row) dim(999)
PI
4p
8p
8p
10i
rtnList is the
returned array.
Notice: LIKEDS!
0 const
0 const
0 const
0
likeds(row) dim(999)
75
76
77
By default, the count for RTNLIST is 999, just like the DIM(999) in my RPG code.
But I can change it to "RTNCOUNT" because RTNCOUNT happens to be a 10i 0 field, IWS knows it
can be used to specify the array size.
Unfotunately, there's no way to stop IWS from sending RTNCOUNT to the consumer, as well. (But
if the consumer doesn't need it, it can ignore it.)
78
Exercises
Download and try the REST services from this talk (using a browser.)
Modify the REST service to take multiple parameters, and return an array (like
the POX example)
Try writing your own REST web service.
Try the POX example. Is it easier or harder than the REST one?
Install/configure a SOAP web service using IWS.
Note how the IWS simplifies writing the service but also note the
performance difference, and limitations of parameter types.
Try calling your IWS web service with SoapUI.
Bigger Challenge: Using the same XML from SoapUI, and the WSDL from
IWS, try creating a SOAP service manually -- like the POX one, where the
data is uploaded/downloaded through Apache. Note the performance
difference.
79
80
http://www.w3schools.com/xml/default.asp
http://www.w3schools.com/webservices/default.asp
http://www.w3schools.com/wsdl/default.asp
http://www.w3schools.com/soap/default.asp
IBM's web site for the Integrated Web Services (IWS) tool:
http://www.ibm.com/systems/i/software/iws/
http://www.ibm.com/systems/i/software/iws/quickstart_server.html
XMethods.net
BindingPoint.com
RemoteMethods.com
83
This Presentation
You can download a PDF copy of this presentation from:
http://www.scottklement.com/presentations/
The Sample Web Service Providers in this article are also
available at the preceding link.
Thank you!
84