Wednesday, 30 May 2007

Don't constrain yourself: displaying alternative database constraint error messages with ADF BC

An existing SQL database such as Oracle will have a full range of table constraints, including primary keys, unique keys, foreign keys, not nulls and check constraints. JDeveloper's ADF Business Components (ADF BC) provides a number of different mechanisms for validating data before it hits the database. However does ADF BC provide any mechanisms for overriding the database constraint error messages if they do occur, supplying an alternative "user friendly" error message?

The following post was raised on request for a client to explain the ADF BC facility provided. The discussion assumes you are familiar with Oracle's default schema "HR" and its associated table employees, and the constraints implemented in the employees table:

CREATE TABLE employees
(employee_id NUMBER(6,0)
,first_name VARCHAR2(20)
,last_name VARCHAR2(25) CONSTRAINT emp_last_name_nn NOT NULL
,email VARCHAR2(25) CONSTRAINT emp_email_nn NOT NULL
,phone_number VARCHAR2(20)
,hire_date DATE CONSTRAINT emp_hire_date_nn NOT NULL
,job_id VARCHAR2(10) CONSTRAINT emp_job_nn NOT NULL
,salary NUMBER(8,2)
,commission_pct NUMBER(2,2)
,manager_id NUMBER(6,0)
,department_id NUMBER(4,0)
,CONSTRAINT emp_salary_min CHECK (salary > 0)
,CONSTRAINT emp_email_uk UNIQUE (email)
,CONSTRAINT emp_emp_id_pk PRIMARY KEY (employee_id)
,CONSTRAINT emp_dept_fk FOREIGN KEY (department_id)
REFERENCES departments (department_id)
,CONSTRAINT emp_job_fk FOREIGN KEY (job_id)
REFERENCES jobs (job_id)
,CONSTRAINT emp_manager_fk FOREIGN KEY (manager_id)
REFERENCES employees (employee_id));

Overriding the database constraint error messages

The Oracle database isn't known for displaying particularly useful or friendly error messages when a table constraint is violated. For example if we create a new HR.employees record with an unknown DepartmentId value, the database throws the following error:

ORA-02291: integrity constraint (HR.EMP_DEPT_FK) violated - parent key not found

This message is not particular useful to the average user as they wont know what EMP_DEPT_FK is, what an integrity constraint is, or why the parent key is not found.

Via ADF BC can we provide a more useful message?

Section "25.8.3 How to Customize Error Messages for Database Constraint Violations" of the "Application Development Framework Developer's Guide for Forms/4GL Developers" manual outlines that a standard ADF BC project can be extended with a custom message bundle to customise the database's constraint error messages when caught by the midtier. Note to implement this, as noted in section 25.8.3, you must follow steps 1 to 5 of section 25.8.1. Take care to follow the special Note in step 3 if you're using JDev 10.1.3+, though it appears unnecessary in JDev 11g.

Section 25.8.3 shows us how to create a custom message bundle class for our ADF BC project, which is comprised of key-value message pairs, where we can list our constraint names and the custom message we wish to show respectively.

If we consider the HR.employees tables named constraints, of which there are 4 not null constraints, 1 uk, 1 pk, and 3 fk constraints, we could create the following custom message bundle class to cover off all the constraints:

public class MessageBundle1 extends ListResourceBundle {

private static final Object[][] sMessageStrings = new String[][] {
{ "EMP_LAST_NAME_NN" ,"A not null error message0" }
,{ "EMP_EMAIL_NN" ,"A not null error message1" }
,{ "EMP_HIRE_DATE_NN" ,"A not null error message2" }
,{ "EMP_JOB_NN" ,"A not null error message3" }
,{ "EMP_SALARY_MIN" ,"A check error message4" }
,{ "EMP_EMAIL_UK" ,"A unique key error message5" }
,{ "EMP_EMP_ID_PK" ,"A primary key error message6" }
,{ "EMP_DEPT_FK" ,"A foreign key error message7" }
,{ "EMP_JOB_FK" ,"A foreign key error message8" }
,{ "EMP_MANAGER_FK" ,"A foreign key error message9" }};

protected Object[][] getContents() {
return sMessageStrings;
}
}

Some caveats to be aware of:

The constraint names in the message bundle class must be in uppercase to match the case-specific constraint name raised by the database.

The HR schema has named the not null constraints within its tables explicitly. In your schema if you choose not to name the not null constraints, Oracle will generate a constraint name of the format SYS_C00000n where n is a counter incremented for each auto named constraint created by the database. It's fine to refer to these constraint names instead in your custom message bundle. However be aware if you recreate your schema and Oracle chooses to name the constraints starting at a different n value, obviously the ADF BC custom message bundle approach above will not work.

If you've setup your ADF BC Entity Object (EO) to have the same primary key as the table, the EO includes a mechanism for validating primary key values within the ADF BC mid-tier before it gets to the database. Because of this the alternative error message above may or may not be shown.

