Saturday, August 22, 2009

How to Skip Validation?

ADF has a very robust validation framework. Validations can be added at different layers (view, model and business services) based on your application's requirement. To learn more about the ADF validation framework, please go through the Fusion Developer's Guide for Oracle Application Development Framework.
That said, however, in a real business scenario there are cases where the validation needs to be skipped (or by passed) conditionally while submitting the form. This post discusses this topic with some common use cases.

Keep immediate=true

A very common way to skip validation is by keeping the value for immediate attribute as 'true' for the UIComponents. Immediate attribute allow processing of components to move up to the Apply Request Values phase of the lifecycle.

Use case scenario

While canceling a specific action, system should not perform the validation. One possible way to achieve this is by keeping immediate=true associated with UI element. To know more abut this feature, please refer this wiki.
Sometimes you may need to update UI controls with model data as part of the ‘immediate’ action. Make sure that you call resetValue() on the UIInput in this scenario. This causes to reset the submitted value and would ensure that UI gets updated with right value from the model.

SkipValidation

Another approach is to use SkipValidation property associated with the page definition file. SkipValidation by pass the model layer validation based on the specified parameter value.

Please note that:
1. This doesn’t have any impact on JSF/ADF Lifecycle.
2. This property doesn’t have any effect on the client side validation (even if it is generated using the EL bound with model layer)


Where can I locate SkipValidation?

SkipValidation can be located as part of the root node of the page definition file.



Possible values for SkipValidation are given below.



a. SkipValidation=true

Setting ‘SkipValidation’ property to true will bypass the ADF Model validation. In this case validation happens only when you commit the transaction( i.e: when you call transaction.commit()). Please note that SkipValidation skips only the entity level validation. The attribute level validation fire irrespective of the value for the boolean flag

Use case Scenario

This is useful where you need to delay the validation till the point where transaction gets committed to Database. There are cases where business data needs to be captured in bulk. A typical example would be capturing transaction data using a grid form/tabular list. Business user must be able to key in values in any order. i.e. even without completing the data capture for the current record, user must be able to move to next set of records. Here model level validation needs to be delayed till we really save the data. SkipValidation=true is the right option to achieve this sort of use case, which does the validation across records, only while committing the transaction.

b. SkipValidation=custom

In this case, framework validates only the 'CustomValidator' specified in page definition file.
The value of the 'CustomValidator' property would be an EL expression that evaluates to a bean that implements the oracle.binding.BindingContainerValidator interface



Use case Scenario

This gives more control to the developer while validating the data. Only validates(or rather executes) what is given in custom implementation for BindingContainerValidator. It is much useful in complex business scenarios where developer needs finer control on validation.

c. SkipValidation=skipDataControls

skipDataControls means that it will skip the data control level validation (also known as Transaction Level validation) and instead only will validate data in the row or rows which got updated through iterator in the current binding container.

Use case Scenario

The property is very much useful while dealing with below given scenarios.
1. A single entity is mapped to multiple tabs in a page.
2. Same page is making use of multiple Data Controls. Here commit on one Data Control should not trigger validation on other Data Controls defined in the same page.

d. SkipValidation=validateCurrentRows (Updated this post on 15 August 2013 to include this property)

If you are using JDeveloper 11.1.1.7.0 or 12.1.2.0.0 (or higher),  use SkipValidation="validateCurrentRows" instead of skipDataControls.  The setting SkipValidation="validateCurrentRows" will validate only those rows dirtied in the current request (by default run time will validate all dirty rows even if they are validated in previous requests) and also, will skip transaction level validation till you commit transaction.

e. SkipValidation=false

This is the default value for SkipValidation, apparently this setting just ensures the normal flow for validation during form submission.

Learn More ...

There are a lot more points like this. If  you are curious to learn the internals of the ADF Business Components and ADF Binding Layer,  the following book is for you - Oracle ADF Real World Developer’s Guide.
More details about this book can be found in this post- http://jobinesh.blogspot.in/2012/07/pre-order-your-copy-of-oracle-adf-real.html

23 comments:

Kevin said...

This blog entry was very useful! However, I'm running into an issue after setting SkipValidation="true"; When my validator DOES fire as needed (when I commit my transaction, which is done by a button => actionListener => data control frame commit in the backing bean) and there is an error, I now receive the message "Failed to validate all rows in a transaction" instead of my desired error message, which originally appeared when SkipValidation wasn't populated... do you know anything about this?

thanks!

Jobinesh said...

You may need to try reporting the error throught the BindingContainer.

Check out the below code snippet .

public String someAction() {
try {
BindingContext bc = BindingContext.getCurrent();
DCDataControl dc = bc.getDefaultDataControl();
dc.commitTransaction();
} catch (Exception ex) {
BindingContext bc = BindingContext.getCurrent();
DCBindingContainer c =
(DCBindingContainer)bc.getCurrentBindingsEntry();
c.reportException(ex);

}
return null;
}

Manish said...

Say you have an inline table, and you are creating multiple rows. When you hit the commit button, only then both entity level validation and transaction level validation is fired. Shouldn't be that, Entity level validation should fire, if we do a simple submit or when row currency changes? I have set SkipValidation to skipDataControls.

Jobinesh said...

Appears to be the expected behaviour, and this setting is specifically useful to isolate the validation to the current binding contianer(think of popup windows innoked from a parent page, validation needs to be restricted to popup up region alone).

Lakshaman said...

Need advice on skipValidation="custom"

Usecase: In a page laid out with a panelTab component with each tab holding details of different entities we need to skip validation for certain tabs.

