Saturday 23 February 2013

ORACLE ADF INTERVIEW QUECTIONS

Here are a set of Interview Question and Answers/Tips for Oracle ADF :
Q : What is Oracle ADF?
A : Oracle ADF is an commercial java/j2ee framework, which is used to build enterprise applications.
It is one of the most comprehensive and advanced framework in market for J2EE
Q : What are the advantages of using ADF?
A : Following are the advantages of using :
  • It supports Rapid Application Development.
  • It is based on MVC architecture
  • Declarative Approach (XML Driven)
  • Secure
  • Reduces maintenance cost and time
  • SOA Enabled
Q : What are various components in ADF?
A : Oracle ADF has following components
  • ADF Business Components(Model)
  • ADF Faces (View)
  • ADF Taskflows(Controller)
Q : What is the return type of Service Methods?
A : Service Methods can return Scalar or Primitive Data types.
Q : Can Service Methods return type Void?
A : Yes, Service Methods can Return type Void
Q : Can Service Methods return Complex Data types?
A : No, service methods can return only primitive/scalar data types.
Q : Which component in ADF BC manages transaction ?
A : Application Module, manages transaction.
Q : Can an entity object be based on two Database Objects(tables/views) or two Webservices ?
A : No entity objects will always have one to one relationship with a database object or web service.
Q : Where is that we write business rules/validations in ADF and why?
A : We should be writing validations at Entity Object level, because they provide highest degree of reuse.
Q : What is Managed Bean?
A : Managed bean is a java class, which is initialized by JSF framework. It is primarily used to hold view and controller logic. It is also used to execute java code to be executed on a user action like Button Click.
Q : What are Backing Bean?
A : Backing beans are those managed beans which have 1:1 mapping with a page. They have getters and setters
for all the components in the related page.
Q : What is difference between managed and backing beans?
A : Backing bean has 1:1 relation with page whereas managed beans can be used in multiple pages.
Backing beans scope is limited to the page whereas managed beans can have other scopes too.
Q : What is a Taskflow?
A : Taskflow is the controller of an ADF application, it provides us an declarative approach to define the control flow.  It is used to define the navigation between pages and various taskflow activites.
Q : What are the different types/categories of Taskflows ?
A :  Taskflows are of two categories : Bounded and UnBounded.
Q : What is the difference between Bounded and UnBounded taskflows?
A : Differences between Bounded and UnBounded taskflows :
  • Bounded taskflows can be secured but Unbounded can’t.
  • Bounded taskflows can accept parameter and return values but unbounded taskflows don’t support parameters
  • Bounded taskflows has a single entry point or a default activity but unbounded taskflows have multiple entry points.
  • Bounded taskflows can be called from other bounded/unbounded taskflows but unbounded cannot be called or reused.
  • Bounded taskflows support transactions unbounded don’t
Q : What are the various access scopes supported by ADF?
A : ADF Faces supports the following scopes
  • Application Scope
  • Session Scope
  • PageFlow Scope
  • Request Scope
  • BackingBean Scope.
Q : Describe life cycle of a ADF Page?
A : ADF page is an extension of JSF and has following phases in its lifecycle
  1. Initialize Context: In this phase the adf page initializes the LifecycleContext with information that will be used during the Lifecycle.
  2. Prepare Model:  In this phase ui model is prepared and initialized. In this phase page parameters are set and methods in the executable section of the page definition of the ADF page are executed.
  3. Apply Input Values: This phase handles the request parameters. The values from the HTML are sent to the server  and applied to the page binding in page definitions.
  4. Validate Input Values:  This phase validates the values that were built in the Apply input values phase
  5. Update Model:  Validated values supplied from user are sent to ADF business components data model
  6. Validate Model Updates:  In this phase the business components will validate user supplied values.
  7. Invoke Application:  This phase will process the ui events stack built during the life cycle of page and also fire navigational events
  8. Prepare Render:  This is the final phase where HTML code is generated from the view tree.
Q : What is PPR and how do you enable Partial Page Rendering(PPR)?
A : PPR is a feature supported by ADF Faces, using which we can render a small portion of a HTML Page, without refreshing the complete page.
It is enabled by.
  • Setting AutoSubmit property to true on the triggering element.
  • Setting the PartialTriggers property of target component to refer to component id of the triggering element.

Friday 15 February 2013

Clearing the stale messages from the previous request on client side validation error

While going through a specific use case, I came to know that ADF Faces run time does not auto clear the messages added to the page from the previous request. This indeed is the expected behavior as of now. I'm sure many of you know this already, however thought of posting this for the benefit of developers who has not worked on such scenarios before, like me;).

The side effect of this implementation is that, once you displayed any message to the end user by adding a FeacesMessage to a FacesConetxt from an event handler method and if the next immediadte action from the end user result in anay client side validation error, you may get the previous message and the newly generated validation error in the message window as shown in the following screen shot.