The EO pk routine checks any created/updated pk value against all pk values for the existing EO that have been cached in the midtier at submit time. If it finds a matching value (or in other words that the values aren't unique) it throws the following JBO (JDeveloper) exception where X is the primary key value(s):

JBO-25013: Too many objects match the primary key oracle.jbo.Key[X ].

In this case you will not see your message, but the JBO error above.

EOs and their associated View Objects (VOs) are by default configured to lazy fetch records from the database into the midtier in ranges (record sets of say 10 records) based on user requests. This lazy loading feature is designed to make it unnecessary to load all the records from a table into the midtier for speed and memory efficiencies while taking advantage of the fact the user probably doesn't want to view all 1000 employee records at once, but will be happy viewing a sub set at a time.

As noted above, if the record has been fetched into the midtier's ADF BC memory structures, the JBO-25013 error will display (without our custom message) when a new record's pk violates the pk constraint at submit time. However if the record with the matching pk value hasn't yet been fetched into the midtier, the check will be left to the database and is done at commit time. In this case the database will raise the error message, and our custom message bundle message will also be shown.

To my knowledge JDeveloper 10.1.3+ has no facility with the EOs to validate uk values similar to the pk check above. The JDeveloper 11g Technical Preview release introduces a new uk mechanism as separate to the pk facility and should be considered.

Beating the database constraints at their own game in ADF BC

In my opinion however, good user interface (UI) design dictates that it would be better to stop the database errors occurring in the first place to provide a relatively more satisfying experience for the user. How do you do this? Well you stop the user from ever entering data that violates the constraints in the first place.

The first set of suggestions here are obvious but need to be stated:

Using and generating surrogate read-only primary keys - if you're allowing the user to create or edit records, and the table has a surrogate primary key generated via a sequence in the database that guarantees uniqueness, make the field read-only (or hidden). Then within the ADF BC EO for the associated table, populate the pk programmatically on creating a new record via the sequence. In this fashion the user can never enter a non unique pk for the primary key value.

Use poplists and list of values (LOVs) for foreign keys - if the user in creating or editing a record needs to enter a foreign key value, don't allow them to manually type potentially invalid foreign key values. Instead provide poplists and LOVs for the user to select a valid value from.

Make mandatory database fields mandatory in ADF BC objects and the UI components - the ADF BC EO and VO attributes have a property Mandatory that will enforce the user entering a value before it hits the database. In turn the UI technologies usually provide facilities to check this too. For instance the 10.1.3 ADF Faces component has a required boolean attribute, that shows a star next to the item at runtime indicating it is mandatory, and fires Javascript to check for a value and raises an error otherwise at runtime. (Admittedly this is done by default, but some users may miss this point)

Beyond the obvious ideas, JDeveloper also provides a number of validators at the EO level that enforce data integrity checks and supply custom error messages if a problem is found before they hit the database. For the brevity of this post they will not be considered here. I note that Jan Kettenis under the recent post UML Rules is currently writing a whitepaper on implementing business rules in ADF BC which hopefully will cover the majority of the validators and a useful source of information beyond Section "6.7 Using Declarative Validation Rules" in Oracle's developer's guide.

Sunday, 27 May 2007

How to backup a Blogger blog

Note to self and anybody interested in backing up their blog: an easy way to backup a Blogger blog under a 1000 posts.

http://blogname.blogspot.com/search?max-results=1000

To backup comments:

http://blogname.blogspot.com/feeds/comments/default?max-results=1000

Hopefully Google will get around to creating a better mechanism rather than this lame attempt.

4 things I read this week (sort of)

I'm going to take a leaf out of Eddie Awad's great blog and publish some useful links from around the web. Like a lot of other bloggers I spend a fair amount of time reading other blogs, so it seems like an opportunity to a) catch what I'm reading in my own blog for later reference, and b) share the pain, ah, I mean the useful discoveries from time to time.

So it doesn't look like I'm ripping off Eddie too much, we'll call this the "4 things I read this week" post.

  • Rethinking JSF - The Real Problem - JavaServer Faces, a key technology of Oracle's ADF Faces gets at times a bad wrap on the web. But why? According to Joseph Ottinger on TheServerSide.com the issue is the quality of the components in the base JSF specification. I wonder how Trinidad and ADF Faces RC fit into this picture?
  • Core JavaServer Faces 2nd Ed - not so much a blog post and I haven't exactly read it yet, but rather a new edition of a popular JSF text by David Geary and Cay Horstmann that I'll get my hands on soon. I find such books invaluable as they give a 3rd party look at the whole JSF framework without the Oracle bias (for want of a better term - no offence intended to Oracle), and a useful insight into alternative explanation of JSF concepts.
  • Ban the Bulb - I spend a lot of my time either a) playing games with my daughter, b) hacking with Oracle related stuff, or c) getting stressed about the environment. Australia has recently taken the initiative of banning the incandescent light bulb. A lot of decisions made by the Australian Federal government (IMHO) just show no foresight but for making money for some geezer or other, but this one seems to be all good so far. I'm currently researching if anybody has any cons on the compact fluorescents replacement - the only arguments so far appears to be that CFLs can contain mercury which are a danger when they break, and they don't work with dimmer switches, both of which are pretty trivial issues.
This post also allows me to trial ScribeFire for the first time, a blog editor add-on for Firefox.

Friday, 25 May 2007

AUSOUG Victoria - Connor McDonald is in town

The following is blatant advertising for a local Australian Oracle User Group Victorian/Melbourne event to my local readers.

