Showing posts with label ADF Business Components. Show all posts
Showing posts with label ADF Business Components. Show all posts

Wednesday, 2 February 2011

JDev: ADF BC and ADF Libraries: The Library Private property

ADF Libraries are a very useful feature of JDeveloper 11g. They allow a master application, via the Resource Palette, to load Bounded Task Flows (BTFs) and the BTF's associated ADF Business Components from separate applications, without having to include the BTF and ADF BC objects in it's own application.
In the following picture you can see the Resource Palette exposing adflibChildBTF.jar, a BTF application containing both the ChildBTF bounded task flow, and it's associated Business Components including the ChildAppModule Application Module, Events Entity Object and so on:

If this ADF Library is loaded into a consuming application's ViewController project, the consuming application is free to call the adflibChildBTF's embedded Bounded Task Flow. However it's also free to call directly the Business Components of the adflibChildBTF. This is revealed by the Data Control Panel in the Application Navigator, it will by default include the Application Module of the child application as can be seen here:

Yet this isn't always desirable behaviour, the Child Application may not want to expose all its Business Components for easy picking by the consuming application. For example, you may have included a collection of test Business Components in the Child Application which really aren't appropriate for the consuming application to use, or, you may think it inappropriate for the consuming application to even reference the regular Business Components of the Child Application. How to fix?

When you open the editor for most Business Components including Application Modules, Entity Objects and View Objects, you may notice that the Property Inspector also reflects options for the selected and edited Business Component. In the Property Inspector for each Business Component there's typically a boolean property not included in the associated editors called Library Private. In the following diagram you can see the property inspector for the Application Module from the Child Application:

This property, when set to true for each Business Component (the default is false), means the Business Components will not be available in the Resource Palette when the ADF Library is redeployed (note: you must refresh the Resource Palette to see this effect):

As can be seen in the previous picture, the ChildAppModule Application Module is no longer available in the Resource Palette. In addition in the consuming Application's Data Control Palette, as we've hidden the ChildAppModule, simply it doesn't appear in the Data Control Palette:

Returning to the Resource Palette, you may in fact want to hide *all* of the Business Components. This requires you to simply set the Library Private property of each Business Component to true, and then regenerate the ADF Library JAR. We can see the end effect here:

However it must be noted, in the consuming application, this does not stop the consumed BTF from working. All the Library Private option is doing is hiding the Business Components from the IDE for the user to use. The Business Components are still used by Child Application/BTF when called from the caller at runtime.

Caveat

I've yet to fully use this feature, so be careful to check it works for you, your mileage will vary. If you find any issues I'd appreciate a comment to this blog post, to assist other readers.

Addendum

This feature is available in the latest version of JDev 11.1.1.4.0 through 11.1.1.2.0. It's possibly available in earlier versions, but I'll leave readers to check themselves as I no longer have these earlier JDev versions installed.

In addition this feature works within an Application too, such that the Business Components don't show in the Data Control Palette for the same Application's ViewController project.

Tuesday, 12 October 2010

ADF BC - Read Only View Objects and missing PK attributes – A Passivation Issue

A recommended ADF development best practice from Oracle is to check your applications are Activation Safe. In recent testing of an ADF 11g application we discovered the following scenario where our application failed Activation Safe testing, documented for others to read-but-not-experience-first-hand.

Problem Scope

Consider an application displaying employee details. The first screen contains a table of employees, and on selecting a specific row, the 2nd screen shows the details of the selected employee.


Note in the screen shots, selecting employee ID 106 in the table, displays employee ID 106 in the form screen. Essentially the expected behaviour.

In this example from the ADF BC point of view the employees data is backed by a Read Only View Object (VO) based on the employees table from Oracle's HR schema. By default the employees VO contains the following attributes. Note the PK employee ID:


By chance if we disable the PK and run the application, it performs in the same way as described in the first picture above on the developer's PC. Selecting employee ID 106 in the table results in the same record 106 shown in the second page.

Interestingly in the JDev console, as we select the employee in the table, the following message is displayed:

<CurrencyRowKeySet><_computeCurrentRowKey> ADFv: Rowkey does not have any primary key attributes. Rowkey: oracle.jbo.Key[], table: oracle.jbo.server.ViewObjectImpl@e48114.

Yet as stated the application works correctly. Can we ignore this error?

Activation Safe testing teases out the problem in more detail. Activation Safe testing requires us to right click the Application Module -> then select Configurations -> AppModuleLocal -> Pooling and Scalability, and then *disable* the Enable Application Module property:


On re-running our application we see the following behaviour:


...that is on selecting employee ID 105, and navigating to the next page, oddly the record shown is employee ID 100. Selecting the back button, on returning to the table page, it still shows employee ID 100 as the selected record regardless of our original selection.

On looking at the JDev console window when selecting employee ID 105, we see that the log message has expanded:

<CurrencyRowKeySet><_computeCurrentRowKey> ADFv: Rowkey does not have any primary key attributes. Rowkey: oracle.jbo.Key[], table: oracle.jbo.server.ViewObjectImpl@9ddef9.
<FacesCtrlHierBinding$FacesModel><makeCurrent> ADFv: No row found for rowKey: [oracle.jbo.Key[]].

If you turn on the -Djbo.debugoutput=console option when running the program the problem is revealed in more detail:

[978] Warning! Binding:noCtrl_oracle_adfinternal_view_faces_ model_binding_FacesCtrlHierNodeBinding_1 requires key attributes to be able to locate nodes in the hierarchy.

Conclusion

From identifying this problem the natural conclusion is in order to build an Activation Safe application, amongst other issues your View Objects require a primary key. Typically this isn't an issue as most VOs are based on EOs, where the IDE enforces each EO has at least one primary key attribute that is shared to the VO. But in the case of Read Only VOs not based on an EO, it's fairly easy to create a VO without a PK attribute. In the simple example from this blog, of course the employees table has a PK attribute, but, if we're building a customised VO based around some complex query, in particular if we use the expert-mode VO option, no PK is defined by default. Thus our application becomes Activation unsafe.

Addendum

Tested under JDev 11.1.1.2.0 build 5536.

Saturday, 27 March 2010

ADF BC 11g – Creating business rules for unique keys on actual database unique keys (rather than primary keys)

Phew, that's the best title I could think of for this post. Not the most inspiring I'd agree. Anyway, let's continue.

Users of JDeveloper 11g ADF Business Components will be familiar with the ability to create Declarative Validation Rules on an EO's underlying table's primary key, somewhat confusingly (as we will see) referred to as a "UniqueKey" validator, though it's based on a primary key. The main reason to create such a rule is to avoid the particularly unfriendly database constraint error that is thrown, to replace it with a more friendly error message defined in ADF BC.

This "UniqueKey" rule can easily be extended to actual schema unique keys through a little trick (as separate to a primary key) as we'll see in this post.

When an EO is created in your Model project based, the IDE takes the opportunity to capture all the constraints of the underlying table (or you can resync these at a later date by right clicking the EO in the App Navigator and choosing the Synchronize with Database option). To create a "UniqueKey" validator based on the primary key of the table you:

a) Open the EO editor
b) Select the Business Rules node
c) Then Entity Validators followed by the plus button

In the resulting Add Validation Rule dialog, selecting the Rule Type of "UniqueKey" gives you the option to pick the relating EO's primary key based on the same constraint from the database:


However you'll notice what it doesn't display is any actual unique keys (such as say a database constraint employees_uk that enforces the first_name and last_name must be unique within the employees table).

One solution to this is to define Alternate Keys in the EO via the EO editor's General page's same named option:


Once created the Alternate Key will then appear as a "UniqueKey" option in the Add Validation Rule dialog.

However there is an easier way.

If you select an EO in the Application Navigator, then open the Structure Window option, you get a list of parts of the EO including Constraints, which will include all the database constraints for the particular EO. As can be seen in the following picture, this includes not only the primary key, but also unique keys:

If you select the unique key constraint and then open the Property Inspector you'll see:


...including an option to create the unique key constraint as an Alternate Key (the default being false). Setting this to true means that when you create the validation rule for a "UniqueKey", you'll see the unique key constraint listed as well as the primary key:


This little trick saves us having to manually create Alternate Keys based on the columns in our unique keys, but rather reuse the unique key constraint definition to define the Alternate Keys for us.

Wednesday, 10 February 2010

ADF BC Groovy – showing old values along with new part II – via ViewRowImpl

A while back I posted about using Groovy within our ADF BC EOs to expose the new and old values of a particular attribute. This method described in that post works fine if you've access to the EOs in the same project. However in our current project EOs are segmented in another application workspace project for reuse and ADF Library JARed into our existing "master" ADF BC workspace project. The external EOs are intended to be shared by multiple other sub-systems, and it really didn't seem ideal to include additional transient attributes on all the attributes in the shared EOs just in case some other application needs them, mostly they wont want this specific requirement.

This lead to the requirement to include the same functionality, namely transient attributes based on a Groovy expression to return the old value of the attributes, from our project's VOs instead. In other words, if a VO needs them, it includes 'em.

We immediately hit a problem on implementing this requirement. The EntityImpl.getPostedAttribute(index) method is a protected method, and there is no equivalent ViewRowImpl method. Arguably it should be provided at the ViewRowImpl level, and a search of the JDev OTN forums shows it's an old issue and I guess not likely to change anytime soon.

Without an immediate change to the ADF BC framework, we needed to find another solution. What we came up with:

(As per the original post we'll assume we're looking at the Employees EO and Position attribute)

1) By default extend the ADF Business Components Framework as per section 37.1 Globally Extending ADF Business Components Functionality of the Fusion Guide.

2) In the extended EntityImpl class, say common.model.CommonEntityImpl, create a public exposed version of the getPostedAttribute method
public Object getPostedAttribute(int index) {
return super.getPostedAttribute(index);
}

3) For the specific VO interested in showing the old values of an attribute, create the associated ViewRowImpl (say EmployeesViewRowImpl). Ensure in the generated class an accessor method to access the underlying EntityImpl has been created, ie:
public EntityImpl getEmployees() {
return (EntityImpl)getEntity(0);
}

4) In the local project's VO transient attributes to show the old values base it on the following Groovy expression:

adf.object.getEmployees().getPostedAttribute(model.entities.EmployeesImpl.POSITION)

What it does:

a) adf.object.getEmployees() calls the EmployeesViewRowImpl.getEmployees() method we checked existed in step 3, to retrieve the associated EntityImpl for the current ViewRowImpl

Note if you haven't undertaken step 3 to generate the associated ViewRowImpl, alternatively you could just call getEntity(0) instead in your Groovy expression. However I'd be cautious on doing this as you're relying on future upgrades of the framework not changing what's at position zero.

b) .getPostedAttribute() calls the now publically exposed getPostedAttribute method we created in the common.model.CommonEntityImpl that gives us the ability to get at old attribute values in the EO

c) The parameter model.entities.EmployeesImpl.POSITION grabs the index position of the Surname field in the EO. Note we need to use the EntityImpl field position rather than the ViewRowImpl field positions, as the order of the fields can be different.


Of interest to this post, an old discussion on the ADF Enterprise Methodology Group, was do most projects extend the ADF framework as per section 37.1 Globally Extending ADF Business Components Functionality? As can be seen from this specific blog post this shows another reason to include the extended classes from day 1 of any ADF development.


Final caveat: Please note this post is mostly for self documentation purposes, posted here so others can make use of it, but is not guaranteed to work; honestly I haven't tested this thoroughly nor has it been placed in a production environment yet. As such be careful to check it works for you, your mileage may vary. If you find any problems it would be appreciated if you could post your findings here to assist other readers.

Thursday, 12 November 2009

ADF BC Groovy – showing old values along with new.

A common requirement in databound applications is to allow the user to view changes before they commit them to the database, showing the user both the original-old value along with the new. This gives users a chance to review their changes visually by comparing the old and new.

For an updated record that has yet been committed to the database, ADF BC stores both the old and new value. Among other reasons ADF BC does this, is it allows the user to cancel any changes, and rather than having to fetch the original value back from the database, ADF BC just retrieves the old value it has cached without a roundtrip to the database.

This cache gives us the ability to solve our original requirements as the ADF BC framework exposes methods to fetch both new and old non committed values from the Entity Object (EO). To fetch the new current value we call the associated accessor such as getPosition() or getName() that was automatically created by the framework in our EntityImpl. To get the old value we use the getPostedAttribute() method passing in the index of the field we wish to fetch.

In JDeveloper 11g through its introduction of Groovy expressions, it's very simple to expose the old value through the Entity Objects:

1) In your required EO create a transient attribute. For example if we want to show the old values for the Position attribute of our EO, we could create a new transient attribute named OldPosition.

2) Ensure the "Persistent" and "Derived from SQL Expression" properties are turned off for the new transient attribute.

3) Set the "Value Type" to Expression and enter the following Groovy expression into the Value field:

adf.object.getPostedAttribute(adf.object.getAttributeIndexOf(model.EmployeesImpl.POSITION))

Note the call to the getPostedAttribute() method, passing in the index of the Position field that it requires.

If the Groovy syntax isn't familiar to you in JDeveloper 11g consult Grant Ronald's Introduction to Groovy.

A bad steer here maybe to try and use ADF Groovy's oldValue and newValue methods. Unfortunately these are only available for Groovy expressions in EO Declarative Validators, not in transient attribute.


4) Expose the attribute through the associated View Objects (VO) if necessary.

At runtime you'll note that initially the OldPosition field shows what's in the Position field. When you change the Position field's value, the OldPosition remains at the pre-cached value. Finally on committing the changes to the database, the OldPosition value is overwritten with the new Position value.

Friday, 20 March 2009

ADF BC: Using Groovy to fetch sequence numbers Part II

I recently posted ADF BC: Using Groovy to fetch sequence numbers for EO/VO attribute default values. This post showed the power of what you can get away with in the new Groovy expressions of ADF Business Components in JDeveloper 11g.

Though power is good (muhahaha!, um, cough), simple is better.

