JBO-27023 Failed to validate all rows

Have you ever experience weird error reporting as shown below, while trying to throw some meaningful validation error from your business methods?
Instead of the desired error, UI reports a generic error saying
JBO-27023 : “Failed to validate all rows”.
What goes wrong?
Take a look at your manged bean where you have the code to invoke methods from ApplicationModule(service layer). Your code may look like as shown below, where you are getting instance of ApplicationModule and invoking methods directly on it.This is not the recommended approach, as you are by passing binding layer. Suggested approach is to let the binding layer to do this job as shown under 'Right Implementation'

Wrong Implementation

    public String someAction() {
        BindingContext bc = BindingContext.getCurrent();
        DCDataControl dc = bc.findDataControl(dataControlName);
        if ((dc != null) && dc instanceof DCJboDataControl) {
            ApplicationModuleImpl amImpl =
                (ApplicationModuleImpl)dc.getDataProvider();
            amImpl.doSomething();
        
        }
        return "success"
    }

Right Implementation

Expose the ApplicationModule method to client and define a methodAction binding for the same, then use the ADF binding api to do the job.

       public String someAction() {
        BindingContainer bindings = getBindings();
        OperationBinding ob = bindings.getOperationBinding("doSomething");
        Object result = ob.execute();
        if (!ob.getErrors().isEmpty()) {
            return "error";
        }
        return "success";
    }

Advantages
1. This gives clear separation between tiers/layers of your application
2. Ensures both binding layer and service layer are in synch.
3. Provides uniform error handling


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

Comments

Mukul said…
This comment has been removed by the author.
Mukul said…
obinesh,
All said and done, I am just curious about a little insight of this error. I understand that best practices include mvc as separate layers , and the second approach you told is perfect, but, what I am interested, even if one is not following best practice, the code should work , why does it gives this error(the wrong approach mentioned in your article)?
--Mukul
Jobinesh said…
Let us take a step back and see the error handling mechanism in ADF. Whenever Service layer throws error(JBO), default error handler intercepts and converts it to meaningful format.Please note that, default error handling( DCErrorHandlerImpl) is associated with the binding layer. But if you bypass binding layer, then there is no way to intercept this JBO exceptions(its sub classed from RuntimeException), so finally raw error is getting displayed in a conventional way as the page is rendered.
Mukul said…
Thanks Jobinesh, for the perfect reply, got the point, since we are bypassing the binding layer, so DCErrorHandlerImpl does not comes into picture and we get a generic error message.

One more curious question, although not very much related to this post, but I think you are the correct person to answer this.

Actually I am from OAF background(not sure, if you have got exposure to it!), have worked in 10g and still in R N D phase of 11 g :) .
I am designing and working on an ADF application with a small team of 4 developers. Since, in OAF, at runtime you can throw OAException message which is displayed like faces message in ADF. Now I wanted to have something similar in ADF.

For that I did following :
1)I have created a custom exception class subclassed from Runtime exception.
2) I have defined a custom exception handler class for my ADF application which extends ADFcExceptionHandler class.Whenever runtimeexception is raised,
i check in this class whether the exception type is my custom exception class or not, if its my custom exception class ,I stop the exception execution furthur and convert this exception message to faces message.The same logic of exception is used in both model anc view-controller layers.
Now my first question is my approach correct?? I am curious is there some other standard way of displaying exception message as faces message, both in model and VC layers. I am aware of EO validation messages,

But I wanna some mechanism of throwing runtime exception (which should be converted as Faces Message in Model layer.. I am aware of extending DCErrorHandlerImpl and add messages in Model layer, but I... want to throw exception and not add message....), while writing my business logic in AM.

--Mukul
Jobinesh said…
Mukul
Implementation is always use case driven :), seems OK for me, one suggestion though. Please consider sub classing the custom exception from oracle.jbo.JboException.As most of the run time exceptions in ADF are subclassed from JboException, this may give you more control on the exception handling
Mukul said…
Good idea and makes sense... have done this change,now my custom exception extends oracle.jbo.JboException instead of java.lang.RuntimeException. Thanks once again for your valuble suggestion.
--Mukul
Anonymous said…
Hi Jobinesh,

I am new to ADF. I am getting the same exception in the following scenario. I have defined business rule on EO. Rule type is method.

Method is returning false. But throwing same exception which you mentioned this blog i.e JBO-27023 instead of user defined error message.

How can i resolve this issue?

Thanks
Narendra
Jobinesh said…
Narendra,
How do you invoke the operation/service method which causes the validation. Please copy that part here. You may need to do this using binding layer as said in the blog post.
Anonymous said…
I created method type rule in EO. This is entity level validation. So, its created method in EOImpl class.

public boolean validateEmployeeResourceUsageDates() {
boolean isResourceStartDateValid=true;

RowSet HRUsageRowSet = getHREmployeeUsage();

if(HRUsageRowSet != null){
prepareRowSetForFiltering(HRUsageRowSet);
while(HRUsageRowSet.hasNext()) {
Row Usagerow = HRUsageRowSet.next();
if(((Date)Usagerow.getAttribute("EffectiveStartDate")).after(getStartDateActive())){
isResourceStartDateValid =false;
break;
}
}
}
return isResourceStartDateValid;
}
Anonymous said…
Hi Jobinesh,

Forgot to mention that the method getHREmployeeUsage() is view accessor in EO.

Thanks
Narendra
Jobinesh said…
Narendra
Please upload a test case to debug your issue email: jobinesh@gmail.com
Anonymous said…
Hi Jobinesh
I found ADF bug logged against this issue already. Will be fixed in D8B4.

thanks
Narendra

Disclaimer

The views expressed on this blog are my own and do not necessarily reflect the views of my employer.