otech magazine - spring 2014

211
OTECH MAGAZINE Sten Vesterli Patrick Barel Simon Haslam THE COST OF TECHNOLOGY ABSOLUTELY TYPICAL #3 MAY 2014 ENTERPRISE DEPLOYMENT OF ORACLE FUSION MIDDLEWARE PRODUCTS – PART 2

Upload: agawish

Post on 19-Jan-2016

40 views

Category:

Documents


0 download

DESCRIPTION

Oracle Tech Magazine

TRANSCRIPT

  • OTECH MAGAZINESten Vesterli

    Patrick Barel Simon Haslam

    THE COsT Of TECHNOlOGy

    AbsOluTEly TypICAl

    #3 MAy 2014

    ENTErprIsE DEplOyMENT Of OrAClE fusION MIDDlEwArE prODuCTs pArT 2

  • 2 OTech Magazine #3 May 2014

    The clicking sounds the rail makes when haul-ing the carriage up. The moment of silence just before the screaming of the passengers starts. The wind in your hair during that first, breath-taking decent into the unknown

    OTech Magazine is going like a rollercoaster, just like my personal life. In the past few months a lot has happened.

    In my personal life I got married to the most wonderful woman in the world (who makes my life the best place in the world sorry guys). OTech Magazine has some new and exciting partners as well. Thanks to Roland (who does wonders with the graphics of the magazine) and Rob (who makes sure the commercial part of the magazine runs) OTech Magazine is becoming more and more professional.

    In my personal life we bought and renovated a new house. Its large and comfortable, has enough space for expansion. OTech Magazine, as you might have noticed by now, also had quite the makeover. The basis is completely changed and it offers us enough room to expand in the future months: the magazine will change and improve a bit every issue.

    In my personal life I broke my foot. Besides the pain, theres the agony of the best timing in the world. But, not everything in life goes the way we plan. This magazine was supposed to be released a few weeks ago, but because of small humps on the road that I mention above, we didnt make it.

    But maybe for the better; this issue of OTech Magazine certainly turned out mighty fine.

    I would like to take this opportunity to thank my beautiful wife Simone for her patience with me, Roland for this exciting new magazine look and feel, Rob for the commercial groundwork, our partners AMIS and More Than Code, our sponsors, most of all the contributors (keep the good stuff coming)

    And all our readers. Enjoy the ride!

    Douwe Pieter van den [email protected]

    twitter.com/omebos

    www.facebook.com/pages/

    OTech-Magazine/381818991937657

    nl.linkedin.com/in/douwepietervandenbos/

    rOllErCOAsTEr

    fOrEwOrD

  • 3 OTech Magazine #3 May 2014

    Try out our platform and book a free session for example:

    - Migration from OWB to ODI-Installation of Oracle enterprise manager 12 c

  • 4 OTech Magazine #3 May 2014

    CONTENT

    THE COsT Of TECHNOlOGy 6

    Sten Vesterli

    wHy AND HOw TO usE OrAClE

    DATAbAsE rEAl ApplICATION TEsTING? 13

    Talip Hakan Ozturk

    ENTErprIsE DEplOyMENT Of OrAClE

    fusION MIDDlEwArE prODuCTs pArT 2 26

    Simon Haslam

    AbsOluTEly TypICAl 32

    Patrick Barel

    sTEp by sTEp INsTAll OrAClE GrID 1

    1.2.0.3 ON sOlArIs 11.1 53

    Osama Mustafa

    THE rElEvANCE Of THE usEr ExpErIENCE 63

    Lucas Jellema

    OrAClE NOsQl pArT 2 89

    James Anthony

    uTIlITy usE CAsEs AsM_METrICs.pl 102

    Bertrand Drouvot

    buIlD A rAC DATAbAsE fOr frEE

    wITH vIrTuAlbOx 109

    Christopher Ostrowski

    DINOsAurs IN spACE -

    MObIlIZING OrAClE fOrMs

    ApplICATIONs 132

    Mia Urman

    prOvIsIONING fusION MIDDlEwArE

    usING CHEf AND puppET pArT I 137

    Ronald van Luttikhuizen & Simon Haslam

    MObIlITy fOr

    wEbCENTEr CONTENT 144

    Troy Allen

    ANAlyTIC

    wArEHOusE pICkING 150

    Kim Berg Hansen

    wHAT DOEs ADApTIvE IN

    OrAClE ACM MEAN? 163

    Lonneke Dikmans

    OrAClE ACCEss MANAGEr:

    ClusTErs, CONNECTION rEsIlIENCE

    AND COHErENCE 174

    Robert Honeyman

    QuMu & wEbCENTEr -

    brINGING vIDEO TO THE ENTErprIsE 182

    Jon Chartrand

    OrAClE DATA GuArD 12C:

    NEw fEATurEs 189

    Mahir M Quluzade

    INTrODuCTION TO OrAClE

    TECHNOlOGy lICENsE AuDITING 204

    Peter Lorenzen

  • Do you want to switch from Oracle Owb to ODi?

    we got the solution!

    www.owb2odiconverter.com

    we are going to be at the next Oracle Open World event, September 28 - October 2, 2014 San Francisco, USA.

    booth 115, Moscone South. why not pay us a visit?

  • 6 OTech Magazine #3 May 2014

    THE COsT Of TECHNOlOGySten Vesterli

    www.vesterli.com

    twitter.com/stenvesterli

    www.facebook.com/

    it.more.than.code

    dk.linkedin.com/in/stenvesterli

  • 7 OTech Magazine #3 May 2014

    In the United Kingdom, the National Health Service (NHS) has just given Microsoft more than 5 million pounds (equivalent to 9 million U.S. dollars). This is money that could have paid for 7,000 eye operations or 700 heart bypass operations, but now it goes to Microsoft to pay for extended support for Windows XP. The reason for this cost is that the NHS is a technological laggard, still running thousands of obsolete Windows XP installations.

    The Technology Adoption LifecycleThe adoption of new technology follows a classical path called the tech-nology adoption lifecycle. This is a widely applicable model that shows how new practices spread through a population, originally based on studies of new farm practices in the U.S. in the 1950s.

    This model divides the population of individuals or organizations into five groups: Innovators Early adopters Early majority Late majority Laggards

    The distribution of these types follows a normal distribution (bell curve) as shown below.

    The innovators are the risk-takers. They are financially strong in order to be able to make the necessary investments in unproven technology and survive any bets that do not pay off.

    The early adopters are open to innovation, focusing on using existing technology to achieve improved business outcomes. They are open to redesigning their processes and interactions when new technology makes it attractive.

    The early majority is more careful and prefers smaller, incremental im-provements to existing processes. They like to see others lead the way before they invest in technology or process improvements.

    THE COsT Of TECHNOlOGy1/4 Sten Vesterli

  • 8 OTech Magazine #3 May 2014

    had collected as others had retired these ancient systems. Shortly before I left, the second last disc controller in the world for these systems went up in flames, leaving us running a system for which the last spare part had run out.

    Considered as a working museum, it was interesting. Considered as a professional IT organization, it was indefensibly irresponsible.

    The cost of being an innovatorInnovators spend a lot of money on their technology, betting that they will recoup their investments later. They are risk-takers and sometimes their bets do not pay off during the dot-com bubble of the late 1990s, companies like Webvan spent literally billions but ended up going out of business.

    Many years ago, when Microsoft had just released the first version of Microsoft Windows, the young Bill Gates went to the most prominent software companies of the day to try to persuade them to build a Win-dows version of their software. But leading word processor WordPerfect and leading spreadsheet Lotus 1-2-3 were happy with their dominance of the character-based world and rejected Bill Gates. So he decided to build his own applications to showcase what a modern Windows applica-tion would look like. Microsoft invested heavily and built Word and Excel which has come to completely dominate the market for office software and has repaid the investment many, many times.

    The late majority is conservative and will only implement new technol-ogy when it is cheaper than the status quo. Sometimes, financially weak organizations end up in this category even if they have the mindset from one of the higher groups.

    The laggards are extremely risk-averse and typically not well-informed about technological trends. They will stick with tried-and-true solutions even when everybody else has moved on.

    The cost of being a laggardLaggards incur a serious cost. They are stuck with unsupported software versions from which there is no upgrade path and the necessary skills are rare and expensive. Do you know what a COBOL programmer costs these days?

    Often, the main cost is financial, but sometimes laggards place the entire organization at risk

    Early in my career, I worked at an organization that was still running their business on a very old mainframe computer. It had a disk drive the size of a washing machine, with 14-inch removable stacks of magnetic disks to store information. Occasionally, some component would fail, which would be evident from actual smoke and flames in the server room. We were paying a very expensive yearly support fee to the vendor, and the vendor actually kept a stock of spare parts specifically for us parts they

    THE COsT Of TECHNOlOGy2/4 Sten Vesterli

  • 9 OTech Magazine #3 May 2014

    This attrition explains why the laggards end up with the toxic combina-tion of low benefit and high cost. Their application might have provided a significant benefit when it was created 15 years ago, but now it offers no competitive advantage and is very expensive to maintain.

    The late majority does not get much benefit because of benefit attrition, but at least they are using well-known software where skills and support resources are available and can easily be purchased offshore.The early majority is getting a middling benefit from their systems at a cost comparable to the late majority.

    The early adopters are getting a significant business benefit from their systems because they continually renew them. Because they keep step-ping forward, they do not drift to the left as the majority does. Their cost tends to be slightly higher than the majority because they pick up new tools and technologies early, before all the kinks have been worked out. Finally, the innovators are furthest to the right on the benefit scale, but they are also incurring a high cost because they tend to use cutting-edge technology in radically new ways.

    Improving yourselfYou should make this kind of cost/benefit analysis continually for all of your major IT systems. The important part is not to classify yourself into one of the five groups, but to follow where your systems are moving over time. To track this, you need to gather some data on both costs and benefits.

    Companies like Amazon and Tesla have yet to show a significant profit, but have stratospheric stock valuations. Why? Because investors ap-preciate that they are innovators and have a chance of reaping outsize rewards from dominating new markets.

    Cost and BenefitEvery organization tries to achieve the best balance between cost and benefit based on their understanding of the world. The cost is fairly straightforward to calculate, but the benefit is relative. It depends on what your competitors are doing, and the benefit suffers from attrition it automatically becomes smaller over time as your competitors catch up.

    THE COsT Of TECHNOlOGy3/4 Sten Vesterli

  • 10 OTech Magazine #3 May 2014

    Cost is easiest to calculate. You can read your software, hardware and support costs directly from your financial system, and you can allocate your total personnel cost to the various systems you are running. Be-cause many people will be supporting different systems, you need to allocate their cost across the systems they support. A simple ratio (25% of this persons time on that system) is enough. If you already have more detailed time tracking implemented, you can also use this for additional precision.

    The benefit is harder to calculate. Some organizations can calculate a direct financial benefit from a system (profit from sales on the web site), but most will have to use other metrics. If your organization is already measuring Key Performance Indicators (KPIs), you can use these as a starting point. There will be other non-financial benefits that you need to figure out a way to measure consistently (customer satisfaction, churn, service request resolution time, etc.).

    Plot this measurement for each major system with regular intervals, for example quarterly. This will make you aware of the benefit attrition as it happens, and will prevent you from ending up with low benefits and high costs.

    THE COsT Of TECHNOlOGy4/4 Sten Vesterli

  • 11 OTech Magazine #3 May 2014

    Sten Vesterliwww.vesterli.com

    More Than CodeCopenhagen, Denmark+45 26 81 86 [email protected]

    @stenvesterli

    www.facebook.com/it.more.than.code

    OTECH pArTNEr:

    Success in IT depends on three things: Good people, good processes, and good technology. At More Than Code, we work with all three, in any combination.

    We help IT organizations build applications their users really love, we help you choose the right technology, we help you operate at maximum efficiency, and we help individual IT developers become as happy and productive as possible. And if you have chosen Oracle ADF as your technology, we have one of the worlds leading experts to help you build amazing ADF applications as fast as possible.

    Client Caser:The users did not use the functionality of the new HR system, depending on their own shadow systems based on spreadsheets or paper. After interviewing the us-ers, we determined that the new system was too complex for casual users. We sug-gested and designed a simple, user-friendly front-end to the system focusing only on the tasks relevant for these users and achieved almost complete data coverage in the central HR system and the elimination of shadow systems.

  • FOEX

    Bu i l d b eau t i f u l a nd powe r f u l A pp l ic a t io ns u s i n g you r e x i s t i n g PL /SQL a nd APEX S k i l l s

    www.tryfoexnow.com email: [email protected]

    Weve enhanced APEX to make

    it the perfect PL/SQL based

    alternative to ADF and Forms

    development, not just for your

    developers but most importantly

    for your end users.

    FOEX Plugin Framework for Oracle APEX

    Open multiple Applications within the Desktop Plugin

    Single Page, multiple Components linked together

  • 13 OTech Magazine #3 May 2014

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?

    Talip Hakan Ozturkwww.bankasya.com.tr

    www.twitter.com/

    taliphaknozturk

    www.facebook.com/thozturk

    www.linkedin.com/in/

    taliphakanozturk

  • 14 OTech Magazine #3 May 2014

    The importance of competition is increasing day by day. Today, enterpris-es have to offer service quality to their customers to be at the forefront. Improvements and investments in IT infrastructure are the foundation of service quality. The Databases located in the center of IT infrastructure have important place in terms of the quality of services. Any changes made to our databases will be reflected directly to our customers. So it must be considered well before any changes are made. And the neces-sary testing process also must be operated.

    A. SQL Performance Analyzer (SPA)System changes such as upgrading database, changing a parameter, adding new index, database consolidation testing, configuration changes to the OS, adding/removing hardware that affect execution plans of SQL statements can significant impact on SQL statement performance. These system changes may improve or regress SQL/Application perfor-mance. For example, we may encounter with a surprise after upgrading the production database. Only a SQL statement is enough to disrupt the functioning of our database. In this situation, Database Administrators spend enormous amounts of time identifying and fixing regressed SQL statements.

    We can predict SQL execution performance problems and prevent ser-vice outage using SQL Performance Analyzer. Using it, we can compare the performance degradation of SQLs by running the SQL statements serially before and after the changes. SPA is integrated with SQL Tuning

    Oracle Database Real Application Testing option addresses this testing process. It offers cost-effective and easy-to-use change assurance solution. It enables you to perform real-world testing of your production database. With this comprehensive solution, we can do a change in a test environ-ment, measure performance degradation or improvements, take any cor-rective action, and then to introduce the change to production systems. Real Application Testing offers two complementary solutions, SQL Perfor-mance Analyzer(SPA) and Database Replay.

    Figure 1 Lifecycle of change management

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?1/12 Talip Hakan Ozturk

  • 15 OTech Magazine #3 May 2014

    SPA Performance Analyzer or on remote database using database link. Explain Plan Only - This method generates execution plans only for SQL

    statements through SQL Performance Analyzer. This can be done on the database running SPA Performance Analyzer or on remote data-base using database link.

    Convert SQL tuning set - This method converts the execution statistics and plans stored in a SQL tuning set.

    3 Making the system change (upgrading database, changing a param-eter, adding new index, database consolidation testing, configuration changes to the OS, adding/removing hardware, etc.)

    4 Creating a post-change SQL trial. It is recommended that you create the post-change SQL trial using the same method as the pre-change SQL trial. After this step, a new SQL trial will be created and stored new execution statistics/plans.

    5 Comparing the SQL Statement Performance. SQL Performance Analyz-er compares the pre-change and post-change SQL trials using metrics like CPU time, User I/O time, Buffer gets, Physical I/O, Optimizer cost, and I/O interconnect bytes. It produces a report identifying any chang-es in execution plans or performance metrics of the SQL statements.

    Set, SQL Tuning Advisor, and SQL Plan Management components. You can capture SQL statements into a SQL Tuning Set, compare the perfor-mance of SQL statements before and after the change by executing SPA on SQL Tuning Set. Finally, we can tune regressed SQL statements using SQL Tuning Advisor component.

    There are 5 steps to evaluate system changes:1 Capturing the SQL statement workload. There are several methods to

    capture SQL workload such as AWR, Cursor Cache. Captured SQL state-ments loaded into a SQL Tuning Set. SQL Tuning Set (STS) is a database object that contains many SQL statements with execution statistics and context. If SQL workload contains more SQL statements, it will better simulate the state of the application. So we must capture as many SQL statements as possible. It is possible to move STS from pro-duction system to test system using export/import method. You should install and configure the test database environment (platform, hard-ware, data, etc.) to match the database environment of the production system as closely as possible.

    2 Creating a pre-change SQL trial. It is possible to generate the perfor-mance data needed for a SQL trial with SQL Performance Analyzer using the following methods.

    Test Execute - This method executes SQL statements through SQL Per-formance Analyzer. This option can be done on the database running

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?2/12 Talip Hakan Ozturk

  • 16 OTech Magazine #3 May 2014

    1 Create a SQL Tuning Set (STS) on production database

    BEGIN

    DBMS_SQLTUNE.create_sqlset (sqlset_name => STS_TALIP, sqlset_owner => TALIP

    );

    END;

    /

    Load SQL Statements into created STS from cursor cache as belows.

    DECLARE

    sqlset_cur DBMS_SQLTUNE.sqlset_cursor;

    BEGIN

    OPEN sqlset_cur FOR

    SELECT VALUE (p)

    FROM table(DBMS_SQLTUNE.select_cursor_cache (NULL,

    NULL,

    NULL,

    NULL,

    NULL,

    1,

    NULL,

    TYPICAL

    )) p;

    DBMS_SQLTUNE.load_sqlset (sqlset_name => STS_TALIP,

    populate_cursor => sqlset_cur,

    load_option => MERGE,

    update_option => ACCUMULATE,

    sqlset_owner => TALIP

    );

    END;

    /

    Figure 2 SQL Performance Analyzer Workflow

    You can use SQL Performance Analyzer through DBMS_SQLPA API and through Oracle Enterprise Manager interface.

    The DBMS_SQLSPA package is a command line interface can be used to test the impact of system changes on SQL performance. How to use SPA through DBMS_SQLPA API? The following step by step example illus-trates the impact of a new index creation.

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?3/12 Talip Hakan Ozturk

  • 17 OTech Magazine #3 May 2014

    staging_table_name => STG_TABLE,

    staging_schema_owner => TALIP

    );

    END;

    /

    Now, the SQL Tuning Set (STS) is ready for analyzing.3 The first step is to create an analysis task by calling the create_analy-sis_task procedure of the DBMS_SQLSPA package. This procedure cre-ates an advisor task and sets its corresponding parameters according to the user provided input arguments.

    BEGIN

    dbms.sqlpa.create_analysis_task

    (

    sqlset_name => TALIP_STS,

    task_name => talip_spa_task,

    description => index_creation_test

    );

    END;

    /

    You can verify the analysis task as follows.

    SQL> select task_name, advisor_name, created, status from dba_advisor_tasks where

    task_name=talip_spa_task;

    2 Move the created STS to test database a To move STS, we must create a staging table.

    SQL> BEGIN

    DBMS_SQLTUNE.create_stgtab_sqlset (table_name => STG_TABLE,

    schema_name => TALIP,

    tablespace_name => TALIP_TS

    );

    END;

    /

    b Pack the STS into staging table

    SQL> BEGIN

    DBMS_SQLTUNE.pack_stgtab_sqlset (sqlset_name => STS_TALIP,

    sqlset_owner => TALIP,

    staging_table_name => STG_TABLE,

    staging_schema_owner => TALIP

    );

    END;

    /

    c Export the staging table and copy export file to test system.

    # expdp talip@dbtalip directory=export dumpfile=stg_table.dmp logfile=stg_table.log tables=talip.stg_table

    e Unpack staging table to STS.

    BEGIN

    DBMS_SQLTUNE.unpack_stgtab_sqlset (sqlset_name => STS_TALIP,

    sqlset_owner => TALIP,

    replace => TRUE,

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?4/12 Talip Hakan Ozturk

  • 18 OTech Magazine #3 May 2014

    (

    task_name => talip_spa_task,

    execution_type => explain plan,

    execution_name => second_trial

    );

    END;

    /

    6 We can compare the result of first and second trial using same proce-dure.

    BEGIN

    dbms_sqlpa.execute_analysis_task

    (

    task_name => talip_spa_task,

    execution_type => compare performance,

    execution_name => analyze_result,

    execution_params => dbms_advisor.arglist(

    execution_name1, first_trial,execution_name2, second_trial,

    comparison_metric, optimizer_cost)

    );

    END;

    /

    7 When the analysis task execution is completed, the comparison results can be generated in HTML/TEXT format by calling the report_analysis_task procedure as follows.

    SQL> set heading off long 1000000000 longchunksize 10000 echo off;

    set linesize 1000 trimspool on;

    spool report.html

    select xmltype(dbms_sqlpa.report_analysis_task(talip_spa_task, html, top_

    4 When the analysis task is successfully created, it is at an initial state. Now, it is time to build the SQL performance data before making the change.

    BEGIN

    dbms_sqlpa.execute_analysis_task

    (

    task_name => talip_spa_task,

    execution_type => explain plan,

    execution_name => first_trial);

    END;

    /

    The procedure called execute_analysis_task is invoked with the execu-tion_type argument set to explain plan makes the Analyzer produce execution plans only. If we invoked with the execution_type argument set to test execute then it requests SQL Performance Analyzer to ex-ecute all SQL statements in the SQL tuning set in order to generate their execution plans as well as their execution statistics. You can check the task execution status as follows.SQL> select task_name, execution_name, execution_start, execution_end, status from dba_advisor_executions where task_name=talip_spa_task order by execution_end;

    5 Now, we can create new index on test database and call again the execute_analysis_task procedure using the same arguments.

    BEGIN

    dbms_sqlpa.execute_analysis_task

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?5/12 Talip Hakan Ozturk

  • 19 OTech Magazine #3 May 2014

    Figure 4 Regressed SQL statements in the comparison report.

    It is also possible to see changed new plans using dba_advisor_sqlplans view.

    B. Database ReplayDatabase Replay solution enables real-world testing of production sys-tem changes such as database upgrades, patches, configuration changes (Single instance to RAC or far from it), data storage changes (ASM fail-groups, Storage SRDF configuration, etc.), file system changes (OCFS2 to

    sql => 500) ).getclobval(0,0)

    from dual;

    spool off

    You can see the comparison report summary generated in HTML for-mat in figure 3-4. In this reports, there are improved and regressed SQL statements after change. You must analyze changed execution plans of regressed SQL statements.

    Figure 3 The comparison report summary generated in HTML format.

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?6/12 Talip Hakan Ozturk

  • 20 OTech Magazine #3 May 2014

    (Workload Replay Client) replays the preprocessed capture files in test database. Using the WRC tool in calibration mode you can determine the number of wrc client to replay process.

    4 Analyzing the result. You can perform detailed analysis of workload during capture and replay process. You can also take AWR (Automatic Workload Repository) reports to compare performance statistics dur-ing capture and replay process. I think, AWR report is the best method for detailed analysis.

    Figure 5 Database Replay Workflow

    ASM), operating system changes (Windows, Linux, Solaris), and database consolidation testing projects using Oracle 12c Multitenant Databases, etc. It captures the whole production database workload including all concurrency, dependencies and timing. After capturing real-world pro-duction workload, it replays the workload on the test database. There are 4 steps to evaluate system changes.

    1 Capturing the production workload. After the starting capture process, all client activities including SQL queries, DML statements, DDL state-ments, PL/SQL blocks and Remote Procedure Calls are stored in binary files which extension likes wcr_rec*,wcr_capture.wmd and wcr_*.rec . These binary files contain all information about client requests such as SQL statements, bind variables, etc. Captured files are stored in an Ora-cle directory that we created in first step with the CREATE DIRECTORY statement.

    2 Preprocessing the workload. After the capturing production workload, you must be copied the captured files to test system. In this step, the captured data stored in binary files must be prepared to replay pro-cess. This step creates the metadata needed for replaying the work-load.

    3 Replaying the workload. The data in production database and test database must be same. So you must restore the backup taken before capture process to the test database. And also you must make nec-essary system change on test system. A client program called WRC

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?7/12 Talip Hakan Ozturk

  • 21 OTech Magazine #3 May 2014

    not valid in subsequent releases. After upgrading the database, you must remove the parameter from the parameter file otherwise, the database will fail when it start up.

    BEGIN

    dbms_workload_capture.start_capture

    (

    name => CAPTURE,

    dir => CAPTUREDIR,

    default_action => INCLUDE

    );

    END;

    /

    3 You can filter out activities based on instance, program, user, module, and so on. Conversely, you can also record specific types of activities.

    SQL> exec dbms_workload_capture.ADD_FILTER ( fname =>INSTANCE_NUMBER,

    fattribute => INSTANCE_NUMBER,

    fvalue =>1);

    SQL> exec dbms_workload_capture.ADD_FILTER ( fname =>USERNAME,

    fattribute => USER,

    fvalue =>TALIP);

    SQL> exec dbms_workload_capture.DELETE_FILTER(fname=>USERNAME);

    Database replay can be used via both the command line interface and Oracle Enterprise Manager. Note that Oracle Database releases 10.2.0.4 and above support Enterprise Manager functionality for capture/replay of workloads. The replay process can only be performed on Oracle Data-base 11g and higher versions.

    The following step by step example illustrates using database replay from command line interface (CLI).

    1 Before starting the capture process, it is recommended that restart the database to ensure that ongoing and dependent transactions are allowed to be completed or rolled back before the capture begins. It is recommended but not required. Because, you can not restart the busi-ness critical production database running on 24 X 7 basis. First we need to create a directory object in the database where capture files will be stored.

    # mkdir /data1/dbreplay

    SQL> CREATE DIRECTORY capturedir AS /data1/dbreplay;

    2 Take a RMAN level 0 backup of production database to restore target test system and start the capture job.

    Note that, to capture pre 11g databases you must set PRE_11G_ENABLE_CAPTURE initialization parameter to value TRUE. This parameter can only be used with Oracle Database 10g Release 2 (10.2). This parameter is

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?8/12 Talip Hakan Ozturk

  • 22 OTech Magazine #3 May 2014

    restore database;

    recover database;

    }

    Now, the test database is same as the production database was when the workload capture started.

    7 First we need to create a directory object in the database where the copied capture files are stored.

    SQL> CREATE DIRECTORY replaydir AS /data1/dbreplay;

    8 We need to preprocess the captured files on test system. It creates necessary metadata to replay. Preprocess is required only once per capture. After preprocessing the captured files, you can replay it many times.

    BEGIN

    dbms_workload_replay.process_capture

    (

    capture_dir => REPLAYDIR

    );

    END;

    /

    9 The test database is now ready for replay process. Let initialize replay process as belows.

    BEGIN

    4 Let the capture process run long enough. For example, for a core banking database, you can capture the database in peak hours through branches and channels, batch job execution and end-day op-erations. After running the capture process long enough, you can stop it as belows.

    SQL> exec dbms_workload_capture.finish_capture;

    5 Navigate to the /data1/dbreplay directory. The captured workload files are located in this directory. Copy these files to the target test system (via ftp, scp, etc.). Before the capture process, an AWR snapshot is taken by database. After the capture process, it is also taken and ex-ported to /data1/dbreplay directory automatically.

    You can also export the AWR report of capture process when it needed. Select the capture_id using the DBA_WORKLOAD_CAPTURES view and export necessary AWR snapshots as belows. 27 is the capture id.SQL> exec dbms_workload_capture.export_awr(27);

    6 Restore the backup of the production database taken before cap-ture process on the target test system. You must recover it up to the minute the capture started. You can use RMAN set until time clause for it as belows.

    RMAN> run {

    set until time 2014-02-19 10:08:46;

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?9/12 Talip Hakan Ozturk

  • 23 OTech Magazine #3 May 2014

    We can also set the scale_up_multiplier parameter defines the number of times the workload is scaled up during replay. Each captured session will be replayed concurrently for as many times specified by this parameter. However, only one session in each set of identical replay sessions will ex-ecute both queries and updates. The rest of the sessions will only execute queries. For example,

    BEGIN

    dbms_workload_replay.prepare_replay

    (

    scale_up_multiplier => 10

    );

    END;

    /

    11 Start a replay client from the command line, using the wrc command. # $ORACLE_HOME/bin/wrc userid=system password=***** replaydir=/data1/dbreplay

    It gives a message like below.

    Wait for the replay to start (10:11:26)

    Note that the number of wrc clients that needs to be started depends on the captured workload. To find number of wrc clients that needs to be started, you must execute wrc utility with calibrate mode as belows.

    dbms_workload_replay.initialize_replay

    (

    replay_name => REPLAY,

    replay_dir => CAPTUREDIR

    );

    END;

    /

    10 You can specify some parameters below.

    synchronization: whether or not commit order is preserved

    connect_time_scale:scales the time elapsed between the start of the replay and the start of each session

    think_time_scale:scales the time elapsed between two successive user calls from the same session

    think_time_auto_correct - Auto corrects the think time between calls when user calls takes longer during the replay than during the capture

    BEGIN

    dbms_workload_replay.prepare_replay

    (

    synchronization => TRUE,

    connect_time_scale => 100,

    think_time_scale => 100,

    think_time_auto_correct => FALSE

    );

    END;

    /

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?10/12 Talip Hakan Ozturk

  • 24 OTech Magazine #3 May 2014

    l_cap_id NUMBER;

    l_rep_id NUMBER;

    BEGIN

    l_cap_id := dbms_workload_replay.get_replay_info (dir => CAPTUREDIR);

    SELECT MAX (id)

    INTO l_rep_id

    FROM dba_workload_replays

    WHERE capture_id = l_cap_id;

    :v_rep_rpt := dbms_workload_replay.report (replay_id => l_rep_id,

    format => dbms_workload_capture.type_html

    );

    END;

    /

    PRINT :v_rep_rpt

    You can also get reports in Oracle Enterprise Manager even you have used CLI during replay process.

    Figure 6 Database Replay comparison reports via Oracle Enterprise Manager.

    # $ORACLE_HOME/bin/wrc userid=system password=***** mode=calibrate replaydir=/data1/

    dbreplay

    12 Start the replay process.

    SQL> exec dbms_workload_replay.start_replay;

    When the replay process starts, the wrc replay client displays a message below.

    Replay started (10:12:09)

    When the replay process finishes, the wrc replay client displays a mes-sage below.

    Replay finished (04:53:03)

    During the replay process we can pause, resume or cancel the process.

    SQL> exec DBMS_WORKLOAD_REPLAY.PAUSE_REPLAY();

    SQL> exec DBMS_WORKLOAD_REPLAY.RESUME_REPLAY();

    SQL> exec DBMS_WORKLOAD_REPLAY.CANCEL_REPLAY();

    13 The last step is analyzing and reporting. We can get replay report as belows.

    SQL>SET SERVEROUTPUT ON TRIMSPOOL ON LONG 500000 LINESIZE

    200

    VAR v_rep_rpt CLOB;

    DECLARE

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?11/12 Talip Hakan Ozturk

  • 25 OTech Magazine #3 May 2014

    Please check the metalink document 463263.1 for Database Capture And Replay common errors and reasons. That is all :-) Test and Enjoy it.

    Summary:Change made to our systems will be reflected directly to our customers. So it must be considered well before any changes are made. Using the Oracle Database Real Application Testing option, you can easily manage system changes with confidence. Real Application Testing helps you to take lower change risks, lower system outages, and improve quality of service. You can adopt new technologies with complacence.

    wHy AND HOw TO usE OrAClE DATAbAsE rEAl ApplICATION TEsTING?12/12 Talip Hakan Ozturk

  • 26 OTech Magazine #3 May 2014

    ENTErprIsE DEplOyMENT Of OrAClE fusION MIDDlEwArE prODuCTs pArT 2

    Simon Haslamwww.veriton.com

    Consultant at Veriton Ltd

    Technical Director, O-box Products Ltd

    twitter.com/simon_haslam

    www.facebook.com/thozturk

    uk.linkedin.com/in/simonhaslam

  • 27 OTech Magazine #3 May 2014

    Welcome to the second in a series of articles about building production-grade Fusion Middleware platforms, focussing on the Enterprise Deploy-ment Guides (EDGs). Hopefully you have already read Part 1 from the last issue of OTech Magazine where I introduced the EDGs and why you might want to use them.

    So, to catch up where we left off, an EDG offers a recipe of how to build a secure and highly available system using one of the layered, or upper stack product sets, such as SOA Suite or Identity Management. As an Oracle-supplied blueprint it offers a number of well thought out practic-es, though, in my experience, you rarely implement a 100% EDG compliant system for reasons which will hopefully become apparent.

    There are some areas where I think you may consider deviating from an EDG in this issue I am going to cover: Physical versus Virtual Implementations Licensing Considerations Failover Approaches Component Workloads Lifecycle RequirementsLets drill into each of these in a bit more depth and, to make it a little easier to follow, here is one of the EDG diagrams I have stuck on the wall in front of my desk!

    Diagram 1: SOA EDG diagram of MySOACompany Topology with Oracle Service Bus

    ENTErprIsE DEplOyMENT Of OrAClE fusION MIDDlEwArE prODuCTs1/4 Simon Haslam

  • 28 OTech Magazine #3 May 2014

    There are two reasons that introducing virtual machines alters some de-sign decisions though:

    1) When you are using virtual machines you have a lot of flexibility in terms of VM sizing, plus you can have as many of them as you like (within reason). This encourages you to have one machine per function so, where the EDG suggests multiple managed servers per host, you may instead choose to have one managed server per VM as this can be beneficial for administration and tuning.

    2) Virtual machines give you a degree of location neutrality, above the physical hardware. This may negate the need to use networking ab-stractions, such as virtual hostnames and virtual IP addresses (VIPs) which can then simplify the configuration within the VMs. For exam-ple, if you put an Admin Server on its own VM you could save having to configure and manage a VIP for this purpose, instead leaving it up to the hypervisor to ensure that the Admin Server VM is always running somewhere. Incidentally this is the approach that Oracle has taken for their Admin Servers in the WebLogic implementation on the Oracle Database Appliance.

    So separating out software components onto different (virtual) ma-chines, and reducing the use of virtual (network) hosts are two areas you may want to diverge from the EDGs suggestions.

    The above diagram is taken from the SOA 11g EDG. This EDG actually con-siders 4 product combinations SOA (by which we primarily mean BPEL) and OAM alone, plus BAM, plus BPM, and finally SOA with OSB. Please forgive my excessive use of acronyms hopefully if you are working with Fusion Middleware they will be familiar to you (though the meaning of these abbreviations isnt too important for the purposes of this article).The diagram shows the software components used, the hosts they run on, and the communication channels between both themselves and the outside world. I have zoomed in on the SOA with OSB combination as its a very common use case and illustrates several possible EDG deviations.

    Physical versus Virtual ImplementationsIt is now several years since I designed or built a production Fusion Mid-dleware environment using operating systems running on bare metal instead most middleware administrators have to deal with virtual machines (VMs). With modern servers having tens of cores it is hard to imagine many situations, certainly for the sort of mid-sized organisations where I work, where you would use all of that compute power for a sin-gle function. The EDGs talk about physical hosts where they discuss virtual they are usually talking about virtual hostnames, i.e. a means of abstracting the services hostname away from the underlying host. Even though, for middleware, I think you can mostly treat physical hosts and virtual machines the same, if an EDG described both virtual host-names and the hostname of virtual machines that it could get quite confusing!

    ENTErprIsE DEplOyMENT Of OrAClE fusION MIDDlEwArE prODuCTs2/4 Simon Haslam

  • 29 OTech Magazine #3 May 2014

    Furthermore when you start considering Disaster Recovery (DR) this is an area that the EDGs dont cover instead they refer you to the Fusion Middleware Disaster Recovery Guide . There are numerous DR alterna-tives these days, especially when using virtualization your ultimate ap-proach will depend on the network connectivity between sites, your RTO and RPO s, and how much you want to use an Oracle-specific method as compared to something provided by the underlying infrastructure. So its very important to consider DR from the start of your project as this will probably influence your architecture.

    Component WorkloadsA more subtle topic where you might want to have a different approach to the EDG is with regards to relative sizes/locations of the various com-ponents. A particular example of this the Web Services Manager Policy Manager (WSM-PM) which is given its own managed server by the SOA EDG you might decide that is oversized for your environment and co-locate it in managed servers alongside other products. By and large the EDGs appears to have made carefully considered decisions in this area though so, if you do choose to ignore Oracles advice, make sure you understand the ramifications.

    Licensing ConsiderationsAnother consideration for most organisations is Oracle licensing. Prod-ucts within the technology area described by a single EDG may have dif-ferent prices. A good example is OSB and SOA Suite ($23,000 and $57,500 per Oracle Processor respectively) whilst SOA Suite includes OSB it is cheaper to license the cores you need for OSB separately with the cheap-er OSB-only licence. If we are not running on bare metal, the options to partition your licences vary according to underlying hardware and soft-ware , but in some cases licensing will be a good reason to decompose the products on your physical hosts or VMs and deviate from the EDG.

    Failover ApproachesFailover design, to handle the loss (planned or otherwise) of a single hardware or software component, is very important for most production systems. The EDGs suggest a middleware-led approach to failover. This is usually by means of VIPs and Whole Server Migration for WebLogic, or may involve a cluster manager of some sort (e.g. Oracle Clusterware or software supplied by the hardware vendor). However, depending on your requirements, some services may be need to be more highly avail-able than others, mostly depending on whether the service is transac-tional and customer-facing in nature. To avoid the relative complexity of configuring failover in middleware, you could choose a hybrid approach where some services, such as JMS, are failed over by WebLogic and oth-ers, like the Admin Server, are failed over by a virtualization feature (like Oracle VMs Live Migration or VMwares HA/vMotion).

    ENTErprIsE DEplOyMENT Of OrAClE fusION MIDDlEwArE prODuCTs3/4 Simon Haslam

  • 30 OTech Magazine #3 May 2014

    Lifecycle RequirementsPatching lifecycle is another factor which could influence how you decide to split out your software components. For example, do you want to patch all components at the same time? If you look at Diagram 1 you will see that SOA (BPEL) and OSB, whilst having their own managed servers, share the same domain you might decide that the patching timeframes and frequency, as well as the availability requirements, of these services are different and so youd like to patch them independently, thus have them in 2 separate domains. This is a trade-off though between flexibil-ity and complexity; in fact Oracle SOA professionals seem undecided on this, with as far as I can tell, a fairly even mix of both approaches used in production environments.

    So, hopefully this has given you some food for thought. For the next article in this series we will cover a few more areas where you need to diverge from the EDG approach, including security, network topology and the occasional documentation error. In the meantime, if youre not too familiar with the EDG for your chosen product set, I encourage you to dive in, spin up a few virtual machines, and try out an EDG configuration for yourself!

    ENTErprIsE DEplOyMENT Of OrAClE fusION MIDDlEwArE prODuCTs4/4 Simon Haslam

  • 31 OTech Magazine #3 May 2014

  • 32 OTech Magazine #3 May 2014

    AbsOluTEly TypICAlPatrick Barel

    www.amis.nl

    twitter.com/patch72

    nl.linkedin.com/in/patrickbarel

  • 33 OTech Magazine #3 May 2014

    This article will convince database developers that types in the Oracle Database are worth their salt - and more. With the recent improvements in 11gR2, the pieces are available to complete the puzzle of structured and modern programming with a touch of OO and more importantly to create a decoupled, reusable API that exposes services based on tables and views to clients that speak SQL, AQ, PL/SQL, Types, XML, JSON or RESTful, through SQL*Net, JDBC or HTTP. We will show through many examples how types and collections are defined, how they are used be-tween SQL and PL/SQL and how they can be converted to and from XML and JSON. Everyone doing PL/SQL programming will benefit immediately from this article.

    Every Database Developer should be aware of Types and Collections. For structured programming, for optimal SQL to PL/SQL integration and for interoperability to client application. This article introduces Types and Col-lections, their OO capabilities and the conversion to XML and JSON.

    IntroductionTypes have been available in the Oracle database since day one. Every column in a table is of a specified type. For instance the SAL column of the EMP table is a numeric type, where the column ENAME is a character based type. They are only partially interchangeable. You can put a numer-ic value into a character based type but you cannot put a character value into a numeric type. These are so-called scalar data types. They can hold exactly one value of a specified type. There are also composite types, like

    SDO_GEOMETRY which holds a combination of some scalar types and some collection types. You can even add behavior to the type that will run on the values of that instance of the type.

    As you can see, types are a implemented the way object oriented lan-guages do this. This is available since Oracle version 8.0 (which is eight-oh, not eight-zero). User Defined Types (or UDTs) can be helpful to do structured programming in PL/SQL.

    We will show you how to create a simple User Defined Type (UDT). Then a type which holds references to other types and how to add behavior to the UDT. We will also see how we can convert these types to XML and JSON files. UDTs, in their many forms, can be used for the interaction be-tween SQL and PL/SQL but also for interaction with the outside world, for example through Java programs. They can used to do OO development in a PL/SQL environment.

    DefinitionTo create a UDT which can be used in the SQL layer of the database you have to create an object using the create (or replace) TYPE statement. To create a UDT which can only be used in the PL/SQL layer you create a type in a program.

    An example of creating an object is shown on the left:

    AbsOluTEly TypICAl1/19 Patrick Barel

  • 34 OTech Magazine #3 May 2014

    To address the different fields in the UDT you use the dot notation (.).

    DECLARE l_person person_t := person_t ( John , Doe , to_date(12-29-1972,MM-DD-YYYY) , M );BEGIN l_person.first_name := Jane; l_person.gender := F;END;

    FunctionsYou can use the UDT as a parameter in for instance a function. This way you can send in a complete set of values as a single parameter instead of all separate parameters. This can help making your code not only more readable, but also a bit more self-documenting (provided you use a logi-cal name for the UDT). Note that a UDT can be both an IN and an OUT parameter.So, instead of creating a function like this:CREATE OR REPLACE FUNCTION display_label ( first_name_in IN VARCHAR2 , last_name_in IN VARCHAR2 , birthdate_in IN DATE , gender_in IN varchar2) RETURN VARCHAR2ISBEGIN RETURN CASE gender_in WHEN M THEN Mr. WHEN F THEN Mrs. END || || first_name_in || || last_name_in ||

    It looks a lot like the creation of a database table indicated on the right- but data in the UDT is not persisted unless you use a database table to store the data.

    The UDT can be used as the data type in the creation of a table just as you would use a scalar datatype:

    CREATE TABLE t_person( person person_t)

    Using a UDT doesnt make much sense here, but if we extend the type it will make more sense.

    Using the UDT in your PL/SQL code is a bit different from using a scalar data type. Instead of just declaring the variable and then using it you should instantiate (initialize) it, before you can use it. To instantiate the variable you call the constructor of the UDT. When you create a UDT, a default constructor is automatically created. This is called by sending in all the values for the properties to a function which has the same name as the UDT. After instantiating the variable it can be used like any other.

    CREATE OR REPLACE TYPE person_t AS OBJECT( first_name VARCHAR2(30), last_name VARCHAR2(30), birthdate DATE, gender VARCHAR2(1))

    CREATE TABLE t_person( first_name VARCHAR2(30), last_name VARCHAR2(30), birthdate DATE, gender VARCHAR2(1))

    AbsOluTEly TypICAl2/19 Patrick Barel

  • 35 OTech Magazine #3 May 2014

    Complex typesTypes can consist of other types. Suppose we have a UDT with the infor-mation for the social profile. It might look something like this:CREATE OR REPLACE TYPE social_profile_t AS OBJECT( linkedin_account VARCHAR2(100), twitter_account VARCHAR2(100), facebook_account VARCHAR2(100), personal_blog VARCHAR2(100))We can now extend our person type to include this social profile as an attribute:CREATE OR REPLACE TYPE person_t AS OBJECT( first_name VARCHAR2(30), last_name VARCHAR2(30), birthdate DATE, gender VARCHAR2(1), social_profile social_profile_t

    )The social profile is now nested inside the person type. Creating an instance of the person object gets a bit more complicated because the social profile has to be created as an instance itself:DECLARE l_person person_t := person_t ( John , Doe , to_date(12-29-1972,MM-DD-YYYY) , M , social_profile_t( JohnDoe , JohnTweets , JohnOnFacebook , http://johndoe.blogspot.com ) );BEGIN dbms_output.put_line(display_label(l_person)); dbms_output.put_line(l_person.social_profile.personal_blog);END;

    || ( || EXTRACT ( YEAR FROM birthdate_in) || );END;

    we can create a function like this:CREATE OR REPLACE FUNCTION display_label (person_in IN person_t) RETURN VARCHAR2ISBEGIN RETURN CASE person_in.gender WHEN M THEN Mr. WHEN F THEN Mrs. END || || person_in.first_name || || person_in.last_name || || ( || EXTRACT ( YEAR FROM person_in.birthdate) || );END;

    We can also call this function from SQL, like this:SELECT display_label(person_t ( John , Doe , to_date(12-29-1972,MM-DD-YYYY) , M ) ) FROM dual

    But it can also be used in PL/SQL, like this:DECLARE l_person person_t := person_t ( John , Doe , to_date(12-29-1972,MM-DD-YYYY) , M );BEGIN l_person.first_name := Jane; l_person.gender := F; dbms_output.put_line(display_label(l_person));END;

    AbsOluTEly TypICAl3/19 Patrick Barel

  • 36 OTech Magazine #3 May 2014

    Feature Associative Ar-ray

    Nested Table VArray

    SQL PL/SQL PL/SQL only SQL and PL/SQL SQL and PL/SQL

    Dense - Sparse

    Sparse Initially DenseCan become sparse

    Dense

    Size Unlimited Unlimited LimitedOrder Unordered Ordered OrderedUsage Any set of data Any set of data Small sets of

    dataUse in Table No Yes Yes

    Most important difference is that the Associative Array can only be used in PL/SQL, where the Nested Table and the VArray can be used in both SQL and PL/SQL. Because the collections can be used in SQL they can also be stored in tables. This is a bit against the normalization principle but it can make sense in some cases.An example of this could be a list of phone numbers. You create a type phone_t like this:

    CREATE OR REPLACE TYPE phone_t AS OBJECT( phone_type VARCHAR2(30), phone_nr VARCHAR2(30))

    Then you create a nested table based on this UDT:CREATE OR REPLACE TYPE phone_ntt AS TABLE OF phone_t

    As you can see in to example above, the function created still works. To access the values of the nested UDT you use the chained dot notation. First you point to the social profile attribute in the person variable and then within that social profile you point to the attribute you want to ac-cess.

    CollectionsBesides record type UDTs you can also create collections of instances of scalar or other, e.g. user defined, types. Collection are either sparse or dense arrays of homogeneous elements. You can think of them as tables (thats why the Associative Array used to be called PL/SQL Table). There are three types of collections available. Associative Array Nested Table VArray

    These collection types are similar though there are some differences as you can see in this table:

    AbsOluTEly TypICAl4/19 Patrick Barel

  • 37 OTech Magazine #3 May 2014

    tional table.

    Complex typesTypes can be as complex as you would want them to be. The can consist of scalars, other UDTs, Nested Tables, VArrays which in turn, except for the scalars, can consist of everything mentioned before. Consider the person UDT we created earlier, including the social profile. One of the properties can be a list of phone numbers, so we can add the Nested Table to the UDT. The nested table of phone numbers itself consists of UDTs with the phone type and the phone number as properties. CREATE OR REPLACE TYPE person_t AS OBJECT( first_name VARCHAR2(30), last_name VARCHAR2(30), birthdate DATE, gender VARCHAR2(1), social_profile social_profile_t, phone_numbers phone_ntt)

    Now that all is in place, the nested table can be used as a column in a normal table:CREATE TABLE persons( first_name VARCHAR2(30), last_name VARCHAR2(30), phone_nrs phone_ntt)NESTED TABLE phone_nrs STORE AS phone_nrs_ntt_tab

    Since we are using a nested table as a column and there is no way of telling how big this is going to become, you have to tell Oracle where to store the data. If you were using a VArray, then Oracle would know upfront how big it could become at maximum.To use a VArray instead of a nested table you would use this to create the VArray:CREATE OR REPLACE TYPE phone_vat AS VARRAY(10) OF phone_t

    And this for the table:CREATE TABLE persons( first_name VARCHAR2(30), last_name VARCHAR2(30), phone_nrs phone_vat)

    Storing Nested Tables or VArrays in a table feels a bit strange, especially when you are always normalizing your schema. It does make sense though when you are building a data warehouse or some sort of histori-cal data storage. You could for instance create a database table to hold both the invoice header information and all its invoice lines in a single record. In this case the invoice lines could be a Nested Table in the rela-

    INSERT INTO persons ( first_name , last_name , phone_nrs ) VALUES ( 'John' , 'Doe' , phone_ntt ( phone_t ( 'business' , '555-12345' ) , phone_t ( 'private' , '555-67890' ) ) )

    AbsOluTEly TypICAl5/19 Patrick Barel

  • 38 OTech Magazine #3 May 2014

    customer for instance may have a credit limit. For an employee we want to know what job he or she is in. We can of course create entirely differ-ent types based on their different usage, but that would mean we would have to create code that does basically the same at least two times. The Object Oriented way of approaching this would be that we create a UDT with the common properties and then create children of this UDT with the specific properties added. We create the UDT like we did before, but we add the keywords NOT FINAL indicating there can be children defined under this type.CREATE OR REPLACE TYPE person_t AS OBJECT( first_name VARCHAR2(30), last_name VARCHAR2(30), birthdate DATE, gender VARCHAR2(1), social_profile social_profile_t, phone_numbers phone_ntt) NOT FINAL

    Now we create the other two UDTs under this typeCREATE OR REPLACE TYPE employee_t UNDER person_t( ID NUMBER(10), NAME VARCHAR2(30), job VARCHAR2(30), department_id NUMBER(10), hiredate DATE, salary NUMBER(10,2))

    AndCREATE OR REPLACE TYPE customer_t UNDER person_t( company_name VARCHAR2(100), telephone_number VARCHAR2(15))

    The code gets a bit more complicated, but all the data is kept together.DECLARE l_person person_t := person_t( John , Doe , to_date(12-29-1972,MM-DD-YYYY) , M , social_profile_t( JohnDoe , JohnTweets , JohnOnFacebook , http://johndoe.blogspot.com ) , phone_ntt ( phone_t ( business , 555-12345 ) , phone_t ( private , 555-67890 ) ) );BEGIN dbms_output.put_line(display_label(l_person)); dbms_output.put_line(l_person.social_profile.personal_blog); dbms_output.put_line(l_person.phone_numbers(1).phone_nr);END;

    The last line displays the phone number that is stored in the first entry of the nested table.

    Type hierarchyTypes can be created as children of other types. For instance, a person can just a person or more specifically an employee or a customer. They share some of the properties, but some properties are very specific. A

    AbsOluTEly TypICAl6/19 Patrick Barel

  • 39 OTech Magazine #3 May 2014

    the specified type and not one of its subtypes. A customer is a person, but a person is not necessarily a customer.

    Using the TREAT (AS type) operator you cast the instance to a specific subtype. This way you can access the specific attributes that are only available in this subtype.CREATE OR REPLACE FUNCTION display_label (person_in IN person_t) RETURN VARCHAR2IS l_label VARCHAR2(32767); l_customer customer_t; l_employee employee_t;BEGIN l_label := CASE person_in.gender WHEN M THEN Mr. WHEN F THEN Mrs. END || || person_in.first_name || || person_in.last_name || || ( || EXTRACT ( YEAR FROM person_in.birthdate) || ); -- check what the actual type is of the parameter sent in CASE -- when it is a person_t and not one of the subtypes WHEN person_in IS OF (ONLY person_t) THEN NULL; -- when it is actually a customer_t WHEN person_in IS OF (customer_t) THEN l_customer := TREAT(person_in AS customer_t); l_label := l_label || of company ||l_customer.company_name; -- when it is actually an employee_t WHEN person_in IS OF (employee_t) THEN l_employee := TREAT(person_in AS employee_t); l_label := l_label || function: ||l_employee.job|| in department ||l_employee.department_id; END CASE; RETURN l_label;END;

    We use the keyword UNDER to indicate that this type should inherit all the properties of its specified parent type. The subtype created has multiple identities. For instance: The EMPLOYEE_T is both PERSON_T and EMPLOYEE_T. Any code created that can handle a PERSON_T can also handle an EMPLOYEE_T (and a CUSTOMER_T). But, besides handling the common properties, it is also possible to handle a subtype in a spe-cific manner. As we saw earlier we can send a subtype as a parameter to a program that expects its supertype. In the program, we can check what was actually sent in and run the appropriate code. Using the IS OF opera-tor you can check what is the actual type of the parameter that was sent in. If you add the keyword ONLY then you check for the parameter being

    AbsOluTEly TypICAl7/19 Patrick Barel

  • 40 OTech Magazine #3 May 2014

    access to the values of the properties of this instance. The instance is referenced using the SELF keyword, so a property is referenced as SELF.CREATE OR REPLACE TYPE person_t AS OBJECT( first_name VARCHAR2(30), last_name VARCHAR2(30), birthdate DATE, gender VARCHAR2(1), social_profile social_profile_t, phone_numbers phone_ntt, CONSTRUCTOR FUNCTION person_t RETURN SELF AS RESULT CONSTRUCTOR FUNCTION person_t(first_name_in IN VARCHAR2 ,last_name_in IN VARCHAR2 ,birthdate_in IN DATE ,gender_in IN VARCHAR2) RETURN SELF AS RESULT,, MEMBER FUNCTION display_label RETURN VARCHAR2) NOT FINAL

    This UDT has both constructors and a member function defined. We still have to provide the implementation for these functions, which is done in the BODY of the UDT:CREATE OR REPLACE TYPE BODY person_t AS CONSTRUCTOR FUNCTION person_t RETURN SELF AS RESULT IS BEGIN self.first_name := NULL; self.last_name := NULL; self.birthdate := NULL; self.gender := NULL; self.social_profile := NULL; self.phone_numbers := NULL; RETURN; END;

    CONSTRUCTOR FUNCTION person_t(first_name_in IN VARCHAR2 ,last_name_in IN VARCHAR2 ,birthdate_in IN DATE ,gender_in IN VARCHAR2) RETURN SELF AS

    Member functionsBesides creating a function that takes a UDT as a parameter, we can also define the function as part of the UDT. It is very OO to combine the data and the behavior of that data. The behavior is defined in the specification of the type and implemented in the body of the type. There are two main types of member functions. Constructor functions Normal member functions

    Constructor functionsWhen you instantiate a variable based on a UDT you call the constructor function. A default constructor function is always created for you, but you can add your own, overloaded, constructor functions to the type. The default constructor expects you to send in values for every property in the type. By creating (overloaded) constructors you can control what properties need to be set when initiating an instance. A good practice is to create a constructor without any parameters and to instantiate the variable with NULL values for all properties. But you can also create a constructor that takes just a couple of arguments and instantiates the rest of the properties with NULL values.

    Member functionsWe created a function that accepts a UDT as a parameter. We can also implement this function as a member function with the type. Instead of accepting a parameter with the instance of the type the code has

    AbsOluTEly TypICAl8/19 Patrick Barel

  • 41 OTech Magazine #3 May 2014

    den function we can reference the function defined in the super type by casting the UDT to its supertype:CREATE OR REPLACE TYPE customer_t UNDER person_t( company_name VARCHAR2(100), telephone_number VARCHAR2(15), OVERRIDING MEMBER FUNCTION display_label RETURN VARCHAR2)

    And then the implementation:CREATE OR REPLACE TYPE BODY customer_t AS OVERRIDING MEMBER FUNCTION display_label RETURN VARCHAR2 IS BEGIN RETURN (self AS person_t).display_label -- display label of the parent type || of company ||self.company_name; END;END;

    In this example we use the display_label function as defined on the super type and add some extra info to it.

    Map and Order functionsBy creating Map or Order functions we can use the UDT in the order by clause of a SQL statement. You can define either a Map or Order function, not both. In the order function you define the outcome of a comparison with another instance of the UDT. The function takes the other instance as an argument and returns -1 (when this instance comes first), 1 (when this instance comes last) or 0 (when they draw).

    If you can come up with a scalar value based on the properties that can be used to order the instances, then you can also create a map function,

    RESULT IS BEGIN self.first_name := first_name_in; self.last_name := last_name_in; self.birthdate := birthdate_in; self.gender := gender_in; self.social_profile := NULL; self.phone_numbers := NULL; RETURN; END;

    MEMBER FUNCTION display_label RETURN VARCHAR2 IS BEGIN RETURN CASE self.gender WHEN M THEN Mr. WHEN F THEN Mrs. END || || self.first_name || || self.last_name || || ( || extract(YEAR FROM self.birthdate) || ); END;END;

    If this UDT is created we can use it pretty much the same way we did earlier, but now we can call the member function display_label and we do not need a stand-alone function anymore.DECLARE l_person person_t := person_t( John , Doe , to_date(12-29-1972,MM-DD-YYYY) , M );BEGIN dbms_output.put_line(l_person.display_label);

    END;

    If we create a UDT under this base type, then the new UDT automatically inherits the member function. We can also override the behavior of the member function by OVERRIDING the member function. In this overrid-

    AbsOluTEly TypICAl9/19 Patrick Barel

  • 42 OTech Magazine #3 May 2014

    Traditional approach Bulk processing approachDECLARE CURSOR c_emp IS SELECT ename FROM emp; r_emp c_emp%ROWTYPE;BEGIN OPEN c_emp; FETCH c_emp INTO r_emp; WHILE c_emp%FOUND LOOP dbms_output.put_line(r_emp.ename); FETCH c_emp INTO r_emp; END LOOP; CLOSE c_emp;END;

    CREATE OR REPLACE TYPE enames_ntt AS TABLE OF VARCHAR2(10);

    DECLARE CURSOR c_emp IS SELECT ename FROM emp; l_emps enames_ntt;BEGIN OPEN c_emp; FETCH c_emp BULK COLLECT INTO l_emps; CLOSE c_emp; FOR indx IN l_emps.first .. l_emps.last LOOP dbms_output.put_line(l_emps(indx)); END LOOP;END;

    Table FunctionsAnother application of the collections is the creation of table functions. These are functions that return a collection (instead of a single value) and that can be queried from a SQL statement using the TABLE() operator. Using this approach you can leverage all the possibilities of the PL/SQL engine in the SQL engine. Be advised, that there are still context switches going on, so if you can solve your issue in plain SQL then that is the pre-ferred way.

    instead of the order function. This function is more efficient, because the order function has to be called repeatedly since it only compares two objects at a time, where the map function maps the object into a scalar value which is then used in the sort algorithm.

    Bulk ProcessingBesides creating UDTs that hold data for a specified object, you can also create sets of data. These sets can consist of scalars or even UDTs you created. This way you can work with the data as if it were relational tables, but actually they are in memory variables or values of the record that is stored in the database. The most important use for collections is probably the bulk processing. In traditional programming a cursor is opened, a record is fetched from it, the data is being processed and then onto the next record. Just as long as there are records available in the cursor. Every time a record is being fetched, there are two context switches. One from the PL/SQL Engine to the SQL engine and then one back. This Row-By-Row approach is also referred to as Slow-By-Slow. Using collections you can minimize the number of context switches be-cause multiple rows are collected and then returned in a single pass. This means all the data you selected in your cursor is available right away in the program you are running. This can have a major impact on the mem-ory usage, that is why you can limit the number of rows returned in one roundtrip. This means a little more coding, but the performance benefits are enormous.

    AbsOluTEly TypICAl10/19 Patrick Barel

  • 43 OTech Magazine #3 May 2014

    data. There are functions to retrieve an element at a specific path in the document but also functions to extract a portion of the xml document.

    There are numerous ways to construct XML in a database application. It can for instance be loaded from a file or created from an SQL statement using XML specific functions like XMLAgg, XMLElement, XMLForest and others. But it can also be instantiated based on another UDT instance.DECLARE l_person person_t := person_t( John , Doe , to_date(12-29-1972,MM-DD-YYYY) , M ); l_xml XMLTYPE;BEGIN l_xml := XMLTYPE(l_person); dbms_output.put_line(l_xml.getstringval);END;

    The output would be:

    John Doe 29-12-72 M

    If you would want to convert a nested table to XML you will need a wrap-per object. You cannot convert a Nested Table to XML directly. You can however convert a UDT which holds a nested table to XML.CREATE OR REPLACE TYPE persons_ntt IS TABLE OF person_t

    Create a wrapper UDT to convert the Nested Table to XML.CREATE OR REPLACE TYPE persons_wrap AS OBJECT( persons persons_ntt)

    First you create a collection type in the database. Notice that you can only use VArrays and Nested Tables for this, since these are the only ones available in the SQL layer:CREATE OR REPLACE TYPE enames_ntt AS TABLE OF VARCHAR2(10)

    Then you create the code that returns the collection:CREATE OR REPLACE FUNCTION scrambled_enames RETURN enames_nttIS CURSOR c_emp IS SELECT ename FROM emp; l_returnvalue enames_ntt;BEGIN OPEN c_emp; FETCH c_emp BULK COLLECT INTO l_returnvalue; CLOSE c_emp; FOR indx IN l_returnvalue.first .. l_returnvalue.last LOOP l_returnvalue(indx) := translate (abcdefghijklmnopqrs , srqponmlkjihgfedcba , l_returnvalue(indx) ) ; END LOOP; RETURN l_returnvalue;END;Then you query this function as if it were a relational table:SELECT * FROM TABLE(scrambled_enames)

    XMLXML is also stored in a specific type in the Oracle Database. Even though XML is just a plain text/ASCII file, which could be stored in a varchar2 type or (if it gets too big) in a clob type Oracle now provides us with the XML-Type. This is a specialized type for handling XML. Besides storing the XML content it also provides us with a lot of functions to manipulate the XML

    AbsOluTEly TypICAl11/19 Patrick Barel

  • 44 OTech Magazine #3 May 2014

    John Doe 29-12-72 M ); l_xml.toobject(l_person);END;

    Note that the tags should be in uppercase otherwise the conversion will fail. Not all properties have to be present in the XML. If a tag doesnt exist in the XML, the corresponding property will be NULL.

    JSONSometimes XML is a bit heavy. It is quite a verbose method to store the data. Every value in the document is surrounded by tags which tell us which field it is. This is where JSON may help. JSON consists of name-value-pairs. Where XML is written like this: John The JSON equivalent is: { FIRST_NAME : John }. Unfortunate-ly there is no support for JSON like there is for XML in the database yet. There is however an opensource library available that implements JSON functionality. There is no implementation (yet) to convert a UDT to JSON

    DECLARE l_persons persons_ntt := persons_ntt( person_t( John , Doe , to_date(12-29-1972,MM-DD-YYYY) , M) ,person_t( Jane , Doe , to_date(03-06-1976,MM-DD-YYYY) , F) ); l_xml XMLTYPE;BEGIN l_xml := XMLTYPE(persons_wrap(l_persons)); dbms_output.put_line(l_xml.getstringval);END;

    The output would be1:

    John Doe 29-12-72 M Jane Doe 06-03-76 F

    As you can convert a UDT to XML, it can also be done vice versa.DECLARE l_xml XMLTYPE; l_person person_t;BEGIN l_xml := XMLTYPE(

    AbsOluTEly TypICAl12/19 Patrick Barel

  • 45 OTech Magazine #3 May 2014

    tion developers will use SQL to access the database. However, in apply-ing some of the core concepts from Service Oriented Architecture and basic good programming practice we quickly realize that it may not be such a good idea to expose our data model so directly. Any change to the data model may directly impact many users of our database. Yet we do not want to be held back from creating improvements by such external consumers. Additionally, having 3rd parties fire off SQL statements to our database may result in pretty lousy SQL being executed which may lead to serious performance issues. When it comes to data manipulation there are even more reasons why direct access to our tables is undesirable. En-forcing complex data constraints and coordinating transaction logic are two important ones.

    So instead of allowing direct access to our tables, we should be thinking about publishing an API that encapsulates our data model and associated business logic and presents a third party friendly API. Using views on top of the data model is one way of implementing such an API, and if we use Instead Of triggers along with those views we can route any DML to PL/SQL packages that take care of business logic. Other options for imple-menting an API include the native database web service option that was introduced in Oracle Database 11g that allows us to publish SOAP Web Services from the database or use of the Embedded PL/SQL Gateway to expose simple HTTP services to be discussed a little bit later on. Note that APEX 4.x provides a lot of help for creating such RESTful services, as they are called.

    directly, but PL/JSON implements functionality to convert XML to JSON. Using XML as an intermediate step we can convert a UDT to JSON.

    DECLARE l_json json_list;BEGIN l_json := -- convert json_ml.xmlstr2json( -- a converted XML instance XMLTYPE ( -- of a UDT instance person_t( John , Doe , to_date(12-29-1972,MM-DD-YYYY) , M ) ).getstringval() ); l_json.print;END;[PERSON_T, [FIRST_NAME, John], [LAST_NAME, Doe], [BIRTHDATE, 29-12-72], [GENDER, M]]

    Publishing APIsExposing the functionality and data in our database to external consum-ers is a frequent challenge. Traditionally, many applications and applica-

    AbsOluTEly TypICAl13/19 Patrick Barel

  • 46 OTech Magazine #3 May 2014

    Despite all the data involved, the API itself can be very simple:

    PACKAGE music_api PROCEDURE search_for_cds ( p_cd_query IN cd_query_t , p_cd_collection OUT cd_collection_t );

    The complexity is hidden away in the definition of the UDTs involved:TYPE song_t AS OBJECT( title VARCHAR2(40), duration NUMBER(4,2))

    TYPE song_list_t AS TABLE OF song_t

    TYPE cd_t AS OBJECT( title VARCHAR2(40), year NUMBER(4), artist VARCHAR2(40), track_list song_list_t);

    TYPE cd_collection_t AS TABLE OF cd_t

    TYPE cd_query_t AS OBJECT( title VARCHAR2(40), from_year NUMBER(4), to_year NUMBER(4), artist VARCHAR2(40))

    TYPE song_t AS OBJECT( title VARCHAR2(40)

    Somewhere between the View approach and the HTTP based service way of thinking is the option of publishing a PL/SQL API. In this case, we use PL/SQL packages that define the public interface in their Specification and contain the firmly encapsulated implementation in their Body. Note that the Web Services will typically be just another layer on top of such a PL/SQL API.

    When the operations supported in the interface need to leverage com-plex, nested data structures such as an Order with Order Lines or a Hotel Booking with all guests sharing a room UDTs are the perfect vehicle to use. Using a single parameter, a complex data set can be transferred. Because UDTs support if not enforce a structured program-ming style inside the package body, the case for UDTs is even stronger. And, the database adapter that is frequently used in Oracle SOA Suite and Service Bus to integrate with the Oracle Database, knows very well how to interact with PL/SQL APIs based on UDTs. In fact, many organizations have adopted the use of UDT based PL/SQL APIs as their best practice for making SOA Suite & Service Bus interact with the Database.

    Lets take a look at an example of such a PL/SQL API. The API exposes a search operation through which consumers can lookup CDs. This search can be based on a number of search criteria currently title, artist, year range. The result of the search is a collection of CDs with for each CD data such as title and year of release and a listing of all songs. Per song, the title and the duration are included.

    AbsOluTEly TypICAl14/19 Patrick Barel

  • 47 OTech Magazine #3 May 2014

    er, working with UDTs is somewhat cumbersome in most cases. They are usually pretty good at XML processing though. One approach then is to add a wrapper around the UDT based API. This wrapper interacts in terms of XML and converts to and from the UDT based API.Such a wrapper could be as simple as:PROCEDURE search_for_cds( p_cd_query IN XMLTYPE, p_cd_collection OUT XMLTYPE) IS l_cd_query cd_query_t; l_cd_collection cd_collection_t;BEGIN p_cd_query.toobject(l_cd_query); search_for_cds ( p_cd_query => l_cd_query , p_cd_collection => l_cd_collection ); p_cd_collection := XMLTYPE(jukebox_t(l_cd_collection));END search_for_cds;

    Some technologies have a hard time dealing with XMLType structures and prefer to have their XML served in strings. That would call for anoth-er wrapper layer, that converts XMLType to and from VARCHAR2. Again, a simple feat to accomplish.

    , duration NUMBER(4,2))

    TYPE song_list_t AS TABLE OF song_t

    TYPE cd_t AS OBJECT( title VARCHAR2(40), year NUMBER(4), artist VARCHAR2(40), track_list song_list_t);

    TYPE cd_collection_t AS TABLE OF cd_t

    TYPE cd_query_t AS OBJECT( title VARCHAR2(40), from_year NUMBER(4), to_year NUMBER(4), artist VARCHAR2(40))

    Implementing this API should be fairly straightforward for seasoned PL/SQL programmers. An example implementation is available on this link: http://bit.ly/1dCNDnV.

    Interacting with such an API is also straightforward, from a number of environments at least. PL/SQL programs can of course invoke the Music API and process the results returned from it. The Database Adapter can also invoke the API and process results returned from it taking care of the conversion from and to XML that is the lingua franca inside the SOA Suite and Service Bus.

    Other technology settings may be able to interact with stored proce-dures, but may have a problem in dealing with UDTs. For example, Java programs can call stored procedures through most JDBC drivers. Howev-

    AbsOluTEly TypICAl15/19 Patrick Barel

  • 48 OTech Magazine #3 May 2014

    RESTful ServicesThere are many definitions in use for what RESTful services exactly are. We will not go into the intricacies of that theoretical debate. The es-sence is that a RESTful service exploits the core features of HTTP, can be accessed over HTTP using simple HTTP calls (plain old GET & POST, and GET & PUT for more advanced interaction). Messages exchanged with a RESTful service can be in any format, although XML and especially JSON are most common. RESTful services are stateless (do not remember a conversation, only the current question).

    RESTful services called for retrieving information are the simplest and by far the most common. When the provider of the service tries to main-tain a semblance of true RESTful-ness, such services are typically defined around resources and suggest a simple drill down navigation style. A sequence of RESTful calls in our world of Employees and Departments could look like this:

    PROCEDURE search_for_cds( p_cd_query IN CLOB, p_cd_collection OUT CLOB) IS l_cd_query XMLTYPE := XMLTYPE(p_cd_query); l_cd_collection XMLTYPE;BEGIN search_for_cds ( p_cd_query => l_cd_query , p_cd_collection => l_cd_collection ); p_cd_collection := l_cd_collection.getClobVal();END search_for_cds;

    Of course through the use of PL/JSON, it is quite easy to also expose a JSON based API. Converting from UDT through XMLType to JSON and vice versa is an out of the box operation with PL/JSON after all.

    AbsOluTEly TypICAl16/19 Patrick Barel

  • 49 OTech Magazine #3 May 2014

    The question then becomes: how to make such services with this style of URL composition available from PL/SQL. We need an underlying package HRM_API - that contains the following pseudo code: gather the requested data using SQL collect the data into an UDT convert the UDT to XML and perhaps onward to JSON write the converted result to the HTP buffer

    HTTP GET requests in the format shown in the table above are received by the Embedded PL/SQL Gateway (EPG) and have to be interpreted in order to result in a call to the HRM_API package with the appropriate parameters. Typically, an HTTP request handled by the Embedded PL/SQL Gateway looks something like:http://database_host:http_port/path/package.procedure?parameter1=value&parameter2=value

    To make the EPG work with the REST-style URL requires the use of a little known feature in the dbms_epg package. This is the same package used for creating the DAD database access descriptor that links a URL path to a database schema.

    HTTP GET request RESTful meaninghttp://HRM_SERVER/hrma-pi/rest/departments List of all Department resourceshttp://HRM_SERVER/hrma-pi/rest/departments/10 Details for resource Department with identifier 10http://HRM_SERVER/hrma-pi/rest/departments/10/employees List of all detail resources of type employee under Department re-source with identifier 10http://HRM_SERVER/hrma-pi/rest/departments/10/employees/4512(could perhaps also be ac-cessed as http://HRM_SERV-ER/hrmapi/rest/employ-ees/4512)

    Details for employee resource with identifier 4512

    The response to these calls will typically be a text message in either XML or JSON format. Such service calls can be made from virtually any tech-nology environment even from within a browser in JavaScript. All mod-ern day programming languages have ample support for making HTTP calls. That is one of the key reasons for their popularity.

    AbsOluTEly TypICAl17/19 Patrick Barel

  • 50 OTech Magazine #3 May 2014

    The signature of this procedure is very straightforward:procedure handle_request (p_path in varchar2);

    The parameter p_path will contain whatever comes in the URL after hrm-restapi/rest. Looking back to the table of RESTful URLs, the procedure may expect to have to deal with these values for p_path: /departments /departments/10 /departments/10/employees /departments/10/employees/4512 /employees/4512

    The article at http://bit.ly/1k3PjVx provides a complete example of the source code for dealing with these URLs and implementing the RESTful service.

    ConclusionWorking with User Defined Types not only simplifies your code, instead of sending five parameters, you can now send a single parameter with all five values in it, it can also speed up the interaction between PL/SQL and SQL, using the bulk operations. By adding behavior to the UDT you define logic as close to the data as you possibly can. Communicating with the outside world can also be done using UDTs, that way hiding the datamod-el and achieving a high level of decoupling.

    The statementbegin DBMS_EPG.create_dad ( dad_name => hrmrestapi , path => /hrmapi/* );end;creates a DAD called hrmrestapi that is associated with the path hrmapi. Subsequently, this DAD is authorized to a specific database schema, say SCOTT or HR.

    That then means that any HTTP request starting with http://database_host:http_port/hrmapiis routed to that database schema and expects to be handled by a pack-age in that schema. The additional step we need to take is to configure a special handler package that interprets the REST-style URL for us. We do so with a code like this:BEGIN dbms_epg.set_dad_attribute ( dad_name => hrmrestapi , attr_name => path-alias , attr_value => rest); dbms_epg.set_dad_attribute ( dad_name => hrmrestapi , attr_name => path-alias-procedure , attr_value => hr.hrm_rest_api.handle_request); END;

    Here we instruct the EPG to send any request that arrives on the hrm-restapi DAD and starts with rest (meaning: all requests like http://data-base_host:http_port/hrmapi/rest/andsomethingelseintheurl) to the handle_request procedure on the hrm_rest_api package.

    AbsOluTEly TypICAl18/19 Patrick Barel