Skip to Main Content
  • Questions
  • SQL client for soap web-service (parse MTOM response)

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Aleksandr.

Asked: February 22, 2017 - 7:41 am UTC

Last updated: March 23, 2017 - 3:56 am UTC

Version: 11g

Viewed 1000+ times

You Asked

Good day, dear colleagues!

Sorry for bad English. I'm from Russia.

There is a client in oracle pl/sql that using UTL_HTTP makes a request to the Web service and parses the response. Everything works perfectly.
But in the particular case of the service may return a response with attachments using MTOM (xop+xml).
A test response of my service, saved in a clob variable, as follows:

--uuid:63178c45-ea9e-424d-b27e-7612f6523dee+id=2
Content-ID: <http://tempuri.org/0>
Content-Transfer-Encoding: 8bit
Content-Type: application/xop+xml;charset=utf-8;type="application/soap+xml"

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing"><s:Header><a:Action s:mustUnderstand="1">http://tempuri.org/IMtomService/GetBytesResponse</a:Action></s:Header><s:Body><ByteResponse xmlns="http://tempuri.org/"><Data><xop:Include href="cid:http://tempuri.org/1/636232853596073353" xmlns:xop="http://www.w3.org/2004/08/xop/include"/></Data></ByteResponse></s:Body></s:Envelope>
--uuid:63178c45-ea9e-424d-b27e-7612f6523dee+id=2
Content-ID: <http://tempuri.org/1/636232853596073353>
Content-Transfer-Encoding: binary
Content-Type: application/octet-stream

binary data


Where binary data - embedding binary data.

Can I parse response as this and get attachments separately from the request body in pl/sql? Maybe it is possible to call specific Java methods from pl/sql?

Thank you!

and Connor said...

We dont have anything native to parse the output, but you could easily just read the stream as raw and take what action your wanted, eg some psuedo-code below