For 4th June 2007 we have lined up Connor McDonald, one of the world renowned Oracle speakers to present at our next educational seminar. As far as we're concerned we shouldn't have to sell Connor because your feedback from when we last heard him present in Melbourne says you think he is one of the best Australian Oracle presenters of all:

  • Excellent, Connor delivered a difficult topic beautifully
  • Great presenter
  • This chap really hits the spot. Professional, knowledgeable and enthusiastic!
  • Good as always
  • Excellent! and very entertaining
  • Very entertaining & informative approach to technical topics
Maybe you're not yet convinced? Well Connor's credentials should sell you. Connor is a member of the Oaktable, an author of 2 Oracle books "Mastering Oracle PL/SQL: Practical Solutions" and "Oracle Insight: Tales of the OakTable", an award winning speaker at our 2006 + 2005 AUSOUG/OAUG conferences, best speaker at the 2005 UKOUG annual conference, 2nd most popular speaker at OOW 2003, and best speaker at the UKOUG 2002 conference.

If you're a developer or DBA, and you're going to attend an Oracle event in June, make sure this is it. To attend this event you must submit the following registration form along with AU$55 (inc GST) payment for members, and AU$110 (inc GST) for non-members.

Date: Monday 4th June
Time: 8:30am Start - 12:30pm Finish
Presenter: Connor McDonald, OracleDBA.co.uk
Venue: Cliftons, Lvl 1, 440 Collins Street, Melbourne, Australia

Connor will present the following topics:

The evolution of SQL and PL/SQL

Peruse through a version 8, 9 or 10 database application and typically you'll find that the SQL and PL/SQL code could just as easily have been written, compiled and run against a version 7.3 database. Perhaps the developers wanted to ensure backward compatibility, but a more probable reason is failure to embrace and take advantage of the myriad of improvements that have been implemented in SQL and PL/SQL over the last 10 years. This presentation takes a look at how PL/SQL and SQL have evolved since version 7.3 - and why it is the responsibility of all Oracle developers to keep up to date.

Moving data quickly

We've all been there. We've got a shedload of data "here", and we need to move it "there"... And of course, it's got to go from "here" to "there" as quickly as possible. This presentation gives an introduction to the various ways Oracle offers to load, read and modify large volumes of data quickly, and the pros and cons of each.

Re-orgs and rebuilds: regular, redundant or really bad idea?

Just like a gardener can always find something to do in the garden, the average DBA just loves to reorg things. There is always the feeling that a little tinkering here and there will always be better than just leaving a database to its own devices. This presentation focusses on assessing the motivation for regular reorganisations of tables, and the associated rebuilds of indexes. What are the true costs of reorgs? Should you be doing them at all? Are there any features in version 9i and 10g that change things?

Sunday, 20 May 2007

Does the average Oracle IT worker read Oracle blogs?

As I posted a few weeks ago, last week I had the privilege to present a 1 day hands on JDeveloper presentation to the Canberra Oracle User Group (ACTOUG). With just on 30 attendees I was very happy with the outcome, and I must thank the delegates and ACTOUG committee for efforts all round. Presenting just gets more and more fun everytime I do it, mostly because of the great enthusiasm and kind thanks I get from delegates at the end :)

One thing surprised me during the presentation though. I asked how many attendees regularly read Oracle blogs? The response, well, 1 or 2 of the attendees kind of put their hand up half heartedly. What the?

Now I know I'm preaching to the converted for anyone who reads this blog (because you obviously read blogs). But in the recent discussions about how (un)successful Oracle blogs have been in gaining respect and penetration in the IT market, this result shows me that there is another aspect to the whole discussion, in that the average Oracle IT worker isn't paying attention to the Oracle blogosphere. What a waste!

Does anybody have any opinion on such a premise that "the average Oracle IT worker doesn't read Oracle blogs?" .... and any ideas on how this could be turned around?

Wednesday, 16 May 2007

Oracle RDBMS Q&A with Doug Burns

In an ongoing series of articles, Chris Muir chats to Oracle blogger and well known UK presenter Doug Burns who maintains his slightly off-center Oracle DBA blog (check out the stuffed toys!?). Doug, who holds 9i DBA certification, has 16 years experience as an Oracle DBA and is a member of the expert Oaktable group. His opinions, insights and experience in the Oracle arena are held in considerable regard by the Oracle community.

Q) Let's start with the most important question, what's with the stuffed toys on your blog?

A) Well, I've had Tigger for years because Tiggers are wonderful things, aren't they? My sister was probably the original inspiration for that because she used to be Tigger-crazy. Then my mum bought me Flatcat as one of my Christmas presents five or so years ago and things have expanded steadily since then. They're all real, they all have their own personalities and there's much more chat about them around my house than I could justify psychologically. As for their integration into the blog, there's a slightly serious message in there that people can take themselves a little too seriously online. I'm also not the most photogenic gentleman, so I reckon a picture of Flatcat is more welcome than one of me.

Q) Now that we've cleared that up, what was your original reason for blogging about Oracle?

