Chris Muir

Subscribe to Chris Muir feed
Updated: 8 hours 47 min ago

A special event for ADF EMG members - world wide and virtual

Tue, 2011-04-12 07:14

I'm happy to announce that three key participants of the ADF EMG will be presenting alongside Oracle staff at the upcoming "OTN Virtual Developer Day - Rich Enterprise Applications" .... a virtual conference on all things "ADF" in early May, open to the general public.

Jean-Marc Desvaux, John Stegeman and Sten Vesterli will be presenting under the "Best Practices" stream on the following topics:

* ADF Security in a Project-Centric Environment - An ADF Case Study (Jean-Marc)
* The bit every one forgets: Unit testing your ADF applications with JUnit (John)
* Starting an Enterprise ADF project (Sten)

I need not remind members that these three gentlemen are well known in the ADF community for their volunteer efforts in writing blogs and presenting, writing OTN forum papers, answering OTN forum questions, and even an upcoming ADF book!

Overall what I like about this event is there's a good opportunity to pick and choose across 5 streams. As such depending on your experience and background, you can dip your toe into all sorts of different ADF topics, from basics to best practices, all from the comfort of you're own desk.

The online conference will be repeated in several time zones to ensure everyone gets a chance to attend:

N. America - Tuesday, May 3rd, 2011
08:00 a.m. – 12:30 p.m. US PT

Europe / Russia - Tuesday, May 10th, 2011
08:00 a.m. – 12:30 p.m. U.K. Time
9:00 a.m. – 1:30 p.m. CET

Central / South America - Tuesday, May 17th, 2011
08:00 a.m. – 12:30 p.m. US Eastern Time
09:00 a.m. – 1:30 p.m. Brazil time

Asia Pacific - Tuesday, May 24th, 2011
08:00 a.m. – 12:30 p.m. India Standard Time
10:30 a.m. – 02:30 p.m. Beijing Time

If you're interested in attending please follow this link to register.

Good luck to Jean-Marc, John and Sten, I look forward to hearing them present, all 3 always have valuable information to share.

af:table – Restoring the basic browser copy functionality

Sun, 2011-04-03 23:45
One of the first things any computing user learns is how to select text with the mouse or keyboard, then copy & paste the selected text. This simple functionality is supported in most applications including browsers, making it a very familiar facility to all users.

There are specific scenarios under certain browsers with the af:table component in ADF Faces RC 11.1.1.4.0 (also verified in 11.1.1.2.0) where the ability to select and copy text is absent.

This post identifies the specific scenarios, as well as a potential workaround for Internet Explorer (only).

The Issue

The following picture from Internet Explorer 7 (also replicated in IE8) shows a simple af:table without its selectionListener and rowSelection properties set.

If you look closely you can see with my mouse I've selected and highlighted the "Hong" in "HongKong".

While I can't demonstrate it in a screenshot, if you were to right click on the selected text you would see IE's standard right mouse menu with options such as Copy.

Here we can see similar functionality in Firefox 3.6, with the "Kingdom" in "United Kingdom" selected:

And finally Chrome 10, the "Can" in "Canada" selected:

(Unfortunately I don't have access to Safari to test its behaviour)

In all of these browsers it would be a reasonable requirement that the user would want to be able to highlight text and copy it to some other application running on their desktop.

Let's revisit the same af:table within each browser, this time with the selectionListener and rowSelection properties set.

The following picture shows IE7 (also confirmed in IE8) where you can see the effects of the selectionListener and rowSelection properties, highlighting the selected row. But what you can't do with your mouse is select any text. This disables the user from copying any text from the table:

Yet oddly in Firefox 3.6 the user can do both:

And in Chrome 10 they can too:

The behaviour or lack of it in Internet Explorer is certainly undesirable, even more so as most corporate environments will choose IE as their preferred browser. However via bug 9830307 Oracle has noted that this is in fact by design, and Oracle is planning to remove the functionality from the other browsers too.

Solution

The following technique demonstrates a solution for Internet Explorer displaying an af:table with its selectionListener and rowSelector properties set.

The technique requires us to create our own Copy contextMenu option for the table, and then via a combination of JavaScript, af:clientListener and af:clientAttribute tags, we'll copy the user selected table cell's data to the clipboard.

Starting out this is the code for the page containing the af:table before any modifications:
<?xml version='1.0' encoding='UTF-8'?>
xmlns:h="http://java.sun.com/jsf/html" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">





rows="#{bindings.CountriesView1.rangeSize}"
emptyText="#{bindings.CountriesView1.viewable ? 'No data to display.' : 'Access Denied.'}"
fetchSize="#{bindings.CountriesView1.rangeSize}" rowBandingInterval="0"
selectedRowKeys="#{bindings.CountriesView1.collectionModel.selectedRow}"
selectionListener="#{bindings.CountriesView1.collectionModel.makeCurrent}" rowSelection="single"
id="t1" columnStretching="last">
headerText="#{bindings.CountriesView1.hints.CountryId.label}" id="c1">


headerText="#{bindings.CountriesView1.hints.CountryName.label}" id="c2">






We then extend the af:table with a contextMenu facet, which includes an af:clientListener:








For each column we wish to provide the copy functionality, we extend each by including an af:clientListener tag and af:clientAttribute tag as follows:
                     headerText="#{bindings.CountriesView1.hints.CountryId.label}" id="c1">




....note the use of the af:clientListener and af:clientAttribute tags *within* the af:outputText. Also note how the af:clientAttribute's value EL expression has been changed to match that of the parent af:outputText value.

From the code above, each af:clientListener makes a call to separate JavaScript functions captureTableFieldName() and copyMenu. We provide these in JavaScript attached to the page :

var globalLastVisitedField = null;

/*
* Given the user clicking on a field in a table, captures the field name to be later used by the copyMenu
* function
*/
function captureTableFieldName() {
return function (evt) {
evt.cancel();
globalLastVisitedField = evt.getSource();
}
}
/*
* Function referenced from the clientListener on the copy menu option
*/
function copyMenu(evt) {
// Copy the last visited field to the clipboard
if (globalLastVisitedField == null) {
alert("copyMenu() Error: No field could be identified to be in focus");
}
else if (navigator.appName != "Microsoft Internet Explorer") {
alert("Copy function is only supported in Microsoft Internet Explorer");
}
else {
var txt = globalLastVisitedField.getProperty("ItemValue");
window.clipboardData.setData('Text', "" + txt);
}
evt.cancel();
}
The complete code for the page is as follows:
<?xml version='1.0' encoding='UTF-8'?>
xmlns:h="http://java.sun.com/jsf/html" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">




var globalLastVisitedField = null;

/*
* Given the user clicking on a field in a table, captures the field name to be later used by the copyMenu
* function
*/
function captureTableFieldName() {
return function (evt) {
evt.cancel();
globalLastVisitedField = evt.getSource();
}
}
/*
* Function referenced from the clientListener on the copy menu option
*/
function copyMenu(evt) {
// Copy the last visited field to the clipboard
if (globalLastVisitedField == null) {
alert("copyMenu() Error: No field could be identified to be in focus");
}
else if (navigator.appName != "Microsoft Internet Explorer") {
alert("Copy function is only supported in Microsoft Internet Explorer");
}
else {
var txt = globalLastVisitedField.getProperty("ItemValue");
window.clipboardData.setData('Text', "" + txt);
}
evt.cancel();
}



rows="#{bindings.CountriesView1.rangeSize}"
emptyText="#{bindings.CountriesView1.viewable ? 'No data to display.' : 'Access Denied.'}"
fetchSize="#{bindings.CountriesView1.rangeSize}" rowBandingInterval="0"
selectedRowKeys="#{bindings.CountriesView1.collectionModel.selectedRow}"
selectionListener="#{bindings.CountriesView1.collectionModel.makeCurrent}" rowSelection="single"
id="t1" columnStretching="last">









headerText="#{bindings.CountriesView1.hints.CountryId.label}" id="c1">





headerText="#{bindings.CountriesView1.hints.CountryName.label}" id="c2">









How The Solution Works

When the user wants to invoke the Copy function, there's effectively two actions. First they right click the individual af:outputText rendered in a cell of the table. Second after the contextMenu appears as a result of the right click, the user then left clicks on the Copy af:commandMenuItem. The action of selecting the af:commandMenuItem obscures the table cell clicked. As such the two distinct operations require we handle them separately:

1) On the first right click we capture the name of the field. This is what the af:clientListener within the af:outputText field does, by calling captureTableFieldName() storing the field name as a JavaScript global to be retrieved later.

