السبت، 23 يوليو 2011

Validating User Input



Validation Options for ADF BC Applications
There are various options for handling validation in ADF BC applications:
Business services. You should build in as much validation as you can when creating the business services in order to protect the integrity of the data in the database and to prevent malicious attacks. There are a multitude of opportunities to add validation at the business services level:
-Oracle ADF Business Components provides a number of predefined validation rule classes that enable you to add business logic without writing a single line of code, or you can also add programmatic validation.
-You can implement validation in the database; however, such validation cannot be exposed in the UI. For example, you cannot use database validation to expose a list of valid values in the UI.
User interface. The ADF Faces input components that you use to build the pages of your application also have built-in validation capabilities. You use these prebuilt ADF Faces validators to ensure that when a user edits or enters data in a field and submits the form, the data is validated against the rules and conditions you have specified. However, UI validation should always have equivalent validation at the business services layer, so that the same validation is applied when the model is exposed in other ways.

Triggering Validation Execution
Each entity row tracks whether or not its data is valid. When a user modifies a persistent attribute of an existing entity row or creates a new entity row, the entity is marked as invalid, and any validation that you have implemented is evaluated again before the entity is again considered valid. In validation rules, you can specify when this validation is executed as follows:
Validation Level: In an entity validation rule, you can specify whether validation should be performed at the entity-level (the default) or at the transaction level. If you specify that it should be performed at the transaction level, it will be carried out after all entity-level validation. For this reason you should use this option where you want to ensure that a specific piece of validation is performed at the end of the process.
Conditional Execution: You can enter a Boolean condition using a Groovy expression to define conditional validation execution. When the condition evaluates to true, the rule is executed. You have the option to test your expression to see if it is valid.
Triggering Attributes: By default a validator fires on an attribute whenever the entity as a whole is dirty.  However, in an entity validation rule, you can choose to trigger validation only when certain attributes change (when one of the triggering attributes is dirty).
Validation always occurs before changes are posted to the database. If you must code validation that depends on seeing posted changes, override the beforeCommit() method in the object’s Java file.
Handling Validation Errors
When a validation rule throws exceptions, the exceptions are bundled and returned to the client, and any database changes pertaining to the transaction are rolled back.
The Failure Handling tab in the Validation page of the Validation Rule page of the entity object editor (or the attribute editor) is where you specify the error message that you want to display to the end user when the validation fails.
You use the Validation Failure Severity option buttons to specify whether the message is an Error message (default) or Informational Warning.
You can enter Groovy expressions to populate variables in error message text to make the message more meaningful. And you can store messages in a resource bundle or property file to make them translatable.
Specifying the Severity of an Error Message
 If you define the message as an Error message, the end user is not able to navigate out of the current field or record and must revisit the field where the data has failed the validation test. If the message is classified as a Warning, the user can continue after the message has been acknowledged.

Using Groovy Variables in Error Messages
Using Groovy variables in error messages enables you to display dynamic labels and values in your messages. This also makes your messages more reusable when adding to a resource, as described in the next slide.
When you create the message, use any variable name, surrounded by curly braces. JDeveloper automatically adds the variable as a message token in the lower part of the Failure Handling page.
You must supply the values for the message tokens. You can use expressions such as source.hints.OrderDate.label to reference the value of the user-friendly display label of the OrderDate attribute of the source entity object being evaluated. To reference the value, simply use the name of the attribute.
At run time, the error message is displayed with the specified labels and values.