Steve Muench suggested the following to make retrieving sequence numbers a breeze via the Groovy expression facilities.

Readers will be familiar with the common recommendation for ADF Business Components to create a layer of framework extensions, as per Section 33.2 of the JDeveloper 11g Fusion Guide.

With this in mind we can create the following helper method seqNextVal() to fetch the next value for a named sequence in our custom EntityImpl:


...which we can then make use of in our Groovy expression in the Entity Object attribute's default value field:


Remember to set the Value Type = Expression.

Thanks to Steve for his suggestion.

Tuesday, 10 March 2009

ADF BC: Using Groovy to fetch sequence numbers for EO/VO attribute default values

I've recently been fooling around with the new ADF Business Component support for Groovy expressions in JDeveloper 11g, and thought I'd share the following discovery.

(Usual caveat this hasn't yet been tested in a production system, so your mileage may vary)

JDeveloper's ADF BC supports a number of different mechanisms to fetch database sequence numbers for Entity Object & View Object primary key attributes when a new record is created.

One such method is to override the create(AttributeList) method in the Entity Object and include the following Java code:

@Override
public void create(AttributeList attributeList) {
  super.create(attributeList);
  SequenceImpl seq = new SequenceImpl("LOG_SEQ", getDBTransaction());
  Number seqNextval = seq.getSequenceNumber();
  setId(seqNextval);
}


This example retrieves the next value from the database's LOG_SEQ sequence and writes it to the local Entity Object's ID attribute via a call to setId().

This minor piece of code can now be replaced with a Groovy expression in JDeveloper 11g's ADF Business Components.

If we open the Entity Object editor, then double click the primary key attribute we're interested in populating with the sequence number, we can now enter the following Groovy expression for the Value field with the Expression radio button selected:

(new oracle.jbo.server.SequenceImpl("LOG_SEQ", (cont)
object.getDBTransaction())). (cont)
getSequenceNumber()


The following picture shows the entry in context of the Edit Attribute dialog:

Note in the expression how we must explicitely name the package + Java class for the SequenceImpl as we don't have a mechanism for importing classes in the simple Groovy expression.  In addition for the getDBTransaction() call we need to make reference to the Groovy "object" expression (or is that class? Whatever).  "object" passes a copy of the Entity Object class to the Groovy expression evaluator allowing it to call methods of the Entity Object, in this example getDBTransaction().  More information on Groovy expressions can be found in Steve Muench's following blog post.

The advantage of this Groovy approach is one less reason to code in Java in JDeveloper if you feel the desire (though the Java code example from above isn't exactly difficult).  The disadvantage of this approach, I can imagine it would be difficult to debug if something went wrong.

In conclusion we can see the power of the new Groovy expressions supported through JDeveloper 11g and ADF Business Components.

Friday, 28 November 2008

JDev11g new feature: Effective Dated Entity Objects

Many data models have the concept of effective dates where each row includes effective_from and effective_to dates. For example an employee's wage may very over time, so we store multiple records each with an effective date range with no overlaps in time (unless we want to pay our employees double of course). Within the database we could store this in a separate table to the employees table, tracking the employees changing wages to a specific time period:

CREATE TABLE emp_wages
(wage_id NUMBER(10) PRIMARY KEY
,emp_id NUMBER(10) CONSTRAINT emp_wages_fk REFERENCES employees(emp_id)
,eff_from DATE NOT NULL
,eff_to DATE
,wage NUMBER(10));

INSERT INTO emp_wages
VALUES (1, 1000, '19/OCT/2005','01/MAR/2007', 50000);

INSERT INTO emp_wages
VALUES (2, 1000, '01/MAR/2007','01/JUN/2007', 60000);

INSERT INTO emp_wages
VALUES (3, 1000, '01/JUN/2007', NULL, 70000);


A potential query based on this data is what was the employee's wages 1st April 2007 with the desired result being record 2.

With JDeveloper 10g a potential solution to this using ADF Business Components was to deliver a default EO/VO based on emp_wages, and within the VO add a bind variable and modify the query such that the data could be queried at a certain date.

JDeveloper 11g introduces the concept of Effective Dated Entity Objects which effectively (no pun intended) does this for you based on property settings. You can find documentation on this within the JDev 11g Fusion Guide under section 4.2.8 and section 5.4.

To turn this facility on do the following in your EO:
  • In your EO identify your eff_from attribute. In the Edit Attribute dialog select the Effective Date checkbox followed by the Start radio button.
  • Ditto for the eff_to attribute, except select the End radio button.
  • With the EO document window open, select the General tab, then within the Property Inspector under the Type category, and change the Effective Date Type property = EffectiveDated.
  • Return to the EO document window, under the Attribute tab you'll see a new transient attribute column SysEffectiveDate.
You next need to turn the facility on for the specific VO you want to support this functionality:
  • Open the VO document window.
  • With the General tab selected, in the Property Inspector set the Effective Dated field = True.
  • You'll note within the VO document window Attribute tab, the EO attribute transient attribute SysEffectiveDate.
On running the Business Component Browser and opening the specific VO you'll be prompted to enter a date for SysEffectiveDate. On entering a valid date (eg. 2007-04-01).....


....the records returned in the result set are filtered to this specific date:


If you don't enter a date for the bind variable, the current date is taken as default.

Returning back to the EO Effective Date Type property, you will have noted in the Edit Property dialog you had the option of selecting either EffectiveDated or Dated. The difference in functionality is best explained by the queries ADF BC undertakes on your behalf:

EffectiveDated query:

SELECT emp_wages.wage_id
,emp_wages.emp_id
,emp_wages.eff_from
,emp_wages.eff_to
,emp_wages.wage
FROM emp_wages emp_wages
WHERE (:Bind_SysEffectiveDate
BETWEEN emp_wages.eff_from
AND emp_wages.eff_to)


Dated query:

SELECT emp_wages.wage_id
,emp_wages.emp_id
,emp_wages.eff_from
,emp_wages.eff_to
,emp_wages.wage
FROM emp_wages emp_wages
WHERE (:Bind_SysEffectiveDate
BETWEEN emp_wages.eff_from
AND COALESCE(emp_wages.eff_to, TO_DATE('12/31/4712', 'MM/DD/RRRR')))

Thursday, 18 September 2008

JDev 11g ADF BC – New feature "Static List View Objects"

Following on from the Property Sets and Declarative View Object posts, another new feature in ADF Business Components in JDeveloper 11g is the "Static List View Object".

To create a Static List View Object, via the View Object Wizard you select the "Rows populated at design time (Static List)" option:


You then define the individual attributes of the VO yourself similar to a programmatic VO:


Then manually create the actual rows and attribute values yourself, hardcoded:


It's even possible to import the data at design time from the Import button on this same screen using a CSV file.

The key advantage of the Static List View Object is it's suitable for small datasets that never change. A great example would be gender values (M = Male, F = Female) or statuses (O = Open, C = Closed), or in Australia where the Australian State values are set at 8 (ACT, NT, NSW, QLD, SA, TAS, VIC, WA) and unlikely to change anytime soon (ignoring the obligatory "come-the-revolution" quotes ;).

Prior to the static list, in 10.1.3 one "hack" way to create a static VO was to create a R/O VO with a SELECT statement similare to following to load in some hard coded values:

SELECT 'a hardcoded value' FROM DUAL
UNION ALL
SELECT 'another hardcoded value' FROM DUAL


This was a kludge and required a database roundtrip to return the values. Simply not ideal.

With the new 11g feature, there's a valid argument that such data should be in fact stored in a database table anyway. Yet it's really upto you as the well-informed-programmer to decide what would be suitable for a Static List VO as separate to a normal R/W or R/O View Object. Note Oracle recommends in their JDev 11g documentation that the Static List is only suitable for 100 rows or less, otherwise use a database derived VO anyway.

I've also found Static List VOs suitable for stub VOs in creating ADF Faces RC web page mockups for demonstration purposes, where the database tables have yet to be designed. We instead create some dummy data Static List VOs, some web pages based on those VOs, and it looks like the pages are showing real data. A key problem with this approach though is if you then need to transform the Static List VOs into real database VOs, it's a pain in the butt, because you need to delete the Static List VO and all its dependencies, create the new database derived VO, and then plug this correctly back into the web page and bindings. Hint hint Oracle, a "transform" VO facility would be neat.

Note that Static List VOs are a great candidate for the new Shared Application Module feature, of which Avrom Roy-Faderman has recently posted about in part 1 and part 2.

Sunday, 14 September 2008

JDev 11g ADF BC – New feature "Declarative View Objects"

Following on from my Property Sets post, another new feature in ADF Business Components for JDeveloper 11g is the "Declarative View Object".

To create a Declarative View Object, you need a View Object based on an Entity Object, and under the Query page of the View Object Wizard or Editor, you set the SQL Mode to Declarative:


On switching a View Object to the Declarative SQL Mode option you'll notice the Wizard/Editor hides the SQL Query from you, instead providing an interface to modify the Where clause by selecting and/or constructing View Criteria, and selecting View Object attributes to participate in the Order By clause.


The key to Declarative View Object is they calculate the SQL statement to execute at runtime from the underlying Entity Object's database table and attribute database columns. With the previous Normal and Expert modes, the SQL query was effectively defined at design time by the programmer. The Declarative VO approach reminds me of how Oracle Forms works, in the fact that Oracle Forms uses the Block-table and Item-column mappings to construct the SQL statement at runtime; there is no complete SQL query you can look at design time in Forms.

The main advantage of Declarative mode is it removes the need to understand SQL queries, including the Where and Order By clauses. The query is now effectively hidden from the programmer.

I can hear a million Oracle programmers asking "why would we want to do that?" Taking the broad idea that not all programmers are born equal, and not all programmers know SQL, moving to a Declarative approach will assist such non-SQL-savvy programmers, as well as beginners or business users in working with ADF.

Another advantage is this approach uses the new 11g VO View Criteria feature in specifying the filtering Where clause. The View Criteria feature is a powerful one as it allows the programmer to name each Where clause essentially, and reuse that Where clause throughout the program, potentially in combination with other named View Criteria. For an example of this reuse have a look at how the new LOV controls in ADF Faces Rich Client support the defined View Criteria.

Obviously Declarative View Objects aren't for everyone, but they provide an interesting new feature extending the declarative programming concept in JDeveloper. Soon there wont be much programming left to actually do!

One caveat I need to state with this post, and I forgot previously with the Property Sets post, is this feature is currently available in the JDev 11g Drop 6 release (and potentially TP4) that the Oracle ACE Directors have access to. There's the possibility it wont be in the production release, but maybe we'll know for sure in a week or so.

Wednesday, 10 September 2008

JDev 11g ADF BC – New feature "Property Sets"

"Property Sets" are a new addition to ADF Business Components (ADF BC) in JDeveloper 11g. Property Sets are related to the extensible Custom Properties framework definable on EO & VO attributes, as well as at the EO, VO and & AM levels. If you're not familiar with the power and usage of ADF Business Component extensible Custom Properties look at my previous post I rest my case: Converting ADF BC EO/VO attributes to upper and lower case with custom properties or Avrom Roy-Faderman's post The Power of Properties.

Property Sets allow us to define a set of Custom Properties, essentially key value pairs, and then apply them to the ADF BC objects, without having to manually create each key value pair manually ourselves.

If we take a rather simplistic example, we could define a new Property Set "Alpha", with 2 properties "Beta" and "Charlie" as follows:

Then for example, we can select an attribute out of an EO or VO, and change the Property Set value to our new Property Set:

To prove the Custom Properties apply at runtime, without coding, within the Business Components Browser, we can right click on the attribute in question, and you can see a small information box that shows the runtime properties of the field, including the Property Set key value pairs we created.

This is obviously just a small new feature within JDeveloper 11g, but yet again a declarative productivity booster to stop the programmer having to waste time inputing values.

Tuesday, 5 August 2008

The 1st OOW08 Unconference session! - An ADF Methodology for the masses

2008 sees Oracle continue to expand their Oracle Open World offerings, with a greater participation from delegates as well as the usual "speaker mob". Last year Oracle and specifically OTN offered the Unconference for the first time, a great chance for anybody "off-the-streets" to sign up and present on any topic they felt interesting.

I'm excited to announce that the OOW08 Unconference is up and running and the ADF Methodology is the first cab out of the ranks.

As many of us know, a software development methodology is designed to assist experienced and uninitiated technology practicionist standardise their approach to software design & development. A methodology can help highlight common decision points, outline best practices, promote code reuse, and propose standard deliverables among many other things.

The goal of the ADF Development Methodology is to propose just such a methodology for JDeveloper Application Development Framework (ADF) based projects. With the experience of real-world experts, including Oracle ACEs and Oracle staff, we'd like you to join us to put such a methodology together.

Obviously a methodology is a huge undertaking. The intention of the OOW08 Unconference session is not to define a complete methodology at this time, but begin the process of constructing the methodology, to be filled in and expanded upon at a later date. All proceeds from the Unconference session will be placed on the Oracle Wiki allowing all to access the outcomes for their own use.

If you're interested in attending, it would be great if you could register your interest to assist us in planning please.

And as Shay Shmeltzer recently blogged, we've also started a Google Group to discuss the methodology before and after the event. Feel free to check it out and join, all participants welcome.

Thanks to Justin Kestelyn and the OTN team for their assistance behind the scenes, and to Shay for his blog post.

Tuesday, 22 July 2008

ADF BC: EO/VO create() state + JBO-25030 revisited

Recently I blogged about why you might receive JBO-25030: Failed to find or invalidate owning entity in ADF BC, a follow up to a further description by Steve Muench.

I'd like to blog about another reason you'll receive JBO-25030 and is related to my recent post on ADF BC: EO/VO initial state post create() explained.

In that blog post it details that an EO/VO that is instantiated and attributes are defaulted via declarative default settings or your own programmatic code, the record's status is set to STATUS_NEW, but the ADFm binding layer overrides this with STATUS_INITIALIZED. This status implies the record is not a candidate to be inserted into the database until the user or calling program changes another value in the record or programmatically changes the status of the record to STATUS_NEW.

This behaviour has further implications for EOs involved in Associations, more commonly known as foreign key or master-detail relationships, and Composition Associations in particular.

In the case of a master-detail EO Association that is not marked as a Composition Association, on the programmer creating the master entity which has its values defaulted (status STATUS_INITIALIZED), and creating a child entity which the user then sets some of the attributes manually (status STATUS_NEW), on pressing commit the programmer may be surprised to receive a foreign-key constraint error returned from the database. This occurs because the master EO status STATUS_INITIALIZED marks it not as a candidate to insert into the database, but the user setting the child EOs attributes does mark it as a candidate for the database with status STATUS_NEW. As such at commit time, the ADF BC mid-tier searches the EO cache looking for records with status STATUS_NEW (and STATUS_MODIFIED to be strictly true, but not considered here), discards the parent record because it has the wrong status, but sends the insert DML to the database for the child record, raising the FK error.

In the case of a master-detail EO Composition Association, on the programmer creating the defaulted parent EO, creating the child EO and manually setting values, and finally pressing commit, this time the programmer will hit "JBO-25030: Failed to find or invalidate owning entity". Why? As you know a Composition Association says that a child can't exist without a parent. So in this case the ADF BC mid-tier is enforcing that the child cannot be inserted into the database with a parent whose status is STATUS_INITIALIZED, because the parent is not a candidate for the database. In other words the mid-tier is enforcing a mandatory FK relationship, with unfortunately a some-what obscure error message.

As detailed in my previous post, you can override the default behaviour of the parent VO such that it's defaulted state will mark it as a candidate to insert into the database.

I'd like to thank Steve Muench for his assistance on the issues behind this blog post.

This post along with other posts describing common JDeveloper error messages are indexed on the Oracle Wiki.

Tuesday, 8 July 2008

ADF BC: EO/VO initial state post create() explained

Thanks to Steve Muench, Olivier and Rob on the JDev OTN Forums, I learnt some valuable lessons about the state of ADF Business Component (ADF BC) Entity Objects (EOs) after the create() method is called. I thought I'd share this new knowledge for others to benefit.

In JDeveloper's ADF BC Entity Objects (EOs) and View Objects (VOs), on instantiating an EO/VO, it's possible to set the default value for the EO/VO attributes declaratively or programmatically through code. The declarative fashion is done by setting the Default property to simple literals for the individual EO/VO attributes in the associated EO/VO editor. Within JDev 11g this has been expanded to support Groovy expressions.

Alternatively both the EntityImpl and ViewRowImpl that represent the EO/VOs in code, the programmer can override the create() method to programmatically set the EO/VO attributes. For example you may wish to set an attribute to the next sequence number from a sequence in the Oracle database, and some other attribute to a static value:

public MyEntityImpl extends EntityImpl {

  public void create(AttributeList attributeList) {
    super.create(attributeList);
    SequenceImpl seq = new SequenceImpl("my_db_seq", getDBTransaction());
    setSomeId(seq.getSequenceNumber());
    setSomeField("some value");
  }
  .. and so on ..
}


Thus in the Business Components Browser if you open the associated VO, and create a record, you'll see the defaulted attributes set to the values above.

As per section "9.2.5 Understanding Entity Object Row States" in the 10g JDev guide for Forms/4GL Programmers (this also exists in the 11g guide, but at the time of writing this article the 11g guide is still in draft), on creating a new record the EO's state should be set to STATUS_NEW. STATUS_NEW says that at least 1 of the attributes of the EO has been updated, and thus the record is a candidate to be inserted to the database.

There are other alternative statuses for an EO, including STATUS_INITIALIZED. This status indicates a new record that is not yet a candidate to insert into the database as no changes have yet occurred to its attributes, it's basically just empty. Again to be clear, ADF BC will only mark the record to be a candidate to insert into the database (STATUS_NEW) when either the user sets a value, or programmatically overrides the status of the new row. (The user in this case means the consumer, or the program that is interfacing to the ADF BC project; this won't be a real human user directly, at the very least an UI will sit in front and provide access to the user)

So from our example above, given that we've programmatically updated attributes, is it reasonable to assume the EO's status will be STATUS_NEW once the user has created the record and we've programmatically defaulted the values?

If we consider the Business Components Browser (the Tester), and we consider JDev 10.1.3 the answer is Yes. However if we consider JDev 11g the answer is No. (Groan I hear you say ;)

Why? The key is the statement above:

"ADF BC will only mark the record to be a candidate to insert into the database (STATUS_NEW) when either the user sets a value manually, or programmatically overrides the status of the new row. (The user in this case means the consumer, or the program that is interfacing to the ADF BC project; this won't be a real human user directly, at the very least an UI will sit in front and provide access to the user)"

Note my emphasis, that the calling program can override the EO state if desired.

In JDev 10.1.3 the Business Components Browser (known as the Tester), as confirmed by Steve Muench is a "cheater" and doesn't actually implement a full blown ADFm binding layer, acting like a true ViewController to the ADF BC Model project. Instead it directly invoked the ADF BC project with its own functionality.

In JDev 11g the Business Components Browser sits on a real ADFm binding layer and as such acts like any ADF Faces/RC page.

The ADFm binding layer being the calling program to the ADF BC layer in this case, actually has code in it to override the status of an EO record if it can't detect any attribute changes by the real "human" user, regardless of the programmatic defaultedv values in the code above. And it sets the EO status back to STATUS_INITIALIZED, marking the record as a non-candidate for database inserts.

Conversely the 10.1.3 Business Components Browser because of its own custom functionality didn't.

This means in 10.1.3 when you commit the new-programmatically-defaulted but not user changed EO record, it will be inserted into the database. Conversely in 11g even though you commit the new record, unless you as the user make a change to one or more of the attributes, the 11g ADFm binding layer will override the status of the EO and it won't be written to the database.

Obviously this functionality isn't always desired. To override this default behaviour such that the record is inserted into the database regardless, you can override the ViewRowImpl's setNewRowState() method as follows:

@Override
public void setNewRowState(byte b) {
  if (b != Row.STATUS_INITIALIZED || getNewRowState() != Row.STATUS_NEW) {
  super.setNewRowState(b);
  }
}


It's this method that's called by the ADFm binding layer, so effectively you're intercepting the status set.

Ideally I'd like to see this as a property on the EO/VO editor, but at the very least ADF BC gives us the ability to override the default functionality by code.

Please note for the simplification of the discussion above, when I say that the ADFm binding layer sets the EO status, it can't actually do this directly. It needs to interface with the parent Application Module, then the View Object that represents the EO. Thus why we override the setNewRowState() method in the VO rather than the EO.

Thanks to Steve, Olivier and Rob for their assistance with this post.

This post was written against JDev 10.1.3 and JDev 11gTP4. As usual check everything under your specific version as your mileage may vary.

Tuesday, 27 May 2008

JBO-25030: Failed to find or invalidate owning entity

Steve Muench has blogged about this error before. In this example we'll talk about 2 settings in an ADF BC composition association that will cause the same error, and an alternative explanation of why the error occurs which some might find useful.

Consider an ADF BC project with a master-detail relationship between two EOs Events and Bookings. The relationship is modelled by an EO Association. The EO Association has either the Composition Association – Lock Top-Level Container property set, or the Composition Association – Update Top-Level History Columns property set (or both). For your reference these are set within the EO Association editor under the Association Properties page.


In addition consider two VOs to represent the EOs, namely EventsView and BookingsView. Within the parent Application Module these are exposed as follows:


Note how the BookingView is both exposed as a detail to the EventsView1 called BookingsView2, and as a parent in its own right called BookingsView1.

Now if you open the Business Components Browser, and create a record in BookingsView2 which is the detail of EventsView1, you'll have no issue. However if you create a record in BookingsView1 which is not a detail VO, you'll receive the error message:

(oracle.jbo.InvalidOwnerException) JBO-25030: Failed to find or invalidate owning entity: detail entity <entity name>, row key null.


The reason you receive this error is because of the Association properties you set above. Specifically you've defined BookingsView as a child within a Composition Association. A Composition Association is an EO Association which says the child VO rows cannot exist outside the context of the parent, in this case the EventsView1 parent row. And in addition by either setting the Lock Top-Level Container or Update Top-Level History Columns options, you're forcing ADF to go search for the parent VO for the current child VO to either Lock the Top-Level VO, or Update the Top-Level VO's history columns.

So when you create records in BookingsView1 you get an error because it has no parent VO, but if you create records in BookingsView2 which is a child to EventsView, you don't get the error because the parent EventsView VO exists.

Note this issue has been replicated in JDev 10.1.3 and JDev 11g TP4.

If you're interested on finding more help on JDeveloper errors, visit the wiki.oracle.com Understanding ADF Error Codes page.

Monday, 28 April 2008

JDev - alternative uses for the ADF BC DBSequence datatype

Thanks to Steve Muench on the OTN JDev Forums, and possibly poor lateral thinking on my part, I've discovered another use for the DBSequence datatype within ADF BC entity objects which I'd like to share.

Under section "6.6.3.8 Trigger-Assigned Primary Key Values from a Database Sequence" of the ADF Developer's Guide for Forms/4GL Developers 10g it details that the DBSequence datatype is useful for entities with a PK populated via a database trigger assigning a sequence. In addition before the record has hit the database, ADF BC will assign a unique negative number as a temporary value to flag to the user the real sequence number has yet to be retrieved.

With this in mind and thanks to Steve's help, for a current client we found that the DBSequence was useful in another scenario not actually involving a database sequence.

My client has an EO with a mandatory PK that is generated by a database function, not a sequence number. The internals of the function are irrelevant, but the function guarantees to generate unique numbers when called. Obviously a sequence number would be a better replacement but there are business reasons why the number must come from the function, including that it has check digits, starts with a 2 digit year, and the main counter starts from 1 each year.

My client also has a business case that the numbers generated from the function aren't wasted. The database doesn't guarantee sequence numbers are allocated contiguously so are a bad fit in this case. As such the numbers should be allocated when the record is committed only, rather than relying on the EntityImpl.create() method, as users may rollback changes after the create() method is called causing gaps in the number chain.

What approaches could we take in attempting to solve this problem?

The first possible answer is to place this logic in the EntityImpl.doDML() method. Yet this isn't appropriate because the method fires after EO validation and doDML() hasn't yet had a chance to assign a value to the mandatory PK. Maybe there is a more appropriate method to override in the EntityImpl to do this? My understanding of the order of EntityImpl methods called are as follows:

EntityImpl.create()
~ user in UI inserts some attributes and submit/commits ~
LOOP through each new EO {
  EntityImpl.validateEntity()
  EntityImpl.prepareForDML()
  EntityImpl.doDML()
} END LOOP
LOOP through each new EO {
  EntityImpl.beforeCommit()
} END LOOP

Because validateEntity() is called before prepareForDML() and doDML(), neither method provide an appropriate place to default the PK attribute as validation has already fired and the mandatory PK error will raise itself.

We could place logic in the validateEntity() to default the value on a new record. However validateEntity() is also called when navigating rows so we run the risk of the user rolling back their changes and losing the generated PK.

We could make the PK non mandatory and update it on the doDML() method. But we'd still like the visual indicator on the UI that the field is mandatory and to derive this from the EO attribute properties rather than some properties hack which the next programmer will miss.

So we seem to be a bit stuck in finding a solution. DBSequence to the rescue!

The workaround is to set the PK datatype to a DBSequence datatype in combination with the doDML() method. When EntityImpl.create() is called the DBSequence sets the PK attribute to -1. Within our EntityImpl.doDML() method, we detect if we're executing an Insert, if the value is -1, and call our database function to derive the attribute, such as:

protected void doDML(int operation, TransactionEvent e) {
  if (operation == DML_INSERT) {
    // Call our function to update the PK attribute
  }
  super.doDML(operation, e);
}

As you can see the DBSequence provides a useful work around here. In fact it wouldn't be a work around at all if the datatype wasn't called DBSequence which makes you think it's for sequences only.

Tuesday, 9 October 2007

New OTN article: Integrating JDeveloper and Designer's Table API

I'll tag this post under "another 23 + 6.2 seconds of fame".

Thanks to OTN, my article Integrating the Oracle Designer Legacy Table API with Oracle JDeveloper 11g ADF Business Components has been published, and even indexed on their front page.... be quick! I'm sure it'll be gone soon.

Without attempting to sound like a complete amateur, but indeed sounding like a complete amateur, it's pretty neat to be published at this international level. Up till now most of my articles and white papers have been published in the Australian Oracle User Group's (AUSOUG) magazine Foresight. Suddenly I've an article up in lights on the OTN front page, and for the record, a big cheesy grin to match.

My Mum will be so proud..... except she doesn't understand anything I do and listens with a blank look most of the time. I think I lost her way back in 1998 when I mentioned the acronym RDBMS.

Thanks to Justin Kestelyn and the Oracle team for accepting and editing the article, and putting up with my poor grammar, spelling mistakes, and outrages demands.

This of course makes me excited that hopefully Oracle will accept my next article, a romance-crime-mystery Oracle-Forms crossover.

Wednesday, 29 August 2007

JDeveloper documented "Recommendations"

I've been sitting on this post for a long time, 4 months in fact, as a back up post in case I'm too busy to write anything new. The next few weeks are such a time and it's about time I published this post before the imminent release of JDeveloper 11g Gold! (not that I know anything, but I'd be placing my bets on a November release date)

