Using IBM i? Need to create Excel, CSV, HTML, JSON, PDF, SPOOL reports? Learn more about the fastest and least expensive tool for the job: SQL iQuery.
I have a web service that I am working on that needs to accept arrays as input parameters. The problem is that the XML is ugly. Is there any way to allow a well-formed XML request to be made?
Right now the XML must look like this:
<Item>SKU1</Item>
<Item>SKU2</Item>
<Qty>1</Qty>
<Qty>2</Qty>
<Price>1.22</Price>
<Price>2.22</Price>
But I want it to look like this:
<OrderLine>
<OrderLine>
<Item>SKU1</Item>
<Qty>1</Qty>
<Price>1.22</Price>
</Product>
<Product>
<Item>SKU2</Item>
<Qty>2</Qty>
<Price>2.22</Price>
</OrderLine>
</OrderLines>
Is there something in Webshere I can do to allow this format to be accepted?
A second issue I have is the reponse includes all 999 elements of my arrays and not just the number of elements passed in.
Hi Fish, I don't know if you really mean WebSphere or if you mean RPG IV? To me, "WebSphere" was used as term like "Lotus" to identify a family of products but no specific product--while many assumed the product they were using was called "Lotus" or "WebSphere".
In RPG IV, you can control what gets extracted by using a POSIX-style path to the sub-elements of the XML.
/OrderLines/OrderLine/Qty
This would extract the Qty value only. To pull out all the entries from OrderLine, then you'd extract them into a data structure named OrderLine and specify:
/OrderLines/OrderLine
on the XML-INTO statement.
I am using Soap/XML and letting Apache handle all the parsing. I have created an application server to call my program and pass it the parameters.
The problem is that we want to have a 'List' in the XML request being sent by the consumer.
Then, why don't you just build it in code and pass out a single field that has the xml structure in it that you want?
A list is processed as an array in RPG. THe XML parser will return the count for you. Then you typically create a "Handler" routine that is just a subprocedure with a pre-defined parameter list (the parms include the array of data and the count of elements).
That is what I was thinking...it would basically be an array in RPG. But I don't get any of the parameters when we build the XML the way we want it. It has to be in the first format I posted before the arrays will load up.
I don't know what you mean by a "handler" routine though. Is this something IBM has documented? I have not been able to find any good documentation on how to deploy web services that allow for more complex structured XML (like lists or root elements).
If you're parsing XML with RPG, then yes, the %HANDLER function identifies the subprocedure that is auto-called (aka "callback" function) that is run when the XML parses a set (aka, array) of "records". It's document here in the RPG Reporter and in the RPG manuals.
No, I am not doing any XML parsing. My app never sees XML. Apache is handling all that and I just get parameters passed in.
Okay. Well, can't help you. When I get in a SOAP/XML request, I save it to the IFS and then parse it in RPG using XML-INTO.
That is what I really wanted to do, but I couldn't figure out how to tell Apache to do that either. Plus, everyone else on this project is tired of waiting on me to figure out how to make this work so we decided to do it this way...even though it seems to be very limited, or at least not very well documented.
THANKS!
Bob,
Can you point me to some documentation that explains how to deploy a web service so that the XML is placed into a unique file name on the IFS and then calls my RPG program?
This is actually what I was attempting to figure out a couple of weeks ago but was too dumb to figure it out with everyone here telling me to HURRY and figure it out. I still want to learn how to do it "right", but for now I think I am stuck having Apache do the parsing and passing my program indicidual parameters. I will continue to play around and look for documentation to figure out how to make XML Lists work with this approach.
I have played around with this a bit more this weekend and I have it a little closer to what I am needing. Making the array parameter a data structure effected the PCML which allowed the parameter to be identified as 'struct' instead of a character string.
D GetProducts Pr ExtPgm('WSTEST')
d CountRet 10i 0
d Products Likeds(Product) Dim(20)
d Options(*Varsize)
Now I have a test that is generates XML that looks like this:
<GETPRODUCTS>
<COUNTRET>2</COUNTRET>
<PRODUCTS>
<STYLE>A</STYLE>
<COLOR>CLR1</COLOR>
<SIZE>SIZE1</SIZE>
<BACKING>01</BACKING>
<WHSE>MID</WHSE>
<PRICE>1.11</PRICE>
<WEIGHT>101.10</WEIGHT>
</PRODUCTS>
<PRODUCTS>
<STYLE>B</STYLE>
<COLOR>CLR2</COLOR>
<SIZE>SIZE2</SIZE>
<BACKING>02</BACKING>
<WHSE>MID</WHSE>
<PRICE>2.22</PRICE>
<WEIGHT>202.20</WEIGHT>
</PRODUCTS>
</GETPRODUCTS>
But I am needing it to look like this with a repeating once for each array element within the :
<GETPRODUCTS>
<COUNTRET>2</COUNTRET>
<PRODUCTS>
<PRODUCT>
<STYLE>A</STYLE>
<COLOR>CLR1</COLOR>
<SIZE>SIZE1</SIZE>
<BACKING>01</BACKING>
<WHSE>MID</WHSE>
<PRICE>1.11</PRICE>
<WEIGHT>101.10</WEIGHT>
</PRODUCT>
<PRODUCT>
<STYLE>B</STYLE>
<COLOR>CLR2</COLOR>
<SIZE>SIZE2</SIZE>
<BACKING>02</BACKING>
<WHSE>MID</WHSE>
<PRICE>2.22</PRICE>
<WEIGHT>202.20</WEIGHT>
</PRODUCT>
</PRODUCTS>
</GETPRODUCTS>
I think I have this figured out. THANKS!
I would still like to know how to have the XML request placed on the IFS and have WebSphere call my program to process the XML as opposed to having WebSphere parse the XML request and pass all the parameters into my program.
Fish, if you were using COZCGILIB (COZTOOLS CGI library) I would say, start the program (specify it as the URL for the remote to transfer the XML/SOAP package to) then just do a cgiSaveFileToIFS. There is also a "save raw CGI buffer" if you want to also save the SOAP wrapper. But I'm suspecting you're doing most of the roll-your-own stuff, so that's not going to help much.
I can show you how in php if interested. This is not SOAP (but a PHP class can be a SOAP server with a WSDL - created via Zend Studio).
Put a php !--script-- in /www/zendsvr/htdocs/test.php and
point URL to http://my400:10088/test.php?Num=1&Name=Bob
<?php
// Save GET to POST data to IFS
define('BR','<br />') ;
$fileName = '/tmp/FilePutContents_' .
time() . '_' . strtr(uniqid('',true),'.','_') . '.txt';
echo 'File Name: ', $fileName, BR;
$method = $_SERVER['REQUEST_METHOD'] ;
echo 'REQUEST_METHOD: ', $method, BR;
if ( $method == 'POST' ) {
$rawData = file_get_contents('php://input');
else {
$rawData = $_SERVER['QUERY_STRING'] ;
}
file_put_contents($fileName, $rawData);
echo htmlentities($rawData, ENT_QUOTES), BR ;
// File Name: /tmp/FilePutContents_1370972810_51b7628a5d1f50_24466868.txt
// REQUEST_METHOD: GET
// Num=1&Name=Bob
Chris Ringer