Storing Error Messages as Translatable Strings
Typically you store error messages in a resource bundle or other property file to facilitate translation and reuse of messages. A resource bundle contains key-value pairs for any messages and data strings in your application that you want to translate or reuse.
To use an existing message or create a new stored message, perform the following steps:
1.  Click the Select Text Resource button to go to the Select Text Resource dialog box.
2.  In the Select Text Resource dialog box:
-To use an existing message, select it and click Select
-To create a new message, enter the message in the Value field. This automatically populates the Key field, but you can change the key to a more meaningful name if desired. You also enter a description, which can assist the translator in knowing how the message is to be used.
-Click Save and Select to store and use the message
Defining Validation in the Business Services
When you incorporate validation into the ADF BC business model, the most logical place to implement such validation is in the entity objects. Encapsulating business logic in these shared reusable components provides the following benefits:
Ensures that your business information is validated consistently in every page where end users are allowed to make changes
Simplifies maintenance by centralizing validation
Using Prebuilt Declarative Validation Rules
The easiest way to create and manage validation rules is through the declarative validation framework. Oracle ADF is shipped with a number of built-in declarative validation rules that will satisfy many of your business needs. You implement these rules through the entity object editor and they are stored in the entity object’s XML file.
You can implement these rules either on the entity object itself, or on its attributes. The next few slides show how to use the built-in declarative validation rules.
Defining Declarative Validation
To include declarative validation on an entity object, perform the following steps:
1.  Double-click the entity object in the Application Navigator to invoke the editor.
2.  Invoke the Validation Rule editor:
-For entity validation, in the Entity Validation Rule section of the General tab, click Add Validation Rule.
-For attribute-level validation, select the Attributes page and double-click the attribute for which you would like to define a validation rule. In the Edit Attribute dialog box, click Validation in the list on the left of the page. In the Validation pane (with the attribute selected) click New. You can also define attribute.
3.  In the Add Validation Rule dialog box, select the type of validation required from the Rule Type list and add details of the rule. 
4.  Define validation execution rules and failure handling procedures by clicking the relevant tabs and entering the preferences.
5.  Click OK. The validation rule is displayed in the list of validation rules for the entity or attribute that owns it. 











الأحد، 1 مايو 2011

Using bind variable for the SQL statements with IN clause

Bind variable improves the performance of query execution by avoiding the repeated parsing of the SQLs (prepare once and execute multiple times). In this post, I'm discussing about the possibility of using bind variable for a ViewObject whose WHERE clause is formed using IN clause.

Obviously, you cannot directly bind a single value to an IN clause and expect it to be treated as many values. A common solution is to have a DB function which takes comma separated String as parameter and let this return a user defined object type. This post is also based on same 'age old' idea. The query generated using the custom db function(in_list_char) to support bind variable for IN clause may look like as shown below,

 SELECT Departments.DEPARTMENT_ID, Departments.DEPARTMENT_NAME  FROM DEPARTMENTS Departments WHERE 
   ( ( Departments.DEPARTMENT_NAME IN (select * from TABLE (cast (in_list_char ( :CommaDelimitedDeptNames ) as ChartableType))A)) )

Generate custom where clause fragment for the ViewCriteriaItem

If you want to enable multi-value search for a specific ViewCriteriaItem in a ViewCriteria, then you can provide the custom interpretation for ViewCriteriaItem by overriding ViewObjectImpl::getCriteriaItemClause(ViewCriteriaItem vci) as shown below.
@Override
public String getCriteriaItemClause(ViewCriteriaItem vci) {
 if (vci.getAttributeDef().getName().equals("DepartmentName") &&
    vci.getViewCriteria().getName().contains("DeptSampleVC")) {
    if (vci.getViewCriteria().getRootViewCriteria().isCriteriaForQuery()) {
    return getINClauseForDatabaseUse(vci);
    } else {
    return getINClauseForCache(vci);
    }
 } else {
    return super.getCriteriaItemClause(vci);
 }

}

protected String getINClauseForDatabaseUse(ViewCriteriaItem vci) {

 String bindVarValue = getCommaDelimitedDeptNames();
 String bindVarName = "CommaDelimitedDeptNames";
 String whereCluase = "1=1";
 if (bindVarValue != null && bindVarValue.trim().length() != 0) {
    whereCluase =
        this.getEntityDef(0).getAliasName() + ".DEPARTMENT_NAME IN (select /*+ CARDINALITY(A, 50) */ * from TABLE (cast (in_list_char ( :" +
        bindVarName + " ) as ChartableType))A)";
 }
 return whereCluase;
}

protected String getINClauseForCache(ViewCriteriaItem vci) {
 String whereCluase = "1=1"; 
 return whereCluase;
}

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11g R1 PS2 + HR Schema]

How to run this sample?