Oracle's JDeveloper team has to be commended for the large leap in the quality and breadth of documentation from the 10.1.2 to 10.1.3 releases, with the introduction of the ADF Developers' guides. In my opinion the effect of this has been noticeable on the JDev OTN forum where beginner questions have become thinner on the ground, possibly thanks to RTFM.

Of course now with so much documentation -- one such guide is over 1000 pages -- there is an awful lot to digest. Unfortunately within such a large set of documentation, Oracle's "JDeveloper Recommendations" and best practices can be lost or forgotten.

I recently took time out to search within Oracle's JDeveloper 10g provided documentation for any JDeveloper and ADF BC/Faces recommendations that they thought necessary to document. I provide a summary of the recommendations below to assist your JDeveloper experience, may it be a good one ;)

The mileage you experience from each recommendation may vary. Some are trivial, others encompass the whole development cycle.

Disclaimer: please note this is not a definitive list of recommendations, just my own summary. You should persist in regularly reading white papers, blogs and attending Oracle related conferences to keep up with the latest recommendations. If I've missed any of the recommendations you think crucial in the JDev documentation, let me know via a comment with appropriate links, and I'll update this blog. Also take time out to read the original quote in context of the actual JDev documentation by following the links.

Copyright disclaimer: the following quotes are all sourced from Oracle's own documentation and as such please respect their copyright if you source this page and acknowledge their efforts appropriately if you reference a section.