A) I was working on a Data Warehouse implementation and every time I googled for related information, I would find myself looking at Mark Rittman's blog, so he was the original inspiration. I'd been aware of blogs a long time ago, via The Guardian's IT pages, but thought they sounded stupid! Then I saw Howard Roger's and Niall Litchfield's blogs and when I noticed that my hosting provider offered a (rather poor) blogging tool, I thought I'd give it a whirl. Oh, and I was pre-Tom Kyte. Not by much, but that's *very* important ;-)

Q) How has the blog changed from your original expectations?

A) I actually thought I'd be writing about Oracle much more often. I may return to that idea one day.

Q) Can you describe your average working day?

A) Well, I've just started a new role with the Pythian Group in Canada and will be working from home in Edinburgh, so things are changing and tend to change with each new contract. Usually though, I'll get up at about 6:30 or 7 and combine getting ready for work with reading email and looking at blogs. Getting a laptop was a bad move because I can get online very quickly and stay online while doing other things. Even when I'm doing my ironing, I tend to have the laptop near by for when I need a break from ironing :-(

It would be fair to say that it's very unusual to leave computers alone for more than an hour or two, unless I'm out of the house.

Because I'll be working in a different timezone from Pythian head office, I expect my near future to be a day filled with overnight pages, as I try to stop the Canadian employees being dragged out of their beds.

Seriously, though, every site I work at is completely different to the others as far as daily activities are concerned.

Q) How did you first get involved in computing, and later the Oracle arena?

A) Oh, that's quite a long story – buckle up! When I was at school, one of my friends got a Sinclair ZX80 so we messed around with that a bit in BASIC. Then, the first Christmas after I left school, my mum and dad bought me a ZX81. As I was on the dole (unemployed) I would just sit in the house, playing around with this thing, hand-disassembling commercial games and taught myself Z80 assembly language. Eventually I stumbled into a job as a games programmer and stuck at that (somewhat unsuccessfully) for the next 3 or 4 years. Then I was on the dole again (this was Britain in the '80s, so I wasn't alone), then a spell working with a PC dealership, writing dBase III Plus and Foxbase programs for clients (I couldn't believe people got paid for something so easy!). This led to a job with a finance company writing some C and Clipper. While there, my team lead and I pitched an internal bid for a new direct marketing system, based on Oracle 6 and AIX on one of the just-released RS6000 servers and we were successful. That was in 1990 and I've been working with Oracle since then.

Q) Are there any skills you learnt in your earlier career that still assist you today and are sorely missed by new graduates?

A) Despite the fact that I never work at anything like such a low level these days (and it would be next to impossible given the environmental complexity of modern systems), a grounding in Assembly Language meant that I've always retained important basic concepts about how computer systems work. If I'd started from a very high level, using Forms for example, I would assume that everything 'just works' and take the underlying technology for granted.

Although I'm a bit insecure about it, I was probably lucky to be self-taught too. It took me longer to get there, but I didn't have to learn as many useless things to satisfy a college examiner. There are some things that I'm much worse at, through lack of formal training, but by the time most people had left college, I'd already written a couple of games and it would be safe to say I see computing as a vocation, not just the job that pays the most these days.

Q) Given your 16 years experience with the Oracle RDBMS, what do you think the strengths of the product are?

A) The fundamental architecture - transaction and concurrency model, backup and recovery techniques and, even if it can be frustrating at times, the optimiser. I think Oracle's RDBMS is a pretty impressive design that gets a lot of things right and whenever I don't know exactly how something works, it usually ends up working in roughly the way I would have guessed, based on my knowledge of other areas. i.e. It's reasonably consistent and stands up well to new extensions.

Q) And its weaknesses?

A) Not so much from a personal point of view but, like Unix, the fact that so much detail is exposed is both a strength and a weakness. I wouldn't want a 'self-managing database' because I think it's an impossible target, but there is a very steep learning curve and there are times when things are more difficult than they should be. That's largely based on watching new users struggling through courses, wondering why they need to understand so much.

Maybe Oracle XE will break down some of the barriers, but I still think you're going to need to understand how the damn thing works if you want to be a DBA

Q) Core-tech Oracle skills tend to be divided into DBAs and developers. Many (including the author in jest) like to point out the divide between the 2 groups. Any comments on this divide, its impact on a successful project, and why DBAs need a good whack on the head?

A) Even as someone who has also jokingly encouraged the divide, it is a bit of a nonsense. All of the best people that I've worked with or met in the user community tend to be a bit of a mix of both, I've done a few development jobs myself and came from a development background. I'd also put my SQL and PL/SQL skills up against any of the developers I've worked with.

Then again, those who lean towards being DBAs have always been the best! (Until that pesky Tom Kyte popped his head out of his cubicle.)

Q) Many DBAs are carefully avoiding any involvement with the middle tier software. Do you consider the administration of Oracle Application Server to be part of a DBA's role, and if not, who should be doing it?

A) It depends on the type of DBA and on the type of environment. For DBAs who are very technically-orientated, they could and should include it in their skills. I was involved in writing an App Server course at Learning Tree and, frustrating and bug-ridden though the product was, it's undoubtedly something to get your teeth in to, a server product with complexity to spare, so I think it's a good fit for the technical DBA. If however, you're a database design and minor maintenance DBA, then you've no chance of ever getting your head round App Server!

