6. Get, put, delete, rename, mkdir, rmdir
Ascii, binary
Our use:
● We buy data regarding cars on the danish market
● Data supplier generates files on FTP server monthly
● Scheduled job uses FTP_UTIL_PKG to get files and
imports via external table
FTP_UTIL_PKG
7. FTP GET file to directory
create directory ftp_downloads as
'/mnt/vol1/ftp_downloads';
grant read, write on directory
ftp_downloads to scott;
create or replace package body car_data
is
procedure get_carinfo_file
is
l_conn utl_tcp.connection;
begin
l_conn := ftp_util_pkg.login(
p_host => 'ftp.oursupplier.dk'
, p_port => '21'
, p_user => 'mycompany'
, p_pass => 'myPas$w0rd'
);
util_ftp.ascii(p_conn => l_conn);
util_ftp.get(
p_conn => l_conn
, p_from_file => '/carinfo.txt'
, p_to_dir => 'FTP_DOWNLOADS'
, p_to_file => 'carinfo.txt'
);
util_ftp.logout(l_conn);
end get_carinfo_file;
... continues ...
Server directory and
grants to work with files
(as SYS or other dba)
FTP protocol calls:
login, get, logout
8. External table and materialized view
create table carinfo_ext (
crm_artcode number
, approval_id number
, variant number
, year number
, population number
) organization external (
type oracle_loader
default directory ftp_downloads
access parameters (
records delimited by newline
territory 'DENMARK'
skip 1
fields terminated by 't'
lrtrim missing field values are null (
crm_artcode
, approval_id
, variant
, year
, population
)
)
location ('carinfo.txt')
);
create materialized view carinfo_mview
build deferred
refresh complete on demand
as
select *
from carinfo_ext;
create index carinfo_mview_key on
carinfo_mview ( crm_artcode );
External table defined on
the file we got by FTP
Materialized view defined
on the external table
9. FTP GET and refresh mview
...continued...
procedure fresh_carinfo
is
begin
get_carinfo_file;
dbms_refresh.refresh('CARINFO_MVIEW');
end fresh_carinfo;
end car_data;
/
declare
jobno binary_integer;
begin
dbms_job.submit(
job => jobno
, what => 'car_data.fresh_carinfo'
, next_date =>
add_months(trunc(sysdate,'MM'),1) + interval
'3' day + interval '22' hour
, interval =>
q'[add_months(trunc(sysdate,'MM'),1) +
interval '3' day + interval '22' hour]'
);
commit;
dbms_output.put_line(jobno);
end;
/
When we need fresh data,
we first call procedure that
FTP downloads the file,
then refresh the mat.view
from the file Fresh data every 3rd day of month
Use Scheduler rather than jobs if
more complex rules are needed
10. Not quite as easy to do SFTP protocol
AskTom discussion:
● https://asktom.oracle.com/pls/apex/f?
p=100:11:0::::P11_QUESTION_ID:25564058003464
33753
Load SFTP java libraries – examples:
● http://michailgalvidis.blogspot.com/2010/03/sftp-
from-oracle.html
● http://dbashavefeelingstoo.wordpress.com/2011/07/2
2/sftp-with-plsql/
SFTP
11. Network Access Control List
FTP_UTIL_PKG
UTL_HTTP
HttpUriType
UTL_DBWS
JPublisher
APEX_WEB_SERVICE
Topics
12. Fairly low-level
Can do SOAP, REST, practically whatever
- manual code whatever protocol on top of http
GET, POST, …
Cookies, redirects, SSL (https), authentication
Set parameters for connections, charsets, …
In many ways a ”browser emulator”
Our use: http POST to SMS service provider
UTL_HTTP
13. Eric van Roon
http://www.evrocs.nl/evenementen/kscope14-seattle/
HTTP GET of KScope14 HTML session list
UTL_HTTP read HTML a line at a time
Pipelined function
String functions search for content
Pipe sessions allow SELECT from webpage
UTL_HTTP scraping HTML webpage
14. function pagesource(p_url in st_maxchar, p_proxy in st_maxchar default null)
return ta_ero_sourcelines pipelined
is
t_http_req utl_http.req;
t_http_resp utl_http.resp;
t_line st_maxchar;
t_lineno integer := 0;
r_return to_ero_sourcelines := to_ero_sourcelines();
begin
if p_proxy is not null then
utl_http.set_proxy(p_proxy);
end if;
t_http_req := utl_http.begin_request (p_url);
utl_http.set_header (t_http_req,'User-Agent','Mozilla/4.0');
t_http_resp := utl_http.get_response (t_http_req);
loop
utl_http.read_line (t_http_resp, t_line, true);
t_lineno := t_lineno + 1;
r_return.lineno := t_lineno;
r_return.text := t_line;
pipe row (r_return);
end loop;
exception
when utl_http.end_of_body then
utl_http.end_response(t_http_resp);
when no_data_needed then
utl_http.end_response(t_http_resp);
end pagesource;
HTTP request, header
and get response
Read response line by line
Close when everything
read or "client cursor"
stops reading the pipe
15. procedure retrieve_field_values(p_itemtext in st_maxchar, p_fieldvalues out to_ero_kscope_sessions)
is
cn_start_indicator_title constant st_maxchar := gc_start_of_new_item||gc_eol;
cn_end_indicator_title constant st_maxchar := '<a name="';
cn_start_indicator_presenterid constant st_maxchar := 'presenterlist?last_id=';
cn_end_indicator_presenterid constant st_maxchar := '">';
cn_start_indicator_presenter constant st_maxchar := '">';
cn_end_indicator_presenter constant st_maxchar := '</a>';
cn_start_indicator_company constant st_maxchar := '<span style="font-style: italic;">'||gc_eol;
cn_end_indicator_company constant st_maxchar := '</span>';
cn_start_indicator_copresenter constant st_maxchar := 'Co-presenter(s):</span>';
cn_end_indicator_copresenter constant st_maxchar := '</div>';
cn_start_indicator_date constant st_maxchar := 'When: </span>'||gc_eol;
cn_end_indicator_date constant st_maxchar := ',';
...
begin
get_stripped_value (p_itemtext => t_itemtext
,p_start_indicator => cn_start_indicator_title
,p_end_indicator => cn_end_indicator_title
,p_value => r_sessions.title );
get_stripped_value (p_itemtext => t_itemtext
,p_start_indicator => cn_start_indicator_presenterid
,p_end_indicator => cn_end_indicator_presenterid
,p_value => t_presenterid );
...
p_fieldvalues := r_sessions;
end retrieve_field_values;
Look for certain html elements
Parse one by one
16. select *
from table(ero$kscope_sessions.kscope_sessions('http://kscope14.com/seminarlist'))
where lower(presenter) like '%hansen%'
order by starttime;
TOPIC SUBTOPIC STARTTIME ENDTIME SESSION_ID PRESENTER COMPANY COPRES
------------------- ----------- ---------------- ---------------- ---------- ---------- ----------------- ------
TITLE
----------------------------------------------------------------------------------------------------------------
DESCRIPTION
----------------------------------------------------------------------------------------------------------------
Developer's Toolkit Languages 2014-06-24 11:15 2014-06-24 12:15 Session 7 Kim Hansen T. Hansen Gruppen
Analytic Functions: Advanced Cases
Analytic functions can often help you, using data across rows in ways to allow you to solve tasks that otherwise
might have called for slowly using the data one row at a time procedurally. This presentation will show several
such cases of using analytic functions to avoid slow procedural data handling. All cases are from actual produc
tion system and will hopefully serve as inspiration.
Developer's Toolkit No Subtopic 2014-06-25 14:00 2014-06-25 15:00 Session 14 Kim Hansen T. Hansen Gruppen
External Data via HTTP, FTP, and Web Services
There are many ways you can access external data from within the Oracle database. This presentation will show di
fferent methods using HTTP or FTP protocol getting raw data, files, or XML via proprietary calls or web-service
calls (either REST or SOAP). Topics include HttpUriType, UTL_HTTP, UTL_DBWS, APEX_WEB_SERVICE API, and more.
Just two presentations by a presenter named Hansen
17. select presenter, title
from table(ero$kscope_sessions.kscope_sessions('http://kscope14.com/seminarlist'))
where session_id = 'Session 14'
order by presenter, title;
PRESENTER TITLE
--------------- ------------------------------------------------------------------------------------------------
Ashley Chen Hands-On Training: Developing RESTful APIs with Oracle REST Data Services for On-Premises or the
Charles Beyer Bulletproofing Excel and Smart View
Donald Clarke How to Integrate EBS 11i with APEX 4.2
Eric Erikson Why Aren't You Using Calc Manager with HFM Yet?
Heli Helskyaho Nine Use Cases for Oracle SQL Developer Data Modeler
Jackie Womble Production-Level Control of APEX Troubleshooting and Performance Tracing
Jake Turrell Planning Experts Panel
Jason Jones How to Integrate Essbase with Oracle and Third-Party Applications
Jeremy Harms Sorry, McGinley: Even Advanced OBIEE Modeling and Front-End Features Show Big Ten Football < SEC
John Flack Magic Managed Beans: A Primer for Jack and Jill ADF Developer
John Kozar Common APEX Responsive Design Issues and How to Correct Them
Jonathan Lewis Developers' Guide to Cost-Based Optimization
Kenny Vernon Numbers Don't Always Tell the Whole Story: Allowing Users to Enter Comments on OBIEE Dashboards
Kim Hansen External Data via HTTP, FTP, and Web Services
Kyle Hailey Agile Data Platform: Revolutionizing Database Cloning
Michael Casey Using the Open Interface Adapter in FDM Enterprise Edition 11.1.2.3
Paul Hoch Driver-Based Planning: When More Isn't Better
Scott LeBeau Implementing Advanced Financial Reporting Concepts for Rolling Trend Reports
Tiffany Briseno Hyperion Financial Reporting: Tips, Tricks, and Best Practices at TeleTech
19 rows selected.
Uh oh… Jonathan Lewis in same timeslot…
18. • Save site certificate using browser
• Create wallet on db server and add certificate:
mkdir /home/oracle/admin/wallet
orapki wallet create -wallet /home/oracle/admin/wallet -pwd myW4lletPasswd -auto_login
orapki wallet add -wallet /home/oracle/admin/wallet -trusted_cert -cert
"/mnt/share/savedcertificate.crt" -pwd myW4lletPasswd
• Set wallet for utl_http:
utl_http.set_wallet('file:/home/oracle/admin/wallet', 'myW4lletPasswd');
• Wallet will now be used for https:// urls
• http://www.oracle-base.com/articles/misc/utl_http-and-ssl.php
SSL (https) with UTL_HTTP
19. Network Access Control List
FTP_UTIL_PKG
UTL_HTTP
HttpUriType
UTL_DBWS
JPublisher
APEX_WEB_SERVICE
Topics
20. Very simple for HTTP GET of content
No SSL, No POST, No Cookies, No…
Object type with member methods
● GetBlob()
● GetClob()
● GetXml()
Not browser simulator
But easy to get a resource from the web
HttpUriType
21. Our use:
HttpUriType('url').GetBlob()
● Retrieve employee picture from intranet website
HttpUriType('url').GetClob()
● Get simple up/down status from payment provider
HttpUriType('url').GetXml()
● Google Maps routes to find time needed for delivery
routes from shop to shop in fireworks season
HttpUriType
22. declare
directions xmltype;
begin
directions := httpuritype(
'maps.googleapis.com/maps/api/directions/xml'
|| '?origin=' || utl_url.escape(convert(
'100 Oracle Pkwy, Redwood City, CA'
, 'UTF8'
))
|| '&destination=' || utl_url.escape(convert(
'1400 6th Ave, Seattle, Washington'
, 'UTF8'
))
|| '&mode=driving&alternatives=true&units=metric'
|| '®ion=us&language=en&sensor=false'
).getxml();
end;
/
REST-like Google Maps
Simply pass complete URL to HttpUriType
In SQL*Plus use SET DEFINE OFF to avoid substitution variable prompting
Or use || '&' || 'destination... as single '&' will not be treated as variable
24. select r.routenum, l.legnum
, numtodsinterval(l.seconds, 'second') time, l.meters / 1000 distance_km
, extractvalue(x.x,'/DirectionsResponse/status') status
, convert(r.routename,'WE8ISO8859P1','UTF8') routename
, convert(l.startaddr,'WE8ISO8859P1','UTF8') startaddr
, convert(l.endaddr,'WE8ISO8859P1','UTF8') endaddr
from xmltable(
'/DirectionsResponse'
passing httpuritype(
'maps.googleapis.com/maps/api/directions/xml'
|| '?origin=' || utl_url.escape(convert(
'100 Oracle Pkwy, Redwood City, CA'
, 'UTF8'
))
|| '&destination=' || utl_url.escape(convert(
'1400 6th Ave, Seattle, Washington'
, 'UTF8'
))
|| '&mode=driving&alternatives=true&units=metric'
|| '®ion=us&language=en&sensor=false'
).getxml()
columns x xmltype path '/'
) x,
...
Process with XMLTABLE …
httpuritype().getxml()
in passing clause for
xmltable for easy
parsing of the result
25. ...
xmltable(
'if (fn:empty(/DirectionsResponse/route)) then <route><leg></leg></route>
else /DirectionsResponse/route'
passing x.x
columns routenum for ordinality
, routename varchar2(100) path 'summary'
, r xmltype path '/'
) r,
xmltable(
'for $l in /route/leg return $l'
passing r.r
columns legnum for ordinality
, seconds number path 'duration/value'
, meters number path 'distance/value'
, startaddr varchar2(100) path 'start_address'
, endaddr varchar2(100) path 'end_address'
) l
order by r.routenum, l.legnum;
… and some Xquery …
Xquery here used to
make dummy empty
route if Google returned
an error status
26. ROUTENUM LEGNUM TIME DISTANCE_KM STATUS ROUTENAME
-------- ------ ------------------------------ ----------- ------ --------------------
STARTADDR ENDADDR
------------------------------------------------ ---------------------------------------
1 1 +000000000 12:37:44.000000000 1334.2 OK I-5 N
100 Oracle Parkway, Redwood City, CA 94065, USA 1400 6th Avenue, Seattle, WA 98101, USA
2 1 +000000000 15:19:09.000000000 1521.3 OK I-5 N
100 Oracle Parkway, Redwood City, CA 94065, USA 1400 6th Avenue, Seattle, WA 98101, USA
… to get route data
Google shows two alternative routes
- one 1334 km in a bit more than 12½ hours
- one 1521 km in a bit less than 15½ hours
27. select r.routenum, l.legnum, s.stepnum
, numtodsinterval(s.seconds, 'second') time, s.meters / 1000 distance_km
, convert(s.html_instructions,'WE8ISO8859P1','UTF8') html_instructions
from xmltable(
'/DirectionsResponse'
passing httpuritype(
'maps.googleapis.com/maps/api/directions/xml'
|| '?origin=' || utl_url.escape(convert(
'100 Oracle Pkwy, Redwood City, CA'
, 'UTF8'
))
|| '&destination=' || utl_url.escape(convert(
'1400 6th Ave, Seattle, Washington'
, 'UTF8'
))
|| '&mode=driving&alternatives=true&units=metric'
|| '®ion=us&language=en&sensor=false'
).getxml()
columns x xmltype path '/'
) x, xmltable(
'if (fn:empty(/DirectionsResponse/route)) then <route><leg></leg></route>
else /DirectionsResponse/route'
passing x.x
columns routenum for ordinality
, routename varchar2(100) path 'summary'
, r xmltype path '/'
) r, xmltable(
'for $l in /route/leg return $l'
passing r.r
columns legnum for ordinality
, seconds number path 'duration/value'
, meters number path 'distance/value'
, startaddr varchar2(100) path 'start_address'
, endaddr varchar2(100) path 'end_address'
, l xmltype path '/'
) l, xmltable(
'/leg/step'
passing l.l
columns stepnum for ordinality
, seconds number path 'duration/value'
, meters number path 'distance/value'
, html_instructions varchar2(1000) path 'html_instructions'
) s
order by r.routenum, l.legnum, s.stepnum;
More XMLTABLE for route steps
Put on yet another XMLTABLE
to get individual steps
28. RO LE STE TIME DISTANC HTML_INSTRUCTIONS
-- -- --- ------------------------------ ------- --------------------------------------------------------------------------------
1 1 1 +000000000 00:02:50.000000000 1.2 Head <b>northwest</b> on <b>Oracle Pkwy</b> toward <b>Marine Pkwy</b>
1 1 2 +000000000 00:00:58.000000000 .7 Turn <b>right</b> onto <b>Marine Pkwy</b>
1 1 3 +000000000 00:21:28.000000000 33.6 Merge onto <b>US-101 N</b> via the ramp to <b>San Francisco</b>
1 1 4 +000000000 00:00:33.000000000 .6 Take the <b>Interstate 80</b> exit toward <b>Bay Bridge</b>
1 1 5 +000000000 00:14:30.000000000 19.0 Merge onto <b>I-80 E</b>
1 1 6 +000000000 00:39:50.000000000 69.2 Keep <b>left</b> to stay on <b>I-80 E</b><div style="font-size:0.9em">Partial to
ll road</div>
1 1 7 +000000000 00:28:11.000000000 55.0 Take the exit onto <b>I-505 N</b> toward <b>Winters/Redding</b>
1 1 8 +000000000 10:48:17.000000000 1154.3 Merge onto <b>I-5 N</b><div style="font-size:0.9em">Passing through Oregon</div>
<div style="font-size:0.9em">Entering Washington</div>
1 1 9 +000000000 00:00:24.000000000 .4 Take exit <b>165</b> on the <b>left</b> for <b>Seneca St</b>
1 1 10 +000000000 00:00:43.000000000 .3 Slight <b>right</b> onto <b>6th Ave</b><div style="font-size:0.9em">Destination
will be on the right</div>
2 1 1 +000000000 00:02:50.000000000 1.2 Head <b>northwest</b> on <b>Oracle Pkwy</b> toward <b>Marine Pkwy</b>
2 1 2 +000000000 00:00:58.000000000 .7 Turn <b>right</b> onto <b>Marine Pkwy</b>
2 1 3 +000000000 00:21:28.000000000 33.6 Merge onto <b>US-101 N</b> via the ramp to <b>San Francisco</b>
2 1 4 +000000000 00:00:33.000000000 .6 Take the <b>Interstate 80</b> exit toward <b>Bay Bridge</b>
2 1 5 +000000000 00:14:30.000000000 19.0 Merge onto <b>I-80 E</b>
2 1 6 +000000000 00:52:11.000000000 91.9 Keep <b>left</b> to stay on <b>I-80 E</b><div style="font-size:0.9em">Partial to
ll road</div>
2 1 7 +000000000 00:10:46.000000000 19.5 Keep <b>left</b> to stay on <b>I-80 E</b>
2 1 8 +000000000 02:04:42.000000000 220.0 Keep <b>right</b> to stay on <b>I-80 E</b>, follow signs for <b>Reno</b><div sty
le="font-size:0.9em">Entering Nevada</div>
2 1 9 +000000000 01:13:38.000000000 129.5 Take exit <b>15</b> to merge onto <b>US-395 N</b> toward <b>Susanville</b><div s
tyle="font-size:0.9em">Entering California</div>
2 1 10 +000000000 00:00:06.000000000 .1 Slight <b>left</b> to stay on <b>US-395 N</b>
2 1 11 +000000000 00:03:12.000000000 4.6 Continue onto <b>CA-36 W</b>
2 1 12 +000000000 00:00:20.000000000 .2 Turn <b>right</b> onto <b>Riverside Dr</b>
2 1 13 +000000000 00:00:47.000000000 .6 Continue straight onto <b>Johnstonville Rd</b>
2 1 14 +000000000 00:02:52.000000000 3.3 Turn <b>left</b> onto <b>Skyline Rd</b>
2 1 15 +000000000 01:31:15.000000000 140.0 Turn <b>right</b> onto <b>CA-139 N</b>
2 1 16 +000000000 00:51:31.000000000 88.5 Turn <b>left</b> to stay on <b>CA-139 N</b><div style="font-size:0.9em">Entering
Oregon</div>
2 1 17 +000000000 00:19:24.000000000 27.6 Continue onto <b>OR-39 N</b>
2 1 18 +000000000 00:06:36.000000000 9.4 Turn <b>left</b> onto <b>OR-140 W</b>
29. "Proper" REST webservice exposed like Oracle
Rest Data Services with documentcentric URLs
● http://myserver.net/myprefix/hr/employees
GET data with HttpUriType('url').GetXml()
or
GET data with HttpUriType('url').GetClob()
and use 12.2 JsonTable() to parse result
Not POST, PUT, DELETE etc.
RESTful webservicecalls
30. Network Access Control List
FTP_UTIL_PKG
UTL_HTTP
HttpUriType
UTL_DBWS
JPublisher
APEX_WEB_SERVICE
Topics
31. Helps setup SOAP webservice calls
● Handles SOAP envelope, service, port, operation
Can do SSL (https) with wallets
Extra installation (not in default install)
Uses java classes
Our use:
● Payment authorization via provider’s SOAP
webservice that uses SSL
UTL_DBWS
36. ...
utl_dbws.set_target_endpoint_address(l_call, l_endpointurl);
select xmlroot(
xmlelement(
"GetCityWeatherByZIP"
, xmlattributes('http://ws.cdyne.com/WeatherWS/' as "xmlns")
, xmlelement(
"ZIP"
, l_zipcode
)
)
, version '1.0'
)
into l_request
from dual;
l_response := utl_dbws.invoke(call_Handle => l_call, request => l_request);
utl_dbws.release_call(l_call);
utl_dbws.release_service(l_service);
utl_dbws.release_all_services();
dbms_output.put_line(l_response.getclobval());
end;
/
Select from DUAL to avoid error:
PLS-00122: AS as separator is allowed
only with specific built-in functions
38. • Save site certificate using browser
• Add certificate to wallet in path:
$ORACLE_HOME/javavm/lib/security/cacerts
• Java based UTL_DBWS can now use wallet for https:// urls
• MOS (metalink) note 443438.1
SSL (https) with UTL_DBWS
39. Network Access Control List
FTP_UTIL_PKG
UTL_HTTP
HttpUriType
UTL_DBWS
JPublisher
APEX_WEB_SERVICE
Topics
40. Install SQLJ from client installation
See JPublisher user guide for details
● http://docs.oracle.com/cd/E11882_01/java.112/e10587/t
Serverside load java and UTL_DBWS
See previous slides
Can be clientside only on development PC if so
desired – jpub really is just code generator
JPublisher
41. Might use local copy of wsdl file rather than
URL to original WSDL file
● For example to annotate WSDL file with Oracle
datatypes or fix WSDL file xml schema errors
Our use:
● Other cardata from dataprovider we FTP from
● Parcel registering with parcel service
● Parcel track & trace with parcel service
JPublisher for SOAP callout
42. SET JAVA_HOME=%ORACLE_HOME%jdk
SET TNS_ADMIN=%ORACLE_HOME%networkadmin
SET PATH=%JAVA_HOME%bin;%JAVA_HOME%jrebin;%PATH%
SET CLASSPATH=%ORACLE_HOME%sqljlibdbwsa.jar;%ORACLE_HOME%jdklibdt.jar;^
%ORACLE_HOME%jdklibtools.jar;^
%ORACLE_HOME%jlibjssl-1_1.jar;%ORACLE_HOME%jdbclibojdbc5.jar;^
%ORACLE_HOME%sqljlibruntime12.jar;%ORACLE_HOME%jliborai18n.jar;^
%ORACLE_HOME%sqljlibtranslator.jar;%ORACLE_HOME%javavmlibaurora.zip;^
%ORACLE_HOME%rdbmsjlibxdb.jar;%ORACLE_HOME%libxsu12.jar:^
%ORACLE_HOME%jlibjndi.jar;%ORACLE_HOME%rdbmsjlibaqapi.jar;^
%ORACLE_HOME%rdbmsjlibjmscommon.jar;%ORACLE_HOME%libxmlparserv2.jar
SET LOCAL=MYORCL
jpub -user=scott/tiger -sysuser=sys/syspwd -dir=weather -package=weather
-plsqlpackage=weather -proxywsdl=http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL
For testing without loading into the database:
jpub -user=scott/tiger -sysuser=sys/syspwd -proxyopts=noload -dir=weather -package=weather
-plsqlpackage=weather -proxywsdl=http://wsf.cdyne.com/WeatherWS/Weather.asmx?WSDL
On windows client with jpub
43. weatherobject := weather.GetCityWeatherByZIP('98101');
dbms_output.put_line(weatherobject.Description);
select w.weatherobject.Success
, w.weatherobject.ResponseText
, w.weatherobject.State
, w.weatherobject.City
, w.weatherobject.WeatherStationCity
, w.weatherobject.WeatherID
, w.weatherobject.Description
, w.weatherobject.Temperature
, w.weatherobject.RelativeHumidity
, w.weatherobject.Wind
, w.weatherobject.Pressure
, w.weatherobject.Visibility
, w.weatherobject.WindChill
, w.weatherobject.Remarks
from (
select weather.GetCityWeatherByZIP('98101') weatherobject
from dual
) w
/
Use of generated objects PL/SQL or SQL
PL/SQL use object type
Object in SQL as well
Beware this may call the
webservice 14 times as SQL
engine may rewrite to call
package function once for
every column
44. Network Access Control List
FTP_UTIL_PKG
UTL_HTTP
HttpUriType
UTL_DBWS
JPublisher
APEX_WEB_SERVICE
Topics
45. Useful even if not using APEX
SOAP
● Manual SOAP envelope handling
REST
● GET, POST, PUT, DELETE, etc.
SSL made simple with wallet parameters
Uses network ACL, not java privileges
Possibly more "supported" in future
APEX_WEB_SERVICE
46. Add a bit to network ACL
begin
dbms_network_acl_admin.add_privilege(
acl => 'kscope_demo.xml'
, principal => 'APEX_040100'
, is_grant => true
, privilege => 'connect'
);
commit;
end;
/
begin
dbms_network_acl_admin.assign_acl(
acl => 'kscope_demo.xml'
, host => '*.cdyne.com'
);
commit;
end;
/
APEX user granted connect
privilege to our demo ACL
Use APEX user for your
APEX version
Weather URL added to ACL
Was not needed for UTL_DBWS
java based, but is needed for
APEX_WEB_SERVICE
47. declare
directions clob;
begin
directions := apex_web_service.make_rest_request(
p_url => 'http://maps.googleapis.com/maps/api/directions/xml'
, p_http_method => 'GET'
, p_parm_name => apex_util.string_to_table(
'origin:destination:mode:alternatives:units:region:language:sensor'
)
, p_parm_value => apex_util.string_to_table(
'100 Oracle Pkwy, Redwood City, CA:1400 6th Ave, Seattle,
Washington:driving:true:metric:us:en:false'
)
);
dbms_output.put_line(substr(directions,1,4000));
end;
/
APEX_WEB_SERVICE Google Maps
APEX_WEB_SERVICE REST call
Example of our google maps call
Colon separated
name/value pairs
48. declare
envelope clob;
weather xmltype;
begin
select xmlroot(
xmlelement(
"soap:Envelope"
, xmlattributes(
'http://www.w3.org/2001/XMLSchema-instance' as "xmlns:xsi"
, 'http://www.w3.org/2001/XMLSchema' as "xmlns:xsd"
, 'http://schemas.xmlsoap.org/soap/envelope/' as "xmlns:soap" )
, xmlelement(
"soap:Body"
, xmlelement(
"GetCityWeatherByZIP"
, xmlattributes('http://ws.cdyne.com/WeatherWS/' as "xmlns")
, xmlelement("ZIP", '98101')
) ) )
, version '1.0'
).getclobval()
into envelope
from dual;
weather := apex_web_service.make_request(
p_url => 'http://wsf.cdyne.com/WeatherWS/Weather.asmx'
, p_action => 'http://ws.cdyne.com/WeatherWS/GetCityWeatherByZIP'
, p_version => '1.1'
, p_envelope => envelope );
dbms_output.put_line(weather.getclobval());
end;
/
APEX_WEB_SERVICE SOAP call
Example of our weather call
Unlike UTL_DBWS SOAP envelope is
manually created here and response
will be wrapped in SOAP envelope
49. • Save site certificate using browser
• Create wallet on db server and add certificate:
mkdir /home/oracle/admin/wallet
orapki wallet create -wallet /home/oracle/admin/wallet -pwd myW4lletPasswd -auto_login
orapki wallet add -wallet /home/oracle/admin/wallet -trusted_cert -cert
"/mnt/share/savedcertificate.crt" -pwd myW4lletPasswd
• Use wallet in calls like:
directions := apex_web_service.make_rest_request(
p_url => 'https://maps.googleapis.com/maps/api/directions/xml'
, ...
, p_wallet_path => '/home/oracle/admin/wallet'
, p_wallet_pwd => 'myW4lletPasswd'
);
SSL (https) with APEX_WEB_SERVICE
50. Several methods available
Each has different pros and cons
No single "best" way
Pick easiest in each circumstance
Maybe APEX_WEB_SERVICE is where future
development might be from Oracle?
Summary
51. Danish geek
Oracle SQL Evangelist
Oracle PL/SQL Developer
Likes to cook
Reads sci-fi
Member of
Danish Beer Enthusiasts
Questions ?
http://dspsd.blogspot.com
http://dk.linkedin.com/in/kibeha/
@kibeha
Kim Berg Hansen
http://goo.gl/QuHQ1f
for this presentation