Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 26 Next »

Once the data is fetched, there can be a need to manipulate the data that has been fetched from the data provider. Inspired on the ViewRowImpl functionality from ADF BC, we created an annotation framework to manipulate the XML Data Control. On this page all the annotation are described in detail, to show the functionality of this framework we’ll first walk you through an example class.

Just as in the ViewRowImpl in ADF BC, you create a Java class to code the functionality of the data manipulation. This Java class is bound to an Element in the XML Data Control. In the example below, the Java class is to manipulate an Employee element. With the help of an annotation on the Java Class, you inform the customization which data collection you want to customize. With the help of annotations above the different method signatures, you inform the Data Control of the manipulations you want to do.
 


Setting up this Customization Class and refreshing your Data Control panel will result in a new structure of the Data Control.
We believe working with Customization will be close to the comfort zone of the ADF developers used to manipulating a row in the ADF BC framework.
An additional advantage of this manipulation is that it happens on the model side and thus eliminates the use of JSF Managed Beans for this.
 


At the moment we support a total of 8 annotations, you can find out what they do and how to use them in this chapter of the Developers Guide. 
We'll work with example code in an sample application, follow the first steps in the Getting started in 5 Minutes page, to make sure you have downloaded and installed the extension.
You can use the same JDeveloper project that is used in the Getting started page.  
 

Create Simple Page

Now that you are done with creating the data control all you need to do is create a simple page to see if it really works. Open the Web Content/public_html/WEB-INF/adfc-config.xml file. Then drag a View activity from the component palette to the editor.


Double-click the view activity to edit its page and accept all defaults in the dialog to create this page.

Once in the JSF page editor, simply drag-and-drop the Employee collection from the Data Controls panel to the page editor:


When asked what type of component to create, select an ADF Form

The Create Form dialog appears. For now, lets just accept most of the defaults. Tick Row Navigation & Submit and delete all the Job fields then press OK. 


This completes the setup for the application we are going to use to build customizations. 

Run the Page

Before writing the customization, run the page to view how it looks for now. The very first time you run this sample it might take a while as the Google App Engine instance hosting our web service is shutdown after a period of inactivity. Google will start a fresh new Java container the first time you invoke our demo web service.

Customizations

A Customization is extra, custom functionality that is not available in the XML DataControl, you have to program this logic yourself in Java. 
So lets start with creating this Java class, in our example we will customize the Employee shown in the UI.

Right click you project and choose new to bring up the New Gallery, then select a Java Class:
  

Enter a name, for exampl EmployeeCust and enter a package:

After this the Customization Class is created:

We will create all our customizations in the class, but before we are moving on to that, we need to register this class in our DataControl. 
Open the DataControls.dcx and go to the Source view. Here we need to tell our DataControl definition that we have a customization class. 
This is done by adding an customization-provider after the data-provider in the definition node.   

<customization-provider class="org.adfemg.datacontrol.xml.provider.customization.CustomizationProviderImpl">
  <parameters>
    <list-parameter name="classes">
      <value>org.adfemg.xmlsample.cust.EmployeeCust</value>
    </list-parameter>
  </parameters>
</customization-provider>

Since it is possible to have multiple customization classes on one DataControl, this is a list parameter in which you can add multiple value elements with references to customization classes.
That is all you need to tell to the DataControl, so now we can move back to ou Java class and start coding our Customizations.

Warning: The XML DataControl customization-provider works on the compiled classes, not in the design-time source. Make sure that you compile your Java class after every change you make, so the DataControl will pick up the change.  

Note: Both the registration of the customization-provider as well as the compiling of sources are obsolete on the trunk build of the XML Data Control. However, in the official 1.0 release, these steps are still necessary.
This will be removed from the documentation once the newer version of the Data Control is officially released. 

ElementCustomization

Every customization is a customization for one element. We need to tell this to the Java class by adding an annotation to the class.
We add the annotation '@ElementCustomization(target = "")' after which JDeveloper should add an import to the 'org.adfemg.datacontrol.xml.annotation.ElementCustomization' class.
The annotation needs an attribute target, here we need to enter the full name to the package of the element we want to customize with this Java class. 
The easiest way to get the correct information is to go to the pageDef file and copy the BeanClass from the accessorIterator.    

Resulting in the following code:

package org.adfemg.xmlsample.cust;

import org.adfemg.datacontrol.xml.annotation.ElementCustomization;

@ElementCustomization(target = "org.adfemg.xmlsample.HrDeptEmpDC.getDeptEmps.DepartmentEmployeesResponse.Employee")
public class EmployeeCust {
}

Inside this class we can now start writing methods to customize the Employee element.

CalculatedAttr