It also matters what type of site you work at. If you have separate Operating System, Database, Storage and Networks teams, then it probably makes sense to have a separate App Server support team because it requires equal levels of skill, time and commitment. If you're working at a smaller site, you're probably going to have to muck in and get your hands dirty.

Personally, I've found I never have the time to dedicate to it, but I'd like to do more.

Q) How have the management tools provided in Oracle 10g changed the DBA's workload?

A) Personally they haven't made much difference because I'm still a slave to the command line, I'm afraid. I have played around with the various management tools but the problem for most DBAs is that you're extremely unlikely to work at a site that uses 10g exclusively, so you need to work with the lowest common denominator when it comes to management tools. I think that might be changing slowly, though, if only Oracle don't change the product set too often – it makes it impossible to settle on anything.

Q) What do you consider to be the most useful database tuning tool?

A) I think AWR, ASH and ADDM are potentially the most useful database tuning tools but, again, it's difficult to focus on them because I don't just work with 10g databases and Oracle's licensing model doesn't help! As long as that's the case, event 10046 traces will always be useful but I also use Statspack regularly when I want to get to the bottom of a problem quickly. If that doesn't work, I usually end up using tracing.

Q) What is your experience of the adoption rate of ASM, and how do you see its future?

A) Interestingly, I've had two very different experiences in the space of the past month or two. I just left a big enterprise site in the UK and they won't be using ASM in the foreseeable future. They support hundreds of applications, all with their own storage requirements, and the SAN administrators aren't going to major on storage software specifically for Oracle, even though they have a lot of databases. Stability is another issue, so they'll rarely use a product before it's used widely. I realise that's a chicken-and-egg situation, but that's the way it works. Up until the start of January, I couldn't see ASM having any impact for years.

Now I've moved to a company that supports a lot of RAC installations on Linux and they use ASM widely, That's partly because of Oracle's Standard Edition licensing policy for RAC, that encourages it, and partly because they don't want to fork out for something like Veritas Clustering or Polyserve. I haven't been involved long enough to know how successfully it is, but I haven't heard any major complaints yet.

Q) Oracle RDBMS 11g announced with fanfare at the 2006 Oracle Open World marks another milestone in database technology. Do you think it's an evolution or revolution in database technology? Any specific features?

A) I agree with a lot of people that there isn't a great 'wow factor' about the release, but if the version control features work as advertised, I think they could prove very useful for the day-to-day drudgery of the DBA's life, particularly development DBAs, who spend a lot of time restoring and rebuilding test environments and running release scripts. Definitely evolutionary, though, but I have no problem with that. Revolutions are for kids Web 2.0 apps, not for your primary data store.

Q) Are there any features in Oracle that are under utilised in your opinion, by DBAs and separately developers?

A) DBAs – 10046 event tracing (still), resumable storage, parallel execution (for data loads and index rebuilds) (I had to include that one ;-)), dbms_scheduler/dbms_job. Let's face it, most of us, me included, use a fraction of what we've paid for.

Developers – if they're not dedicated database programmers, just about everything! Are there any features most developers *do* use? It may not be true of the people likely to be reading this, but I find that most developers don't have the first idea about the extensive functionality at their disposal for free.

Q) What areas do you believe are the biggest frustration for DBAs in maintaining Oracle databases and do you see 11g addressing this in any form?

A) One area that's an absolute nightmare is patch management. I've had this discussion with various people in the community and, whilst I understand why everyone talks about regular patch maintenance and I'm not arguing about the need for it, does anyone in their right mind think that a majority of sites are really patching all of their databases every quarter? Yeah, right. Until Oracle make patching much, much easier and less disruptive (OEM Grid Control looks promising), security holes are going to exist left, right and centre and the fact is that most companies are utterly dependent on their firewalls. Whether you believe that's adequate or not is for debate.

Q) From your blog on interviewing potential DBAs, you have views on the skillsets they require. What do you think makes a successful DBA in today's IT market?

A) Well, to start off with a facetious answer to your specific wording – the ability to lie effectively on your cv/resume. That seems to do the trick!

More sensibly, I value maturity above all else. When I say maturity, I suppose I really mean responsibility and it's absolutely nothing to do with age. When DBA teams are growing and the number of databases we support is growing even faster, there's no room for cowboys. All they do is screw things up for the entire team and ruin our reputation with developers and the business.

That, of course, is on top of them knowing the basic skills of the job well, which should be a given, but doesn't seem to be these days. Having to look everything up on Google before you do it is winging it, in my opinion. There should be some things you just know, because you are supposed to be a professional technician.

Q) Has the role and concerns of the DBA changed in the last 10 years, and where do you see it going in the future?

A) I've always thought that the DBA role was predominantly managing the environment and developing strategy because the day-to-day stuff is so easy. The product is a lot more complex than it was, though, so it's difficult to know it as intimately as we might in the past, but there's much more information available on how it works. I don't think for a minute that new tools have made things much easier, they just mean we can support more databases per DBA.

Q) Moving on from the technology and focusing instead on Oracle Corporation. Recently Oracle Corporation has acquired organisations like PeopleSoft, JD Edwards and Siebel, changed their marketing message to Oracle Fusion, at what some would consider to the detriment of Oracle core technologies such as the RDBMS. Any comments?