2) On the left click on the Copy menu option that appears in the contextMenu, the af:clientListener within the af:commandMenuItem calls the copyMenu JavaScript function.

The copyMenu function armed with the field name captured and stored in the JavaScript global from step 1, retrieves the relating "ItemValue" property which is the value from the af:clientAttribute tag within the af:outputText. It then copies the relating value to the Browser's clipboard.

Note the call to window.clipboardData.setData. This is the limiting code that makes this solution only useful in Internet Explorer. From research there isn't a simple solution available in other browsers. As such in this example we simply alert the user the functionality is only supported in IE.

Limitations

From a design time point of view, having to add the af:clientListener and af:clientAttribute to each column is certainly a pain. If anybody can think of a simpler solution your comments would be appreciated.

From a runtime point of view, as already explained the workaround is specific to Internet Explorer.

Though we haven't undertaken significant amounts of testing we've also found limitations in applying this to check boxes and date fields. In the case of check boxes we can't seem to derive the underlying value, and with the date field we sometimes get the date and time in the wrong format. There's probably solves for both of these issues but beyond the general technique described here.

As usual developers adopting this code should be careful to test in their own environments as it hasn't been rigorously tested in a production environment.

Credit

Thanks to Penny Cookson from SAGE Computing Services for the original solution.

SAGE Computing Services Success: Forms upgrade to 11g

Wed, 2011-03-30 08:51
I don't normally write these sort of blog posts, but Oracle's been keen to let customers know how simple the upgrade of Oracle Forms 10g to 11g is. One of the major sticking points for customers is that this requires a move from Oracle Application Server and OC4J to WebLogic Server, a foreign application server platform to many traditional Oracle sites.

SAGE Computing Services assisted the Department of Treasury and Finance in Western Australia in undertaking such an upgrade in late 2010, and we can attest to the fact that this is an easy process, Oracle's WebLogic Server is fully capable of running your production Oracle Forms systems.

For those interested Oracle has recorded the success in a whitepaper.

So now there's no reason to upgrade to Apex or ADF, just upgrade your Forms system instead!

Installing Oracle XE 10g on Ubuntu 10.10 Server and VMWare Fusion 3.1

Tue, 2011-03-22 08:03
The following blog post is purely for my own purposes, to document how to install Oracle XE 10g on Ubuntu 10.10 Server as a VM under VMWare Fusion 3.1 on Mac OS X 10.6.6.

These instructions are gathered from numerous internet resources and much of the credit must be given to these authors for their superb guides. The main difference for my guide is the inclusion of screenshots which I prefer over text or video, and the occasional fix where the original instructions didn’t work for me. Reference to the external authors is given throughout this article.

Installing Ubuntu 10.10 Server on VMWare Fusion

Opening credit must go to Ted Wise for his XE on Mac guide. Ted’s guide is very indepth detailing the exact options for installing Ubuntu’s JeOS 8.04. Ubuntu doesn’t appear to have a JeOS download for 10.10 so my instructions are the Ubuntu 10.10 Server .iso instead.

First download the Ubuntu “i386” 10.10 Server edition as the Oracle XE .deb package downloaded later is “i386” too. I’m a little unsure why, but there doesn’t appear to be a 64bit version of the i386 ISO for Ubuntu, but there is an Ubuntu amd64 server release for 10.10. While the amd64 version will run in VMWare Fusion, later on attempting to install the Oracle XE .deb package, it will complain it’s only for the i386 platform, which makes the amd64 Ubuntu unviable.

There’s obviously something I don’t know about the Ubuntu supported platforms and the relating ISOs.

iiNet (local Aussie ISP) provides a handy mirror.