A calculated attribute is read only and based on other attributes inside the same element. 
Inside the java class create the following method:

@CalculatedAttr
public String getFullName(XMLDCElement employee) {
	return employee.get("firstName") + " " + employee.get("lastName");
}

A CalculatedAttr will always be an 'get' method with the annotation '@CalculatedAttr', after adding the annotation you should see an import appear from the class: 'org.adfemg.datacontrol.xml.annotation.CalculatedAttr'.
The return type, String in this case, determines of which type the attribute will be.
The name of the attribute will be based on the method name, the prefix get will be stripped and there will be an attribute with the name 'fullName'.
The XMLDCElement is the mandatory first argument of the method, which represents the actual element we are customizing (Employee).
You can use getters on the element to get information and use this in your result, in this case we want to concatenate the firstName and the lastName. 

Rebuild your Java class and refresh your Data Controls panel, after this you should see an extra element in the Employee:

 
Open the previously created DeptEmp pagefragment and drag and drop the fullName attribute between the lastName and email: 

Add an Text -> ADF Input Text w/ Label:
 

Resulting in the following inputText: 

<af:inputText value="#{bindings.fullName.inputValue}" label="#{bindings.fullName.hints.label}"
			  required="#{bindings.fullName.hints.mandatory}"
              columns="#{bindings.fullName.hints.displayWidth}"
              maximumLength="#{bindings.fullName.hints.precision}"
              shortDesc="#{bindings.fullName.hints.tooltip}" id="it8">
      <f:validator binding="#{bindings.fullName.validator}"/>
</af:inputText>

Now run the page again and check out the fullName attribute in action!

TransientAttr

A transient attribute in the XML DataControl is a lot like the transient attributes in the ADF Business Components layer. 
On the page we want the user to be able to toggle between showing jobs information or not. So we will introduce an transient attribute called 'showJobInfo'.
We create this again with a simple annotation on a method in the same EmployeeCust Java class.   

A TransientAttr will always be an 'init' method with the annotation '@TransientAttr', after adding the annotation you should see an import appear from the class: 'org.adfemg.datacontrol.xml.annotation.TransientAttr'.
The return type, boolean in this case, determines of which type the attribute will be. 
The name of the attribute will be based on the method name, the prefix init will be stripped and there will be an attribute with the name 'showJobInfo'.
The XMLDCElement is the mandatory first argument of the method, which represents the actual element we are customizing (Employee).
The result of the method will be the initial value of the transient attribute.

Do not forget to rebuild your Java class and refresh your Data Controls panel, after this you should see an extra element in the Employee:

Now we are ready to continue building on the interface.
First we add the Element showJobInfo to the bottom of the page:
  

Add this to the page as an ADF Select Boolean Checkbox:

Don't forget to add the property autoSubmit="true" on the selectBooleanCheckbox.
Next we are going to add a read only form with information about the job of the employee:
 

Now all we need to do is add the rendered expression 

After this run the page to look at the result. 
 
Notice the showJobInfo with the initial value set to true (as we returned in the java method).
The layout of the JobInfo form doesn't look too good, but that's for an other time (smile)
Now lets try to toggle the checkbox and see what happens:

 
You see the formLayout with the job information disappear.  

AttrValidation 