Let me discuss a work around solution for such use cases. Its simple, add a af:clientListener to the UI component to clear the messages by calling ADF Fcaes JavaScript API AdfPage.PAGE.clearMessages(componentId);.
 <af:commandButton text="Save with Clearing Prev Message"   
      id="cb2" actionListener="#{TestBean.saveAction}"  
   partialSubmit="true">  
      <af:clientListener method="clearGlobalMessage" type="click"/>  
 </af:commandButton>  
 </af:form>  
 <af:resource type="javascript">  
  function clearGlobalMessage() {  
       AdfPage.PAGE.clearMessages(null);  
  }  
 </af:resource>  

Download

I'm attaching a very simple example illustrating the above solution. You can download the sample workspace from here.
[Built using Oracle JDeveloper 11.1.2.0.0]

How to run this sample?

Run test.jspx, key in some values in the input field and click save button. You may see information message. If you click save button again, validation error message alone appears.The previous INFO message is cleared using javascript method clearGlobalMessage()

Please note that, the above case will be addressed in future releases in a much better way. In fact there is an enhancement request for the same, be happy :)

Thursday 14 February 2013

Google-like Search and LOVs using Oracle Text and ViewCriteria

Do you know the Google Advanced Search page? Very few people have ever seen the page, let alone used it. Now, why is that? It is simply because the "normal" single-field quick-search (that what we normally just call Google) is so incredibly effective.

OK, that's nice, but how can we create a Google-like search experience in ADF? I created a simple sample application that contains Google-like quick-search and LOVs (using Oracle Text). You will find the application below, including a step-by-step guide how to reproduce it.


Example application

To see it working download the example application and follow the instructions in readme.txt to get it running (you need an Oracle Database 10g or 11g (XE is fine) with an HR schema).

It starts with the following page:

On this page I use Oracle Text search for two different scenarios.

Quick search
Use can use the search box to search for arbitrary departments using the name of the department or the name of the manager.

Select the department you want to see or edit and press enter.

LOVs
To change the manager of a department simply start typing in the manager field. You can use a first name, last name,...

username,...

or even phone number or job title or any combination to find the manager.