A) Don't get me started! I suspect you might know my feelings on this subject already. There was a stage where I felt the UKOUG was becoming a Fusion user group and, given that the user base of all those products combined is a small fraction of the RDBMS user base, I'll do everything in my power to stop that happening.

I can understand why Oracle want to grow into these other areas for their corporate health but their corporate health is not my primary concern and I hope they don't lose focus on what they're good at – producing a damn good RDBMS.

Q) Oracle Support. Love it, or lump it?

A) I think I'm in the minority on this one because I think they do a good job. When I first started working with Oracle, I'd avoid phoning Support like the plague because you'd go through layer upon layer of analysts, trying to reach someone who knew more than you did. Now, whilst that's still happening, they've improved the process of data collection that you always need at the start of a service request and, although the layers are still there, I can deal with them electronically on line so it's not as disruptive. i.e. if I have to spend a day or two entering some details in order to reach the right level of analyst, I don't worry too much about that. Put it this way, I'm glad I don't need to support such a complex product and I think it's too easy to moan about Support sometimes.

Then I remember how much companies are paying for Support and my sympathy wanes.

Q) In the past you've presented and supported Oracle user groups around the world including the UKOUG. What's your thoughts about Oracle user groups, their position and importance, their relationship with Oracle Corporation, and why you like to contribute to their success?

A) A strong user group is essential in my opinion. To have a strong user group, it's important that it's not organised for commercial gain, to argue the vendor's case too vehemently (although talking up the product is okay if it's a good one) or to be in the vendor's pocket financially. However, it's also important that the user group have a good relationship with the vendor so that there's a circle of feedback that will hopefully improve both the product and service for the customer.

In the end, we all run into problems and it's good for users to be able to get together, share their experiences and knowledge and passion for the software. I'd encourage as many people as possible to become involved. It's a lot of fun and the more of us there are, the more we can achieve.

(This article is a reprint of the article I published in the quarterly AUSOUG Foresight magazine Autumn 07 edition. I'd like to extend my thanks to Doug Burns for agreeing to the interview, and Penny Cookson for her kind assistance and input on this Q&A article)

Tuesday, 15 May 2007

Follow-up: Programmatic ADF Faces Tree in JDev 11g

As follow-up to my recent post "Back to programming: Programmatic ADF Faces Tree component" I mentioned as a final caveat that the JDev 11g class stack for the ADF Faces components has changed from that in JDev 10.1.3. Thanks to Frank Nimphius's reply on the OTN JDeveloper forums to a question about the deprecation of the TreeModel class, it's now obvious that the org.apache.myfaces.trinidad.model.TreeModel class is the appropriate replacement (assuming you're replacing ADF Faces with Apache Trindad in JDev 11g -- Apache Trinidad is the natural successor to JDev 10.1.3's ADF Faces component set).

As such in my previous example, within the custom TreeModelAdapter class, you simply have to replace the following 2 import lines:


import oracle.adf.view.faces.model.ChildPropertyTreeModel;
import oracle.adf.view.faces.model.TreeModel;


.... with ....


import org.apache.myfaces.trinidad.model.ChildPropertyTreeModel;
import org.apache.myfaces.trinidad.model.TreeModel;


Enjoy.

Saturday, 12 May 2007

Back to programming: Programmatic ADF Faces Tree component

Typically ADF Faces components in our JDeveloper 10.1.3 applications are data bound, meaning they map to objects in the binding layer as specified in separate pageDef files. This is expressed in our components through EL references to bindings}.

However what if we don't want to map to a binding layer object, but instead want to construct the data elements programmatically? For this blog we'll consider the example of an <af:tree> component to demonstrate this, showing how we construct the elements in the tree programmatically rather than relying on bindings.

Our goal is to construct an <af:tree> component comprised of <af:goLink> tags and looks as follows:

Logically understanding our hierarchy

Before we consider the <af:tree> component specifically, have a think about what the hierarchy represents. Each node in the tree has a text title, and a hyperlink destination. Each node is a child to a parent node, and each node may be comprised of 0, 1 or more child nodes. Collectively this represents our tree and is a simple logical concept.

Understanding the ADF Faces Tree component

The code for an <af:tree> in a web page would typically look as follows:

<af:tree var="node" value="#{treeModel.model}">
  <f:facet name="nodeStamp">
    <af:goLink text="#{node.text}" destination="#{node.destination}"/>
  </f:facet>
</af:tree>


In our example you'll note that the nodes within the tree are comprised of <af:goLink> tags that render the links in our tree above. You'll also note if you constructed a <af:tree> tag using the drag n drop facilities of JDeveloper based on a data bound component from the data control palette, the code would look very similar. In other words there isn't anything really special about the code above besides the use of <af:goLink> tags.

The <af:tree value> attribute demands at runtime an oracle.adf.view.faces.model.TreeModel instance. This class is the data model for the ADF Faces Tree component, where rows in the tree may contain other trees, or alternatively described, nodes in the tree can contain children nodes which in turn can also have children nodes and so on.

