Developer Tools
JDeveloper
Written By Duncan Mills, Oracle Corporation
February 2005
Oracle JDeveloper 10g, using the Oracle Application Development Framework (ADF), provides the JSP page developer with simple ways to produce various UI artifacts such as drop-down lists and radio groups which are bound to the business service in use. I have documented the steps to do this in previous How To documents, for example: Creating a Databound Drop Down List in Oracle JDeveloper 10g). In this article though I'll be looking a a slightly different scenario, that of binding a checkbox.
Traditionally in an Oracle database, the kind of boolean choice that you want to expose through a checkbox has been defined as a simple character column on the table for instance VARCHAR2(1), using the valid values "Y" or "N" to indicate the boolean state. The technique outlined in this paper is based on this scenario, but will work just as well with any kind of boolean storage, for instance a CHAR or NUMBER. In this example we'll be working with an employee record that has an addition field called CONTRACTOR. In the database schema this is defined as being NOT NULL, and has a check constraint to enforce valid values of "Y" or "N". Before we proceed I'll assume that you've already defined your business service and the relevant data control is available in the Data Control Palette.
The simplest way to create both the model binding and the UI for the checkbox is to drag and drop the field in question into your input form as normal input field. If you created the input form by dragging and dropping the whole collection as an "Input Form" from the Data Control Palette then of course this will have already been done. To convert the field from a normal text input to a checkbox, switch to Source view in the JSP editor and look for the relevant column name. So in my example I'll just search for the String <html:text property="Contractor"/>. To convert the UI to a checkbox you'll need to change the html:text to html:checkbox. You also need to tell the tag what the checked value is, in this case "Y", using the value attribute. The altered tag will now look like this:
<html:checkbox property="Contractor" value="Y"/>
If you go ahead and run the page at this point, everything will appear to work correctly, existing rows in the collection will be shown either checked or unchecked as expected. However, if you start to test a little you'll begin to see some problems:
The problem we're encountering here is down to a peculiarity of checkboxes in HTML UIs. The value of a checkbox is only sent to the server if it is checked, so for an unchecked checkbox no value is sent. As such, the two problems highlighted above happen because the ADF model layer is simply not been notified of the checkbox status at all.
So let's look at what you have to do to handle this behavior. Fortunately it's a simple thing to detect, if you know it's likely to happen on a particular page:
protected void processUpdateModel(DataActionContext ctx)
{
//First look for the request parameter
Object cbInRequest = ctx.getHttpServletRequest().getParameter("Contractor");
//We only need to do anything if it was not submitted
if (cbInRequest == null)
{
// Get hold of the Form Bean containing the record
BindingContainerActionForm updateForm
= (BindingContainerActionForm)ctx.getActionForm();
//Get the binding for our particular column
JUCtrlAttrsBinding checkBoxBinding
= (JUCtrlAttrsBinding)updateForm.get("Contractor");
//Reset that explicitly to the *unchecked* value (N in this case)
checkBoxBinding.setAttribute(0,"N");
}
//Now let the model update progress using the data in updateForm as normal
super.processUpdateModel(ctx);
}
The above code will need some import statements added to the class for BindingContainerActionForm and so on. JDeveloper will prompt you for these as the type is entered, press Alt-Enter to action the auto-import when prompted.
The above code can usefully be refactored into a small utility method that just takes the name of the field and the unchecked value. If you already have your own framework subclass of DataForwardAction (something I'd generally recommend) then this utility method would be a good candidate for storing in that class for reuse.
Finally, note that the code shown above is deliberately simplified for clarity.Your own code should be defensive and check for things like checkBoxBinding being not null and so forth.
drmills v1.1 16/Feb/2005