1. Unzip the source to your local drive.
2. Setup the required DB objects in your local schema(HR) by running the \select_in_list.sql
3. Run the test.jspx. This page displays query panel and a result table.
4. This sample has enabled multi-value(comma separated values) search for 'DepartmentName' ViewCriteriaItem.
You can try searching the comma separated values for 'DepartmentName' field in the search panel e.g: Finance,Sales,Executive . Have fun!

السبت، 30 أبريل 2011

Export Collection in ADF

In many report based or any other data related application export to excel feature is always required.

Export to excel feature can be achieved in ADF very easily, may be just in 10 minutes we can see the result excel sheet. To achieve this in this project I have first created ADF business components from HR.Employee table. Then I created one jspx page to display the employee details table. Now I want to export this  tabular data in one excel named Employee.xls.  want that the employee details data will be displayed under title "List Of Employees " title. 

Now as export to excel will be available on some action so I added one command button here named "Export Collection"


I have inserted one exportCollectionActionListener inside the command button. This takes 5 parameters, 2 of them are mandatory.
Mandatory fields are:

ExportedId: The table or collection id you want to export

Type: The export type. As it is excel here it should be excelHTML

I have provided values for other two optional  fields :

filename: I wanted that the file name should be Employee.xls

title: I wanted the title to be here "List of Employees"


Now if I run the page and click the command button "Export Collection" it will export the table data in one Excel Sheet named "Employee.xls"



The title of the sheet should be "List of Employees " as shown below.




Please comment.......


السبت، 16 أبريل 2011

How to prevent delete on master if child record exists in Oracle ADF

Hi,

In this post we will see the declarative way to stop deletion of Master record if child record exists in the database without writing much code.

In this example we have only Departments entity and Employee view object i created a ViewLink between DepartmentsView and EmployeesView and accessing the ViewAccessor in Departments entity.