declare
  l_req     utl_http.req utl_http.begin_request('[your source]);
  l_resp    utl_http.resp;
  l_blob    blob;
  l_raw     raw(4000);
  l_header  varchar2(4000);
begin
  l_resp := utl_http.get_response(l_req);
  
  --
  -- ie, read ascii until you get to a key phrase which means the binary is 
  -- to follow.  (This is not working code - just an indication of you might
  -- proceed)
  --
  loop
    utl_http.read_text(l_resp, l_header, 20);
    exit when l_header = 'binary data';
  end loop;
  
  --
  -- then start on the binary stream
  --
  dbms_lob.createtemporary(l_blob, true);
  begin
    loop
      utl_http.read_raw(l_resp, l_raw, 3999);
      dbms_lob.writeappend (l_blob, utl_raw.length(l_raw), l_raw);
    end loop;
  exception
    when utl_http.end_of_body then
      utl_http.end_response(l_resp);
  end;

  -- then do whatever you like with the blob

end;
/


Rating

  (5 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Aleksandr, February 27, 2017 - 6:44 am UTC

Thank you so much! This is really what I wanted to hear!

Looking for same idea to implement in code

Pradeep, March 09, 2017 - 8:41 pm UTC

Hi,

I am looking to solve similar problem where I am getting a PDF file as MTOM XOP attachment as response from a webservice. so PDF file essentially appears as binary(junk) characters, i tried to use your advice using utl_http.read_raw and inserted the resultant BLOB into a temp table.
but my requirement is I should be able to see this file as PDF as originally sent, but it appears as same binary junk characters.
Could you please help me how I can decode the blob after utl_http.read_raw so that it can be stored/viewed as PDF file.


Thanks,
Pradeep
Connor McDonald
March 09, 2017 - 11:35 pm UTC

Really depends on how the data is coming in. If the data is (for example) encoded in say base64, then it would need to be decoded before being stored in the blob etc.

If you're getting junk data in your blob, then a conversion error of some sort must be happening.

Stuck while processing MTOM(XOP + XML) response from a SOAP Webservice in PL/SQL

Pradeep, March 10, 2017 - 3:36 pm UTC

Thanks Connor.
Could you please have a look at my below anonymous block where I am stuck while trying to convert binary data (not BASE64Binary but actually binary characters) back to original format (PDF file).
--------------------------------------------------------
/* Formatted on 3/10/2017 10:31:37 AM (QP5 v5.149.1003.31008) */
DECLARE
soap_request VARCHAR2 (30000);
soap_respond CLOB; -- varchar2(30000);
http_req UTL_HTTP.req;
http_resp UTL_HTTP.resp;
l_resp XMLTYPE;
l_blob BLOB;
l_header VARCHAR2 (32000);
l_raw LONG RAW;
buffer CLOB;
l_CLOB CLOB;
final_blob BLOB;
BEGIN
soap_request :=
'<soap:Envelope xmlns:soap=" http://www.w3.org/2003/05/soap-envelope" xmlns:grad=" http://grades.web.chemspec.quality.allvac.com/" >
<soap:Header/>
<soap:Body>
<grad:getGradeInfoForRM>
<strRMItem>104PT</strRMItem>
</grad:getGradeInfoForRM>
</soap:Body>
</soap:Envelope>';

http_req :=
UTL_HTTP.
begin_request (' http://159.59.1.134:80/chemspec/CSGradeWSPort',
'POST',
'HTTP/1.1');
sys.UTL_HTTP.
SET_HEADER (http_req,
'Content-Type',
'application/soap+xml;charset=UTF-8');
UTL_HTTP.set_header (http_req, 'Content-Length', LENGTH (soap_request));
UTL_HTTP.set_header (http_req, 'Transfer-Encoding', 'chunked');
sys.UTL_HTTP.
set_header (http_req, 'User-Agent', 'Apache-HttpClient/4.1.1 (java 1.5)');
UTL_HTTP.set_header (http_req, 'SOAPAction', '');
UTL_HTTP.write_text (http_req, soap_request);
http_resp := UTL_HTTP.get_response (http_req);
DBMS_OUTPUT.put_line ('got the soap response');
DBMS_OUTPUT.
put_line ('Response> status_code: "' || http_resp.status_code || '"');
DBMS_OUTPUT.
put_line ('Response> reason_phrase: "' || http_resp.reason_phrase || '"');
DBMS_OUTPUT.put_line ('before read_text');

--
-- read ascii until you get to a key phrase which means the binary is
-- to follow.
--
BEGIN
LOOP
UTL_HTTP.read_text (http_resp, soap_respond);
EXIT WHEN REGEXP_INSTR (soap_respond, '[^[:print:]]') > 0; --l_header = 'binary data'; - -Not working
--l_header := SUBSTR(soap_respond, 1,INSTR(soap_respond,'%PDF') );
END LOOP;

--CONVERT ABOVE l_header usign XMLTYPE Later
DBMS_OUTPUT.put_line (' l_header: ' || l_header);
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error: ' || SQLERRM);
END;

--
-- then start on the binary stream
--
buffer := SUBSTR (soap_respond, INSTR (soap_respond, '%PDF'));
DBMS_OUTPUT.put_line ('Buffer: ' || buffer);
DBMS_LOB.createtemporary (l_blob, TRUE);

BEGIN
LOOP
UTL_HTTP.read_raw (http_resp, l_raw, 32767);

IF l_raw IS NOT NULL AND LENGTH (l_raw) > 0
THEN
DBMS_LOB.writeappend (l_blob, UTL_RAW.LENGTH (l_raw), l_raw);
END IF;
END LOOP;
EXCEPTION
WHEN UTL_HTTP.end_of_body
THEN
UTL_HTTP.end_response (http_resp);
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line ('Error at reading raw: ' || SQLERRM);
END;

-- then do whatever you like with the blob
l_CLOB := encode_base64 (l_blob); --encode the binary dat ato BASE64Binary stream , please note that encode_base64 is a seperate function define din DB
final_blob := decode_base64 (l_CLOB); --Decode above base64binary, decode_base64 is a independent function
insert into XXATI_PO_CHEMSPEC_PDF VALUES (1, final_blob, 'test file' ); --want to store this BLOB in its original from i.e. PDF file , but this BLOB appears weired
--
UTL_HTTP.end_response (http_resp);
EXCEPTION
WHEN UTL_HTTP.end_of_body THEN
DBMS_OUTPUT.put_line('end of body');
UTL_HTTP.end_response(http_resp);
WHEN UTL_HTTP.TOO_MANY_REQUESTS THEN
UTL_HTTP.END_RESPONSE(http_resp);
WHEN OTHERS THEN
DBMS_OUTPUT.put_line('others exception '||SQLERRM);

end;
----------------------------------------------------------
Here is sample response from webservice:

<S:Envelope xmlns:S=" http://www.w3.org/2003/05/soap-envelope" >
<S:Header>
<work:WorkContext xmlns:work=" http://oracle.com/weblogic/soap/workarea/" >rO0ABXdJABV3ZWJsb2dpYy5hcHAuQ0hFTVNQRUMAAADWAAAAI3dlYmxvZ2ljLndvcmthcmVhLlN0cmluZ1dvcmtDb250ZXh0AAMxLjYAAA==</work:WorkContext>
</S:Header>
<S:Body>
<ns2:getGradeInfoForRMResponse xmlns:ns2=" http://grades.web.chemspec.quality.allvac.com/" >
<return>
<avSpec>104P-AV</avSpec>
<rev>2</rev>
<pdfFile>
<xop:Include href="cid:f71f052c-09bc-4157-9655-e469cb759e75@example.jaxws.sun.com" xmlns:xop=" http://www.w3.org/2004/08/xop/include"/ >
</pdfFile>
<refDocs>
<docName>Test Doc 1</docName>
<docRev>1</docRev>
</refDocs>
<refDocs>
<docName>Test Doc 2</docName>
<docRev>1</docRev>
</refDocs>
<refDocs>
<docName>Test Doc 3</docName>
<docRev>2</docRev>
</refDocs>
<refDocs>
<docName>Test Doc 4</docName>
<docRev>3</docRev>
</refDocs>
</return>
</ns2:getGradeInfoForRMResponse>
</S:Body>
</S:Envelope>

---Then Binary data------
%PDF-1.4
%âãÏÓ
1 0 obj
<</BaseFont/Helvetica-Bold/Type/Font/Encoding/WinAnsiEncoding/Subtype/Type1>>
endobj
2 0 obj
<</Length 10/Filter/FlateDecode>>stream
±;û 8‚©^íJ
endstream
endobj
3 0 obj.........


Connor McDonald
March 23, 2017 - 3:56 am UTC

Obviously you need to take a lot of care, because if you are even out by a single byte, then whatever tool you use afterwards will probably complain.

I'd be inclined to use "read_raw" and read in chunks until you find the key leading element (eg "%PDF-1.4"). Now that could be (say) 100 bytes along in the chunk you are currently reading, so you would have something like:

tag := 0;
loop
  UTL_HTTP.read_raw (http_resp, l_raw, 32767); 
  if tag = 0 then
    tag := dbms_lob.instr(l_raw, utl_raw.cast_to_raw('%PDF-1.4'));
    if tag > 0 then
       l_raw := dbms_lob.substr(l_raw,32767,tag);  -- get all remaining bytes
    end if;
  end if;
  if tag > 0 then
    dbms_lob.writeappend(l_blob,l_raw);
  end if;
end loop;


The blob does not need any encoding etc, because you are receiving binary data and storing it as such.

Can we decode binary data (not base64binary) response of webservice in Oracle

Pradeep, March 15, 2017 - 3:09 am UTC

Hi Experts,

My Apologies if previous question was quite big and confusing.

I am stuck in processing SOAP webservice MTOM(XOP+Binary) attachment response and any help will be greatly appreciated.

Below is response of SOAP as I get in TOAD(oracle) or in SOAPUI: I need to decode below binary pdf file and convert to BLOB and use it to attach by FND_ATTACHMENT API's.

--------------------------------------------------------------
HTTP/1.1 200 OK
Date: Tue, 14 Mar 2017 17:37:26 GMT
Server: Oracle-Application-Server-11g
X-ORACLE-DMS-ECID: 005IfH82eLCFCCp0^Rn3Fq0006Mg0008ug
X-Powered-By: Servlet/2.5 JSP/2.1
Vary: Accept-Encoding
Content-Encoding: gzip
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: multipart/related;start="<rootpart*97561842-79f4-4303-b736-52f7fae539e4@example.jaxws.sun.com>";type="application/xop+xml";boundary="uuid:97561842-79f4-4303-b736-52f7fae539e4";start-info="application/soap+xml"
Content-Language: en

--uuid:97561842-79f4-4303-b736-52f7fae539e4
Content-Id: <rootpart*97561842-79f4-4303-b736-52f7fae539e4@example.jaxws.sun.com>
Content-Type: application/xop+xml;charset=utf-8;type="application/soap+xml"
Content-Transfer-Encoding: binary

<?xml version='1.0' encoding='UTF-8'?><S:Envelope xmlns:S=" http://www.w3.org/2003/05/soap-envelope" ><S:Header><work:WorkContext xmlns:work=" http://oracle.com/weblogic/soap/workarea/" >rO0ABXdJABV3ZWJsb2dpYy5hcHAuQ0hFTVNQRUMAAADWAAAAI3dlYmxvZ2ljLndvcmthcmVhLlN0cmluZ1dvcmtDb250ZXh0AAMxLjYAAA==</work:WorkContext></S:Header><S:Body><ns2:getGradeInfoForRMResponse xmlns:ns2=" http://grades.web.chemspec.quality.allvac.com/" ><return><avSpec>104P-AV</avSpec><rev>2</rev><pdfFile><xop:Include xmlns:xop=" http://www.w3.org/2004/08/xop/include" href="cid:1e9353c2-1103-4129-8b92-e8880b13a9ea@example.jaxws.sun.com"/></pdfFile><refDocs><docName>Test Doc 1</docName><docRev>1</docRev></refDocs><refDocs><docName>Test Doc 2</docName><docRev>1</docRev></refDocs><refDocs><docName>Test Doc 3</docName><docRev>2</docRev></refDocs><refDocs><docName>Test Doc 4</docName><docRev>3</docRev></refDocs></return></ns2:getGradeInfoForRMResponse></S:Body></S:Envelope>
--uuid:97561842-79f4-4303-b736-52f7fae539e4
Content-Id: <1e9353c2-1103-4129-8b92-e8880b13a9ea@example.jaxws.sun.com>
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary

%PDF-1.4
%âãÏÓ
1 0 obj
<</BaseFont/Helvetica-Bold/Type/Font/Encoding/WinAnsiEncoding/Subtype/Type1>>
endobj
2 0 obj
<</Length 10/Filter/FlateDecode>>stream
±;û 8‚©^íJ
endstream
endobj
3 0 obj
<</Length 150/Filter/FlateDecode>>stream
ù§‚HøþÿƒGùÕ\bòMq{ÚWO¯l¸7¸õ¢Yrßád&È­TÏÂhP¹^d@ëæf‘
õ|XÉ$~©ÙR¤<_§Â­ÛÖÍKŽLÁ`|…lS%oYº·…µ•¢6tCŒµ±T$
_iÃþ E„ü­íú}Œ²Å‘ªÒ^27‘”dËÔlªÂ"u…ÚWÃ
.....
.....
...Complete binary PDF file.
%%EOF
--------------------------------------------------------------

Is it possible to decode above binary data and convert to BLOB in oracle? or do I need to use Java?

Any response will be highly appreciated.


Thanks,
Ppradeep

Extract MTOM attachment from SOAP response

SP, January 24, 2021 - 6:18 pm UTC

Hello,

Can you please share pl/sql code to extract an mtom attachment returned in a SOAP response?
I am struggling to extract the attachment anhy help will be highlyu appreciated.

Regards
SP
(hi_sanjoo@rediffmail.com)

More to Explore

CLOB/BLOB/etc

Complete documentation on Securefiles and Large Objects here