Just experiment with it for a moment. Note that it will search for the beginning of words, but it will always search for complete numbers. (Which is not very useful in this specific case, but it was a request by one of my clients and I really like it that way. The reason for it was that in their case only power users search for numbers and they already know the complete number, so they don't want to search for number prefixes, for speed. Anyway, you can turn it off if you want.)

Do it yourself

First prepare the database.
  • Make sure that the HR user is allowed to use the ctxsys.ctx_ddl package (execute: "grant execute on ctxsys.ctx_ddl to hr" as user sys)
  • Create the procedures and functions that return, for a given rowid, the searchable information for that row (see create_search_package.sql in the sample application).
    Test it with a statement like:
    select ot_search.get_emp_search_item(rowid) from employees
  • Create the Oracle Text indices (see create_indices.sql). Note that the index is created on one specific column per table, this is a limitation of the database. It doesn't matter which column you choose as long as it is a varchar2 column.
    Test it with:
    select ot_search.get_dep_search_item(rowid) from departments where contains(department_name, 'ad%') > 0
Then create the model project.
  • Copy the base classes: Base*.java and  OracleTextSearchSupport.java from the sample application and set them as the default base classes for all ADF BC. I believe that the source code is fairly self explaining (with even a few lines of documentation).
  • Create the default ADF BC components for the Employees and Departments tables (i.e. Entities, ViewObjects and ApplicationModule).
  • Add an extra attribute to each ViewObject that queries the searchable information as follows: (see  DepartmentSearchString and EmployeeSearchString in the example application)
  • Add the custom properties as explained in BaseViewDefImpl.java to the Oracle Text Index attributes in each ViewObject and to the attributes added in the previous step (see DepartmentName, DepartmentSearchString, LastName and EmployeeSearchString in the example).
Now the Oracle Text Quick Search should already work in the ADF BC tester. Just open the DepartmentsVO in the tester, click the binoculars and search for the string "ad" in the field DepartmentSearchString.

Next, we will add support for LOV's.
  • Add a DepartmentsQuickSearch and EmployeesQuickSearch ViewCriteria as follows:
  • Change the List UI Hints of the ViewObjects as follows:
  • Add a ManagerName attribute to the Departments ViewObject (it will provide the LOV, we cannot use the ManagerId attribute for that). Use the database functions to query the searchable information for the employee with id manager_id like this:
    ot_search.get_emp_search_item(ot_search.get_emp_rowid(manager_id))
  • Add an LOV to ManagerName:
Now the Oracle Text Quick Search should already work in LOV's in the ADF BC tester. Open The Departments ViewObject in the tester, go to a department without manager and enter "whal" or "ski" into managername and then press tab. Nice, don't you think?

We continue with the ViewController project.
  • Create a new page, e.g. DepartmentDetails.
  • Drag 'n Drop a Departments Form. It should automatically contain an LOV as in the example application.
  • Now we only have to add an <af:autosuggestbehavior suggesteditems="#{bindings.ManagerName.suggestedItems}"> tag to the LOV.
Now the Oracle Text Quick Search should work in the LOV (ManagerName).
  • Clone the Departments ViewUsage in the ApplicationModule. Clone the DepartmentsIterator in the page-bindings (pointing to the new VO usage) and give it a meaningful name, e.g. DepartmentsIteratorQuickSearch.
  • Now add the QuickSearchBean from the sample application and configure it as a pageFlowScope managed bean in adfc-config.xml with the following properties:
    • iteratorBindingName: The name of the IteratorBinding that is used in the form.
    • searchAttribute: The name of the attribute that contains the searchable information.
    • searchIteratorBindingName: The name of the IteratorBinding-clone.
  • Create a subform with a search field as in the sample application.
That's it. The steps above describe how I created the sample application. I hope it provides enough information for other people to integrate this solution in their own project. If any question arises, please post it as a comment below.

Download the sample application   .

Wednesday 13 February 2013

Debugging ADF Mobile Apps on Android

Not that you'll ever need this, after all your code is perfect. But I did run into a situation where I wanted to figure out what exactly is wrong with my ADF Mobile code. The way to do debugging is documented in the ADF Mobile Developer Guide, but here is a version of those instructions with nice pictures (which might make it easier for you to find files etc).
1. First locate the cvm.properties file (In the Application Resources accordion). In this file you'll want to change the value of java.debug.enabled to be true. Also note in this file the value set for java.debug.port,  by default this is 8000 and we are going to keep that default value in our example.

2. Next have a look at your application level deployment profile, or even better create a new deployment profile and call it debugDeploy. The key thing here is to make sure your build mode is in Debug mode and not Release mode (remember the previous post where we told you that Release mode creates a smaller/faster deployment, but right now we do need the bigger package to be able to debug).

3. Next deploy your application with your new debugDeploy profile. We'll assume deployment directly to the device.
4. Now from the command line locate the directory where your Android's SDK adb.exe utility is and issue the following command to let the device (-d) know that we are going to use port forwarding for debug:
adb -d forward tcp:8000 tcp:8000

5. Now on your device start your application. You'll notice that it seems to be stuck, well this is because it is waiting for the debugger to connect to it. So what are you waiting for?
6. In JDeveloper, stand on your viewController project and right click to choose debug. If you changed the port number you'll need to update that info in the dialog that pops up - but if you kept it at the default 8000 we should be ok.

The debugger will now try and connect to your running application, and will stop at the breakpoint you set.
Happy debugging.
By the way if you want to debug on the emulator of Android the only difference will be in step 4 where instead of -d you'll use a -e .

Tuesday 12 February 2013

Deploying Oracle ADF Applications on the Oracle Java/Database Cloud

                  With the new Oracle Cloud environment you no longer have to maintain a WebLogic server or a database server of your own, you can instead use instances hosted in the Oracle Cloud.
                   One nice feature of the Oracle Cloud is the support for deployment of Oracle ADF applications. In this entry I'll walk you through the basic steps you'll need to follow to get things working.
The first step is to get an Oracle Java Cloud Instance available for you - you can get a trial version here - this will also include an instance of an Oracle database onto which you can deploy your database objects.
                  Once your request gets approved you'll get an email with the cloud connection information for your instance. Guard this email - it has all the basic connection information and you'll be referring to it on a frequent basis.
Now you are ready to deploy your application.
The first step is to create a user in the database that will have your data (tables, procedures etc). To do this, go into the Oracle instance you got - this will be an APEX interface. In there go and create a new user - remember that user name. In the video below the user is called Summit.
Next you'll want to create/populate the tables of data. This can be done from inside JDeveloper. Open the database navigator, and you'll notice a new type of connection there - the cloud connection. Create a new connection mapping to the user you just defined (Summit). Now to create the tables and data we are going to use the Cloud Cart functionality in JDeveloper.
Open the Cloud Cart (from the JDeveloper View->Database->... Menu option). And simply drag into it any DB object that you require directly from your "regular" DB connection. Once you dropped all the tables, you should probably also click the data check box if you want the data to be transferred too (this is missing in the video so here is a picture).


                  When you are ready to do the import click the cloud button on the cart and this will create a new batch job that will upload to the database. You can track this deployment job directly from inside JDeveloper as well.
                 Once the tables are in place you are ready to move to the next step - the ADF application deployment.
                 One thing you'll need to change is the definition of the database that you are connecting to. Since you can't actually define data sources on the hosted WLS, you'll want to use the one which is already defined - it is called "database".
                 Go into your Application Module configuration and update the connection to use a JDBC DataSource called database.
Now you are ready to deploy your application - from the application menu choose deploy -> to application server.
You can define a new application server connection of type "Oracle Cloud" and this will allow you to directly deploy your application onto the server.
Once deployment is done - you are ready to access your cloud based application.
Check out this video for a demo of the above steps.
&amp;lt;p&amp;gt; &amp;lt;/p&amp;gt; If you are running into issues while deploying you'll be able to get more information in two places:
First you'll get a log from your deployment job - this can be directly opened in JDeveloper by clicking the link in the log window:

For more details - you can look into the server's log from the Java service console - click the "View log messages".


Need more information on deploying Oracle ADF on the Oracle Cloud - see additional blog entries:
V.VINAYSANTHOSH - Deploying ADF Applications into the Oracle Cloud Using JDeveloper
V.VINAYSANTHOSH - My ADF Sample Apps Live in Oracle Java Cloud

Monday 11 February 2013

Even More New ADF Bloggers

A couple of weeks back I posted an entry about new ADF related blogs that I found out about.
Well as they say "when it rain it pours"  - and over the past few days I came across several other new bloggers that cover ADF.
So here are a few others that you might want to add to your ADF blog aggregator:
http://adfplus.blogspot.com - Paco van der Linden
https://blogs.oracle.com/aramamoo/ - Arun
http://e20labs.org - Chad Thompson
http://oracleadfhowto.blogspot.com/ - Vinay Agarwal
http://javaosdev.blogspot.com - Donovan Sherriffs
https://blogs.oracle.com/prajkumar - Phil Wang
http://oracle-itself.tumblr.com - Wael Abdeen
https://blogs.oracle.com/adfthoughts - Raphael Rodrigue
http://adfwithejb.blogspot.com - Prateek Kumar shaw
And here are a few more that are not just about ADF but do have the occasional ADF related entry:
http://yonaweb.be - Yannick Ongena
http://blog.whitehorses.nl - whitehorses
https://blogs.oracle.com/imc - ISV Migration Center Team
and the usual reminder here:
To keep track of all things new in the ADF blog world follow the JDeveloper twitter or like JDeveloper on facebook to get notified of the latest entries we find for you around the world.

Sunday 10 February 2013

Oracle ADF Interview Questions and Answers/Tips- Part-2




Q : What is Action Listener ?
Ans : An action listener is a class that wants to be notified when a command component
fires an action event. An action listener contains an action listener method that
processes the action event object passed to it by the command component

Q:What are business Component In ADF.Describe them?
Ans: All of these features can be summarized by saying that using ADF Business
Components for your J2EE business service layer makes your life a lot easier. The key
ADF Business Components components that cooperate to provide the business service
implementation are:
Entity Object
An entity object represents a row in a database table and simplifies modifying its
data by handling all DML operations for you. It can encapsulate business logic for
the row to ensure your business rules are consistently enforced. You associate an
entity object with others to reflect relationships in the underlying database schema
to create a layer of business domain objects to reuse in multiple applications.
Application Module
An application module is the transactional component that UI clients use to work
with application data. It defines an up datable data model and top-level
procedures and functions (called service methods) related to a logical unit of work
related to an end-user task.
View Object
A view object represents a SQL query and simplifies working with its results. You
use the full power of the familiar SQL language to join, project, filter, sort, and
aggregate data into exactly the “shape” required by the end-user task at hand. This
includes the ability to link a view object with others to create master/detail
hierarchies of any complexity. When end users modify data in the user interface,
your view objects collaborate with entity objects to consistently validate and save
the changes

Q: What is Top Link?
Ans:
Top Link is an Object-Relational Mapping layer that provides a map between the Java objects that
the model uses and the database that is the source of their data.
By default, a session is created named default. In the following steps, you create a new session

Q:What is Managed Bean?
Ans:JavaBean objects managed by a JSF implementation are called managed beans. A managed bean describes how a bean is created and managed. It has nothing to do with the bean’s functionality.
Managed bean is about how the bean is created and initialized. As you know, jsf uses the lazy initialization model. It means that the bean in the particular scope is created and initialized not at the moment when the scope is started, but on-demand, i.e. when the bean is first time required.

Q :What is Backing Bean?
Ans:Backing beans are JavaBeans components associated with UI components used in a page. Backing-bean management separates the definition of UI component objects from objects that perform application-specific processing and hold data.

Backing bean is about the role a particular managed bean plays. This is a role to be a server-side representation of the components located on the page. Usually, the backing beans have a request scope, but it is not a restriction.
The backing bean defines properties and handling-logics associated with the UI components used on the page. Each backing-bean property is bound to either a component instance or its value. A backing bean also defines a set of methods that perform functions for the component, such as validating the component’s data, handling events that the component fires and performing processing associated with navigation when the component activates.

What is view object?
Ans :A view object is a model object used specifically in the presentation tier. It contains the data that must display in the view layer and the logic to validate user input, handle events, and interact with the business-logic tier. The backing bean is the view object in a JSF-based application. Backing bean and view object are interchangeable terms

Q: Difference between Backing Bean and Managed Bean?
Backing Beans
Managed Beans
A backing bean is any bean that is referenced by a form.
A managed bean is a backing bean that has been registered with JSF (in faces-config.xml) and it automatically created (and optionally initialized) by JSF when it is needed.

The advantage of managed beans is that the JSF framework will automatically create these beans, optionally initialize them with parameters you specify in faces-config.xml,
Backing Beans should be defined only in the request scope
The managed beans that are created by JSF can be stored within the request, session, or application scopes
Q? What do you mean by Bean Scope?
Bean Scope typically holds beans and other objects that need to be available in the different components of a web application.


Q.  What are the different kinds of Bean Scopes in JSF?
JSF supports three Bean Scopes. viz.,
Request Scope: The request scope is short-lived. It starts when an HTTP request is submitted and ends when the response is sent back to the client.
Session Scope: The session scope persists from the time that a session is established until session termination.
Application Scope: The application scope persists for the entire duration of the web application. This scope is shared among all the requests and sessions.

What is the difference between JSP-EL and JSF-EL?
JSP-EL
JSF-EL
In JSP-EL the value expressions are delimited by ${…}.
In JSf-EL the value expressions are delimited by #{…}.
The ${…} delimiter denotes the immediate evaluation of the expressions, at the time that the application server processes the page.
The #{…} delimiter denotes deferred evaluation. With deferred evaluation ,the application server retains the expression and evaluates it whenever a value is needed.

Q:How to declare the page navigation (navigation rules) in faces-config.xml file in ADF 10g
?
Ans: Navigation rules tells JSF implementation which page to send back to the browser after a form has been submitted. We can declare the page navigation as follows:
<naviagation-rule>
<from-view-id>/index.jsp</from-view-id>
<navigation-case>
<from-outcome>login</from-outcome>
<to-view-id>/welcome.jsp</to-view-id>
</navigation-case>
</naviagation-rule>
This declaration states that the login action navigates to /welcome.jsp, if it occurred inside /index.jsp.
Q: Setting the range of table
Ans : <af:table rows=”#{bindings.LoggedInUserServiceRequests.rangeSize}”…/>

Q : Which component in ADF BC manages transaction ?
A : Application Module, manages transaction.

Q : Can an entity object be based on two Database Objects(tables/views) or two Webservices ?
A : No entity objects will always have one to one relationship with a database object or web service.

Q : Where is that we write business rules/validations in ADF and why?
A : We should ideally be writing validations at Entity Object level, because they provide highest degree of reuse.

Q:What are the JSF life-cycle phases?
Ans:The six phases of the JSF application lifecycle are as follows (note the event processing at each phase):

1. Restore view
2. Apply request values; process events
3. Process validations; process events
4. Update model values; process events
5. Invoke application; process events
6. Render response

Q. Explain briefly the life-cycle phases of JSF?
1. Restore View : A request comes through the FacesServlet controller. The controller examines the request and extracts the view ID, which is determined by the name of the JSP page.
2. Apply request valuesThe purpose of the apply request values phase is for each component to retrieve its current state. The components must first be retrieved or created from the FacesContext object, followed by their values.
3. Process validationsIn this phase, each component will have its values validated against the application’s validation rules.
4. Update model valuesIn this phase JSF updates the actual values of the server-side model ,by updating the properties of your backing beans.
5. Invoke applicationIn this phase the JSF controller invokes the application to handle Form submissions.
6. Render responseIn this phase JSF displays the view with all of its components in their current state.

Q: What is setActionListener?
Ans:SetActionListener – The setActionListener tag is a declarative way to allow an action source ( , , etc.) to set a value before navigation. It is perhaps most useful in conjunction with the “processScope” EL scope provided b ADF Faces, as it makes it possible to pass details from one page to another without writing any Java code. This tag can be used both with ADF Faces commands and JSF standard tags.
Exmaple of this can be as follows. Suppose we have a table “employee”.We want to fetch the salary of an employee of some particular row and want to send this salary in
Next page in process scope or request scope etc.So using this we can do this.
It have two attributes :
From – the source of the value; can be an EL expression or a constant value
To – the target for the value; must be an EL expression
1
<af:setActionListener from="#{row.salary}"
2
to="#{processScope.salary1}"/>
This setActionListener will pick value of salary of that row and store this value into salary1 variable.So anyone can use this salary
As processScope.salary1 . It is very simple to use. And very useful.

Saturday 9 February 2013

Create ADF Input Form Without First Displaying Existing Records

You can create a form that allows a user to enter information for a new record and then commit that record into the data source. While you can choose to use the default ADF Form and then drop the Create operation as a command button, when this type of form is first rendered, it displays the data for the first instance in the collection.

The ADF Creation form allows users to create new instances in the collection without first displaying existing instances, this scenario might be very simple but the new developers find difficulty in creating empty ADF Input Form when page loads for the first time.

You can download the sample workspace from here.
[Runs with Oracle JDeveloper 11.1.2.2.0 + HR Schema]

Implementation Steps:-

Create Fusion web application with Business Components from Tables based on Department table. In view controller project create a jspx page then drag and drop DepartmentsView1->Form as ADF Form as shown in below image.


Go to page bindings, in Bindings section click on create control binding and select action item. In create action binding wizard select AppModuleDataControl->DepartmentsView1->Operation->createInsert.

In Executables section click in create executables Binding and select invokeAction item. In Insert invokeAction wizard and follow as shown in below image.
Edit the invokeCreateInsert and set the refresh to renderModel because when ever the page loaded this will execute the createInsert operation by inserting the empty record in the collection.
Run the jspx page and the web page will loaded with empty record.

Friday 8 February 2013

Book Review - Oracle ADF Real World Developer's Guide

A new addition to the growing collection of Oracle ADF related books is the new  Oracle ADF Real World Developer's Guide by Jobinesh Purushothaman published by Packt Publishing. I got a copy of the ebook version for review, and here is the summary:
If you are familiar with Jobinesh's blog posts, you probably already know what to expect in his book - a deep level of understanding of the internal workings of the Oracle ADF framework.
                 This is what sets this book apart from the other ADF books out there. It might not be the best book to choose in your "getting started with Oracle ADF" stages, but once you know the basics of Oracle ADF application development, you should get this book to understand what is happening below the covers. What does the framework do when you finish a wizard or perform a drag and drop in your IDE.
A big section of the book is dedicated to a deep dive into the inner workings of Oracle ADF Business Components including the various stages of DB interaction, interaction between the EO,VO etc, and the various methods exposed for you to modify the way the framework works.
A similar depth you can find in the chapters about ADF Binding and the ADF Controller. You can expect to learn about the various life cycle stages, and parameters that control the behavior of the framework for those layers too.
A special chapter is dedicated to best practices and performance tips. It provides many tips about various parameters and things you should be aware of to achieve maximum performance for your ADF application.
Overall I think that this book should be part of the bookshelf of serious ADF developers - those who want to know ADF's in and outs.

ADF Mobile - Create Drill Down Graph Reports

Drill Down Graph Report - Scenario here is to show all the cars sales report for this year in Pie Chart and when user click a individual car in pie chart slice, a drill through report opens, which accepts the car type as a parameter, and then displays car models sale in Bar Chart.

In ADF Mobile, "clickListener" method is not provided for DVT components. Click listener interface will receive click events on the gauge components and can do further data process in BC4J.  In ADF Mobile "Action" method is supported on DataItem in the graphs. Action defines a reference to the an action method sent by the command button component, or static outcome of an action. So in this article I'm explaining how to build drill down reports using <dvtm:pieChart> and <dvtm:barChart>.

Application screen looks like below when it deployed and run on Android Device/Emulator. Displays the Cars Sales Reports in first screen.

In above screen, slide the screen towards right. Notice only check boxes are displayed and attributes values are not getting displayed for the pie chart slices, this should be an error. 

Next click on any pie chart slice and respective car models will be displayed in Bar Chart screen.
[Runs with Oracle JDeveloper 11.1.2.3.0]

Implementation Steps

Create an ADF Mobile Application, the application consists of two projects. Application Controller project of Application LifeCycle, Listeners, Device Features DataControl and ViewController project contains mobile features content like AMX Files, Task Flows and DataControl.

In ViewController project, locate and expand the Application Sources folder, create a Cars.java file and add the below code.
public class Cars {
    private String carName;
    private int carSalesCount;
    private transient PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    public Cars() {
        super();
    }

    public Cars(String carName, int carSalesCount) {
        this.carName = carName;
        this.carSalesCount = carSalesCount;
    }

    public void setCarName(String carName) {
        String oldCarName = this.carName;
        this.carName = carName;
        propertyChangeSupport.firePropertyChange("carName", oldCarName, carName);
    }

    public String getCarName() {
        return carName;
    }

    public void setCarSalesCount(int carSalesCount) {
        int oldCarSalesCount = this.carSalesCount;
        this.carSalesCount = carSalesCount;
        propertyChangeSupport.firePropertyChange("carSalesCount", oldCarSalesCount, carSalesCount);
    }

    public int getCarSalesCount() {
        return carSalesCount;
    }

    public void setPropertyChangeSupport(PropertyChangeSupport propertyChangeSupport) {
        this.propertyChangeSupport = propertyChangeSupport;
    }

    public PropertyChangeSupport getPropertyChangeSupport() {
        return propertyChangeSupport;
    }
}
Create CarModels.java file and add the below code.
public class CarModels extends Cars {
    private String modelName;
    private int modelSalesCount;
    private transient PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    public CarModels() {
        super();
    }

    public CarModels(String carName, String modelName, int modelSalesCount) {
        super();
        setCarName(carName);
        this.modelName = modelName;
        this.modelSalesCount = modelSalesCount;
    }

    public void setModelName(String modelName) {
        String oldModelName = this.modelName;
        this.modelName = modelName;
        propertyChangeSupport.firePropertyChange("modelName", oldModelName, modelName);
    }

    public String getModelName() {
        return modelName;
    }

    public void setModelSalesCount(int modelSalesCount) {
        int oldModelSalesCount = this.modelSalesCount;
        this.modelSalesCount = modelSalesCount;
        propertyChangeSupport.firePropertyChange("modelSalesCount", oldModelSalesCount, modelSalesCount);
    }

    public int getModelSalesCount() {
        return modelSalesCount;
    }

    public void setPropertyChangeSupport(PropertyChangeSupport propertyChangeSupport) {
        this.propertyChangeSupport = propertyChangeSupport;
    }

    public PropertyChangeSupport getPropertyChangeSupport() {
        return propertyChangeSupport;
    }
}
Create Generic.java file and add the below code, create DataControl based on Generic.java file.
public class Generic {
    private static List s_cars = null;
    private static List s_carModels = null;
    private static List s_filterCarModels = null;
    private transient ProviderChangeSupport providerChangeSupport = new ProviderChangeSupport(this);
    private transient PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

    public Generic() {
        super();
        if (s_cars == null) {
            s_cars = new ArrayList();
            s_cars.add(new Cars("Audi", 2000));
            s_cars.add(new Cars("BMW", 2500));
            s_cars.add(new Cars("Honda", 5000));
            s_cars.add(new Cars("Mitsubishi", 1000));
            s_cars.add(new Cars("Toyota", 4000));
            s_cars.add(new Cars("Volkswagen", 3000));
        }
        if (s_carModels == null) {
            s_carModels = new ArrayList();
            s_carModels.add(new CarModels("Audi", "A3", 300));
            s_carModels.add(new CarModels("Audi", "A4", 1000));
            s_carModels.add(new CarModels("Audi", "Quattro", 700));
            s_carModels.add(new CarModels("BMW", "BMW128", 1000));
            s_carModels.add(new CarModels("BMW", "BMW528", 800));
            s_carModels.add(new CarModels("BMW", "Gran Coupe", 700));
            s_carModels.add(new CarModels("Honda", "Accord", 1200));
            s_carModels.add(new CarModels("Honda", "Civic", 2000));
            s_carModels.add(new CarModels("Honda", "Hybrid", 1800));
            s_carModels.add(new CarModels("Mitsubishi", "Lancer", 400));
            s_carModels.add(new CarModels("Mitsubishi", "Evolution", 300));
            s_carModels.add(new CarModels("Mitsubishi", "Outlander", 300));
            s_carModels.add(new CarModels("Toyota", "Camry", 1800));
            s_carModels.add(new CarModels("Toyota", "Corolla", 1200));
            s_carModels.add(new CarModels("Toyota", "Cruiser", 1000));
            s_carModels.add(new CarModels("Volkswagen", "Beetle", 1300));
            s_carModels.add(new CarModels("Volkswagen", "Jetta", 800));
            s_carModels.add(new CarModels("Volkswagen", "Tiguan", 900));
        }

    }

    public void addPropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.addPropertyChangeListener(l);
    }

    public void removePropertyChangeListener(PropertyChangeListener l) {
        propertyChangeSupport.removePropertyChangeListener(l);
    }

    public void addProviderChangeListener(ProviderChangeListener l) {
        providerChangeSupport.addProviderChangeListener(l);
    }

    public void removeProviderChangeListener(ProviderChangeListener l) {
        providerChangeSupport.removeProviderChangeListener(l);
    }

    /**
     * Method will populate the result list to s_cars.
     */
    public Cars[] getCars() {
        Cars c[] = null;
        c = (Cars[])s_cars.toArray(new Cars[s_cars.size()]);
        return c;
    }

    /**
     * Method will populate the result list to s_carModels.
     */
    public CarModels[] getCarModels() {
        CarModels cm[] = null;
        cm = (CarModels[])s_carModels.toArray(new CarModels[s_carModels.size()]);
        return cm;
    }

    /**
     * Method will filter the result from s_carModels list.
     */
    public CarModels[] filteredCarModels(String carType) {
        CarModels cm[] = null;
        s_filterCarModels = new ArrayList();
        for (Iterator i = s_carModels.iterator(); i.hasNext(); ) {
            CarModels curCM = (CarModels)i.next();
            if (curCM.getCarName().equals(carType)) {
                s_filterCarModels.add(new CarModels(curCM.getCarName(), curCM.getModelName(),
                                                    curCM.getModelSalesCount()));
            }
        }
        cm = (CarModels[])s_filterCarModels.toArray(new CarModels[s_filterCarModels.size()]);
        providerChangeSupport.fireProviderRefresh("carModels");
        return cm;
    }
}
In ViewController project. Locate and expand the Application Sources folder, then expand the META-INF folder. You will see the adfmf-feature.xml file, click on the adfmf-feature.xml file to launch the Feature editor. Add a new feature by clicking the green plus sign on the Features table near top of the editor this will launch the new Create ADF Mobile Feature dialog, modify the values as shown below.