The nodeStamp facet of the <af:tree> walks the TreeModel, creating for each node the subtags contained within the <f:facet> tag, in this case an <af:goLink> tag. You'll note the <af:goLink> tag makes reference to the current node in the TreeModel as it walks the tree via the <af:tree> tag's var="node" attribute.

So we now logically have an understanding of what we want to model, and we also understand what the <af:tree> component wants. Lets consider our design solution.

Keeping it simple with a POJO

From the design point of view, to model the hierarchy we'd like to create our own very simple POJO TreeItem that stores a String text and String destination required for each goLink, along with a List of children TreeItem objects to reflect the hierarchy. At runtime we'll construct this tree programmatically populating the hierarchy in any way we desire.

The POJO approach is very easy to understand and implement. However the problem with our POJO approach is the datatype doesn't match that required by the <af:tree>, namely oracle.adf.view.faces.model.TreeModel. How do we address this?

Creating an Adapter between our TreeItem and TreeModel

In the OO world they have the concept of the adapter design pattern. An Adapter class is one that wraps another interface, to provide an interface the client expects. In our case we have our POJO TreeItem interface, but our client the <af:tree> demands an oracle.adf.view.faces.model.TreeModel, so we'll provide a class called TreeModelAdapter to work as the adapter. It will be this class that we'll define in our faces-config.xml file as a managed bean for the <af:tree> control to make use of at runtime.

The TreeModelAdapter will internally store our TreeItem hierarchy and TreeModel, and provide accessor methods to access and manipulate these items.

Coding the solution

The following describes the steps in coding our design solution. It assumes you've already created your web page with the <af:tree> code as previous:

Create our POJO Java Bean TreeItem class as follows:

package view;

import java.util.List;

public class TreeItem {
  private String _text = null;
  private String _destination = null;
  private List<treeitem> _children = null;

  public TreeItem(String text, String destination) {
    setText(text);
    setDestination(destination);
  }

  public String getText() { return _text; }
  public void setText(String text) { this._text = text; }

  public String getDestination() { return _destination; }
  public void setDestination(String destination) { this._destination = destination; }

  public List getChildren() { return _children; }
  public void setChildren(List children) { this._children = children; }
}

Note the following about the TreeItem class:
  • Internally stores the Strings text and destination and provides appropriate accessors.
  • Contains a list of child TreeItems _children that may contain 0, 1 or many child TreeItem objects within the current TreeItem. This represents the hierarchy. Note that it is important the Java Bean provides accessors specifically named getChildren() and setChildren() to retrieve the private _children attribute as you'll see in a moment.
Create a TreeModelAdapter class:

package view;

import java.beans.IntrospectionException;
import java.util.ArrayList;
import java.util.List;
import oracle.adf.view.faces.model.ChildPropertyTreeModel;
import oracle.adf.view.faces.model.TreeModel;

public class TreeModelAdapter {
  private Object _instance = null;
  private transient TreeModel _model = null;

  public TreeModelAdapter() {

    ArrayList<TreeItem> rootTreeItems = new ArrayList<TreeItem>();

    TreeItem treeItem1 = new TreeItem("Fish", "http://www.someurl1.com");
    TreeItem treeItem2 = new TreeItem("Dog", "http://www.someurl2.com");
    TreeItem treeItem3 = new TreeItem("Cat", "http://www.someurl3.com");

    TreeItem treeItem2_1 = new TreeItem("Blue Heeler", "http://www.someurl4.com");

    TreeItem treeItem2_1_1 = new TreeItem("Rover", "http://www.someurl5.com");
    TreeItem treeItem2_1_2 = new TreeItem("Ruffus", "http://www.someurl6.com");

    rootTreeItems.add(treeItem1);
    rootTreeItems.add(treeItem2);
    rootTreeItems.add(treeItem3);

    ArrayList<TreeItem> treeItem2Children = new ArrayList<TreeItem>();
    ArrayList<TreeItem> treeItem2_1Children = new ArrayList<TreeItem>();

    treeItem2Children.add(treeItem2_1);
    treeItem2.setChildren(treeItem2Children);

    treeItem2_1Children.add(treeItem2_1_1);
    treeItem2_1Children.add(treeItem2_1_2);
    treeItem2_1.setChildren(treeItem2_1Children);

    this.setListInstance(rootTreeItems);
  }

  public TreeModel getModel() throws IntrospectionException {
    if (_model == null) {
      _model = new ChildPropertyTreeModel(_instance, "children");
    }
    return _model;
  }

  public void setListInstance(List instance) {
    _instance = instance;
    _model = null;
  }
}


