<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;DUYARHg8fip7ImA9WhRRFE4.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867</id><updated>2011-11-28T10:39:05.676+11:00</updated><category term="JDeveloper" /><category term="11g database" /><category term="Materialized Views" /><category term="APEX" /><category term="Forms" /><category term="Context Index" /><category term="10g database" /><category term="SQL Developer" /><category term="ADF" /><title>Marc On Oracle</title><subtitle type="html">My experiences working with Oracle's databases and development tools.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://marc-on-oracle.blogspot.com/" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>19</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/MarcOnOracle" /><feedburner:info uri="marconoracle" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CUcCSH09fyp7ImA9Wx5REEU.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-8869397501532014360</id><published>2010-08-17T22:14:00.003+10:00</published><updated>2010-08-18T08:11:09.367+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-18T08:11:09.367+10:00</app:edited><title>OAUG Winner!</title><content type="html">So, I took the quiz (see the &lt;a href="http://www.oaug.org/portal/page?_pageid=1015,10111025&amp;amp;_dad=portal&amp;amp;_schema=PORTAL"&gt;20th Anniversary Trivia Challenge&lt;/a&gt;) put up by the Oracle Application User Group (OAUG) a couple of weeks ago, and suddenly I notice that I am the winner of a Nook eReader. That's good news, right?&lt;div&gt;Erm, it is a shame that the Barnes and Noble device does not allow you to purchase eBooks from an Australian IP address. That's bad news, right?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, they sent me an email saying that because of the difficulty in getting a Nook to Australia, they would instead give me a shopping gift card. Well, that is definitely good news, right?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Seems like my wife has already claimed and spent said gift voucher...&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-8869397501532014360?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/CDbCMCuKbg0Z-yvqZe4Z_xE8H0E/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CDbCMCuKbg0Z-yvqZe4Z_xE8H0E/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/CDbCMCuKbg0Z-yvqZe4Z_xE8H0E/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/CDbCMCuKbg0Z-yvqZe4Z_xE8H0E/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/w3q7TQM6AVw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/8869397501532014360/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=8869397501532014360" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/8869397501532014360?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/8869397501532014360?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/w3q7TQM6AVw/oaug-winner.html" title="OAUG Winner!" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2010/08/oaug-winner.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4ERHc4eSp7ImA9WxBbF0o.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-5557678549437896065</id><published>2010-03-16T10:56:00.002+11:00</published><updated>2010-03-17T08:11:45.931+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-17T08:11:45.931+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SQL Developer" /><title>SQL Developer - Search Source Code - now including Views!</title><content type="html">&lt;div&gt;I am attempting to promote Oracle's SQL Developer as a standard PL/SQL development tool, in order to reduce current spending on licences for Quest TOAD and SQL Navigator, within our organisation. &lt;/div&gt;&lt;div&gt;Most of my colleagues have managed to move across smoothly, with a few minor issues that will probably see us holding on to a number of TOAD licences for the heavy-users, while the majority should be able to work happily and productively with SQL Developer.&lt;/div&gt;&lt;div&gt;On of the main points of contention in the migration is the in-place editing of SQL results, but Oracle have acknowledged that request and should be fitting it into some future release.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;A fellow developer wanted to know if the Search Source Code report in SQL Developer included Trigger and View source. So I did a little bit of checking around and saw that Trigger code *was* included, but View code was not. So, off I went to see if anyone had created and published an extension that did what we wanted. A quick look at &lt;a href="http://htmldb.oracle.com/pls/otn/f?p=42626:16:2157259497674676::NO:::"&gt;SQL Developer Exchange&lt;/a&gt; brought back nothing, so I set about to create my own.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The tricky thing about Views (see all_views or user_views) is that the source is held as a LONG datatype, which doesn't play well with others. In this instance, I wanted to UNION the results from the standard Search Source Code output (which returns source lines as a VARCHAR2) with the View source, as well as finding the location of the Search criteria within the View source. Clearly a LONG and a VARCHAR2 will not UNION, nor can you SUBSTR or INSTR a LONG, so I had to implement a conversion of some sort. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;According to &lt;a href="http://asktom.oracle.com/pls/asktom/f?p=100:11:2970656783346843::::P11_QUESTION_ID:55212348054"&gt;Tom Kyte&lt;/a&gt; you can easily write a wrapper PL/SQL function to do that for you, but I am lazy (and didn't want to be placing conversion functions in multiple databases) so I began looking for a pre-existing routine that would do that for me. DBMS_METADATA to the rescue! &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Using DBMS_METADATA.GET_DDL gave me the full creation source for the View object, which was just great. But it returned a CLOB, which was not so great. Luckily DBMS_LOB gives us a SUBSTR method which would suit my needs, for display purposes. So, using these DBMS built-ins together, I now had the means to create a user-defined script for including View source within the Search Source Code report.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;And here is the final result, which I have placed up on SQL Developer Exchange: &lt;a href="http://htmldb.oracle.com/pls/otn/dbtools.report?p_id=3341"&gt;(Right-click and Save As)&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-5557678549437896065?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QRMXS7lUj-je8kfMYAayzUaYCn4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QRMXS7lUj-je8kfMYAayzUaYCn4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QRMXS7lUj-je8kfMYAayzUaYCn4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QRMXS7lUj-je8kfMYAayzUaYCn4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/8OTuAJtOqEY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/5557678549437896065/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=5557678549437896065" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/5557678549437896065?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/5557678549437896065?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/8OTuAJtOqEY/sql-developer-search-source-code-now.html" title="SQL Developer - Search Source Code - now including Views!" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2010/03/sql-developer-search-source-code-now.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEGR3Yyfyp7ImA9WxJUEU8.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-6105071223220624495</id><published>2009-07-09T11:08:00.004+10:00</published><updated>2009-07-09T16:23:46.897+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-09T16:23:46.897+10:00</app:edited><title>NVL, NVL2 and CASE</title><content type="html">&lt;div&gt;This blog is simply a note to myself as I attempted to use the NVL2  function in PL/SQL recently. Enjoy.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;Oracle's NVL is a great little function that you can use in SQL or PL/SQL to determine if an item is NULL.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SQL eg.&lt;br /&gt;&lt;pre name="code" class="sql"&gt;SELECT e.ename, NVL(m.ename, 'I AM DA BOSS!') manager&lt;br /&gt; FROM emp e, emp m&lt;br /&gt;WHERE e.mgr = m.empno (+)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;PL/SQL eg&lt;br /&gt;&lt;pre name="code" class="sql"&gt;DECLARE&lt;br /&gt; l_empty VARCHAR2(10);&lt;br /&gt;BEGIN&lt;br /&gt; dbms_output.put_line(NVL(l_empty, 'Forgot to init l_empty!'));&lt;br /&gt;END;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;And now (well, for a while, actually) Oracle have provided as with a new NVL2 function that allows us to translate a NULL value to another value completely.&lt;br /&gt;&lt;div&gt;SQL eg.&lt;br /&gt;&lt;pre name="code" class="sql"&gt;SELECT e.ename, NVL2(e.mgr, 'i am a peon', 'I AM DA BOSS!') who_am_i&lt;br /&gt; FROM emp e;&lt;br /&gt;&lt;/pre&gt;However, &lt;b&gt;the NVL2 function is not available in PL/SQL&lt;/b&gt;! Bah, how annoying! Try it and you will see:&lt;br /&gt;&lt;pre name="code" class="sql"&gt;DECLARE&lt;br /&gt; l_empty VARCHAR2(10);&lt;br /&gt;BEGIN&lt;br /&gt; dbms_output.put_line(NVL2(l_empty, 'Ahh, all safe..','Forgot to init l_empty!'));&lt;br /&gt;END;&lt;br /&gt;&lt;/pre&gt;... gives an error of:&lt;br /&gt;&lt;pre&gt;ERROR at line 4:&lt;br /&gt;ORA-06550: line 4, column 25:&lt;br /&gt;PLS-00201: identifier 'NVL2' must be declared&lt;br /&gt;ORA-06550: line 4, column 4:&lt;br /&gt;PL/SQL: Statement ignored&lt;br /&gt;&lt;/pre&gt;So, what can we do? Why, we can use the CASE statement in all instances!&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SQL eg.&lt;br /&gt;&lt;pre name="code" class="sql"&gt;SELECT e.ename, CASE&lt;br /&gt;                 WHEN m.ename IS NULL THEN 'I AM DA BOSS!'&lt;br /&gt;                 WHEN m.ename IS NOT NULL THEN 'i am a peon'&lt;br /&gt;               END manager&lt;br /&gt; FROM emp e, emp m&lt;br /&gt;WHERE e.mgr = m.empno (+)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;PL/SQL eg.&lt;/div&gt;&lt;div&gt;&lt;pre name="code" class="sql"&gt;DECLARE&lt;br /&gt; l_empty VARCHAR2(10);&lt;br /&gt;BEGIN&lt;br /&gt; dbms_output.put_line(CASE&lt;br /&gt;                       WHEN l_empty IS NOT NULL THEN 'Ahh, all safe..'&lt;br /&gt;                       WHEN l_empty IS NULL THEN 'Forgot to init l_empty!'&lt;br /&gt;                     END);&lt;br /&gt;END;&lt;br /&gt;&lt;/pre&gt;There is a lot more to type, but it may just be a little more readable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-6105071223220624495?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/_Y9bBm_8CgoLWMrYGMoVr2CheVM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_Y9bBm_8CgoLWMrYGMoVr2CheVM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/_Y9bBm_8CgoLWMrYGMoVr2CheVM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/_Y9bBm_8CgoLWMrYGMoVr2CheVM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/zUm6PAKntxg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/6105071223220624495/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=6105071223220624495" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/6105071223220624495?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/6105071223220624495?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/zUm6PAKntxg/nvl-nvl2-and-case.html" title="NVL, NVL2 and CASE" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2009/07/nvl-nvl2-and-case.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQBRXk5eCp7ImA9WxJUEE0.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-3116406727052376462</id><published>2009-07-07T16:27:00.003+10:00</published><updated>2009-07-08T07:32:34.720+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-08T07:32:34.720+10:00</app:edited><title>SQLUnit - PL/SQL Unit Testing using a JUnit Framework.</title><content type="html">&lt;div&gt;For those who come from a purely SQL and PL/SQL background and enter the world of Java programming, there are many sights and sounds to behold, and wonders to experience. Entering the world of Java programming may be the first time you are exposed to the concept of programming frameworks. Frameworks exist as a base supporting structure where you can slot elements of development while being comfortable in the fact that anyone who comes along in the future can pick up your code and 'know' where everything is, assuming they are familiar with the particular framework you used.&lt;/div&gt;&lt;div&gt;Many frameworks eventually become open-sourced as developers collaborate on the definition of the framework.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Code Frameworks examples&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Spring&lt;/li&gt;&lt;li&gt;ADF&lt;/li&gt;&lt;/ul&gt;Build/Deployment Frameworks examples&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Ant&lt;/li&gt;&lt;li&gt;Maven&lt;/li&gt;&lt;/ul&gt;Testing Frameworks example&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Java - JUnit&lt;/li&gt;&lt;li&gt;PL/SQL - utPLSQL, PLUTO, SQLUnit&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;utPLSQL and PLUTO both require extra database objects to be installed/created. These are then used to call your PL/SQL to be tested.&lt;br /&gt;&lt;br /&gt;SQLUnit can be run as a Java application, or incorporated into an ant script as part of an automated build.&lt;br /&gt;Since it uses Java, the database connection uses JDBC. At the outset, this warns that there may be limitations on testing program units that require or output Oracle BOOLEAN variables or PL/SQL type structures. All other types should be usable.&lt;br /&gt;(The following examples use an 11g database and the ojdbc5_g.jar jdbc database driver.)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Basic SELECT&lt;/b&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;sqlunit&amp;gt;&lt;br /&gt;&amp;lt;connection&amp;gt;&lt;br /&gt;&amp;lt;driver&amp;gt;oracle.jdbc.driver.OracleDriver&amp;lt;/driver&amp;gt;&lt;br /&gt;&amp;lt;url&amp;gt;jdbc:oracle:thin:@localhost:1521:orcl&amp;lt;/url&amp;gt;&lt;br /&gt;&amp;lt;user&amp;gt;scott&amp;lt;/user&amp;gt;&lt;br /&gt;&amp;lt;password&amp;gt;tiger&amp;lt;/password&amp;gt;&lt;br /&gt;&amp;lt;/connection&amp;gt;&lt;br /&gt;&amp;lt;test name="#1 Simple SELECT - SELECT count(*) FROM emp" failure-message="Error with Simple SELECT"&amp;gt;&lt;br /&gt;&amp;lt;sql&amp;gt;&lt;br /&gt;  &amp;lt;stmt&amp;gt;select count(*) from emp&amp;lt;/stmt&amp;gt;&lt;br /&gt;&amp;lt;/sql&amp;gt;&lt;br /&gt;&amp;lt;result&amp;gt;&lt;br /&gt;  &amp;lt;resultset id="1"&amp;gt;&lt;br /&gt;    &amp;lt;row id="1"&amp;gt;&lt;br /&gt;      &amp;lt;col id="1" name="c1" type="NUMERIC"&amp;gt;14&amp;lt;/col&amp;gt;&lt;br /&gt;    &amp;lt;/row&amp;gt;&lt;br /&gt;  &amp;lt;/resultset&amp;gt;&lt;br /&gt;&amp;lt;/result&amp;gt;&lt;br /&gt;&amp;lt;/test&amp;gt;&lt;br /&gt;&amp;lt;/sqlunit&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight:bold;"&gt;Basic procedure call&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Given procedure exists:&lt;br /&gt;&lt;pre&gt;CREATE OR REPLACE PROCEDURE get_emp_name(p_empno IN NUMBER,&lt;br /&gt;                                       p_empname OUT VARCHAR2)&lt;br /&gt;AS&lt;br /&gt;CURSOR emp_csr&lt;br /&gt;IS&lt;br /&gt;  SELECT ename&lt;br /&gt;     FROM emp&lt;br /&gt;   WHERE empno = p_empno;&lt;br /&gt;BEGIN&lt;br /&gt;OPEN emp_csr;&lt;br /&gt;FETCH emp_csr INTO p_empname;&lt;br /&gt;CLOSE emp_csr;&lt;br /&gt;END get_emp_name;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Test case would be:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;sqlunit&amp;gt;&lt;br /&gt;&amp;lt;connection&amp;gt;&lt;br /&gt;&amp;lt;driver&amp;gt;oracle.jdbc.driver.OracleDriver&amp;lt;/driver&amp;gt;&lt;br /&gt;&amp;lt;url&amp;gt;jdbc:oracle:thin:@localhost:1521:orcl&amp;lt;/url&amp;gt;&lt;br /&gt;&amp;lt;user&amp;gt;scott&amp;lt;/user&amp;gt;&lt;br /&gt;&amp;lt;password&amp;gt;tiger&amp;lt;/password&amp;gt;&lt;br /&gt;&amp;lt;/connection&amp;gt;&lt;br /&gt;&amp;lt;test name="#2 Simple PROC call" failure-message="Error with Simple PROC call"&amp;gt;&lt;br /&gt;&amp;lt;call&amp;gt;&lt;br /&gt;  &amp;lt;stmt&amp;gt;{call get_emp_name(?,?)}&amp;lt;/stmt&amp;gt;&lt;br /&gt;  &amp;lt;param id="1" name="p_empno" type="INTEGER" inout="in"&amp;gt;7934&amp;lt;/param&amp;gt;&lt;br /&gt;  &amp;lt;param id="2" name="p_empname" type="VARCHAR" inout="out"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&amp;lt;/call&amp;gt;&lt;br /&gt;&amp;lt;result&amp;gt;&lt;br /&gt;  &amp;lt;outparam id="2" type="VARCHAR"&amp;gt;MILLER&amp;lt;/outparam&amp;gt;&lt;br /&gt;&amp;lt;/result&amp;gt;&lt;br /&gt;&amp;lt;/test&amp;gt;&lt;br /&gt;&amp;lt;/sqlunit&amp;gt;&lt;br /&gt;&lt;/pre&gt;Note that INTEGER is used for translating PL/SQL NUMBER types.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Basic function call&lt;/span&gt;&lt;br /&gt;Given function exists:&lt;br /&gt;&lt;pre&gt;CREATE OR REPLACE FUNCTION get_dept_name(p_deptno IN NUMBER)&lt;br /&gt;RETURN VARCHAR2&lt;br /&gt;AS&lt;br /&gt;CURSOR dept_csr&lt;br /&gt;IS&lt;br /&gt;  SELECT dname&lt;br /&gt;    FROM dept&lt;br /&gt;   WHERE deptno = p_deptno;&lt;br /&gt;l_dname dept.dname%TYPE;&lt;br /&gt;BEGIN&lt;br /&gt;OPEN dept_csr;&lt;br /&gt;FETCH dept_csr INTO l_dname;&lt;br /&gt;CLOSE dept_csr;&lt;br /&gt;RETURN l_dname;&lt;br /&gt;END get_dept_name;&lt;br /&gt;&lt;/pre&gt;Test case would be:&lt;br /&gt;&lt;pre&gt;&amp;lt;sqlunit&amp;gt;&lt;br /&gt;&amp;lt;connection&amp;gt;&lt;br /&gt;&amp;lt;driver&amp;gt;oracle.jdbc.driver.OracleDriver&amp;lt;/driver&amp;gt;&lt;br /&gt;&amp;lt;url&amp;gt;jdbc:oracle:thin:@localhost:1521:orcl&amp;lt;/url&amp;gt;&lt;br /&gt;&amp;lt;user&amp;gt;scott&amp;lt;/user&amp;gt;&lt;br /&gt;&amp;lt;password&amp;gt;tiger&amp;lt;/password&amp;gt;&lt;br /&gt;&amp;lt;/connection&amp;gt;&lt;br /&gt;&amp;lt;test name="#3 Simple FUNCTION call" failure-message="Error with Simple FUNCTION call"&amp;gt;&lt;br /&gt;&amp;lt;call&amp;gt;&lt;br /&gt;  &amp;lt;stmt&amp;gt;{? = call get_dept_name(?)}&amp;lt;/stmt&amp;gt;&lt;br /&gt;  &amp;lt;param id="1" name="p_out" type="VARCHAR" inout="out"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;  &amp;lt;param id="2" name="p_deptno" type="INTEGER" inout="in"&amp;gt;10&amp;lt;/param&amp;gt;&lt;br /&gt;&amp;lt;/call&amp;gt;&lt;br /&gt;&amp;lt;result&amp;gt;&lt;br /&gt;  &amp;lt;outparam id="1" name="p_out" type="VARCHAR"&amp;gt;ACCOUNTING&amp;lt;/outparam&amp;gt;&lt;br /&gt;&amp;lt;/result&amp;gt;&lt;br /&gt;&amp;lt;/test&amp;gt;&lt;br /&gt;&amp;lt;/sqlunit&amp;gt;&lt;br /&gt;&lt;/pre&gt;Note that the return value is always the first parameter when calling a function.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Basic Function returning Cursor&lt;/span&gt;&lt;br /&gt;Given Function exists:&lt;br /&gt;&lt;pre&gt;CREATE OR REPLACE FUNCTION get_all_emps&lt;br /&gt;RETURN SYS_REFCURSOR&lt;br /&gt;IS&lt;br /&gt;my_csr SYS_REFCURSOR;&lt;br /&gt;BEGIN&lt;br /&gt;OPEN my_csr FOR&lt;br /&gt;  SELECT *&lt;br /&gt;     FROM emp&lt;br /&gt;  ORDER BY empno;&lt;br /&gt;RETURN my_csr;&lt;br /&gt;END get_all_emps;&lt;br /&gt;&lt;/pre&gt;Test case would be:&lt;br /&gt;&lt;pre&gt;&amp;lt;test name="#4 FUNCTION call returning CURSOR" failure-message="Error with FUNCTION call returning CURSOR"&amp;gt;&lt;br /&gt;&amp;lt;call&amp;gt;&lt;br /&gt;  &amp;lt;stmt&amp;gt;{? = call get_all_emps}&amp;lt;/stmt&amp;gt;&lt;br /&gt;  &amp;lt;param id="1" name="p_out" type="CURSOR" inout="out"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&amp;lt;/call&amp;gt;&lt;br /&gt;&amp;lt;result&amp;gt;&lt;br /&gt;  &amp;lt;outparam id="1" name="p_out" type="CURSOR"&amp;gt;&lt;br /&gt;    &amp;lt;resultset id="1"&amp;gt;&lt;br /&gt;      &amp;lt;row id="1"&amp;gt;&lt;br /&gt;        &amp;lt;col id="1" name="EMPNO" type="NUMERIC"&amp;gt;7369&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="2" name="ENAME" type="VARCHAR"&amp;gt;SMITH&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="3" name="JOB" type="VARCHAR"&amp;gt;CLERK&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="4" name="MGR" type="NUMERIC"&amp;gt;7902&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="5" name="HIREDATE" type="TIMESTAMP"&amp;gt;1980-12-17 00:00:00.000&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="6" name="SAL" type="NUMERIC"&amp;gt;800&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="7" name="COMM" type="NUMERIC"&amp;gt;NULL&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="8" name="DEPTNO" type="NUMERIC"&amp;gt;20&amp;lt;/col&amp;gt;&lt;br /&gt;      &amp;lt;/row&amp;gt;&lt;br /&gt;      &amp;lt;row id="2"&amp;gt;&lt;br /&gt;        &amp;lt;col id="1" name="EMPNO" type="NUMERIC"&amp;gt;7499&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="2" name="ENAME" type="VARCHAR"&amp;gt;ALLEN&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="3" name="JOB" type="VARCHAR"&amp;gt;SALESMAN&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="4" name="MGR" type="NUMERIC"&amp;gt;7698&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="5" name="HIREDATE" type="TIMESTAMP"&amp;gt;1981-02-20 00:00:00.000&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="6" name="SAL" type="NUMERIC"&amp;gt;1600&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="7" name="COMM" type="NUMERIC"&amp;gt;300&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="8" name="DEPTNO" type="NUMERIC"&amp;gt;30&amp;lt;/col&amp;gt;&lt;br /&gt;      &amp;lt;/row&amp;gt;&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;      &amp;lt;row id="14"&amp;gt;&lt;br /&gt;        &amp;lt;col id="1" name="EMPNO" type="NUMERIC"&amp;gt;7934&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="2" name="ENAME" type="VARCHAR"&amp;gt;MILLER&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="3" name="JOB" type="VARCHAR"&amp;gt;CLERK&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="4" name="MGR" type="NUMERIC"&amp;gt;7782&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="5" name="HIREDATE" type="TIMESTAMP"&amp;gt;1982-01-23 00:00:00.000&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="6" name="SAL" type="NUMERIC"&amp;gt;1300&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="7" name="COMM" type="NUMERIC"&amp;gt;NULL&amp;lt;/col&amp;gt;&lt;br /&gt;        &amp;lt;col id="8" name="DEPTNO" type="NUMERIC"&amp;gt;10&amp;lt;/col&amp;gt;&lt;br /&gt;      &amp;lt;/row&amp;gt;&lt;br /&gt;    &amp;lt;/resultset&amp;gt;&lt;br /&gt;  &amp;lt;/outparam&amp;gt;&lt;br /&gt;&amp;lt;/result&amp;gt;&lt;br /&gt;&amp;lt;/test&amp;gt;&lt;/pre&gt;&lt;span style="font-weight:bold;"&gt;Function returning Simple Oracle UDT&lt;/span&gt;&lt;br /&gt;Given Type exists:&lt;br /&gt;&lt;pre&gt;CREATE OR REPLACE TYPE empRec AS OBJECT&lt;br /&gt;(EMPNO  NUMBER(4),&lt;br /&gt;ENAME  VARCHAR2(10),&lt;br /&gt;JOB      VARCHAR2(9),&lt;br /&gt;MGRNO NUMBER(4),&lt;br /&gt;MGRNAME VARCHAR2(10),&lt;br /&gt;SAL      NUMBER(7,2),&lt;br /&gt;COMM   NUMBER(7,2),&lt;br /&gt;DEPTNO NUMBER(2),&lt;br /&gt;DNAME  VARCHAR2(14));&lt;br /&gt;&lt;/pre&gt;Given Function exists:&lt;br /&gt;&lt;pre&gt;CREATE OR REPLACE FUNCTION get_emp_details(p_empNo IN NUMBER)&lt;br /&gt;RETURN empRec&lt;br /&gt;IS&lt;br /&gt;CURSOR emp_csr&lt;br /&gt;IS&lt;br /&gt;  SELECT empRec(&lt;br /&gt;               e.empno,&lt;br /&gt;               e.ename,&lt;br /&gt;               e.job,&lt;br /&gt;               e.mgr,&lt;br /&gt;               e2.ename,&lt;br /&gt;               e.sal,&lt;br /&gt;               e.comm,&lt;br /&gt;               e.deptno,&lt;br /&gt;               get_dept_name(e.deptno))&lt;br /&gt;     FROM emp e, emp e2&lt;br /&gt;   WHERE e.empno = p_empNo&lt;br /&gt;       AND e.mgr = e2.empno (+);&lt;br /&gt;l_emp empRec;&lt;br /&gt;BEGIN&lt;br /&gt;OPEN emp_csr;&lt;br /&gt;FETCH emp_csr INTO l_emp;&lt;br /&gt;CLOSE emp_csr;&lt;br /&gt;RETURN l_emp;&lt;br /&gt;END get_emp_details;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For this test case, we need to tell SQLUnit how to handle the new Oracle UDT, so we fire up JDeveloper (or JPublisher, I suppose). Create a connection to the database, using the schema that owns the UDT. &lt;b&gt;Immense THANKS to the OracleNerd (&lt;a href="http://www.oraclenerd.com/"&gt;www.oraclenerd.com&lt;/a&gt;) for pointing this out&lt;/b&gt; to me. I was stumbling around for a while, trying to figure out how to construct these Type Classes, and he came to the rescue with this easy method.&lt;br /&gt;&lt;br /&gt;JDeveloper (I used 10.1.3.3) allows us to automatically generate Java classes for accessing our UDTs from Java. Perform this step for each of your UDTs, and package them together in a JAR. Place the JAR in the lib directory.&lt;br /&gt;&lt;br /&gt;To reference the generated classes, the &amp;lt;connection&amp;gt; tag needs to be changed to include type-mapping tags to allow SQLUnit to determine which classes to use for which UDTs.&lt;br /&gt;In this case, the test will look like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&amp;lt;sqlunit&amp;gt;&lt;br /&gt;&amp;lt;connection&amp;gt;&lt;br /&gt;&amp;lt;driver&amp;gt;oracle.jdbc.driver.OracleDriver&amp;lt;/driver&amp;gt;&lt;br /&gt;&amp;lt;url&amp;gt;jdbc:oracle:thin:@localhost:1521:orcl&amp;lt;/url&amp;gt;&lt;br /&gt;&amp;lt;user&amp;gt;scott&amp;lt;/user&amp;gt;&lt;br /&gt;&amp;lt;password&amp;gt;tiger&amp;lt;/password&amp;gt;&lt;br /&gt;&amp;lt;typemap&amp;gt;&lt;br /&gt;  &amp;lt;typedef typename="SCOTT.EMPREC"&lt;br /&gt;    classname="net.sourceforge.sqlunit.types.Emprec" /&amp;gt;&lt;br /&gt;&amp;lt;/typemap&amp;gt;&lt;br /&gt;&amp;lt;/connection&amp;gt;&lt;br /&gt;&amp;lt;test name="#5 FUNCTION returning simple UDT" failure-message="Error with FUNCTION returning simple UDT"&amp;gt;&lt;br /&gt;&amp;lt;call&amp;gt;&lt;br /&gt;  &amp;lt;stmt&amp;gt;{? = call get_emp_details(?)}&amp;lt;/stmt&amp;gt;&lt;br /&gt;  &amp;lt;param id="1" name="p_out" type="STRUCT" typename="SCOTT.EMPREC" inout="out"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;  &amp;lt;param id="2" name="p_empno" type="INTEGER" inout="in"&amp;gt;7839&amp;lt;/param&amp;gt;&lt;br /&gt;&amp;lt;/call&amp;gt;&lt;br /&gt;&amp;lt;result&amp;gt;&lt;br /&gt;  &amp;lt;outparam id="1" name="p_out" type="STRUCT"&amp;gt;&lt;br /&gt;    &amp;lt;struct&amp;gt;&lt;br /&gt;      &amp;lt;field name="comm"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="deptno"&amp;gt;10&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="dname"&amp;gt;ACCOUNTING&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="empno"&amp;gt;7839&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="ename"&amp;gt;KING&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="job"&amp;gt;PRESIDENT&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="mgrname"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="mgrno"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="sal"&amp;gt;5000&amp;lt;/field&amp;gt;&lt;br /&gt;    &amp;lt;/struct&amp;gt;&lt;br /&gt;  &amp;lt;/outparam&amp;gt;&lt;br /&gt;&amp;lt;/result&amp;gt;&lt;br /&gt;&amp;lt;/test&amp;gt;&lt;br /&gt;&amp;lt;/sqlunit&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that the struct (UDT) elements are order alphabetically. This is done to provide easier matching of the UDT data structure. Also note that the element names are in lower-case.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Function returning Table Oracle UDT&lt;/span&gt;&lt;br /&gt;Given Type exists:&lt;br /&gt;CREATE TYPE t_empRec AS TABLE OF empRec;&lt;br /&gt;&lt;br /&gt;Given Function exists:&lt;br /&gt;&lt;pre&gt;CREATE OR REPLACE FUNCTION get_dept_emp_details(p_deptno IN NUMBER)&lt;br /&gt;RETURN t_empRec&lt;br /&gt;IS&lt;br /&gt;CURSOR emp_csr&lt;br /&gt;IS&lt;br /&gt;  SELECT empRec(&lt;br /&gt;               e.empno,&lt;br /&gt;               e.ename,&lt;br /&gt;               e.job,&lt;br /&gt;               e.mgr,&lt;br /&gt;               e2.ename,&lt;br /&gt;               e.sal,&lt;br /&gt;               e.comm,&lt;br /&gt;               e.deptno,&lt;br /&gt;               get_dept_name(e.deptno))&lt;br /&gt;     FROM emp e, emp e2&lt;br /&gt;   WHERE e.mgr = e2.empno (+)&lt;br /&gt;       AND e.deptno = p_deptno;&lt;br /&gt;l_emp t_empRec;&lt;br /&gt;BEGIN&lt;br /&gt;OPEN emp_csr;&lt;br /&gt;FETCH emp_csr BULK COLLECT INTO l_emp;&lt;br /&gt;CLOSE emp_csr;&lt;br /&gt;RETURN l_emp;&lt;br /&gt;END get_dept_emp_details;&lt;br /&gt;&lt;/pre&gt;Generate the Java Class for the Table UDT, and insert it into the appropriate JAR.&lt;br /&gt;Add a typemapping to the &amp;lt;connection&amp;gt; tag&lt;br /&gt;&lt;pre&gt;    &amp;lt;typedef typename="SCOTT.T_EMPREC"&lt;br /&gt;    classname="net.sourceforge.sqlunit.types.TEmprec" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;The test case will then be structured like this:&lt;br /&gt;&lt;pre&gt;&amp;lt;test name="#6 FUNCTION returning table UDT" failure-message="Error with FUNCTION returning table UDT"&amp;gt;&lt;br /&gt;&amp;lt;call&amp;gt;&lt;br /&gt;  &amp;lt;stmt&amp;gt;{? = call get_dept_emp_details}&amp;lt;/stmt&amp;gt;&lt;br /&gt;  &amp;lt;param id="1" name="p_out" type="STRUCT" typename="SCOTT.T_EMPREC" inout="out"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;  &amp;lt;param id="2" name="p_deptno" type="INTEGER" inout="in"&amp;gt;10&amp;lt;/param&amp;gt;&lt;br /&gt;&amp;lt;/call&amp;gt;&lt;br /&gt;&amp;lt;result&amp;gt;&lt;br /&gt;  &amp;lt;outparam id="1" name="p_out" type="STRUCT"&amp;gt;&lt;br /&gt;        &amp;lt;struct&amp;gt;&lt;br /&gt;          &amp;lt;field name="comm"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="deptno"&amp;gt;10&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="dname"&amp;gt;ACCOUNTING&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="empno"&amp;gt;7934&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="ename"&amp;gt;MILLER&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="job"&amp;gt;CLERK&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="mgrname"&amp;gt;CLARK&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="mgrno"&amp;gt;7782&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="sal"&amp;gt;1300&amp;lt;/field&amp;gt;&lt;br /&gt;        &amp;lt;/struct&amp;gt;&lt;br /&gt;      &amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="array"&amp;gt;&lt;br /&gt;        &amp;lt;struct&amp;gt;&lt;br /&gt;          &amp;lt;field name="comm"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="deptno"&amp;gt;10&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="dname"&amp;gt;ACCOUNTING&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="empno"&amp;gt;7782&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="ename"&amp;gt;CLARK&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="job"&amp;gt;MANAGER&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="mgrname"&amp;gt;KING&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="mgrno"&amp;gt;7839&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="sal"&amp;gt;2450&amp;lt;/field&amp;gt;&lt;br /&gt;        &amp;lt;/struct&amp;gt;&lt;br /&gt;      &amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="array"&amp;gt;&lt;br /&gt;        &amp;lt;struct&amp;gt;&lt;br /&gt;          &amp;lt;field name="comm"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="deptno"&amp;gt;10&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="dname"&amp;gt;ACCOUNTING&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="empno"&amp;gt;7839&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="ename"&amp;gt;KING&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="job"&amp;gt;PRESIDENT&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="mgrname"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="mgrno"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="sal"&amp;gt;5000&amp;lt;/field&amp;gt;&lt;br /&gt;        &amp;lt;/struct&amp;gt;&lt;br /&gt;  &amp;lt;/outparam&amp;gt;&lt;br /&gt;&amp;lt;/result&amp;gt;&lt;br /&gt;&amp;lt;/test&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;span style="font-weight:bold;"&gt;Function returning Complex Oracle UDT&lt;/span&gt;&lt;br /&gt;Given Type exists:&lt;br /&gt;&lt;pre&gt;CREATE TYPE deptRec AS OBJECT&lt;br /&gt;(DEPTNO    NUMBER(2),&lt;br /&gt;DNAME     VARCHAR2(14),&lt;br /&gt;EMPS      t_EmpRec,&lt;br /&gt;LOC       VARCHAR2(13),&lt;br /&gt;SALSUM    NUMBER(7,2));&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Given Function exists:&lt;br /&gt;&lt;pre&gt;CREATE OR REPLACE FUNCTION get_dept_details(p_deptno IN NUMBER)&lt;br /&gt;RETURN deptRec&lt;br /&gt;IS&lt;br /&gt;CURSOR dept_csr&lt;br /&gt;IS&lt;br /&gt;  SELECT deptRec(&lt;br /&gt;                 d.deptNo,&lt;br /&gt;                 d.dname,&lt;br /&gt;                 get_dept_emp_details(d.deptno),&lt;br /&gt;                 d.loc,&lt;br /&gt;                 sum(e.sal))&lt;br /&gt;     FROM dept d, emp e&lt;br /&gt;   WHERE d.deptno = p_deptno&lt;br /&gt;       AND d.deptno = e.deptno (+)&lt;br /&gt;    GROUP BY d.deptno, d.dname, d.loc;&lt;br /&gt;l_dept deptRec;&lt;br /&gt;BEGIN&lt;br /&gt;OPEN dept_csr;&lt;br /&gt;FETCH dept_csr INTO l_dept;&lt;br /&gt;CLOSE dept_csr;&lt;br /&gt;RETURN l_dept;&lt;br /&gt;END get_dept_details;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Generate the Java Class for the dept UDT, and insert it into the appropriate JAR.&lt;br /&gt;Add a typemapping to the &amp;lt;connection&amp;gt; tag&lt;br /&gt;&lt;pre&gt;    &amp;lt;typedef typename="SCOTT.DEPTREC"&lt;br /&gt;    classname="net.sourceforge.sqlunit.types.Deptrec" /&amp;gt;&lt;br /&gt;&lt;/pre&gt;The test case will then be structured like this:&lt;br /&gt;&lt;pre&gt;&amp;lt;test name="#7 FUNCTION returning complex UDT" failure-message="Error with FUNCTION returning complex UDT"&amp;gt;&lt;br /&gt;&amp;lt;call&amp;gt;&lt;br /&gt;  &amp;lt;stmt&amp;gt;{? = call get_dept_details(?)}&amp;lt;/stmt&amp;gt;&lt;br /&gt;  &amp;lt;param id="1" name="p_out" type="STRUCT" typename="SCOTT.DEPTREC" inout="out"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;  &amp;lt;param id="2" name="p_deptno" type="INTEGER" inout="in"&amp;gt;10&amp;lt;/param&amp;gt;&lt;br /&gt;&amp;lt;/call&amp;gt;&lt;br /&gt;&amp;lt;result&amp;gt;&lt;br /&gt;  &amp;lt;outparam id="1" name="p_out" type="STRUCT"&amp;gt;&lt;br /&gt;    &amp;lt;struct&amp;gt;&lt;br /&gt;      &amp;lt;field name="deptno"&amp;gt;10&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="dname"&amp;gt;ACCOUNTING&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="emps"&amp;gt;&lt;br /&gt;        &amp;lt;struct&amp;gt;&lt;br /&gt;          &amp;lt;field name="array"&amp;gt;&lt;br /&gt;            &amp;lt;struct&amp;gt;&lt;br /&gt;              &amp;lt;field name="comm"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="deptno"&amp;gt;10&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="dname"&amp;gt;ACCOUNTING&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="empno"&amp;gt;7934&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="ename"&amp;gt;MILLER&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="job"&amp;gt;CLERK&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="mgrname"&amp;gt;CLARK&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="mgrno"&amp;gt;7782&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="sal"&amp;gt;1300&amp;lt;/field&amp;gt;&lt;br /&gt;            &amp;lt;/struct&amp;gt;&lt;br /&gt;          &amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="array"&amp;gt;&lt;br /&gt;            &amp;lt;struct&amp;gt;&lt;br /&gt;              &amp;lt;field name="comm"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="deptno"&amp;gt;10&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="dname"&amp;gt;ACCOUNTING&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="empno"&amp;gt;7782&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="ename"&amp;gt;CLARK&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="job"&amp;gt;MANAGER&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="mgrname"&amp;gt;KING&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="mgrno"&amp;gt;7839&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="sal"&amp;gt;2450&amp;lt;/field&amp;gt;&lt;br /&gt;            &amp;lt;/struct&amp;gt;&lt;br /&gt;          &amp;lt;/field&amp;gt;&lt;br /&gt;          &amp;lt;field name="array"&amp;gt;&lt;br /&gt;            &amp;lt;struct&amp;gt;&lt;br /&gt;              &amp;lt;field name="comm"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="deptno"&amp;gt;10&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="dname"&amp;gt;ACCOUNTING&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="empno"&amp;gt;7839&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="ename"&amp;gt;KING&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="job"&amp;gt;PRESIDENT&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="mgrname"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="mgrno"&amp;gt;NULL&amp;lt;/field&amp;gt;&lt;br /&gt;              &amp;lt;field name="sal"&amp;gt;5000&amp;lt;/field&amp;gt;&lt;br /&gt;            &amp;lt;/struct&amp;gt;&lt;br /&gt;          &amp;lt;/field&amp;gt;&lt;br /&gt;        &amp;lt;/struct&amp;gt;&lt;br /&gt;      &amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="loc"&amp;gt;NEW YORK&amp;lt;/field&amp;gt;&lt;br /&gt;      &amp;lt;field name="salsum"&amp;gt;8750&amp;lt;/field&amp;gt;&lt;br /&gt;    &amp;lt;/struct&amp;gt;&lt;br /&gt;  &amp;lt;/outparam&amp;gt;&lt;br /&gt;&amp;lt;/result&amp;gt;&lt;br /&gt;&amp;lt;/test&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The Table of UDTs and the Complex UDT required a change of code in some of the Java classes in the SQLUnit project. Since it is open-source, the code can be downloaded and changed to suit your needs.&lt;br /&gt;&lt;a href="http://sourceforge.net/projects/sqlunit/"&gt;http://sourceforge.net/projects/sqlunit/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Change StructBean constructor method to:&lt;br /&gt;&lt;pre&gt;public StructBean(final Object obj) {&lt;br /&gt;  try {&lt;br /&gt;      PropertyDescriptor[] props =&lt;br /&gt;          PropertyUtils.getPropertyDescriptors(obj);&lt;br /&gt;      Arrays.sort(props, new PropertyComparator());&lt;br /&gt;      for (int i = 0; i &amp;lt; props.length; i++) {&lt;br /&gt;          if (!"SQLTypeName".equals(props[i].getName())&lt;br /&gt;                  &amp;amp;&amp;amp; !"class".equals(props[i].getName())&lt;br /&gt;                  &amp;amp;&amp;amp; !"baseType".equals(props[i].getName())&lt;br /&gt;                  &amp;amp;&amp;amp; !"baseTypeName".equals(props[i].getName())&lt;br /&gt;                  &amp;amp;&amp;amp; !"descriptor".equals(props[i].getName())&lt;br /&gt;                  &amp;amp;&amp;amp; !"accessDirection".equals(props[i].getName())&lt;br /&gt;                  &amp;amp;&amp;amp; !"autoBuffering".equals(props[i].getName())&lt;br /&gt;                  &amp;amp;&amp;amp; !"autoIndexing".equals(props[i].getName())&lt;br /&gt;                  &amp;amp;&amp;amp; !"bytes".equals(props[i].getName())&lt;br /&gt;                  &amp;amp;&amp;amp; !"connection".equals(props[i].getName())) {&lt;br /&gt;              String fieldName = props[i].getName();&lt;br /&gt;              Method readMethod = props[i].getReadMethod();&lt;br /&gt;              if (readMethod != null) {&lt;br /&gt;                  Object fieldValue = readMethod.invoke(obj, new Object[0]);&lt;br /&gt;                  FieldBean fBean;&lt;br /&gt;                  if ("array".equals(props[i].getName())) {&lt;br /&gt;                    Class&amp;lt;?&amp;gt; type = fieldValue.getClass();&lt;br /&gt;                    if (type.isArray()) {&lt;br /&gt;                     int length = Array.getLength(fieldValue);&lt;br /&gt;                     for (int j = 0; j &amp;lt; length; j++) {&lt;br /&gt;                     fBean = new FieldBean(fieldName, Array.get(fieldValue, j));&lt;br /&gt;                     fields.add(fBean);&lt;br /&gt;                     }&lt;br /&gt;                    }&lt;br /&gt;                  } else if (typeMap.containsValue(props[i].getPropertyType())) {&lt;br /&gt;                      // Field is a nested struct&lt;br /&gt;                    fBean = new FieldBean(fieldName, fieldValue);&lt;br /&gt;                      fields.add(fBean);&lt;br /&gt;                  } else {&lt;br /&gt;                      // Field is a simple type&lt;br /&gt;                      fBean = new FieldBean(fieldName,&lt;br /&gt;                          (fieldValue == null) ? "NULL"&lt;br /&gt;                              : fieldValue.toString());&lt;br /&gt;                      fields.add(fBean);&lt;br /&gt;                  }&lt;br /&gt;              }&lt;br /&gt;          }&lt;br /&gt;      }&lt;br /&gt;  } catch (Exception ex) {&lt;br /&gt;      LOG.error("Could not read bean: " + obj.toString(), ex);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Change OutParamHandler process method to:&lt;br /&gt;&lt;pre&gt;...&lt;br /&gt;...&lt;br /&gt;} else if (elStruct != null) {&lt;br /&gt;  if (!(op.getType().endsWith("STRUCT") || op.getType().endsWith("ARRAY"))) {&lt;br /&gt;      throw new SQLUnitException(IErrorCodes.IS_A_STRUCT,&lt;br /&gt;          new String[] {op.getId(), op.getType()});&lt;br /&gt;  }&lt;br /&gt;  IHandler structHandler =&lt;br /&gt;      HandlerFactory.getInstance(elStruct.getName());&lt;br /&gt;  StructBean sb =&lt;br /&gt;      (StructBean) structHandler.process(elStruct);&lt;br /&gt;  op.setValue(sb);&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Change CallHandler setOutputParameters method to:&lt;br /&gt;&lt;pre&gt;...&lt;br /&gt;...&lt;br /&gt;} else if (params[i].getType().endsWith("STRUCT") || params[i].getType().endsWith("ARRAY")) {&lt;br /&gt;  // value is a user-defined type (UDT)&lt;br /&gt;  StructBean sb = new StructBean(value);&lt;br /&gt;  outParam.setValue(sb);&lt;br /&gt;  if (outParamSymbol != null) {&lt;br /&gt;      SymbolTable.setObject(outParamSymbol, sb);&lt;br /&gt;  }&lt;br /&gt;...&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Overview&lt;/span&gt;&lt;br /&gt;SQLUnit provides a neat way to include PL/SQL unit tests as part of an automated build process, since it can be incorporated into an ant script, or run in an isolated standalone mode. The fact that extended User Defined Types can be interrogated and matched with pre-defined XML output provides great flexibility.&lt;br /&gt;For those who have attempted JDBC calls to an Oracle database - in particular to PL/SQL requiring parameters that are either BOOLEAN or of a PL/SQL type (defined in a package specification) - you will be aware of a limitation on accessing those data types. At the moment, there is no easy way to transmit or receive those types (not that I have figured out anyway).&lt;br /&gt;Whilst PLUTO and utPLSQL can handle Booleans and PL/SQL types, I found the setup of test cases for those and complex UDT types a lot more cumbersome.&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-3116406727052376462?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Ps6PsComDzQbQvql789uwfrLv1w/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ps6PsComDzQbQvql789uwfrLv1w/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Ps6PsComDzQbQvql789uwfrLv1w/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ps6PsComDzQbQvql789uwfrLv1w/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/d9f2KCRK8X8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/3116406727052376462/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=3116406727052376462" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/3116406727052376462?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/3116406727052376462?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/d9f2KCRK8X8/sqlunit-plsql-unit-testing-using-junit.html" title="SQLUnit - PL/SQL Unit Testing using a JUnit Framework." /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2009/07/sqlunit-plsql-unit-testing-using-junit.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYARXs4cCp7ImA9WxRWGE4.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-7202207573952985326</id><published>2008-11-05T09:06:00.003+11:00</published><updated>2008-11-05T09:19:04.538+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-05T09:19:04.538+11:00</app:edited><title>Allow Oracle Forms to receive messages from external sources</title><content type="html">Combining Oracle Forms with other technologies and allowing messages and data to communicate between them is one of the challenges facing the enterprise today. If you have a large investment in Oracle Forms and wish to continue using them in partnership with other applications, then you will most likely be looking at some sort of SOA-governed solution. However, there are other solutions that simply require database connectivity to allow transactions to flow between differing technologies. This outlines a few of these 'other' approaches. Note that these are not intended as recommendations, but simply provide alternatives that already exist with the current Oracle database and Forms toolset.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Approach #1: Custom Messaging Database Table&lt;/span&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a table that will hold messages.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create a package to populate and retrieve messages from that table.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;In Forms, create a timer that periodically polls the table for new messages, or allow the user to dictate when to check for new messages (button-click, menu-option, etc).&lt;br /&gt;&lt;/li&gt;&lt;li&gt;On successful retrieval, act upon message as appropriate.&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-weight:bold;"&gt;Approach #2: Advanced Queues&lt;/span&gt;&lt;br /&gt;The Oracle AQ implementation gives great flexibility in the way messages can be sent and received.&lt;br /&gt;See &lt;a href="http://www.oracle-base.com/articles/9i/AdvancedQueuing9i.php"&gt;http://www.oracle-base.com/articles/9i/AdvancedQueuing9i.php&lt;/a&gt; for a quick run-down on how to use this approach.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Approach #3: Forms as a Socket Server&lt;/span&gt;&lt;br /&gt;A variation on the chat server as documented in&lt;br /&gt;&lt;a href="http://sheikyerbouti.developpez.com/forms-pjc-bean/pages/chat.htm"&gt;http://sheikyerbouti.developpez.com/forms-pjc-bean/pages/chat.htm&lt;/a&gt;&lt;br /&gt;and&lt;br /&gt;&lt;a href="http://sheikyerbouti.developpez.com/forms-pjc-bean/pages/socketserver.htm"&gt;http://sheikyerbouti.developpez.com/forms-pjc-bean/pages/socketserver.htm&lt;/a&gt;&lt;br /&gt;this approach opens a specific port that allows direct communication between different users of a Forms application. This can be extended to allow other technologies to also send telnet-style messages to Forms.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Approach #4: DBMS_PIPE&lt;/span&gt;&lt;br /&gt;Ok, here is the technique I spent the most time on.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create a package that implements DBMS_PIPE for sending and receiving messages.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Note that package owner must have execute permissions granted for DBMS_PIPE.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Call send routine from any technology that can access the database: SQLPlus, Java, Forms, etc...&lt;br /&gt;&lt;/li&gt;&lt;li&gt;DBMS_PIPE code based on &lt;a href="http://www.oracle-base.com/articles/misc/dbms_pipe.php"&gt;http://www.oracle-base.com/articles/misc/dbms_pipe.php&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Create Java class that can run asynchronously to call receive method and fire event when message is received.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;See &lt;a href="http://sheikyerbouti.developpez.com/forms-pjc-bean/pages/asyncjob.htm"&gt;http://sheikyerbouti.developpez.com/forms-pjc-bean/pages/asyncjob.htm&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Class must implement Runnable.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Note that the Class requires its own database connection to check pipe.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Package the class into a Jar, and place a signed version on the application server for subsequent distribution with Forms application.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add Java Bean onto your Form to implement the Java asynchronous method.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Add When-Custom-Item-Event to bean item on Form that captures and acts upon message received.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Either alert user to message, or use message contents to automatically navigate toa  different screen.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;formsweb.cfg must be setup to also distribute the packaged and signed Jar containing the asyncjob class, and classes12.jar (DB Connection for JInitiator 1.3 - or use ojdbc14.jar for Sun Java 1.4) in the archive_jini or archive setting&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;If there is enough demand, I will post up some sample code for approach #4, meanwhile I might try and see if I can get #2 (AQ) working...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-7202207573952985326?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/AsDREWd3eNrdcUMmXmBzWaZ77P0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AsDREWd3eNrdcUMmXmBzWaZ77P0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/AsDREWd3eNrdcUMmXmBzWaZ77P0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/AsDREWd3eNrdcUMmXmBzWaZ77P0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/MphZi5xPEUE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/7202207573952985326/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=7202207573952985326" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/7202207573952985326?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/7202207573952985326?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/MphZi5xPEUE/combining-oracle-forms-with-other.html" title="Allow Oracle Forms to receive messages from external sources" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/11/combining-oracle-forms-with-other.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQMQng6eCp7ImA9WxdaGEo.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-2568541978977179694</id><published>2008-08-28T07:35:00.005+10:00</published><updated>2008-08-28T07:59:43.610+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-28T07:59:43.610+10:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Materialized Views" /><category scheme="http://www.blogger.com/atom/ns#" term="Context Index" /><category scheme="http://www.blogger.com/atom/ns#" term="10g database" /><title>Materialized Views, Logs and Context Indexes (Oracle 10.2.0.2).</title><content type="html">I have been playing around with Materialized Views (shouldn't that be 'Materialised Views'? I'm an Aussie!) over the past couple of days. I've been building a rather complex join of several base tables, to work towards allowing 2 major tables of data to have fast search capabilities.&lt;br /&gt;So, the resulting MV construction syntax looks a little bit like this:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:78%;"&gt;&lt;span style="font-family:courier new;"&gt;CREATE MATERIALIZED VIEW CLIENTNAMEADDR&lt;br /&gt;...&amp;lt;storage&amp;gt;...&lt;br /&gt;BUILD IMMEDIATE&lt;br /&gt;USING INDEX&lt;br /&gt;REFRESH FAST ON COMMIT&lt;br /&gt;WITH PRIMARY KEY USING DEFAULT LOCAL ROLLBACK SEGMENT&lt;br /&gt;DISABLE QUERY REWRITE&lt;br /&gt;AS&lt;br /&gt;SELECT cli.clientId,&lt;br /&gt;cn.firstName  ' '  cn.secondName  ' ' cn.familyName  ' ' &lt;br /&gt;addr.streetNum  ' '  addr.streetName  ' ' addr.streetType  ' ' &lt;br /&gt;addr.suburb  ' '  addr.state  ' '  addr.postcode as clientFullText,&lt;br /&gt;cli.rowid cliRowid, cn.rowid cnRowid, ca.rowid caRowid, addr addrRowid&lt;br /&gt;FROM clients cli, client_Names cn, client_Addresses ca, addresses addr&lt;br /&gt;WHERE cli.clientId = cn.clientId&lt;br /&gt;AND cli.clientId = ca.clientId&lt;br /&gt;AND ca.addressId = addr.addressId;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;The theory is that this will allow me to create a Context index on the clientFullText field on the MV to allow end users to search on any combination of name and address within the database. In reality, for the query shown above, I don't really need to join the client table into the query, but for my purposes I have another AND clause and will be filtering some of them out.&lt;br /&gt;&lt;br /&gt;There are a fair number of restrictions you need to keep in mind when creating a materialized view, most of which are especially important when your MV contains a complex query - and let's face it, why else would you be creating an MV if not to contain a query with a large number of joins and/or filters.&lt;br /&gt;&lt;br /&gt;After searching around on the net I found a list of things to consider when creating a Materialized View:&lt;br /&gt;* The defining query of the materialized view cannot contain any non-repeatable expressions (ROWNUM, SYSDATE, non-repeatable PL/SQL functions, and so on).&lt;br /&gt;* The query cannot contain any references to RAW or LONG RAW datatypes or object REFs.&lt;br /&gt;* If the defining query of the materialized view contains set operators (UNION, MINUS, and so on), rewrite will use them for full text match rewrite only.&lt;br /&gt;* If the materialized view was registered as PREBUILT, the precision of the columns must match the precision of the corresponding SELECT expressions unless overridden by the WITH REDUCED PRECISION clause.&lt;br /&gt;* If the materialized view contains the same table more than once, it is possible to do a general rewrite, provided the query has the same aliases for the duplicate tables as the materialized view.&lt;br /&gt;* If a query has both local and remote tables, only local tables will be considered for potential rewrite.&lt;br /&gt;* Neither the detail tables nor the materialized view can be owned by SYS.&lt;br /&gt;* SELECT and GROUP BY lists, if present, must be the same in the query of the materialized view.&lt;br /&gt;* Aggregate functions must occur only as the outermost part of the expression. That is, aggregates such as AVG(AVG(x)) or AVG(x)+ AVG(x) are not allowed.&lt;br /&gt;* CONNECT BY clauses are not allowed.&lt;br /&gt;&lt;br /&gt;If you specify REFRESH FAST, Oracle performs further verification of the query definition to ensure that fast refresh can be performed if any of the detail tables change. These additional checks are:&lt;br /&gt;* A materialized view log must be present for each detail table.&lt;br /&gt;* The rowids of all the detail tables must appear in the SELECT list of the materialized view query definition.&lt;br /&gt;* If there are no outer joins, you may have arbitrary selections and joins in the WHERE clause. However, if there are outer joins, the WHERE clause cannot have any selections. Further, if there are outer joins, all the joins must be connected by ANDs and must use the equality (=) operator.&lt;br /&gt;* If there are outer joins, unique constraints must exist on the join columns of the inner table. For example, if you are joining the fact table and a dimension table and the join is an outer join with the fact table being the outer table, there must exist unique constraints on the join columns of the dimension table.&lt;br /&gt;&lt;br /&gt;If some of these restrictions are not met, you can create the materialized view as REFRESH FORCE to take advantage of fast refresh when it is possible. If one of the tables did not meet all of the criteria, but the other tables did, the materialized view would still be fast refreshable with respect to the other tables for which all the criteria are met.&lt;br /&gt;&lt;br /&gt;In order to support REFRESH FAST on the materialized view (have the MV automatically refresh after each change to the base tables), an MV LOG table has to be created for each of the base tables of the MV and include the columns that are used in the MV, so:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;CREATE MATERIALIZED VIEW LOG&lt;br /&gt;ON client_Names&lt;br /&gt;WITH ROWID, SEQUENCE(clientId,&lt;br /&gt;firstName,&lt;br /&gt;secondName,&lt;br /&gt;familyName)&lt;br /&gt;INCLUDING NEW VALUES;&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;CREATE MATERIALIZED VIEW LOG&lt;br /&gt;ON clients&lt;br /&gt;WITH ROWID, SEQUENCE(clientID);&lt;br /&gt;/&lt;br /&gt;CREATE MATERIALIZED VIEW LOG&lt;br /&gt;ON client_Addresses&lt;br /&gt;WITH ROWID, SEQUENCE(clientId,&lt;br /&gt;addressId)&lt;br /&gt;INCLUDING NEW VALUES;&lt;br /&gt;/&lt;br /&gt;CREATE MATERIALIZED VIEW LOG&lt;br /&gt;ON addresses&lt;br /&gt;WITH ROWID, SEQUENCE(addressId,&lt;br /&gt;streetNum,&lt;br /&gt;streetType,&lt;br /&gt;streetName,&lt;br /&gt;suburb,&lt;br /&gt;state,&lt;br /&gt;postcode)&lt;br /&gt;INCLUDING NEW VALUES;&lt;br /&gt;/&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;During the creation of the MV, I made use of a number of utilities made available as part of the Oracle rdbms. As SYS, I created the REWRITE_TABLE table ($ORACLE_HOME/rdbms/admin/utlxrw.sql) - as well as a public synonym to the same - and granted permissions to public. As SYS, I also ensured the DBMS_ADVISOR package was made made available to particular users as required. As a standard user who was creating the MV and LOG tables, I created the MV_CAPABILITIES_TABLE table ($ORACLE_HOME/rdbms/admin/utlxmv.sql). This is only really needed during the query tuning phase.&lt;br /&gt;&lt;br /&gt;Ok, on to the Context index. Context Indexes are an excellent way to provide fast text searches on large data tables. Think of them as a LIKE operator on steriods. You can search a VARCHAR2 column for portions of text and it can also be configured to be score-based, where your search criteria can be allowed to be 'close to' the actual data.&lt;br /&gt;First off, make sure your friendly DBA grants you EXECUTE permissions to the CTXSYS.CTX_DDL package. This may be needed if you want your index to sit in a non-default tablespace, or if you want to apply a 'stop-list' to the index (ie search words to ignore).&lt;br /&gt;To create a stop-list, syntax follows:&lt;br /&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;BEGIN&lt;br /&gt;CTX_DDL.CREATE_STOPLIST('CLI_NAMES_IGNORE', 'BASIC_STOPLIST');&lt;br /&gt;CTX_DDL.ADD_STOPWORD('CLI_NAMES_IGNORE', 'PTY');&lt;br /&gt;CTX_DDL.ADD_STOPWORD('CLI_NAMES_IGNORE', 'PTY.');&lt;br /&gt;CTX_DDL.ADD_STOPWORD('CLI_NAMES_IGNORE', 'LTD');&lt;br /&gt;CTX_DDL.ADD_STOPWORD('CLI_NAMES_IGNORE', 'LTD.');&lt;br /&gt;CTX_DDL.ADD_STOPWORD('CLI_NAMES_IGNORE', 'THE');&lt;br /&gt;CTX_DDL.ADD_STOPWORD('CLI_NAMES_IGNORE', 'OTHERS');&lt;br /&gt;END;&lt;br /&gt;/&lt;/span&gt;&lt;br /&gt;To create a specific index storage syntax clause:&lt;br /&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;BEGIN&lt;br /&gt;-- CTX_DDL.DROP_PREFERENCE('CLINAMEADDR_STORE_PREFS');&lt;br /&gt;CTX_DDL.CREATE_PREFERENCE('CLINAMEADDR_STORE_PREFS', 'BASIC_STORAGE');&lt;br /&gt;CTX_DDL.SET_ATTRIBUTE('CLINAMEADDR_STORE_PREFS', 'I_INDEX_CLAUSE', 'tablespace large_idx compress 2');&lt;br /&gt;CTX_DDL.SET_ATTRIBUTE('CLINAMEADDR_STORE_PREFS', 'I_TABLE_CLAUSE', 'tablespace large_idx');&lt;br /&gt;CTX_DDL.SET_ATTRIBUTE('CLINAMEADDR_STORE_PREFS', 'K_TABLE_CLAUSE', 'tablespace large_idx');&lt;br /&gt;CTX_DDL.SET_ATTRIBUTE('CLINAMEADDR_STORE_PREFS', 'R_TABLE_CLAUSE', 'tablespace large_idx LOB(DATA) STORE AS (CACHE)');&lt;br /&gt;CTX_DDL.SET_ATTRIBUTE('CLINAMEADDR_STORE_PREFS', 'N_TABLE_CLAUSE', 'tablespace large_idx');&lt;br /&gt;END;&lt;br /&gt;/&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Then, to create the Context index, using the stop-list and index storage preferences from the above two steps:&lt;br /&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;CREATE INDEX CLINAMEADDR_CONTEXT1 ON CLINAMEADDR(CLIENTFULLTEXT)&lt;br /&gt;INDEXTYPE IS CTXSYS.CTXCAT&lt;br /&gt;PARAMETERS('STOPLIST CLI_NAMES_IGNORE STORAGE CLINAMEADDR_STORE_PREFS')&lt;br /&gt;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once this is done, you can use the new context index:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;font-size:78%;"&gt;SELECT clientID, clientFullText&lt;br /&gt;FROM cliNameAddr&lt;br /&gt;WHERE CATSEARCH(clientFullText,'&lt;query&gt;&lt;textquery grammar="context"&gt;'REPLACE(:search_criteria,' ',' NEAR ')'&lt;/textquery&gt;&lt;/query&gt;',NULL) &gt; 0;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;Bear in mind that I have noticed errors when passing in :search_criteria containing double spaces. So, you might want to ensure that whitepace is kept to a minimum - maybe create a little pre-parser for the data contained in :search_criteria.&lt;br /&gt;&lt;br /&gt;After a few days of using this just to search for data, I eventually tried to perform a standard update on one of the base tables. That's when I noticed the performance problems. The database in which I am experimenting with the MV and Context concepts contains the following (active) row counts:&lt;br /&gt;CLIENT_NAMES 7.5 million&lt;br /&gt;CLIENT_ADDRESSES 6.7 million&lt;br /&gt;ADDRESSES 8.4 million&lt;br /&gt;CLIENTS 6.9 million&lt;br /&gt;&lt;br /&gt;On updating a single row in the CLIENT_NAMES table, I noticed a 15 to 20 second wait time before response came back from the commit operation.&lt;br /&gt;So I experimented a little - I tried an update on 4700 rows and noticed it took about 130 seconds to perform the update, plus another &lt;strong&gt;15 MINUTES to perform the commit&lt;/strong&gt;.&lt;br /&gt;I used TOAD to investigate where it was getting stuck and it was definitely a combination of applying changes to both the MV and the Context index.&lt;br /&gt;Without full knowledge on how to improve this ghastly performance problem, I may have to either retire the MV and Context solution, or stick with a refresh of the MV ON DEMAND instead of ON COMMIT.&lt;br /&gt;&lt;br /&gt;A colleague of mine also tried a more substantial update on 300,000 rows and eventually got kicked out with&lt;br /&gt;some internal error - the basis of which was a 'snapshot too old' type of error. Oracle has admitted a bug exists in this circumstance and has issued a one-off patch (5530043), but recommends upgrading to 10.2.0.4 or 11g.&lt;br /&gt;I am waiting for our DBAs to upgrade one of our databases to 10.2.0.4 to see if the fix addresses some of the performance problems I noticed during my experiments, although I am doubtful of a successful outcome.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-2568541978977179694?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/VfmRnt9empJa5gQzBOIajuPLIcE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VfmRnt9empJa5gQzBOIajuPLIcE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/VfmRnt9empJa5gQzBOIajuPLIcE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VfmRnt9empJa5gQzBOIajuPLIcE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/VFyMzD531AQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/2568541978977179694/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=2568541978977179694" title="6 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/2568541978977179694?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/2568541978977179694?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/VFyMzD531AQ/materialized-views-logs-and-context.html" title="Materialized Views, Logs and Context Indexes (Oracle 10.2.0.2)." /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>6</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/08/materialized-views-logs-and-context.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAHRHo_cSp7ImA9WxdTFk8.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-7664804736478155795</id><published>2008-05-13T07:39:00.002+10:00</published><updated>2008-05-13T07:45:35.449+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-13T07:45:35.449+10:00</app:edited><title>AUSOUG Conference on-line registration</title><content type="html">Registration to attend the 2008 Australian Oracle User Group conference can now be done online. Simply visit &lt;a href="http://www.ausoug.org.au/2020/registration.html"&gt;http://www.ausoug.org.au/2020/registration.html&lt;/a&gt; for more information.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-7664804736478155795?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/XbcL8xTSw4UYnBzt3JK5mXwySUU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XbcL8xTSw4UYnBzt3JK5mXwySUU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/XbcL8xTSw4UYnBzt3JK5mXwySUU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XbcL8xTSw4UYnBzt3JK5mXwySUU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/x3EsNvhpau0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/7664804736478155795/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=7664804736478155795" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/7664804736478155795?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/7664804736478155795?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/x3EsNvhpau0/ausoug-conference-on-line-registration.html" title="AUSOUG Conference on-line registration" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/05/ausoug-conference-on-line-registration.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkQER30zcCp7ImA9WxdTFk8.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-6886611665474733960</id><published>2008-04-18T15:52:00.004+10:00</published><updated>2008-05-13T07:38:26.388+10:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-05-13T07:38:26.388+10:00</app:edited><title>Using Oracle Data Access Components through VB .NET 2008</title><content type="html">Oracle has provided a nice set of plugins to allow easy access to Oracle database components within Visual Studio. I've had a bit of a play around with it over the past couple of weeks while our developers evaluate various technologies, so I've put together some different ways of using the functionality. All of these techniques can be gathered from various places around the internet, but I am mainly putting them here for my own reference so I have everything in one place.&lt;br /&gt;&lt;br /&gt;If you have VS2008, you can download the Oracle plugins from Oracle's .NET Developer Center (http://www.oracle.com/technology/software/tech/windows/odpnet/index.html). The latest version (11.1.0.6.21) allows connection to Oracle database versions 9i, 10g and 11g.&lt;br /&gt;&lt;br /&gt;Once that is installed, you will find that VS allows you to define a Data Source using Oracle ODP.NET drivers.&lt;br /&gt;Once your Data Source is set up, and you have also defined the dataset you wish to use (consisting of tables and views - no packages/procedures yet, but more on that later), you can then simply drag and drop tables from the dataset onto Window Forms to automatically create databound grids, or drag individual fields to create databound controls (the types can be configured to suit).&lt;br /&gt;&lt;br /&gt;On the first addition of a table (or field) onto a Form, a function is also created to automatically fill the control with all records from the table, and a call to this function is placed in the Load method of the Form. This is like performing an EXECUTE_QUERY in Oracle Forms with no DEFAULT_WHERE clause, so you will have to create your own filter function to allow a bit more of a parameterized mechanism. Master-Detail relationships are, however, taken care of automatically behind the scenes - as long as the appropriate foreign keys have been set up. For example, if you drag in the DEPT table to create a datagrid for its data, then drag in the embedded EMP table from within the DEPT dataset, the relationship is recognised and the display is synchronized when DEPT entries are cycled through during runtime.&lt;br /&gt;&lt;br /&gt;To add a filtered query, open up the Dataset viewer and right-click on the appropriate table. Choose Add-&gt;Query... Then flick through the wizard until you get to the SQL statement. Add a WHERE clause - for example "WHERE DNAME LIKE :deptName" - and a proceed through to the end of the wizard, remembering to give the new filter method an appropriate name (eg FillByDeptName). You can then either replace the method used in the Load routine, or add a search criteria field and button to accept a query from the user, then use the new method from there. &lt;br /&gt;&lt;br /&gt;Now, this is all well and good for straight direct table and view access, but what about Stored Procedure, Function and Package access? Indeed, some database developers are not given direct access to the tables, but must instead work through a layer of PL/SQL code to get to the data. So we need to be able to call database code.&lt;br /&gt;First, lets look at how to call a simple SQL statement using Visual Basic.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    Private Sub getBonusInfo(ByVal ename As String)&lt;br /&gt;        ' Define variables&lt;br /&gt;        Dim oraconnection As OracleConnection&lt;br /&gt;        Dim oracommand As OracleCommand&lt;br /&gt;        Dim returnJob As String = ""&lt;br /&gt;        Dim returnSal As Decimal&lt;br /&gt;        Dim returnComm As Decimal&lt;br /&gt;&lt;br /&gt;        'Define Oracle database connection&lt;br /&gt;        oraconnection = New OracleConnection(My.Settings.STConnectionString)&lt;br /&gt;        'Open the connection&lt;br /&gt;        oraconnection.Open()&lt;br /&gt;        Try&lt;br /&gt;            'Create a new Oracle command&lt;br /&gt;            oracommand = New OracleCommand()&lt;br /&gt;            With oracommand&lt;br /&gt;                'Associate the command to the Connection opened previously&lt;br /&gt;                .Connection = oraconnection&lt;br /&gt;                'Define the type of command&lt;br /&gt;                .CommandType = CommandType.Text&lt;br /&gt;                'Create the command text&lt;br /&gt;                .CommandText = "SELECT job, sal, comm FROM bonus " + _&lt;br /&gt;                               "WHERE ename = :ename"&lt;br /&gt;                'Add an input parameter&lt;br /&gt;                .Parameters.Add(New OracleParameter(":ename", _&lt;br /&gt;                                       OracleDbType.Varchar2, _&lt;br /&gt;                                    ParameterDirection.Input)).Value = ename&lt;br /&gt;                'Execute the Statement&lt;br /&gt;                Dim reader As OracleDataReader = .ExecuteReader()&lt;br /&gt;                'Interrogate the response for individual returned data elements&lt;br /&gt;                While (reader.Read())&lt;br /&gt;                    returnJob = reader.GetOracleString(0)&lt;br /&gt;                    returnSal = reader.GetOracleDecimal(1)&lt;br /&gt;                    returnComm = reader.GetOracleDecimal(2)&lt;br /&gt;                End While&lt;br /&gt;            End With&lt;br /&gt;            'Close the command&lt;br /&gt;            oracommand.Dispose()&lt;br /&gt;        Catch ex As OracleException&lt;br /&gt;            MsgBox(ex)&lt;br /&gt;        End Try&lt;br /&gt;        'Use the return data as needed&lt;br /&gt;        Me.txtSal.Text = returnSal&lt;br /&gt;        Me.txtJob.Text = returnJob&lt;br /&gt;        Me.txtComm.Text = returnComm&lt;br /&gt;&lt;br /&gt;        'Close the database connection&lt;br /&gt;        oraconnection.Close()&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The code contains comments where appropriate, so it is fairly self-explanitory. &lt;br /&gt;Note that there is no data in the BONUS table by default, so you would have to insert some rows to see this working.&lt;br /&gt;&lt;br /&gt;Now, calling a database function requires you to know that the first Parameter is always going to be the return parameter.&lt;br /&gt;For example, say we had the following function in the database:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION getEmpCount(p_deptno IN NUMBER)&lt;br /&gt;RETURN NUMBER&lt;br /&gt;IS &lt;br /&gt; lvn_count NUMBER := 0;&lt;br /&gt;BEGIN&lt;br /&gt;  SELECT count(*)&lt;br /&gt;    INTO lvn_count&lt;br /&gt;    FROM emp&lt;br /&gt;   WHERE deptno = p_deptno;&lt;br /&gt;  RETURN lvn_count;&lt;br /&gt;END getEmpCount;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Calling the Stored Procedure from VB would look like:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;    Private Function getEmpCount(ByVal deptno As Integer) As Decimal&lt;br /&gt;        ' Define variables&lt;br /&gt;        Dim oraconnection As OracleConnection&lt;br /&gt;        Dim oracommand As OracleCommand&lt;br /&gt;        Dim retVal As OracleDecimal = New OracleDecimal&lt;br /&gt;        ' Function return parameter has arbitrary name&lt;br /&gt;        Dim returnParam As OracleParameter = _&lt;br /&gt;          New OracleParameter("myReturnValue", OracleDbType.Decimal, 10)&lt;br /&gt;        returnParam.Direction = ParameterDirection.ReturnValue&lt;br /&gt;&lt;br /&gt;        'Define Oracle database connection&lt;br /&gt;        oraconnection = New OracleConnection(My.Settings.STConnectionString)&lt;br /&gt;        'Open the connection&lt;br /&gt;        oraconnection.Open()&lt;br /&gt;        Try&lt;br /&gt;            'Create a new Oracle command&lt;br /&gt;            oracommand = New OracleCommand()&lt;br /&gt;            With oracommand&lt;br /&gt;                'Associate the command to the Connection opened previously&lt;br /&gt;                .Connection = oraconnection&lt;br /&gt;                'Define the type of command&lt;br /&gt;                .CommandType = CommandType.StoredProcedure&lt;br /&gt;                'Create the command text&lt;br /&gt;                .CommandText = "getEmpCount"&lt;br /&gt;                'return parameter must be added first&lt;br /&gt;                .Parameters.Add(returnParam)&lt;br /&gt;                .Parameters.Add(New OracleParameter("P_DEPTNO", _&lt;br /&gt;                                          OracleDbType.Decimal)).Value = deptno&lt;br /&gt;                .ExecuteNonQuery()&lt;br /&gt;            End With&lt;br /&gt;            retVal = returnParam.Value&lt;br /&gt;            oracommand.Dispose()&lt;br /&gt;        Catch ex As OracleException&lt;br /&gt;            MsgBox(ex.Message())&lt;br /&gt;        End Try&lt;br /&gt;        oraconnection.Close()&lt;br /&gt;        Return retVal&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Ok, on to the interesting part - User Defined Types. &lt;br /&gt;This method is new to the latest version of ODP.NET (11.1.0.6.21). Previously, User Defined Types could not be handled by VB.&lt;br /&gt;&lt;br /&gt;Let's look at a scenario. Say, for whatever reason, we have the requirement to show a big dump of data combining data from more than one table. It would probably be easier to create a view and access it that way, but where would the fun be in that? Lets create a new User Defined Type!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE TYPE comboRecord IS OBJECT(&lt;br /&gt;EMPNO    NUMBER(4),&lt;br /&gt;ENAME    VARCHAR2(10),&lt;br /&gt;MGR      NUMBER(4),&lt;br /&gt;MNAME    VARCHAR2(10),&lt;br /&gt;HIREDATE   DATE,&lt;br /&gt;SAL   NUMBER(7,2),&lt;br /&gt;DEPTNO   NUMBER(2),&lt;br /&gt;DNAME   VARCHAR2(14)&lt;br /&gt;TOTALBONUS   NUMBER(8,2));&lt;br /&gt;/&lt;br /&gt;CREATE TYPE comboRecordTable is table of comboRecord;&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And, a function to return a table of records:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE OR REPLACE FUNCTION getFullEmpDetails(p_ename IN VARCHAR2)&lt;br /&gt;RETURN comboRecordTable&lt;br /&gt;IS&lt;br /&gt;  CURSOR comboCsr&lt;br /&gt;  IS&lt;br /&gt;    SELECT e.empno, &lt;br /&gt;      e.ename, &lt;br /&gt;      e.mgr, &lt;br /&gt;      e2.ename as mname,&lt;br /&gt;      e.hiredate,&lt;br /&gt;      e.sal,&lt;br /&gt;      e.deptno,&lt;br /&gt;      d.dname,&lt;br /&gt;      tb.totalbonus&lt;br /&gt;      FROM emp e, &lt;br /&gt;        emp e2,&lt;br /&gt;        dept d,&lt;br /&gt;        (SELECT ename, job, sum(sal) + sum(comm) as totalbonus&lt;br /&gt;           FROM bonus b&lt;br /&gt;          GROUP BY ename, job) tb&lt;br /&gt;     WHERE e.mgr = e2.empno(+)&lt;br /&gt;       AND e.deptno = d.deptno&lt;br /&gt;       AND tb.ename(+) = e.ename&lt;br /&gt;       AND tb.job(+) = e.job&lt;br /&gt;       AND e.ename LIKE '%'||UPPER(p_ename)||'%';&lt;br /&gt;&lt;br /&gt;  l_combotab comboRecordTable := comboRecordTable();&lt;br /&gt;  l_comborec comboRecord;&lt;br /&gt;  l_count   NUMBER := 0;&lt;br /&gt;BEGIN&lt;br /&gt;  l_comborec := comboRecord(NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);&lt;br /&gt;  FOR l_rec IN comboCsr&lt;br /&gt;  LOOP&lt;br /&gt;    l_comborec.EMPNO := l_rec.empno;&lt;br /&gt;    l_comborec.ENAME := l_rec.ename;&lt;br /&gt;    l_comborec.MGR := l_rec.mgr;&lt;br /&gt;    l_comborec.MNAME := l_rec.mname;&lt;br /&gt;    l_comborec.HIREDATE := l_rec.hiredate;&lt;br /&gt;    l_comborec.SAL := l_rec.sal;&lt;br /&gt;    l_comborec.DEPTNO := l_rec.deptno;&lt;br /&gt;    l_comborec.DNAME := l_rec.dname;&lt;br /&gt;    l_comborec.TOTALBONUS := l_rec.totalbonus;&lt;br /&gt;    l_combotab.EXTEND(1);&lt;br /&gt;    l_count := l_count + 1;&lt;br /&gt;    l_combotab(l_count) := l_comborec;&lt;br /&gt;  END LOOP;&lt;br /&gt;  RETURN l_combotab;&lt;br /&gt;END getFullEmpDetails;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now, because this new function returns a complex User Defined Type (UDT), &lt;br /&gt;ODAC/ODP used to have problems with it. Now, with the latest version, you can create VB Classes and map them to the UDT. First, create new file to handle the classes.&lt;br /&gt;&lt;b&gt;&lt;br /&gt;UPDATE NOTE: This code can be automatically generated! Connect to the database from within Visual Studio, navigate to the UDT; right-click and choose Generate Custom Class...&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;PRE&gt;&lt;br /&gt;Imports Oracle.DataAccess.Types.OracleUdt&lt;br /&gt;Public Class ComboRec&lt;br /&gt;    Implements INullable, IOracleCustomType&lt;br /&gt;&lt;br /&gt;    Private m_bIsNull As Boolean&lt;br /&gt;    Private m_empNo As Decimal&lt;br /&gt;    Private m_eName As String&lt;br /&gt;    Private m_mgr As Decimal&lt;br /&gt;    Private m_mName As String&lt;br /&gt;    Private m_hireDate As Date&lt;br /&gt;    Private m_sal As Decimal&lt;br /&gt;    Private m_deptNo As Decimal&lt;br /&gt;    Private m_dName As String&lt;br /&gt;    Private m_totalBonus As Decimal&lt;br /&gt;&lt;br /&gt;    &amp;lt;OracleObjectMapping("EMPNO")&amp;gt; _&lt;br /&gt;    Public Property empNo() As Decimal&lt;br /&gt;        Get&lt;br /&gt;            Return m_empNo&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Decimal)&lt;br /&gt;            m_empNo = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    &amp;lt;OracleObjectMapping("ENAME")&amp;gt; _&lt;br /&gt;    Public Property eName() As String&lt;br /&gt;        Get&lt;br /&gt;            Return m_eName&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As String)&lt;br /&gt;            m_eName = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    &amp;lt;OracleObjectMapping("MGR")&amp;gt; _&lt;br /&gt;    Public Property mgr() As Decimal&lt;br /&gt;        Get&lt;br /&gt;            Return m_mgr&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Decimal)&lt;br /&gt;            m_mgr = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    &amp;lt;OracleObjectMapping("MNAME")&amp;gt; _&lt;br /&gt;    Public Property mName() As String&lt;br /&gt;        Get&lt;br /&gt;            Return m_mName&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As String)&lt;br /&gt;            m_mName = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    &amp;lt;OracleObjectMapping("HIREDATE")&amp;gt; _&lt;br /&gt;    Public Property hireDate() As Date&lt;br /&gt;        Get&lt;br /&gt;            Return m_hireDate&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Date)&lt;br /&gt;            m_hireDate = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    &amp;lt;OracleObjectMapping("SAL")&amp;gt; _&lt;br /&gt;    Public Property sal() As Decimal&lt;br /&gt;        Get&lt;br /&gt;            Return m_sal&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Decimal)&lt;br /&gt;            m_sal = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    &amp;lt;OracleObjectMapping("DEPTNO")&amp;gt; _&lt;br /&gt;    Public Property deptNo() As Decimal&lt;br /&gt;        Get&lt;br /&gt;            Return m_deptNo&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Decimal)&lt;br /&gt;            m_deptNo = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    &amp;lt;OracleObjectMapping("DNAME")&amp;gt; _&lt;br /&gt;    Public Property dName() As String&lt;br /&gt;        Get&lt;br /&gt;            Return m_dName&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As String)&lt;br /&gt;            m_dName = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    &amp;lt;OracleObjectMapping("TOTALBONUS")&amp;gt; _&lt;br /&gt;    Public Property totalBonus() As Decimal&lt;br /&gt;        Get&lt;br /&gt;            Return m_totalBonus&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Decimal)&lt;br /&gt;            m_totalBonus = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property IsNull() As Boolean _&lt;br /&gt;    Implements Oracle.DataAccess.Types.INullable.IsNull&lt;br /&gt;        Get&lt;br /&gt;            Return m_bIsNull&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public Sub FromCustomObject( _&lt;br /&gt;        ByVal con As Oracle.DataAccess.Client.OracleConnection, _&lt;br /&gt;        ByVal pUdt As System.IntPtr) _&lt;br /&gt;      Implements Oracle.DataAccess.Types.IOracleCustomType.FromCustomObject&lt;br /&gt;&lt;br /&gt;        SetValue(con, pUdt, "EMPNO", empNo)&lt;br /&gt;        SetValue(con, pUdt, "ENAME", eName)&lt;br /&gt;        SetValue(con, pUdt, "MGR", mgr)&lt;br /&gt;        SetValue(con, pUdt, "MNAME", mName)&lt;br /&gt;        SetValue(con, pUdt, "HIREDATE", hireDate)&lt;br /&gt;        SetValue(con, pUdt, "SAL", sal)&lt;br /&gt;        SetValue(con, pUdt, "DEPTNO", deptNo)&lt;br /&gt;        SetValue(con, pUdt, "DNAME", dName)&lt;br /&gt;        SetValue(con, pUdt, "TOTALBONUS", totalBonus)&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Public Sub ToCustomObject( _&lt;br /&gt;        ByVal con As Oracle.DataAccess.Client.OracleConnection, _&lt;br /&gt;        ByVal pUdt As System.IntPtr) _&lt;br /&gt;      Implements Oracle.DataAccess.Types.IOracleCustomType.ToCustomObject&lt;br /&gt;&lt;br /&gt;        empNo = GetValue(con, pUdt, "EMPNO")&lt;br /&gt;        eName = GetValue(con, pUdt, "ENAME")&lt;br /&gt;        If Not IsDBNull(con, pUdt, "MGR") Then&lt;br /&gt;            mgr = GetValue(con, pUdt, "MGR")&lt;br /&gt;            mName = GetValue(con, pUdt, "MNAME")&lt;br /&gt;        End If&lt;br /&gt;        hireDate = GetValue(con, pUdt, "HIREDATE")&lt;br /&gt;        sal = GetValue(con, pUdt, "SAL")&lt;br /&gt;        deptNo = GetValue(con, pUdt, "DEPTNO")&lt;br /&gt;        dName = GetValue(con, pUdt, "DNAME")&lt;br /&gt;        If Not IsDBNull(con, pUdt, "TOTALBONUS") Then&lt;br /&gt;            totalBonus = GetValue(con, pUdt, "TOTALBONUS")&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;&amp;lt;OracleCustomTypeMapping("SCOTT.COMBORECORD")&amp;gt; _&lt;br /&gt;Public Class ComboRecordFactory&lt;br /&gt;    Implements IOracleCustomTypeFactory&lt;br /&gt;&lt;br /&gt;    Public Function CreateObject() _&lt;br /&gt;    As Oracle.DataAccess.Types.IOracleCustomType _&lt;br /&gt;    Implements Oracle.DataAccess.Types.IOracleCustomTypeFactory.CreateObject&lt;br /&gt;        Return New ComboRec()&lt;br /&gt;    End Function&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;&amp;lt;Oracle.DataAccess.Types.OracleCustomTypeMapping("SCOTT.COMBORECORDTABLE")&amp;gt; _&lt;br /&gt;Public Class ComboRecordTable&lt;br /&gt;    Implements IOracleArrayTypeFactory&lt;br /&gt;   &lt;br /&gt;    Public Function CreateArray(ByVal numElems As Integer) As System.Array _&lt;br /&gt;    Implements Oracle.DataAccess.Types.IOracleArrayTypeFactory.CreateArray&lt;br /&gt;        Dim s(numElems) As ComboRec&lt;br /&gt;        Return s&lt;br /&gt;    End Function&lt;br /&gt;    Public Function CreateStatusArray(ByVal numElems As Integer) As System.Array _&lt;br /&gt;    Implements Oracle.DataAccess.Types.IOracleArrayTypeFactory.CreateStatusArray&lt;br /&gt;        Return Nothing&lt;br /&gt;    End Function&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;&lt;/PRE&gt;&lt;br /&gt;&lt;br /&gt;Now, whenever your VB code attempts to pull in data from your UDT structures, it has something to translate them to.&lt;br /&gt;For instance, we can capture the incoming data as an Array and use it to populate a DataGrid dynamically.&lt;br /&gt;&lt;br /&gt;&lt;PRE&gt;&lt;br /&gt;    Public Sub populateDynamicFullDetails(ByVal eName As String)&lt;br /&gt;        Dim oraconnection As OracleConnection = _&lt;br /&gt;          New OracleConnection(My.Settings.STConnectionString)&lt;br /&gt;        Dim oracommand As OracleCommand = New OracleCommand()&lt;br /&gt;        Dim empArr As System.Array = Nothing&lt;br /&gt;        Try&lt;br /&gt;            oraconnection.Open()&lt;br /&gt;            With oracommand&lt;br /&gt;                .Connection = oraconnection&lt;br /&gt;                .CommandType = CommandType.Text&lt;br /&gt;                .CommandText = "select getFullEmpDetails(:1) from dual"&lt;br /&gt;                .Parameters.Add(New OracleParameter(":1", _&lt;br /&gt;                  OracleDbType.Varchar2)).Value = eName&lt;br /&gt;                Dim subReader As OracleDataReader = .ExecuteReader&lt;br /&gt;                While (subReader.Read())&lt;br /&gt;                    If Not subReader.IsDBNull(0) Then&lt;br /&gt;                        empArr = DirectCast(subReader.GetValue(0), System.Array)&lt;br /&gt;                    End If&lt;br /&gt;                End While&lt;br /&gt;            End With&lt;br /&gt;            If Not oracommand Is Nothing Then&lt;br /&gt;                oracommand.Dispose()&lt;br /&gt;            End If&lt;br /&gt;        Catch ex As Exception&lt;br /&gt;            If Not oracommand Is Nothing Then&lt;br /&gt;                oracommand.Dispose()&lt;br /&gt;            End If&lt;br /&gt;        Finally&lt;br /&gt;            If Not oraconnection Is Nothing Then&lt;br /&gt;                oraconnection.Dispose()&lt;br /&gt;            End If&lt;br /&gt;        End Try&lt;br /&gt;        Me.dgrdDyno.DataSource = empArr&lt;br /&gt;&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;&lt;/PRE&gt;&lt;br /&gt;&lt;br /&gt;During the retrieval of the data into the array, &lt;br /&gt;ODP will detect the data type being returned from the Oracle function (comboRecordTable) and attempt to find a mapped VB class that matches. Now that we have told it how to handle it, everything should work fine.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-6886611665474733960?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-x9BfU2iMkttMiMw-i1jnN7oO94/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-x9BfU2iMkttMiMw-i1jnN7oO94/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-x9BfU2iMkttMiMw-i1jnN7oO94/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-x9BfU2iMkttMiMw-i1jnN7oO94/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/f8ncW-3U2R0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/6886611665474733960/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=6886611665474733960" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/6886611665474733960?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/6886611665474733960?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/f8ncW-3U2R0/using-oracle-data-access-components.html" title="Using Oracle Data Access Components through VB .NET 2008" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/04/using-oracle-data-access-components.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEAHQH07eSp7ImA9WxZUEUo.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-8476342102587987870</id><published>2008-04-03T09:48:00.001+11:00</published><updated>2008-04-03T09:52:11.301+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-03T09:52:11.301+11:00</app:edited><title>AUSOUG National Conference Series 2008</title><content type="html">The 2008 &lt;a href="http://www.ausoug.org.au"&gt;AUSOUG&lt;/a&gt; National Conference Series has been &lt;a href="http://www.ausoug.org.au/2020"&gt;announced&lt;/a&gt; and is making a call for &lt;a href="http://www.ausoug.org.au/2020/speakers.html"&gt;papers to be submitted&lt;/a&gt;. &lt;br /&gt;The conference is going to be located in Perth and the Gold Coast this year, and the organisers are filling the event with as much content and expertise as possible.&lt;br /&gt;With high profile draw-card names like Tom Kyte and Rich Niemiec, as well as another big name in DBA circles likely to join the list, there are a lot of reasons why this year's conference is going to be a great event.  &lt;br /&gt;Add to that the 25% discount to the Warner Village Theme Parks (Gold Coast conference only) and it sounds like there will be heaps to keep you entertained and informed. So, what are you waiting for?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-8476342102587987870?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/8KiEnlbai1aQxGItOUMhBb21_Oo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8KiEnlbai1aQxGItOUMhBb21_Oo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/8KiEnlbai1aQxGItOUMhBb21_Oo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/8KiEnlbai1aQxGItOUMhBb21_Oo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/NpEt0UW9l4g" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/8476342102587987870/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=8476342102587987870" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/8476342102587987870?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/8476342102587987870?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/NpEt0UW9l4g/ausoug-national-conference-series-2008.html" title="AUSOUG National Conference Series 2008" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/04/ausoug-national-conference-series-2008.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4HRncycSp7ImA9WxZUEUo.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-7872430930043287021</id><published>2008-04-03T09:03:00.001+11:00</published><updated>2008-04-03T09:05:37.999+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-04-03T09:05:37.999+11:00</app:edited><title>Is the news all bad for Oracle Development?</title><content type="html">While Oracle ramps up with new versions of JDev and Apex, and secretely suggests that Forms is dead (though never publicly, of course), their development tools have yet to mature to the point where companies are willing to take the leap and join the fray in bashing out code in these new environments.&lt;br /&gt;&lt;br /&gt;With the spotlight on mutli-tiered applications that separate business, application and UI logic, Oracle has been keenly concentrating their efforts on the business and application side of things, and is now attempting to catch up to the requirements of the UI layer with their new ADF Faces RC. &lt;br /&gt;&lt;br /&gt;From other vendors - Microsoft, Sun, and Adobe - we can also see a state of flux as we are currently in an "in-between" phase where technologies seem to be shifting.&lt;br /&gt;Seeing as Sun is looking to replace Swing with their new FX technology, we will see Swing apps fall by the wayside, but FX will probably take some time to reach the same maturity level before it gets to its full potential.&lt;br /&gt;&lt;br /&gt;Meanwhile, Microsoft is introducing Silverlight to be its all-encompassing technology, and with the beast behind it, it will gain ground quickly. And Adobe is refining their Flex development environment along with Flash and AIR.&lt;br /&gt;&lt;br /&gt;So, let us set out and discover what glorious lands abound in the outer ranges. The following guidelines have been set out:&lt;br /&gt;1.) Oracle Forms is not going to be around (and supported) forever, so we need to evaluate a replacement tool to ensure any future UI development work is going to be done with as much future-proofing as possible.&lt;br /&gt;2.) Said replacement tool must give as good or better UI design flexibility as Forms.&lt;br /&gt;3.) Bonus points will be given for being "standards-based" and allow us to swap out the UI for another if need be. This will aid in creating multiple UIs for any given application area - Internal application, External (public) or Remote (business users visiting remote clients/locations) - given common back-end logic.&lt;br /&gt;4.) Existing developer skills (PL/SQL) would be advantageous to harness.&lt;br /&gt;5.) Development Tool must provide coding integration with client-side applications (MS Word, Excel, document-management system, cheque readers, barcode scanners, flatbed printers)&lt;br /&gt;&lt;br /&gt;Anyone like to hazard an educated guess (or do some crystal ball gazing) as to how things are going to pan out?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-7872430930043287021?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/lZCjG6tE1Sdr_2DqXqwhrXL1d8A/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lZCjG6tE1Sdr_2DqXqwhrXL1d8A/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/lZCjG6tE1Sdr_2DqXqwhrXL1d8A/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/lZCjG6tE1Sdr_2DqXqwhrXL1d8A/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/KSl8ooHuJn8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/7872430930043287021/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=7872430930043287021" title="17 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/7872430930043287021?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/7872430930043287021?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/KSl8ooHuJn8/is-news-all-bad-for-oracle-development.html" title="Is the news all bad for Oracle Development?" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>17</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/04/is-news-all-bad-for-oracle-development.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkMARHg-cSp7ImA9WxZWEUQ.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-1945993517376927909</id><published>2008-03-11T12:14:00.002+11:00</published><updated>2008-03-11T12:20:45.659+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-11T12:20:45.659+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Forms" /><category scheme="http://www.blogger.com/atom/ns#" term="APEX" /><category scheme="http://www.blogger.com/atom/ns#" term="JDeveloper" /><title>The war debate continues...</title><content type="html">I managed to get my hands on a copy of an article put together by Chris Muir with contributions from some leading names in Oracle development tool circles. The article attempts to shed light on &lt;a href="http://one-size-doesnt-fit-all.blogspot.com/2008/03/jdev-vs-apex-vs-forms-wars-continue-now.html"&gt;which development tool is the best: JDeveloper, Apex or Forms&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The article stands out as a nice centralised scoring system for basing a decision on which tool to use in different application environments, although there is no direct comparison outlining the &lt;em&gt;disadvantages&lt;/em&gt; of using each of the tools.&lt;br /&gt;&lt;br /&gt;Each of the tools contains a write-up of their capabilites with gradings given on a set of 9 explicit categories, and a score for each category is given out of 5.&lt;br /&gt;I noticed that all of the advocates of the tools made a point that each of their respective products could provide a workable application in "just a few clicks", but that at some point a typical developer would have to get down and dirty with some real coding to apply some complex business rules. &lt;br /&gt;&lt;br /&gt;So it seems to me that it all comes down to realising the actual capabilities of each tool, but the main driving factor would be the comfort the developer has in using the extension language associated with the tool - be that SQL, PL/SQL, Javascript or Java. Once you have enough experience with the tool and - more importantly - the extension language set, the capabilities of the tool open up more possibilities.&lt;br /&gt;&lt;br /&gt;When this point is realised, you can then work out where to apply your development crew. Clearly, since you are going to be working with an Oracle database, you would expect your developers to already have SQL and PL/SQL skills. But, if you want them to produce amazing applications, you also want them to specialise in the extension language. Now, what do think is more likely - Javascript or Java?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-1945993517376927909?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/x0Tqos11tZI6CM-EA1gW2Lj1H7U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/x0Tqos11tZI6CM-EA1gW2Lj1H7U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/x0Tqos11tZI6CM-EA1gW2Lj1H7U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/x0Tqos11tZI6CM-EA1gW2Lj1H7U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/rOYmD1RbxlM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/1945993517376927909/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=1945993517376927909" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/1945993517376927909?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/1945993517376927909?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/rOYmD1RbxlM/war-debate-continues.html" title="The &lt;s&gt;war&lt;/s&gt; debate continues..." /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>7</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/03/war-debate-continues.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEMHQnk8fyp7ImA9WxZQFUk.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-769680990245074984</id><published>2008-02-21T08:21:00.005+11:00</published><updated>2008-02-21T09:27:13.777+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-21T09:27:13.777+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Forms" /><category scheme="http://www.blogger.com/atom/ns#" term="APEX" /><category scheme="http://www.blogger.com/atom/ns#" term="JDeveloper" /><title>What will eventually replace Forms?</title><content type="html">Someone called 'Anonymous' (that guy sure does get around) posed a question from my previous posting on &lt;a href="http://marc-on-oracle.blogspot.com/2008/02/apex-vs-jdev-first-impressions.html"&gt;Apex vs JDeveloper&lt;/a&gt;, which I thought could flesh out nicely into a new blog, so here it is:&lt;br /&gt;&lt;blockquote&gt;Marc what do you think will eventually replace Forms Jdeveloper/ADF? Also, can you use Java/Jdev with Apex or is it basically PLSQL environment ?&lt;/blockquote&gt;&lt;br /&gt;Oracle has the vision of having JDeveloper and the ADF framework as its next "best thing". They are pumping their resources into re-working their eBusiness Suite from Forms to JDev/ADF, so with that investment comes a kind of reassurance that it will not be left by the wayside. They will continue to refine and mature the ADF technology, as well as ensuring that the Support structure is there for both eBusiness Suite users and those moving from Forms to JDeveloper.&lt;br /&gt;&lt;br /&gt;I think that Oracle is in a critical technology transition period, where the ADF technology they are promoting has not yet reached a point where it is mature as Forms. It is critical because people/businesses are going to realise that this is the case and will start to evaluate their other options more openly.&lt;br /&gt;&lt;br /&gt;ADF Faces doesn't come close to delivering the visually appealing UI that users demand for viewing their applications, although Faces RC is getting there. ADF Swing looks like it has the capability to be a contender to a Forms UI, but Swing itself seems to be falling out of favour amongst the Java community. Even Sun themselves are not expanding the Swing framework, but are instead developing and promoting Java FX as the replacement for Swing. So we can see that there is this never ending cycle of maturing a technology then putting it out to pasture in favour the new up-and-coming solution to everything. But I guess that's how the world turns and corporations make their money.&lt;br /&gt;&lt;br /&gt;So, I'm not really sure what will eventually replace Forms. In terms of Oracle tools, then I would side with JDeveloper/ADF for your standard application that involves not just database operations, but interaction with third-party/client-side applications. There is more emphasis on Apex for database centric applications that can be purely web-based. It depends how the application is to be deployed and used. &lt;br /&gt;For non-Oracle tools, it's worth looking at Adobe Flex and Microsoft's .NET (Oracle provides a nice .NET Data Access Components plugin for rapid database-app development) to see what they offer.&lt;br /&gt;&lt;br /&gt;Onto the second question. Apex is basically a PLSQL environment, sitting on top of (within) an Oracle database. It relies heavily on Javascript for client-side operations and AJAX functionality. I'm not sure if you can (or would want to) use Java or JDeveloper with Apex, since it is really just an application running from within the database. HTML pages are generated and served from the database, so the only Java calls would be to those classes that have been imported into the database. &lt;br /&gt;So, I would say No, Apex and JDeveloper are not meant for each other - a marriage such as that would not even last through the honeymoon period, there would be waaaay too much bickering and fighting going on.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-769680990245074984?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Fgl3lL9uHViCUY0kZccFK_3E_tU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Fgl3lL9uHViCUY0kZccFK_3E_tU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Fgl3lL9uHViCUY0kZccFK_3E_tU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Fgl3lL9uHViCUY0kZccFK_3E_tU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/JPTboZT5ktc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/769680990245074984/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=769680990245074984" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/769680990245074984?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/769680990245074984?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/JPTboZT5ktc/what-will-eventually-replace-forms.html" title="What will eventually replace Forms?" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>4</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/02/what-will-eventually-replace-forms.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUYGQXY8fip7ImA9WxZQE0U.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-6263478419768226170</id><published>2008-02-19T09:33:00.004+11:00</published><updated>2008-02-19T13:12:00.876+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-19T13:12:00.876+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="APEX" /><category scheme="http://www.blogger.com/atom/ns#" term="JDeveloper" /><title>Apex vs JDev - first impressions</title><content type="html">Following on from our &lt;a href="http://marc-on-oracle.blogspot.com/2008/01/jdeveloper-training.html"&gt;JDeveloper/ADF workshop&lt;/a&gt;, we also reserved some time to compare the benefits of Apex (formerly HTMLDB). We brought in Penny Cookson from &lt;a href="http://www.sagecomputing.com.au"&gt;Sage Computing&lt;/a&gt; to give us a 3-day run-down. Now I feel that I can give a quick first-impressions comparison between the two development approaches. Here's a quick overview, in no particular order.&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Apex seems to be very good at rapid development for simple every-day data and database actions.&lt;br /&gt;&lt;li&gt;Apex does not seem to be very good at calling and interacting with third-party applications (except through webservices).&lt;br /&gt;&lt;li&gt;Apex allows rich data displays, although it is restricted to browser-compatible constructs such as HTML, Javascript and Flash charts.&lt;br /&gt;&lt;li&gt;JDev requires a larger learning curve than Apex, but allows separation of layers (MVC), making it easier if a differing (UI) technology is to be introduced later on down the track.&lt;br /&gt;&lt;li&gt;Apex simply requires the database (which can be scaled), and does not require separate Application Servers for distribution.&lt;br /&gt;&lt;li&gt;Neither Apex nor JDev's ADF Faces would allow us to reproduce our current Forms application look-and-feel as it stands.&lt;br /&gt;&lt;li&gt;JDev's ADF Swing may come close to providing the same Forms application UI, but requires a larger amount of Java programming skills.&lt;br /&gt;&lt;li&gt;Oracle is using Apex on its subdomains Metalink and AskTom, and seems to be quite productive with the experience.&lt;br /&gt;&lt;li&gt;Oracle is using JDev/ADF for re-developing its eBusiness Suite.&lt;br /&gt;&lt;li&gt;(As an aside, Oracle also uses Adobe Flex on Metalink - and it looks good.)&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;To explain where I am coming from, and the users our application has to appease, our current Forms application was met with a furious uproar when we moved from Forms 6i to Forms 10g. The users were very keen to retain all visual aspects (even down to the specific shades of grey), and also expected to retain productivity using either keyboard or mouse. In most cases we were able to provide a one-to-one match, but we had to fight the code to allow interaction with some client-side third-party apps.&lt;br /&gt;&lt;br /&gt;If we are to attempt to reproduce Oracle Forms usability with a new technology - be that Apex, JDeveloper, or something else entirely - it has to allow the users to be as productive (or more so) based on how they already operate using the current Forms application. But we also have to consider developer productivity, and whole range of other factors.&lt;br /&gt;&lt;br /&gt;As it stands, it seems that Apex would only be suitable for reproducing a small subset of our security/maintenance screens, or for our internet-facing applications, but could probably not cope with the demand from our internal users. JDeveloper (ADF Faces) may &lt;em&gt;eventually &lt;/em&gt;be a candidate for our internal application development, but still does not seem to be mature enough in regard to rich UI components (note that I have not had a chance to review the offerings of ADF Faces RC to any extent).&lt;br /&gt;&lt;br /&gt;So, the search is still on for a development approach that achieves that fine balance between developer productivity and user satisfaction...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-6263478419768226170?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fjCIezJ1wZJzjfm8H0wy9N36NEA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fjCIezJ1wZJzjfm8H0wy9N36NEA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fjCIezJ1wZJzjfm8H0wy9N36NEA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fjCIezJ1wZJzjfm8H0wy9N36NEA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/wP4x7h7BBGI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/6263478419768226170/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=6263478419768226170" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/6263478419768226170?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/6263478419768226170?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/wP4x7h7BBGI/apex-vs-jdev-first-impressions.html" title="Apex vs JDev - first impressions" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>7</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/02/apex-vs-jdev-first-impressions.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUUGQ3s_cCp7ImA9WxZRE0g.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-4071845289346247306</id><published>2008-02-07T13:38:00.000+11:00</published><updated>2008-02-07T15:07:02.548+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-02-07T15:07:02.548+11:00</app:edited><title>Flexing Oracle</title><content type="html">Attempting to create a Data Access Descriptor so that I can access pl/sql via a web browser, or other simple http access. This will come in handy if/when I need to access XML data when using another UI framework (such as Adobe Flex)&lt;br /&gt;First, login as SYS into my 11g database and run the following:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;BEGIN&lt;br /&gt;  DBMS_EPG.create_dad (&lt;br /&gt;    dad_name =&gt; 'dataAccess',&lt;br /&gt;    path     =&gt; '/dataAccess/*');&lt;br /&gt;END;&lt;br /&gt;/&lt;br /&gt;&lt;br /&gt;BEGIN&lt;br /&gt;  DBMS_EPG.authorize_dad (&lt;br /&gt;    dad_name =&gt; 'dataAccess',&lt;br /&gt;    user     =&gt; '&amp;lt;databaseuser&amp;gt;');&lt;br /&gt;END;&lt;br /&gt;/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Then I create a simple test procedure in my &lt;databaseuser&gt; schema&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;CREATE OR REPLACE get_test_xml_p&lt;br /&gt;AS&lt;br /&gt;  lvc_cust_id VARCHAR2(10) := '1';&lt;br /&gt;BEGIN&lt;br /&gt;  htp.p('&amp;lt;?xml version="1.0" ?&amp;gt;&lt;br /&gt;        &amp;lt;CUSTOMERS&amp;gt;&lt;br /&gt;          &amp;lt;CUSTOMER&amp;gt;&lt;br /&gt;            &amp;lt;ID&amp;gt;'||&lt;br /&gt;            lvc_cust_id||&lt;br /&gt;            '&amp;lt;/ID&amp;gt;&lt;br /&gt;            &amp;lt;NAME&amp;gt;'||&lt;br /&gt;            'John Doe|| &lt;br /&gt;            '&amp;lt;/NAME&amp;gt;&lt;br /&gt;          &amp;lt;/CUSTOMER&amp;gt;&lt;br /&gt;        &amp;lt;/CUSTOMERS&amp;gt;');&lt;br /&gt;END GET_TEST_XML_P;&lt;br /&gt;/&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;I can alter that to grab dynamic data later. Meanwhile, test access to that procedure in my favourite browser.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;http://&amp;lt;machinename&amp;gt;:&amp;lt;port&amp;gt;/dataAccess/&amp;lt;databaseuser&amp;gt;.get_test_xml_p&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It brings the expected results, so let's go from there...&lt;br /&gt;In Adobe Flex, I can then create a request to call the procedure:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;...&lt;br /&gt;&amp;lt;mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" width="682" height="426" creationComplete="getTestXML.send()" &amp;gt;&lt;br /&gt; &amp;lt;mx:HTTPService &lt;br /&gt;  id="getTestXML" &lt;br /&gt;  url="http://&amp;lt;machinename&amp;gt;:8080/dataAccess/&amp;lt;databaseuser&amp;gt;.get_test_xml_p" &lt;br /&gt;  useProxy="false" /&amp;gt;&lt;br /&gt;...&lt;br /&gt;    &amp;lt;mx:TextInput width="100" id="custID" text="{getTestXML.lastResult.CUSTOMERS.CUSTOMER.ID}"/&amp;gt;&lt;br /&gt;    &amp;lt;mx:TextInput id="custName" text="{getTestXML.lastResult.CUSTOMERS.CUSTOMER.NAME}"/&amp;gt;&lt;br /&gt;...&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And, hey presto, the data is returned into the expected fields...&lt;br /&gt;Interesting points to note:&lt;br /&gt;1. The XML nodes are case sensitive, so when you are retrieving data, make sure you code it correctly.&lt;br /&gt;   getTestXML.lastResult.CUSTOMERS.CUSTOMER.ID is not equal to getTestXML.lastResult.customers.customer.id&lt;br /&gt;2. You will be prompted for an XDB login, which equates to the &lt;databaseuser&gt; login. I am fairly sure this can be setup programmatically somewhere along the line (and can of course be added as a parameter to the Data Access Descriptor through EnterpriseManager. Putting the username and password into the URL does not seem to want to work.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-4071845289346247306?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TTXbFMxg9B0LcSiB4b3gGDrWzJk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TTXbFMxg9B0LcSiB4b3gGDrWzJk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TTXbFMxg9B0LcSiB4b3gGDrWzJk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TTXbFMxg9B0LcSiB4b3gGDrWzJk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/jMmB60DTSYQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/4071845289346247306/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=4071845289346247306" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/4071845289346247306?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/4071845289346247306?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/jMmB60DTSYQ/flexing-oracle.html" title="Flexing Oracle" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/02/flexing-oracle.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUDQng6fyp7ImA9WxZSFUs.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-3878276199078972865</id><published>2008-01-29T09:30:00.000+11:00</published><updated>2008-01-29T09:44:33.617+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-01-29T09:44:33.617+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="JDeveloper" /><category scheme="http://www.blogger.com/atom/ns#" term="ADF" /><title>ADF - Using Proxy Authentication</title><content type="html">An interesting article has appeared on JHeadstart's Blog that outlines the approach to use if you currently have an application that uses database login credentials to define authentication and access. Once you move to a web application, database connections are channeled through a connection pool that consists of one pre-defined login user. &lt;br /&gt;&lt;br /&gt;Using proxy authentication allows you to maintain the user details of logged-in users. &lt;a href="http://blogs.oracle.com/jheadstart/2008/01/28"&gt;This article &lt;/a&gt;steps through the options available when this approach is needed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-3878276199078972865?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/XLU45Y7gwil951IGh1hgNGyZmIw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XLU45Y7gwil951IGh1hgNGyZmIw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/XLU45Y7gwil951IGh1hgNGyZmIw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/XLU45Y7gwil951IGh1hgNGyZmIw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/dp-4rjYgAws" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/3878276199078972865/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=3878276199078972865" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/3878276199078972865?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/3878276199078972865?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/dp-4rjYgAws/adf-using-proxy-authentication.html" title="ADF - Using Proxy Authentication" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/01/adf-using-proxy-authentication.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYASHkzeSp7ImA9WxZSFUg.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-2980656024448256271</id><published>2008-01-29T08:24:00.000+11:00</published><updated>2008-01-29T08:35:49.781+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-01-29T08:35:49.781+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Forms" /><category scheme="http://www.blogger.com/atom/ns#" term="JDeveloper" /><title>JDeveloper Training</title><content type="html">We had &lt;a href="http://one-size-doesnt-fit-all.blogspot.com/"&gt;Chris Muir &lt;/a&gt;come in to give us a 5-day JDeveloper/ADF run-down. Our class of 12 were all extremely impressed with the presentation and we have all come away with a vast amount of new knowledge and respect for the new techniques we can employ. &lt;br /&gt;&lt;br /&gt;In regards to the viewpoint of some Forms developers, I can see there will be some points of confusion when undertaking development in JDeveloper using ADF Business Components.&lt;br /&gt;&lt;br /&gt;For example, when creating Entity Objects we are basically abstracting the database columns as attributes of a java class.&lt;br /&gt;Then, when we create a View Object, those attributes are used to define what is displayed. However, if we want to filter or join 2 entity objects in the view object, we have to return to the database field definition (basically add a WHERE clause to join them).&lt;br /&gt;&lt;br /&gt;The reason for this is that a VO can be based directly on database tables and fields without referring to any EOs. So, that is something that people switching between Relational and Object-Oriented related thinking must bear in mind.&lt;br /&gt;&lt;br /&gt;There is also the learning curve of Java programming, but I guess this is just something that has to be done. In Forms development, it is easy to put together a Forms module that provides easy access to any database table and provide Enter- and Execute-Query functionality without any PL/SQL coding whatsoever. The same is true for JDeveloper programming - it seems easy enough to put together a basic web application that will give access to any particular table and automatically provide the tools and code to allow a page with that same Enter- and Execute-Query-like functionality. &lt;br /&gt;&lt;br /&gt;However, everyone knows that sooner or later (probably sooner), you are going to have to enforce some particularly complicated business rules and calculations that lead to complex navgation rules. As with Forms, where you will have to code up some PL/SQL either in the Form (or PLL) or within the database, the same holds true for JDeveloper. Somewhere along the line you will realize that the simple Enter-Execute methods are not enough, and you will need to place some Java code in a backing bean.&lt;br /&gt;&lt;br /&gt;We will be attending an APEX course in a couple of weeks, and I'm sure the same concept will be shown again - all the simple stuff will be visually appealing, of course. But, as soon as some complex algorithms need to be referenced, we will be forced to use Javascript to twist the simple concepts into something that works the way the users want it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-2980656024448256271?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/GjRKU6Jnjj2OMOgQba53DvrWRuo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GjRKU6Jnjj2OMOgQba53DvrWRuo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/GjRKU6Jnjj2OMOgQba53DvrWRuo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/GjRKU6Jnjj2OMOgQba53DvrWRuo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/_X4r7IXuteY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/2980656024448256271/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=2980656024448256271" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/2980656024448256271?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/2980656024448256271?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/_X4r7IXuteY/jdeveloper-training.html" title="JDeveloper Training" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/01/jdeveloper-training.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYFRHk7eyp7ImA9WxZSFUg.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-2587213949824139037</id><published>2008-01-18T08:09:00.000+11:00</published><updated>2008-01-29T08:35:15.703+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-01-29T08:35:15.703+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Forms" /><category scheme="http://www.blogger.com/atom/ns#" term="JDeveloper" /><category scheme="http://www.blogger.com/atom/ns#" term="ADF" /><title>Forms Lingo translated to JDeveloper using ADF (Part 1)</title><content type="html">Oracle Forms packages a lot of functionality up for us so that we don't have to worry too much about things like data binding.&lt;br /&gt;Creating an application using ADF in JDeveloper requires us to do a lot of thinking that was previously done for us by Forms, but also attempts to provide us with some flexibility.&lt;br /&gt;&lt;br /&gt;In Forms, we usually create a Forms Module by firstly determining the base table/view that we are going to use, then creating a block based on one or more of those tables/views.&lt;br /&gt;In JDeveloper, this process is more involved, as its inherent flexibility allows you to define the tables/views you are going to use, as well as specifying whether you want to allow that data to be read-only or updateable. Specifying this accessibility level early on allows you to restrict the data access methods that are auto-generated later. The application construction methods used by JDeveloper aid in using a bottom-up approach to development. The developer is made to think about the transactions that are to be involved in the module, and apply specific coding style to the development of each screen depending on the final required functionality, as well as being given the flexibility of changing the entire approach if more functionality is later required.&lt;br /&gt;&lt;br /&gt;In Forms, once a base table block is set up, you have control over the fields that are to be returned and populated from the query, as well as the physical layout characteristics of those fields. This concept is slightly separated in JDeveloper. At the point where you specify the query (or queries) that you are going to use within the app, you only have control over the suggested physical labelling of the returned fields at that time. The other physical characteristics are handled in the View component. Because ADF development promotes the separation of the visual aspects from the business logic components, its development is split up into what is referred to as MVC - the Model/View/Controller. The Model component takes care of the data model and its relationship structure(s). The View components take care of how the user interface is presented. The Controller components hold the events and actions that interaction with the View components have on the Model components, such as pressing button, or clicking a link.&lt;br /&gt;&lt;br /&gt;MVC terminology can be translated into Forms components. The Model is the underlying database tables (or stored procedures or dynamic SQL statements, etc) on which you base your blocks. The View is the physical canvas layout of your Forms Items - all of the UI components such as items, tabs, buttons, trees, drop-down lists etc. The Controller is all of the triggers and program units that translate events and user actions into business logic - as well as the Forms built-ins that control the flow of triggers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-2587213949824139037?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/pDVmq-vUi9-uzfOlTC4lMy0L0cQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pDVmq-vUi9-uzfOlTC4lMy0L0cQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/pDVmq-vUi9-uzfOlTC4lMy0L0cQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/pDVmq-vUi9-uzfOlTC4lMy0L0cQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/YRQfHJpC4ek" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/2587213949824139037/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=2587213949824139037" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/2587213949824139037?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/2587213949824139037?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/YRQfHJpC4ek/forms-lingo-translated-to-jdeveloper.html" title="Forms Lingo translated to JDeveloper using ADF (Part 1)" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2008/01/forms-lingo-translated-to-jdeveloper.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C04GSXYyeyp7ImA9WxZTFk0.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-5373286047567398327</id><published>2007-12-27T15:39:00.000+11:00</published><updated>2008-01-18T07:32:08.893+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-01-18T07:32:08.893+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="11g database" /><title>11g database installation and native webservices</title><content type="html">Downloaded and installed an 11g database on a spare Windows XP machine that was floating around, while our local DBA finishes up installing our real playground on a Solaris box.&lt;br /&gt;&lt;br /&gt;The first thing I noticed was the size of the download - Whoa! 1.8 Gb for the 11g database setup, expanding out to 2.9 Gb for the real installed database. Compare this to the download size of a 10g setup which was a smidgeon under 700Mb, expanding out to 1.6 Gb for a final installed database. I don't know what is included in the new features to take up that much more space, but *insert expletive here*, it seems to have taken quite a leap.&lt;br /&gt;&lt;br /&gt;Once the Windows installation completed (after re-starting a couple of times due to a very invasive piece of currently installed software on the machine that had taken over the JVM - thanks Mercury!), I ensured the standard SCOTT/TIGER schema was there (Ah, EMP and DEPT, will I never forget thee), and then used the Enterprise Manager to setup a new schema. Oh, and I notice that the EM address is now accessed over https - good to see, although I kept getting certificate errors - probably an IE setting gone awry. Yes, yes, I should be using Firefox, move on...&lt;br /&gt;&lt;br /&gt;One of the driving forces behind getting the database up and running was to test out a new capability of 11g - native Web Services for database PL/SQL code.&lt;br /&gt;Ok, so new schema gets the XDB permissions granted (XDB_WEBSERVICES, XDB_WEBSERVICES_OVER_HTTP, XDB_WEBSERVICES_WITH PUBLIC) which are required for various methods of accessing web services, I assume. Then a new package is created. Something simple first - GET_TEXT_F: a function that returns some text; should we use the tried and tested "Hello World", or try something new and exciting?&lt;br /&gt;&lt;code&gt;&lt;br /&gt;create or replace&lt;br /&gt;function get_text_f return varchar2 is&lt;br /&gt;begin&lt;br /&gt;return ('Marc was here');&lt;br /&gt;end;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Spectacular! So, in theory with all of that in place, we should be able to call that little function as a web service. First, determine the WSDL:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;http://&amp;lt;myuser&amp;gt;:&amp;lt;mypassword&amp;gt;@&amp;lt;mymachine&amp;gt;:&amp;lt;myport&amp;gt;/orawsv/&amp;lt;MYSCHEMA&amp;gt;/GET_TEXT_F?wsdl&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Have to ensure schema and function name are in UPPERCASE! Also had a bit of a stumble with the first run, because the port for webservices had not been set! To fix that, it can simply be set manually, although I'm not sure if you are restricted to certain ports (topic for investigation later...).&lt;br /&gt;&lt;code&gt;&lt;br /&gt;execute dbms_xdb.setHttpPort(8080);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Trying the wsdl retrieval again after that is set gives a nice auto-generated WSDL document based on the function.&lt;br /&gt;&lt;br /&gt;Use SOAP UI (&lt;a href="http://www.soapui.org"&gt;www.soapui.org&lt;/a&gt;) to do some quick tests of the simple function (you must also remember to enter your database credentials in the SOAP request attributes) before trying something a bit more meaty! &lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Complex data types.&lt;/strong&gt;&lt;br /&gt;OK, say I have a database table called customers, structured something like&lt;br /&gt;&lt;code&gt;&lt;br /&gt;CREATE TABLE customers (&lt;br /&gt;ID NUMBER(10),&lt;br /&gt;NAME VARCHAR2(50),&lt;br /&gt;DOB DATE);&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Fairly simple, yes? Could I expect a table ROWTYPE return to be automatically translated by the native 11g webservice to WSDL without any extra coding? Lets see....&lt;br /&gt;&lt;code&gt;&lt;br /&gt;create or replace function get_customer_f (p_customer_id in number) return customers%ROWTYPE is&lt;br /&gt;lvt_customer_rec customers%ROWTYPE;&lt;br /&gt;begin&lt;br /&gt;select *&lt;br /&gt;into lvt_customer_rec&lt;br /&gt;from customers&lt;br /&gt;where customer_id = p_customer_id;&lt;br /&gt;return (lvt_customer_rec);&lt;br /&gt;end;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Yes, I know, I don't have any exception handling, move on...&lt;br /&gt;Meanwhile, lets test to see what the WSDL comes out as&lt;br /&gt;&lt;code&gt;&lt;br /&gt;http://&amp;lt;myuser&amp;gt;:&amp;lt;mypassword&amp;gt;@&amp;lt;mymachine&amp;gt;:&amp;lt;myport&amp;gt;/orawsv/&amp;lt;MYSCHEMA&amp;gt;/GET_CUSTOMER_F?wsdl&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Bzzzzzzzzzzzz, you basically get a 'Error processing input' error.&lt;br /&gt;What we need to do is transform the return data into a native database data type, which means you are going to have to create TYPEs based on what your functions are going to accept and return. So, in this instance, we would need to create a customer_type&lt;br /&gt;&lt;code&gt;&lt;br /&gt;CREATE OR REPLACE TYPE CUSTOMER_TYPE AS OBJECT (&lt;br /&gt;ID number(10),&lt;br /&gt;NAME varchar2(50)&lt;br /&gt;)&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;then, we need to change our function to cope with the new type:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;create or replace function get_customer_f (p_customer_id in number) return customer_type is&lt;br /&gt;lvt_customer_type customer_type;&lt;br /&gt;begin&lt;br /&gt;lvt_customer_type := customer_type(null,null);&lt;br /&gt;select id, name&lt;br /&gt;into lvt_customer_type.id, lvt_customer_type.name&lt;br /&gt;from customers&lt;br /&gt;where customer_id = p_customer_id;&lt;br /&gt;return (lvt_customer_type);&lt;br /&gt;end;&lt;br /&gt;&lt;/code&gt;&lt;br /&gt;Now, since the database can trace the CUSTOMER_TYPE back down to primitive database types, the WSDL can be auto-generated. I would like to see if Oracle could manage to make this just a little bit easier for us kids who don't want to go around making up database types left, right and center.&lt;br /&gt;Time for a post to &lt;a href="http://mix.oracle.com"&gt;mix.oracle.com&lt;/a&gt;&lt;br /&gt;That's all for now...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-5373286047567398327?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/O74srVJfWt8X-gXSXpT-W8H1gQk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/O74srVJfWt8X-gXSXpT-W8H1gQk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/O74srVJfWt8X-gXSXpT-W8H1gQk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/O74srVJfWt8X-gXSXpT-W8H1gQk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/vhu_GGM_EpM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/5373286047567398327/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=5373286047567398327" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/5373286047567398327?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/5373286047567398327?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/vhu_GGM_EpM/11g-database-installation-and-native.html" title="11g database installation and native webservices" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2007/12/11g-database-installation-and-native.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEYASHczeip7ImA9WxZTFk0.&quot;"><id>tag:blogger.com,1999:blog-2152080674695102867.post-4135166721019138316</id><published>2007-12-24T07:49:00.000+11:00</published><updated>2008-01-18T07:35:49.982+11:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-01-18T07:35:49.982+11:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Forms" /><category scheme="http://www.blogger.com/atom/ns#" term="JDeveloper" /><title>ADF Beginnings</title><content type="html">Ok, I have started the ascent into the learnings of Oracle's ADF technology stack.&lt;br /&gt;&lt;br /&gt;A bit of background first: I am mainly an Oracle Forms/Reports and PL/SQL developer, and have been for the past 10+ years, but its been a bit of a static learning path, and I have only picked up a few new things here and there since I have been on basically the same project during all of that time. I started my first real-world project with Forms 4.5 (16-bit) and when it was in a production state, helped migrate it up to a 32-bit version. Then I moved interstate (from the Australian West Coast, to Sydney) since the project I originally worked on was sold as an application package to an interstate related organisation. &lt;br /&gt;&lt;br /&gt;This move saw the same app being migrated and enhanced to a 6i/8i app, and I also had the chance to code a subset of it into a VB6/Access application that could be used during network/database downtime. &lt;br /&gt;&lt;br /&gt;Then the application code was picked up by another interstate related organisation in Melbourne, so I packed my bags and arrived there on Boxing Day of 1999. Things started to get a little more interesting here as the team was interested in making a a more robust application with more emphasis on visual navigation, so among other things, I spent some time helping to put together a Hierarchical Tree control for navigation between Forms. This has worked out very well, and continues to be a great way for the users to jump between application areas.&lt;br /&gt;&lt;br /&gt;At the end of 2005, we started the migration to 10g (both Forms and the Database), and successfully deployed the 're-stumped' application in early 2007. The migration gave us a few headaches - since our users had a high reliability on the visual and navigational aspects of the application, sorting out the JVM idiosynchrasies required close (intimate?) interaction with Oracle support. Neither JInitiator nor Sun Java 1.5 gave us 100% satisfaction, but JInitiator turned out to be the lesser of two evils, so we have gone the route for now.&lt;br /&gt;&lt;br /&gt;I also spent some time creating a build and deployment tool (using Forms) that comes in two flavours:  One that developers could use to easily transfer and compile Forms code to our development unix application server and allow them to run it in their own isolated environment; and another that the Build Administrator can use to extract modules from our Source Control application and transfer and compile it in a series of easy steps to our Test application server.&lt;br /&gt;&lt;br /&gt;Meanwhile, we have started looking at expanding requirements and the need to ensure we are working on a supported development base. Since the wafting tendrils of the fear of Forms being de-supported seems to be looming, we have started looking at alternatives for a future front-end for our application. Management has also been throwing around the 'SOA' acronym, and we all know what that means! (If any does actually know what that means, please feel free to enlighten me...)&lt;br /&gt;&lt;br /&gt;So, a couple of months ago (hey, I've been a busy man), I downloaded JDeveloper 10g (10.1.3.2 AND 10.1.3.3) and I've been using it for a bit of Java development that we have gradually been implementing on both the Application Server, and on the Client. &lt;br /&gt;Now, I have downloaded JDev 11g (Tech Preview 2) and have noticed a few annoying bugs with it (Refactoring is a nightmare), as well as the complete absence of SOA and web servce functionality.&lt;br /&gt;&lt;br /&gt;My intention now is to have a bash at ADF development as well as looking at APEX and whatever it has to offer.&lt;br /&gt;&lt;br /&gt;*UPDATE* JDev 11g Tech Preview 3 has just been made available. Stay tuned for more excitement as the story unfolds...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/2152080674695102867-4135166721019138316?l=marc-on-oracle.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/cwXmDYGTI23ezygMEduiuNNIT9U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cwXmDYGTI23ezygMEduiuNNIT9U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/cwXmDYGTI23ezygMEduiuNNIT9U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/cwXmDYGTI23ezygMEduiuNNIT9U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/MarcOnOracle/~4/IWUEdiA7A10" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://marc-on-oracle.blogspot.com/feeds/4135166721019138316/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=2152080674695102867&amp;postID=4135166721019138316" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/4135166721019138316?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/2152080674695102867/posts/default/4135166721019138316?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/MarcOnOracle/~3/IWUEdiA7A10/adf-beginnings.html" title="ADF Beginnings" /><author><name>Marc Thompson</name><uri>http://www.blogger.com/profile/14806085398344354993</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://marc-on-oracle.blogspot.com/2007/12/adf-beginnings.html</feedburner:origLink></entry></feed>