In the Features table, select the newly created feature Departments. Under the Features table, click the Content tab, and locate the Content table. Notice that the content item Departments.1 is created by default. Next add a new file by clicking the green plus sign and select taskflow option, this will launch the new Create ADF Mobile Task Flow dialog, modify the value as shown below.


Click on the GraphTaskflow.xml to open the file in taskflow editor and follow the below steps.
1) Create two views and name them as carsView and carModelsView respectively.
 2) Draw the control flow case from carsView to carModelsView and Outcome as "carsModel", Behavior->Transition as "flipRight".
 3) Draw the control flow case from carModelsView to carsView and Outcome as "car", Behavior->Transition as "slideLeft".

Double click on carsView view will launch Create ADF Mobile AMX Page dialog. Open the carsView.amx page and to source tab and follow the below steps:

1) In Header facet, amx:outputText set the value as "Sales Report"
2) From DC palette drag and drop Generic->Cars->ADF Mobile Chart and in Component Gallery dialog, select Pie chart and click ok.
3) In Create Mobile Pie Chart dialog, select the values as shown in below image.


4) For dvtm:pieDataItem, set the action as "action" and drop amx:setPropertyListener and modify the values as shown in below code.
 <dvtm:pieChart var="row" value="#{bindings.cars.collectionModel}" id="pc1" animationOnDisplay="auto"
                       inlineStyle="width:400px; height:280px; float:left; background-color:white;" threeDEffect="on"
                       title="Car">
            <amx:facet name="dataStamp">
                <dvtm:pieDataItem sliceId="#{row.carName}" value="#{row.carSalesCount}" action="carsModel">
                    <amx:setPropertyListener from="#{row.carName}" to="#{pageFlowScope.carName}"/>
                </dvtm:pieDataItem>
            </amx:facet>
 </dvtm:pieChart>           