Note the following about the TreeModelAdapter class:
  • It contains a private oracle.adf.view.faces.model.TreeModel _model attribute. This is the TreeModel we'll provide to the <af:tree> tag. It is exposed via the getModel() method, and you previously saw this method was called via the <af:tree value="#{treeModel.model"> EL expression.
  • The class also contains an Object named _instance. This is where we'll store our own programmatic tree constructed from our own home baked Java Bean TreeItem hierarchy. The nice thing about this implementation is it doesn't care if it gets our TreeItem class, or any other sort of Java Bean, as long as it follows the Java Bean spec by providing accessors to retrieve the attributes, including specifically accessors for _children (more on this soon). The setListInstance() accessor provides a method to set the Object _instance.
  • In our simple example here, the constructor creates 3 root TreeItem nodes "Fish", "Dog", "Cat". For the "Dog" TreeItem node it creates a child "Blue Heeler" node. For the "Blue Heeler" node it creates 2 TreeItem nodes "Rover" and "Ruffus" in turn. The constructors last action is to assign the TreeItem hierarchy we've populated into rootTreeItems into the TreeModelAdapter class's _instance private attribute.
  • The getModel() method requires further explanation. The ChildPropertyTreeModel class is a subclass of oracle.adf.view.faces.model.TreeModel. It allows the construction of a TreeModel based on a list of beans. This suites our purposes well as we've constructed a list of TreeItem beans stored in the TreeModelAdapter's _instance attribute. You'll note that the ChildPropertyTreeModel constructor for its 2nd parameter specifies the String "children". The ChildPropertyTreeModel class uses this name to work out what accessor methods it needs to use in the TreeItem Java Bean to access the hierarchical part of the TreeItem class. It's important that the string "children" matches the accessor names getChildren() and setChildren() in the TreeItem class following the Java Bean specification rules. If these mismatch you'll get a runtime error.
Finally in our faces-config.xml file we declare our managed bean as follows:

<managed-bean>
  <managed-bean-name>treeModel
  <managed-bean-class>view.TreeModelAdapter
  <managed-bean-scope>request
</managed-bean>

Note that the request scope used for treeModel will result in the instantiation of TreeModelAdapter for each request to the page containing the treeModel reference, potentially an expensive exercise. If the tree is duplicated across multiple screens a session scope may be appropriate.

Credit

To give credit the inspiration for the TreeModelAdapter in this solution is a modification of MenuTreeModelAdapter from Oracle's ADF Developer's Guide for Forms/4GL Developers 10.1.3 (page 19-8). Those with lateral thinking should be able to see the ability to create programmatic <af:page> and <af:panelPage> menus with this technique.

Final Caveat

The code above is not applicable for JDev 11g and its new Rich Faces components as the class structure for the components has changed. Once Oracle releases the JavaDocs for the components I'll look at revising this article on request.

Friday, 11 May 2007

JDeveloper in the Aussie media wild

JDeveloper made it into the local Aussie online media again thanks to Oracle's JavaOne announcements, with a news story at Builder.au. Mind you I'm not so sure why the journalist refers to JBuilder and who "a company" is? Nice to see the tool is getting some local coverage though.

Addition: a more detailed post at itNews.com.au reports the announcement.

Wednesday, 9 May 2007

Boost your productivity with JDev 11g's new faster "Red" IDE

Thanks to Brian Duff I've happily discovered we can now all experience JDeveloper in our favourite colour scheme. Thanks to the Tools -> Preferences -> Environment -> Theme option we have a relative rainbow of colour schemes to choose from under the JDev 11g preview edition.

If you run JDev 11g under the Sky Red theme your productivity will increase by no less than a guaranteed 3.824% according to the new 11g documentation. Rumours are that at this year's San Fran OOW the JDev team will announce a new "Racey Red" colour scheme that will boost programmer productivity by a minimum 12.66%.

Nice work on the Swing themes JDev team!

Tuesday, 8 May 2007

JDev 11g Tech Preview is here

Many congtraz to the JDev team for finishing the JDeveloper 11g Tech Preview (as blogged by Shay Shmeltzer) available from here for JavaOne. Just this morning I was telling customers I wished JDev had a page templating mechanism and some sort of task flow facility, and "Yeehaw!".... it arrived today :)

Now if only they would turn the whole IDE interface to "Racey-Red" like I requested some time back.

Thursday, 3 May 2007

Canberra ACTOUG JDeveloper demonstration

For those readers in Canberra Australia, the ACT Oracle User Group (ACTOUG) has invited me to present a 1 day demonstration of Oracle's JDeveloper 10.1.3, focusing on ADF Business Components and ADF Faces, on the 17th May. As I'm always keen to support local Oracle user groups and the Oracle community, I readily agreed to show how simple JDev is for web application development.

More details regarding the presentation are below. If you're interested in attending please head to the ACTOUG website to retrieve the registration details. Hope to see you there.

Taking the J out of Oracle JDeveloper - web page development without the fear of Java

Scared of JDeveloper because you don't know Java, but dying to develop Oracle web applications? Fear not! Let the ACT Oracle User Group introduce you to JDeveloper web development without a single line of Java! In this 1 day presentation Chris Muir from Sage Computing Services will introduce you to the beauty of JDeveloper's drag 'n' drop, wizard and editor IDE for quickly developing a web application using ADF Business Component and ADF Faces.

Agenda

Morning session:

  • Introduction to JDeveloper and the Application Development Framework (ADF)
  • JDeveloper installation and creating a database connection
  • Creating an application workspace and projects
  • Using the ADF Business Components from Table wizard
  • Adding Entity Object business default values, formatting and validation rules
  • Adding View Object SQL calculate attributes and bind variables

Afternoon session:

  • Introduction to ADF Faces and the binding layer
  • Creating JavaServer Faces web pages, read only tables, editable input forms and master-detail pages
  • Implementing page navigation rules
  • Enhancing your web pages