Final comment and appreciation: Thanks to Victoria Lira for her assistance in getting this post finally published.

JDeveloper recommendations
....(from the Oracle documentation set)

JDeveloper migration

Migrating Projects from Pre-Oracle9i Releases - Direct migration from pre-Oracle9i releases to Oracle JDeveloper 10g is not certified. We recommend that you first migrate to release 9.0.x (see the 9.0.x documentation), and then proceed from there.

Migrating System Settings to Oracle JDeveloper 10g - Select the settings and customizations you want to migrate. We recommend selecting all available options.

Projects

Working with Large Projects - It is strongly recommend to use ANT for such tasks as building and deploying.

ADF Business Components

Introducing Oracle ADF Business Components - In addition, if you are an Oracle Forms user, we recommend reading the following topic: About Oracle ADF Business Components: An Oracle Forms Developer's Perspective

Working with ADF Business Components in the Model Project - If you are comfortable with UML modelling, we recommend selecting Business Components Diagram, which provides a graphical interface for designing your business components. You can drag tables onto this diagram to create business domain components. For more information, see the Related Topics list.

ADF BC Application Modules

Accessing a Root - Level Application Module From an Entity Object - You can access a root-level application module directly from an entity object if the entity object is hosted by the application module. Generally speaking, this is not the recommend approach, as your entity object will only work with that particular application module. You might want to do this, for example, if you need to create rows of a view and insert new records in an entity object's doDML() method.