Double click on carModelsView view will launch Create ADF Mobile AMX Page dialog, in page facets select Header, Primary Action. Open the deptList.amx page and to source tab and follow the below steps:

1) In Header facet, amx:outputText set the value as "Sales Report"
2) In Seconday Action facet, for amx:commandButton modify the values text: Back, action: __back.
3) From DC palette drag and drop Generic->filteredCarModels->CarModels->ADF Mobile Chart and in Component Gallery dialog, select Bar chart and click ok.
4) In Create Mobile Bar Chart dialog, select the values as shown in below image.
Enter the carType parameter value as #{pageFlowScope.carName}.

Open the carModelsView.amx and modify the properties for dvtm:barChart as shown below.
<dvtm:barChart var="row" value="#{bindings.CarModels.collectionModel}" id="bc1"
      inlineStyle="width:400px; height:300px; float:left; background-color:white;"
      title="#{pageFlowScope.carName} Car Models">
 <amx:facet name="dataStamp">
  <dvtm:chartDataItem group="#{row.modelName}" value="#{row.modelSalesCount}" series="Sales Count"/>
 </amx:facet>
 <dvtm:legend position="end" id="l1"/>
</dvtm:barChart>
Click on Create Executable binding and select Invoke action and follow as shown in below image.

Edit invokeFilterdCarModels invoke actiion and set the Refresh to always, so when ever page loads employeesTotalRows method will get executed.

Note:- When the screen loads for the first time Bar Chart will get cached and for second time execution filteredCarModels method will not get executed at all even if the parameter value changed. To overcome this we have to set invoke Action for filteredCarModels method, this executes the  invokeAction every time a page is navigated to regardless of the state of the binding container.

Preview of the carsView.amx and carModelsView.amx will looks like below.


In the Application menu, select Deploy - New Deployment Profile to start the Create Deployment Profile dialog box. In the Profile Type drop-down list, ensure ADF Mobile for Android/IOS is selected and then click OK. Next select Deploy - New Deployment deployment profile. In the subsequent dialog box, select Deploy application to device/emulator/package, and click Finish.