Later i override the remove() method as follows



  public void remove() {
    RowIterator ri = getEmployeesView();
    int count = ri.getRowCount();
    if (count > 0) {
      throw new JboException("You cannot delete this record, Child record exists!!!");
    } else {
      super.remove();
    }

  {

ADF Application with multiple Data Sources or Database connections


The Problem: ADF Application with multiple Data Sources or Database connections.

This is a pretty normal use-case, but can be a bit puzzling to new developers. Most apps have more than one database that they connect to. One way of dealing with this is to hide the fact there are multiple databases under the DB layer through the use of synonyms and DBlinks, but sometimes such access is not possible or desirable.  Here I discuss how to use multiple databases from ADF BC.

Solution: Multiple Root Application Modules

The basic element here is the notion of the Root Application Module. For starters, the Root Application Module defines the transactional context.  You need to create two application Modules, each one connecting to its own Database. You could also connect the very same application module to two different databases if you need to, more on that later.  Nesting one application module inside another to get access to it won’t work as nested application modules share the same root.
So the way to do this is to create a *new* _Root_ Application Module directly from the BC4J configuration. This ensures that the connection associated with that Application module’s configuration is used. The ADF model layer usually takes care of handling instances of you Application Modules, and here, you are doing it manually. This brings some risk, and be careful to release the Application Module after use.

Create Project

Start out by creating one or more model projects in your application. In most cases you’ll only require one project, but if you need to create the ADF BC objects from database tables, you will likely need two projects so you don’t have to switch connections in the same project at design time. The “Connection” you see in the Project Properties > Business Components (click on Business Components) is used only during design time to generate ADF BC objects from a DB. An Application Module’s Configuration(bc4j.xml) defines the connection it uses at run time .

Figure 1
The two model projects will house the Application Modules that connect to the two different Databases.

Configuration

Once the model projects are created, open the Configuration dialog box for the Application modules. The connection an Application Module uses at runtime is defined in the Application Module’s configuration and not the project properties.


      

The Manage Configurations dialog lists the Configurations available for that AM. The configuration for an AM encapsulates the parameters for the AM like the connection it uses. The configuration name is important as we’ll later use it to identify a particular named configuration and use that named configuration to create an Application Module instance. To specify the parameters inside the named configuration, select the configuration name, and choose Edit
  

I’m assuming that a Data Source will be used. If using a JDBC URL, the steps are the same. A valid Data Source name is defined for the first DB and the steps should be repeated the same for the second Application Module connecting to the second DB. These Data sources need to be available at runtime, so either they need to exist in the Application server you are deploying to, or you need to deploy them as part of your application.  I’m using the automatic deployment of DS provided by JDeveloper (this might not be suitable for production) so JDeveloper automatically provides a Data Source entry in this wizard based on the connections defined at the Application or IDE level. These Data sources have name that is the connection name appended with the two letters ‘DS’.   After editing the Data source, you have effectively created a Configuration called DB_One_ServiceLocal  (see screenshot) that uses the Data Source /jdbc/database_1DS  . This configuration can now be used anytime to create a root application module with the configured parameters (like an alternate Data Source ).

A note about Data Sources

See this for how to deploy a Data source manually.
This explains how to make use of JDeveloper’s automatic data source deployment.


Here is where most people get puzzled. After creating two Application Modules, you would be tempted to nest your second application module inside your first. This does not work, as the transaction context is defined for the rootapplication module, and when you nest, the root application module does not change, and so the connection does not change. The connection used is the root Application Module’s connection. The solution is to create a new RootApplication Module directly from the named BC4J configuration we created. This being a root application module on its own ensures that the connection associated with that Application module’s configuration is used. 

The Code

The following screenshot shows the classes generated by JDeveloper, nothing out of the ordinary.

The second app module exposes a method on its client interface that the first application module invokes.
Here is the method the second AM exposes on its client interface:
  1. /** 
  2.    * Method exposed by this AM to provide the query results from its VO. 
  3.    * Since this AM's configuration connects it to the second database, 
  4.    * the VO query is executed agaist that DB 
  5.    * 
  6.    * @return 
  7.    */  
  8.    public String querySecondDB()  {  
  9.       getDBTwoVO().executeQuery();  
  10.       return ((DBTwoVORowImpl) getDBTwoVO().first()).getSampledata();  
  11.    }  
   
Now in order for the first application module t access and query the second data base, it creates a new root application module instance of the second application module using the named configuration that connects it to the second database. Once the new root application module instance is obtained, the exposed method is invoked and depending on the scenario, the root application module instance is released. The method used is Configuration. createRootApplicationModule()
  1. public String queryMulipleDBs(){  
  2.     getDBOneVO().executeQuery();  
  3.     String fromDBOne;  
  4.     String fromSecondDB;  
  5.     fromDBOne = ((DBOneVORowImpl) getDBOneVO().first()).getSampledata();  
  6.     // Create new root AppModule from the named Configuration  
  7.     DB_Two_Service service =  (DB_Two_Service)Configuration.createRootApplicationModule("sample.model2.services.DB_Two_Service""DB_Two_ServiceLocal");  
  8.     // Query the second DB  
  9.     fromSecondDB = service.querySecondDB();  
  10.     Configuration.releaseRootApplicationModule(service,true); //releases and removes the AppModule  
  11.     return "from first DB : " + fromDBOne + " from second DB : " +fromSecondDB;  
  12.   
  13.   }  
   
If you have the queryMulipleDBs() method of the first Application Module exposed on its client interface, you can use the Business components test to validate the whole thing since with 11g, the Business components tester can work with Data sources as well.


A note about multiple Projects and Application Modules

Here we used a separate project and an Application Module to connect to our second DB. This however is a personal preference, I like this because it keeps the code easily readable and separates the artifacts cleanly. The real crux of the technique is an alternative root application module using a particular configuration. So ineffect you could have two ApplicationModules in the same project with thier configurations connecting to two DBs or you could have the same ApplicationModule definition with just an alternative Configuration(that connects to the other DB) and instantiate a new instance of the same ApplicationModule definition as a root AM, with the alternate Configuration using the same code. 
  1. Configuration.createRootApplicationModule(  
  2.                                   "sample.model.services.DB_One_Service",  
  3.                                   "CONFIG_WITH_A_SECOND_DATASOURCE");  
So here we have the first AM instantiating another root instance of itself with another Configuration, one that connects to another DataSource.
source : 
http://jdeveloperandadf.blogspot.com/2011/02/adf-application-with-multiple-data.html