Creating a Package of Data Model Components - We recommend using packages to separate your data model components (view objects, view links, and application modules) from your business domain components (entity objects, associations, and domains). This allows you to reuse your business domain components with multiple sets of data model components. For more information, see the related topics list.

About Oracle ADF Business Components Packages - We recommend putting business domain components (entity objects and associations) in a separate package from data model components (view objects, view links, and application modules). This allows you to reuse your business domain components with multiple sets of data model components.

ADF BC View Objects

Understanding the Default View Link Consistency Setting and How to Change It
- Conversely, you could globally enable this feature by setting jbo.viewlink.consistent to the value true, but Oracle does not recommend doing this. Doing so would force view link consistency to be set on for view objects with secondary entity usages that are not marked as a reference which presently do not support the view link consistency feature well.

Efficiently Scrolling Through Large Result Sets Using Range Paging - As a general rule, for highest performance, Oracle recommends building your application in a way that avoids giving the end-user the opportunity to scroll through very large query results. To enforce this recommendation, call the getEstimatedRowCount() method on a view object to determine how many rows would be returned the user's query before actually executing the query and allowing the user to proceed. If the estimated row count is unreasonably large, your application can demand that the end-user provide additional search criteria.

Consider Whether Fetching One Row at a Time is Appropriate - Caution - Unless your query really fetches just one row, leaving the default fetch size of one (1) in the in Batches of field on the Tuning panel is a recipe for bad performance due to many unnecessary round trips between the application server and the database. Oracle strongly recommends considering the appropriate value for each view object's fetch size.