Now lets work on an attribute validation. Lets create a rule that the salary of an employee can not be lowered (we would all like that, wouldn't we?). 
An attribute validation is a validation specific for one attribute, if you want to have validation over multiple attributes or an element, you need to use the ElementValidation customization.
You will not see this attribute validation in the DataControl, but once the attribute on the page is submitted, the validation will fire.
If the validation fails, it is up to you as programmer to throw the correct error message as an AttrValException. 

     @AttrValidation
    public void validateSalary(AttrChangeEvent event) throws AttrValException {
        BigDecimal oldVal = (BigDecimal) event.getOldValue();
        BigDecimal newVal = (BigDecimal) event.getNewValue();
        if (newVal != null && oldVal != null && newVal.compareTo(oldVal) < 0) {
            throw new AttrValException(AttrValException.TYP_ATTRIBUTE, "Salary can not be lowered", "SAL-0001",
                                       event.getElement().getDefinition().getFullName(), event.getAttribute());
        }
    }


The signature of an AttrValidation is very specific, the name of the method needs to have the prefix 'validate' followed by the attribute name.
The parameter is an AttrChangeEvent which holds the old value and the new value as well as the Attribute and the Element. The AttrChangeEvent is imported from the package: 'org.adfemg.datacontrol.xml.events.AttrChangeEvent'.
Your method also needs to throw an AttrValException or an AttrSetValException which is an subtype of the AttrValException. Most of their constructors require a resource bundle (class), but their is one simple alternative without using a resource bundle as shown in the code example above. 
The method needs to have the annotation '@AttrValidation', after adding the annotation you should see an import appear from the class: 'org.adfemg.datacontrol.xml.annotation.AttrValidation'. 

Rebuild your Java class.
Now run the page.
You will notice that if you want to lower the salary and then press the submit button, you will get an error on the salary field:
 

ElementValidation

Sometimes, just an attribute validation is not enough, you want to do a validation involving two or more attributes in your validation. This is supported by the ElementValidation. 
The ElementValidation is invoked at the end of the request during the validate of the DataControl. The ElementValidation throws an ValidationException.
Optional you can provide a list of attributes to limit firing when only specified attributes have changed.

    @ElementValidation(attr = { "salary", "commissionPercentage" })
    public void validateIfAttrChanged(XMLDCElement employee) {
        BigDecimal salary = (BigDecimal) employee.get("salary");
        BigDecimal commissionPercentage = (BigDecimal) employee.get("commissionPercentage");
        if (salary == null && commissionPercentage == null) {
            throw new ValidationException("Salary and commission percentage can not both be empty");
        }
    }  


Just like the AttributeValidation, at design time you don't notice the validation in the DataControl panel, but on run time it will be executed.
In the above example, the ElementValidation will only be invoked if the salary or the commissionPercentage field has changed.  
The signature of the method is less specific, it does not need to start with the word validate, although we suggest you do.
For non existing attributes in the attr list an InvalidMethodSignatureException will be thrown. 
As an argument to your method, you need to add the XMLDCElement representing you Element.

You need to add the annotation ElementValidation to you method, resulting in an import of the class 'org.adfemg.datacontrol.xml.annotation.ElementValidation'.
When the validation fails, it is up to the programmer to throw an oracle.jboValidationException.  

When rebuilding the Java class and running the page, you will notice that clearing both the Salary field as well as the commissionPercentage will result in an error: 

PostAttrChange

Sometimes you have some logic that you want to execute after an attribute has been changed. For this we introduced the PostAttributeChange annotation. 
This annotation will monitor an attribute based on the method signature. 

 

    @PostAttrChange
    public void salaryChanged(AttrChangeEvent event) {
        event.getElement().putInternal("commissionPercentage", null);
    }

 

The method signature needs to start with the attribute name with Changed as suffix. The argument is an AttrChangeEvent.
The AttrChangeEvent will contain attribute name, old value, new value and XMLDCElement (aka ViewRow).
In this case, we will clear the commissionPercentage field if the salary changes.
 

 

Employee with commissionPercentageChange the Salary from 2900 to 3100commissionPercentage will be cleared

 

Created

In some use cases you want to manipulate an Element the moment it is created (a “new row”). For this you can use the Created annotation. The XML Data Control will call your java method if a new Element is created.

@Created
public void elementCreated(XMLDCElement employee) { 
employee.putInternal("hireDate", new Date()); 
}


The method has a void return type and the XMLDCElement as input parameter.
The name of the method needs to be ‘elementCreated’, else the Data Control will throw an InvalidMethodSignatureException.
In this case we will set the default hireDate to the current sysdate on the creation of a new Employee element.

Drag and drop the ‘Create’ operation on the form, so we can create a new element.


Run the page and click the Create button, you will see the employee form is created with the sysdate as default:
 

Operation

Next to manipulating data, there are also scenario’s in which case we want to write a custom method, for these cases we introduced to @Operation annotation. You can write any java code including input and return parameters and use the @Operation method to generate an operation on the Data Control.

@Operation
public BigDecimal calculateYearlySalary(XMLDCElement employee, BigDecimal salesVolume) {
	BigDecimal retval = null;
	BigDecimal salary = (BigDecimal) employee.get("salary");
	BigDecimal commissionPercentage = (BigDecimal) employee.get("commissionPercentage");
	if (salesVolume == null || salary == null || commissionPercentage == null) {
		return retval;
	}
	retval = salary.add(salesVolume.multiply(commissionPercentage));
	return retval;
}


The return type of the method is used to create the return attribute in the Data Control.
The first argument has to be an XMLDCElement, but after that you can use as many other arguments as you please.
In this case, we ask for a salesVolume input to calculate the yearly salary. The result will look as followed in the Data Control panel:


We can now drag and drop the BigDecimal return type of the method into our Employee form.


These will result in a popup to edit the Action Binding. Here you typically point to where the data comes from that you want to use as input. For the purpose of this example we will just enter a fixed value of 50.000.
 


Now you also need to drag and drop the button on the screen since you need to fire the method:


Add a partialtrigger on the result field, pointing to the Form Layout:
 

After this run the page, it should look like this:
 


Press the button and the result should be shown in the page:

 

  • No labels