What we tried:
Set skipvaliadation="custom" and invoked validate method on the datacontrol for one of the tab. We expected only the entities in that tab to run through their validateEntity calls but validations were invoked for other entities also at this point in time. From the call stack it was clear that the validate call was inturn resulting in transaction.validate().

What should be the implementation of customValidationBean such that only the entities under a particular dataControl are validated and not all the entities across all the dataControls.

Jobinesh said...

Lakshman
Sounds like you may need to try using, SkipValidation=skipDataControls.
If this doesnot help you , please pass a simeple test case that illustrartes the issue. jobinesh@gmail.com

Judy said...

Thanks Jobinesh. This is very helpful. I have a couple of questions regarding SkipValidations=skipDataControls.

1. It appears to me that this needs to be set only at the top level PageDef. Setting it at the lower level doesn't seem to work. Is that how it is?

2. Once this is set, I am seeing the issue that Kevin raised. Your suggestion seem to have fixed the 'Failed to validate' issue. But, will there be any side effect in reporting the error through BindingContainer?

Thanks in advance!

Jobinesh said...

Judy
1. Yes, that seems to be the expected behavior if both levels share same DCTxn.
2. I don't think there is any side effect in this approach. However managed bean doesn't seems to the ideal place for doing this DC level operations. The right place to do the Txn Commit/Roll back is BC layer. So defining a business method implementing business logic ,follwe dby txn commit/rollback is the best practice. Apparently this method can be invokes from Bean through binding layer APIs. So we can leverage the automatic error handling mechanism provided by the binding container.
BindingContext bindingContext = BindingContext.getCurrent();
BindingContainer bc= bindingContext.getCurrentBindingsEntry();

OperationBinding operation = (OperationBinding)bc.get("someMethod");
operation.getParamsMap().put("someParam", empNo);
operation.execute();
if(operation.getErrors().isEmpty()){
//Handle erroneous condition, e.g: returning "Error" string is this an action method or similar stuff.
}

Damian Acevedo said...

Very useful article ! thanks.

A couple of questions,

-is there any way to change the skipValidation property programmatically to disable it conditionally ?

-you know if exists any documentation about a SkipValidation=custom, i cant find anything on how to implement it to skip validations conditionally based on certain flags.
(By example, i want to validate only on a 'accept' button and not on the rest of the page buttons)

Thanks for any suggestion

A.S said...

I have a add and a delete button.Certain validations apply on the add button but these shouldnot be applicable on the delete button.
For this I tried applying immediate=true property for delete button.However, with the delete functionality there is a transient attribute (Of Boolean type)which is not recognized when immediate property of the delete button is set to true thereby affecting delete functionality.While as when the immediate property is set to false the delete functionality works just fine.

Any help please.

Jobinesh said...

You mean to say validation is triggered for boolean attribute. Check whether immediate =true set for the control bound to this attribute. If yes, get rid of this.

abhijeet said...

Hi Jobinesh,

For few days, I am struggling with one validation issue. I am getting validation error as soon as the popup is rendered in the page containing a form to insert new row. This happens only when there is no data in the table and it works fine when there is at least one row in the table.
Screen Shot: http://picpaste.com/adf_error-BAdP8Thv.JPG

I have tried SkipValidation with true and skipDataControl but it did not resolve the issue.

Do you have any idea what could be wrong here?

Thanks
Abhijeet

Jobinesh said...

Abhijeet
SkipValidation will help you to skip only EO level and Transaction level validation. The validation wht you there in your form is attribute level validations. Whats the version of JDeveloper you work with?

abhijeet said...

Hi Jobinesh,
I am using JDev: 1.1.2.0.0. Also tried with JDev Ver. 1.1.2.1.0 and faced the same issue.

Thanks
Abhijeet

P.S. It only fails, when there is no data in the table.

Anonymous said...

Hi ,

This is really useful. But, could you please let me know. Is there any way that i can skip validation for a specific field in a table on click of commit button.?

Thanks & Regards,
Ravi.

Anonymous said...

I want to skip the required text fields validation, when i click on command button . so , how can i achieve it. If i keep Immediate = true , i am not able to save the details to database.

Jobinesh said...

Two possibilities that I can think of -
1. Keep autoSubmit=true for those fields whose value needs to be saved.
2. Queue the action for the button with immediate=true in actionListener method for InvokeApplication phase.

Sandeep Koul said...

I made the skipValidation="true" but now i see exception pop up instead of error message pop up on my screen. Although the validation is happening properly during commit. I see get RowValException during invoke application phase.

How to handle this so that error message are shown?

Regards,
Sandeep

Jobinesh said...

If framework is not able tp associate validation error to a specific components an error popup will be displayed by design

Florin Marcus said...

I was testing SkipValidation="skipDataControls" with UI Shell.

This looks like the appropriate behavior, when you want to have separate transaction per tab.

Thanks,

Florin Marcus
Red Samurai Consulting.

Sreedhar said...

Can you please let me know how to skip default validations for minimum date and maximum date on Date component

winston said...

In Adf i created a menu navigation using navigation pane. I have two tabs, Register a complaint and Register a new user. In Register new user Tab i have a command button(createInsert option) that directs to a page with user details fields. Committing the values works fine but when clicking on the other tab it shows validation error that the fields should not be left empty. For this i have selected the page bindings and selected skip validation to true. But its not working fine. How to resolve this issue

Maha said...

Hi and thanks for you this article..
When you mentioned skipValidation=true will work on entity validation - does that include unique constraints?

i've got a case where i have a validation rule defined in EntityObject to check uniqueness of an attribute.
Say for example - DepartmentEO and has uniqueKey set on deptName.
Skip validation=true does not shift validation to commit time though it's defined at EntityLevel?

Thanks.