How a RowMatch Affects Rows Fetched from the Database - Oracle recommends using database-level filtering to retrieve the smallest-possible rowset first, and then using RowMatch as appropriate to subset that list in memory

Creating a Calculated Attribute at the View Object Level - Ensure View Row Class > Generate Java File and Generate Accessors are selected. We recommend selecting Ex pose Accessors to the Client as well.

Adding a View Link Instance with a New View Object Attribute - Based Definition at Runtime - Note: This is the most flexible, but the most complex, way to create view link instances dynamically. If you have a view link definition or association that might be appropriate, we recommend that you use another method. For more information, see the related topics list.

Using Parameterized WHERE Clauses - In the Where field, enter a WHERE clause using parameters. Do not include the word "WHERE". Unless you are running against a non-Oracle database, we suggest you use Oracle-style parameters: ORDER_TOTAL > :1 + :2

ADF BC Runtime Properties

Oracle ADF Business Components System Properties # 1 - jbo.locking.mode - Note: In the case of session-oriented programs, such as web applications, it is recommended that the Oracle ADF Business Components property jbo.locking.mode should be set to optimistic unless you also set the RELEASE_MODE property to Reserved. Pessimistic locking is not compatible with Stateful or Stateless modes because the database transaction is always rolled back to allow the connection to be reused by another user. This results in the lock being released and makes pessimistic locking unusable. If you want to use pessimistic locking, you must set RELEASE_MODE to Reserved.

* and *

jbo.maxpoolcookieage - The maximum age of the browser cookies used to help clients retrieve stateful application modules. If these cookies do not time out, the value is -1. It is recommended that the max cookie age is always set less than or equal to the session cookie age. It is set that way by default (both are -1). If you change the the max cookie age then you must also change the session cookie age to the same value.

ADF BC Java stack

oracle.jbo.server.EntityCacheOverRowSet jdoc - getRow - use instead findByKey() for larger datasets

Note this discussion is repeated in:

oracle.jbo.common.ws.WSObject
oracle.jbo.client.remote.ViewUsageImpl
oracle.jbo.RowIterator
oracle.adf.model.generic.DCRowSetIteratorImpl

oracle.jbo.CSMessageBundle - In general, we recommend using EXC_INVALID_PARAMETER instead of EXC_INVALID_PARAM_NO_EXPL_GIVEN.

ADF Faces

The ADF Faces Dialog Framework - Note that we've also set "partialSubmit" on the commandButton to "true"; we highly recommend using this option on buttons that launch dialogs, as it avoids an otherwise unnecessary flash of the main page as the dialog is launched.

Configuring ADF Faces for Performance - In adf-faces-config.xml.....

When configuring ADF Faces for deployment, it is most critical that debug options have been turned off. Specifically: < debug-output > should be removed or set to false. oracle.adf.view.faces.CHECK_FILE_MODIFICATION should be removed or set to false. oracle.adf.view.faces.DEBUG_JAVASCRIPT should be removed or set to false.

* and *

The < c:if > will show "You're in an English locale" if the locale's language is English. This means that in English, a user's version of the page will have an extra component over users who aren't using English; the state will vary accordingly. This sort of problem can cleanly be resolved by using "rendered" instead of < c:if > , which is always a recommended JSF best-practice:

ADF Faces Page Definitions

What You May Need to Know About Binding to Values in Other Pages - While Oracle does not recommend this approach, you can access the bound values in another page's binding container from the current page using the data binding variable in an EL expression. The data binding variable references the binding context itself, which provides access to all the binding containers that are available. Use this variable when you want to bind to an object in the binding container of another page. The data variable must be immediately followed by the name of a page definition file that defines the binding container being referenced. For example: #{data.mypagePageDef.BindingObject.propertyName}

*and*

You may find cases, where you need to use the data variable to bind to values across binding containers. However, Oracle recommends that instead you use a backing bean to store page values and make them available to other pages. For more information about storing values in backing beans, see Using a Managed Bean to Store Information.

ADF Faces Components

<af:subform>
+ oracle.adf.view.faces.component.core.CoreSubForm

We strongly recommend the use of a single < af:form > per page, and using < af:subform > where you might otherwise be tempted to use multiple forms. Multiple forms require multiple copies of page state, and user edits in forms that aren't submitted are always lost. When a page using subforms is submitted, page state is only written once, and all user edits are preserved

ADF Faces Support Platforms

About ADF Faces Supported Platforms - Tip: On a UNIX server box, button images may not render as expected. Assuming you're using JDK 1.4 or later, we strongly recommend using -Djava.awt.headless=true as a command-line option with UNIX boxes.

CVS

About CVS and JDeveloper - We strongly recommend that you read the CVS Manual ("Version Management with CVS" by Per Cederqvist et al), which is freely available from www.cvshome.org

Note. Even if you know how to use existing checked out modules with JDeveloper CVS version control, you should not do so. We strongly recommend that you instead perform fresh checkouts from within JDeveloper.

Configuring JDeveloper for CVS - If you wish to use an external CVS client, we recommend the following: CVSNT 2.0.58a for Windows platforms - http://www.cvsnt.org/archive cvshome's CVS 1.11.9 for other platforms

Thursday, 9 August 2007

JDev 11g new features - ADF BC Entity Object Validation Rules part 3 of 3

This is the 3rd and final post in a 3 part series on the new Entity Object (EO) Validation Rule facilities in ADF Business Components (ADF BC) within the JDeveloper 11g Technical Preview edition. Follow these links for the previous posts part 1 and part 2.

The JDeveloper 11g Technical Preview (TP) edition introduces extended functionality which can be categorised under the tabs they exist within the Add Validation Rule dialog. This post specifically looks at the Failure Handling tab within the dialog:

The Failure Handling tab is an entirely new tab in the 11g TP release and provides the following functionality:

Validation Failure Severity - errors are now categorised into errors and warnings. An "error" based validation rule if invalidated will display the corresponding error message and will not save the changes until the issue is fixed. Alternatively "warning" based validation rules will fire on exactly the same conditions, but if the validation rule condition is true, while an error message is still displayed, the transaction will not be halted. This provides a nice mechanism to give users informational messages about problems in the data they entered, but not stopping them from saving their work just in case the user knows more than the business rule assumes.

Message Text - this field allows the entering of an error message including positional message expressions (see below). This is similar to the 10.1.3 functionality of entering an error message to display when the validation rule is invalidated. However in the 11g release via the new Select Message button, you may in the associated dialog select an error message out of an existing message bundle file, or even create a new message bundle file. Of particular use this allows you to reuse existing messages defined once in a single message bundle, unlike the 10.1.3 release where error messages where stored in separate MsgBundle class files for each EO.

Error Message Expressions - error messages may include positional fields to be substituted when the error messages is displayed at runtime to make the message more meaningful to the user. The positional fields take the form {n} within the error message where n is a sequential unique number within the error message. The Error Message Expressions option is populated with rows as you enter new substitution variables in your message. The value for the message to be displayed at runtime is defined by a Groovy expression.

Note: the use of positional fields in error messages was supported in 10.1.3, but the dialog did not include this level of sophistication for specifying the fields nor adding Groovy expressions.

In summary within the 10.1.3 release the error messages associated with validation rules was a simple text message. In the 11g release the developer now has the declarative ability to easily parameterise error messages from a single standard message bundle with no coding required.

In summary to the 3 part post, the declarative approach adopted in the EO validators in JDeveloper 10.1.3 and expanded upon in the JDeveloper 11g Technical Preview release, within software development saves much complex coding and uses a tested framework over writing custom validation code that may be error prone (no pun intended). However if necessary the programmer still has the flexibility to drop back to code and write whatever functionality if deemed necessary.

Disclaimer: this post is written against the JDeveloper 11g Technical Preview (pre-production) edition. Oracle reserves the rights to remove or change this functionality in the final release so ensure to check your facts if you're using a later version when reading this post.

Monday, 6 August 2007

JDev 11g new features - ADF BC Entity Object Validation Rules part 2 of 3

This is the 2nd post in a 3 part series on the new Entity Object (EO) Validation Rule facilities in ADF Business Components (ADF BC) within the JDeveloper 11g Technical Preview edition. The previous post can be found here, and part 3 here.

The JDeveloper 11g Technical Preview (TP) edition introduces extended functionality which can be categorised under the tabs they exist within the Add Validation Rule dialog. This post specifically looks at the Validation Execution tab within the dialog:

The Validation Execution tab is an entirely new tab since the 10.1.3 release and provides the following new functionality:

Validation Level - under the 10.1.3 release validation was always fired at entity level and immediately. This was an issue if the user had yet to complete work in order to satisfy the business rule. Under 11g, if creating the validation rule at the EO level the Validation Option is available, and validation can be set to fire at entity level or when the transaction is committed. This provides the same sort of functionality and advantages as transactional deferred constraints in the Oracle RDBMS.

Conditional Execution - a Groovy expression may be added to the validation rule that when true enforces the validation rule. As mentioned in the previous post Steve Muench has posted on this under his article Groovy Scripting Tips for ADF Business Components.

Triggering Attributes - if the validation rule is defined at the EO level, one or more attributes can be selected, and if any of the selected attributes' values are changed the validation rule will fire. If the validation rule is created at an attribute level rather than EO level, this option does not appear but rather only the single selected attribute is assumed to be defined against the rule.

Available for Real Time Client Execution - this option is only available for validation rules that are defined against an EO attribute, not for validation rules at the EO level. At this stage I'm sketchy on what this feature does, but I'm guessing it indicates to ADF Faces Rich Client components that it is fine to implement and fire this validation within Javascript on the client side. This will have the advantage of saving a round trip to the mid-tier, with the disadvantage of performance loss on the client.

In summary the 10.1.3 release provided little declarative control over when a validation rule should fire. Within the 11g release the developer now has the ability to be very specific under which conditions a validation rule should enforce its business rules, giving a sophisticated declarative approach to business rule programming with little to no coding required.

Part 3 of this post will look at the final tab within the Add Validation Rule dialog, namely Failure Handling.

Disclaimer: this post is written against the JDeveloper 11g Technical Preview (pre-production) edition. Oracle reserves the rights to remove or change this functionality in the final release so ensure to check your facts if you're using a later version when reading this post.