Once downloaded open the VMWare Fusion. From the menu select File -> New which opens the New Virtual Machine Assistant wizard:

Select the “Continue without disc” button which opens the Installation Media page in the wizard:

Select the “Use operating system installation disc image file” radio button. This will open a select file dialog where you select the Ubuntu 10.10 Server i386 iso:

Presenting the following options in the previous dialog:

Selecting “Continue” presents the Operating System page. By default Linux and Ubuntu should already be selected under the respective Operating System and Version options:

Selecting “Continue” presents the Linux Easy Install options:

Note in the above picture we unselect the “Use Easy Install” option as this will skip many of the options we want to configure when the Ubuntu installation starts in the VM. Selecting the “Continue” button will present the Finish page:

The default options for the VM are fine. However you can click the “Customize Settings” button to change them. Note on selecting either this button or the Finish button will display a save dialog asking you to name and place the VM file on the OSX file system. The default location appears to be /Users/(your username)/Documents/Virtual Machines:

Note in the above picture I already have a number of other Ubuntu VMs that were previous trials.

Once you press Save the VM will start and the Ubuntu installer will flash through some startup screens, quickly arriving at the first option to select English as the preferred language:

At the next screen select the “Install Ubuntu Server” option:

For whatever reason we’re prompted for the language again, “English damn you, English”:

Then select your country:

Select No at the “Detect keyboard layout” option:

Select USA on the “Origin of the keyboard” screen:

Wow, Ubuntu loves it’s keyboard options. Select USA at the “Keyboard layout” screen:

Change the hostname to something more suitable at the Hostname prompt on the next screen, such as “oraclexe”:

At the timezone prompt assuming the right default has been picked, press Yes:

The next set of steps owes all its credit to Ted Wise’s instructions. As Ted notes Oracle XE will require a Linux swap partition twice the size of the available RAM. This can be done post install but it’s easier done now through the install screens with no typing required. The first screen titled “Partitioned disks” select the Manual option:

On the next screen select the SCSI3 option representing the VMWare disk available to the VM:

The screen will warn you that we’re going to drop and recreate the partition, which we select the Yes prompt:

This returns to the previous screen where under the SCSI option you’ll see that there is an entry for the empty partition entitled “pri/log 21.5GB” which we select:

In the following screen select the “Create a new partition” option to create a new partition in the empty partition we just selected:

In the following screen downgrade the partition size from 21.5GB to 20GB. The remaining size will be used for the swap partition soon.

Select “Primary” to make this the primary partition:

Allow the partition to be created at the “Beginning” of the available space:

Select “Done setting up the partition” which completes the primary partition. Next we create the swap partition:

Returning to the main partition page, select the remaining “pri/log FREE SPACE” option, which will be used for the swap:

Again select the “Create a new partition” option:

Take the default 1.5GB partition space next which will allocate the remaining free space to the swap:

Again make this a Primary partition:

Select the “Use as” option as we want to change what the partition is used for:

Select “swap area” when prompted “How to use this partition”:

Then finally “Done setting up this partition”

Returning to the partitions screen select “Finish partitioning and write changes to disk”:

A final prompt warning you on your changes will display, select Yes:

At this point the installer will start copying and configuring files:

At the “Set up users and passwords” screen you have the chance to configure the primary none-root user. The first page prompts you for the user’s name, not the account name. However they can be the same. As seen in this screenshot “administrator” is entered:

Next screen you enter the actual user account name, again “administrator” is entered in this screenshot:

Over 2 screens you’ll be asked to enter and confirm a password for the new account:

Choose not to encrypt the home directory:

Only if you have a HTTP proxy between the internet and the Mac set the following options, otherwise just select Continue. The install requires access to the internet so it’s essential this is configured if required:

Now the installer will download and install additional files:

Select your preference at the screen prompting you how to apply security updates:

At the software selection page, as we want this to be a very small server install just to run Oracle XE, leave the software package selection undone:

At the GRUB Boot prompt select Yes:

Hurray!… the installation is complete:

On a reboot the VM will display the Ubuntu command line login:

On logging in using the administrator account created in the previous steps, force the Ubuntu Server to update itself using the APT package installer via the following command:

sudo apt-get update && sudo apt-get dist-upgrade

When prompted press Y

Finally reboot the server:

sudo shutdown –r now

Install VMWare Tools

Here we depart from Ted's instructions. The Ubuntu Community documentation provides under the "Installing from Ubuntu package from VM-tools" heading the instructions for installing the VMWare Tools. A number of prescribed methods didn't work, including those requiring the VMWare Tools to be mounted via a virtual cdrom.

On logging in again as administrator, enter the following commands. Note the third command; as we've installed a UI-less Ubuntu Server we use this specific command (the Ubuntu documentation lists 2 options):

sudo apt-get install linux-headers-virtual
sudo apt-get install --no-install-recommends open-vm-dkms
sudo apt-get install --no-install-recommends open-vm-tools


Installing Oracle XE

First login as administrator and install the prerequisite libraries and packages:

sudo aptitude install libaio-dev
sudo apt-get install bc


Note that there appears to be some documentation around that indicates if Oracle XE is installed under Ubuntu 64bit, there are additional prerequisite libraries that must be installed including "bc" and "ia32-libs".

In the next step I had significant issues in using the usual method that most others used to download Oracle XE. As described in Ted's instructions, the typical manner is to download and Oracle XE is to add an entry to your /etc/apt/sources.list, use wget to retrieve the GPG key for the Oracle XE package and install it the APT repository, then finally download Oracle XE using APT.

Instead I came up with the following solution.

Via my browser I discovered the URL of the Oracle XE i386 deb package from the OTN web page was as follows:
http://download.oracle.com/otn/linux/oracle10g/xe/10201/oracle-xe_10.2.0.1-1.0_i386.deb

Still logged in as administrator, issue the following command changing the username and password to match your OTN username and password:

(Post edit: It appears the wget command can't deal with the licence prompt the Oracle website asks for. To solve this, in your Mac and your favourite browser, access the following page and accept the license condition. This will set your IP up to be allowed to download the software, such that both your Mac and the VMWare session can download the .deb file. Obviously another option is to download the .deb file onto your Mac, and then access it from your VMWare session)

wget --user=(username) --password=(password) http://download.oracle.com/otn/linux/oracle10g/xe/10201/oracle-xe_10.2.0.1-1.0_i386.deb

This will download the XE .deb file. Once completed we can install the .deb file using dpkg (more information on .deb files and dpkg can be found via Chris Buckridge's page):

sudo dpkg -i oracle-xe_10.2.0.1-1.0_i386.deb

Ensure to complete the usermod step next otherwise the administrator user will not be given correct privileges to install and start the database after a reboot:

(Post edit: there's a mistake in my notes here. Either the following command must be entered now, or, after the oracle-xe configure line next. Without reinstalling the whole VM it's currently hard for me to check this)

sudo usermod -g dba administrator

The next command configures and installs the database:

sudo /etc/init.d/oracle-xe configure

At the prompts:

1) Enter a port for Apex, the default being 8080
2) Enter a port for the Oracle Listener, the default being 1521.
3) Enter a password for the SYS/SYSTEM database accounts.
4) When prompted enter Y to allow Oracle XE to be started with the VM boots.

For reference /etc/default/oracle-xe is the configuration file which stores these options.

Once completed, edit the following file via or similar:

vi ~/.bashrc

At the end of the file enter the following:

ORACLE_HOME=/usr/lib/oracle/xe/app/oracle/product/10.2.0/server
PATH=$PATH:$ORACLE_HOME/bin
export ORACLE_HOME
export ORACLE_SID=XE
export PATH


Finally we need to login to the database as system and allow remote access to the HTTP server:

sqlplus system/(password)
EXEC DBMS_XDB.SETLISTENERLOCALACCESS(FALSE);
quit;

Accessing the APEX homepage from the VM Host (not Guest)

Finally to access the APEX homepage from the VM Host, on the guest issue the command "ifconfig" which will reveal the current IP of the VM guest, listed under the "eth0" "inet addr" entry, as example 192.168.197.131.

On the VM Host, return to your favourite browser and enter: http://192.168.197.131:8080/apex

..and the APEX home page should display. Ensure you can login using the SYSTEM account.

It's worth checking from a tool like JDeveloper installed under OSX that you can also access the database.

Voila.

Check out the ADF content at this year's ODTUG KScope11 conference

Fri, 2011-03-04 01:47
For all ADF developers, I'd like the chance to point out that this year's ODTUG Kaleidscope '11 conference in Long Beach USA has a substantial amount of ADF presentations. In fact quite a few active members of the ADF EMG will be presenting this year which is great.

For anyone who doesn't know much about the KScope events, ODTUG's conference series highlights real world experience with developers who are actually using Oracle products in the field. For anyone who doesn't consider themselves an expert, the KScope conference provides a great opportunity to learn from the pros tips n tricks on how to get your ADF applications from development to production

In turn for Fusion MiddleWare there's just on 60 sessions covering topics from SOA to WebCenter and of course ADF. Further incentives include streams dedicated to PL/SQL, the database, Apex and more. (Oh, and apparently it's sunny and warm in Long Beach and there's beaches too!)

If you're interested in the content, specifically the Fusion MiddleWare content, check out: http://kscope11.com/fusion ...then select either the Symposium or Presentations links.

We hope to see you there.

ADF BC: Creating an "EXISTS" View Criteria

Thu, 2011-02-17 19:10
The EXISTS keyword in SQL queries is an efficient mechanism for returning record sets from one dataset when they exist in another dataset. For example we can write queries like:

SELECT org.org_id, org.name FROM organisations org WHERE EXISTS
(SELECT 1 FROM events evt WHERE evt.org_id = org.org_id
AND evt.contact_name = 'Eddie Harris')

....which returns all organisations which have a related event whose contact is Eddie Harris.

ADF Business Components in JDeveloper 11g allow the creation of EXISTS subqueries via the View Object named View Criteria feature. They're easy to implement if you already know how to create View Criteria, as long as you know one small trick.

Default Business Components

Given the SQL query above using the one-to-many organisations-to-events example, imagine we have default Entity Objects (EOs), EO Associations, View Objects (VOs) and VO Links, as seen in this picture:

View Object Link Accessors

When created via the Business Components from Table wizard, the VO Link OrgEvtFkLink created, based on the EO Association OrgEvtFkAssoc, will include Accessors options under its Relationship tab in the VO Link editor:

If you select the pencil icon next to the Accessors options it reveals the View Link Properties dialog:

....from which you can see the "Generate Accessor" option selected for the "In View Object: Organisations View". While the selected state is the default option when created, it's this option which is essential for setting up the EXISTS View Criteria.

View Object View Criteria

Once you've ensured the Accessor option is set as described above, when you create a new View Criteria for the View Object, Organisations in our case, we configure the View Criteria as follows. First in the Create View Criteria dialog we should change the View Criteria name to something more suitable to reflect what the View Criteria will do for us:

Next select the Add Criteria button, which will create the basis of the expression used by the query:

On selecting the Attribute drop down, you'll discover a list of attributes from the OrganisationsView VO. In this list you'll note an attribute called "EventsView". This attribute is only available because of the options you configured in the View Object Link Accessors above. If you hadn't gone with the default options, the EventsView attribute would not be available, and you would not be able to create the EXISTS View Criteria:

With the EventsView Accessor selected the dialog for the first time shows the EXISTS clause:

The only think left to do is to select the Criteria Group expression of the EXISTS statement, in the example above this is the "Event No =" option, and change this using the supplied options in the fields below, to the actual expression we want to use in the EXISTS clause. From our example this is matching the Events Contact Name to a String:

Once completed in the right hand side you can see the EXISTS subquery that the View Criteria will apply to the OrganisationsView VO when executed.

Note I've also turned off the Ignore Case and Ignore Null Values options.

Testing

In the Business Components Browser, on opening the OrganisationsView, and selecting the View Criteria via the Find button, we're first prompted for a value for the bind variable:

...which once supplied, returns the only matching Organisations record:

Thanks

Thanks to Eddie Harris at SAGE Computing Services for revealing the technique.

Pages