31 Dec 2013

In this post I am going to show how we can enrich an ADF application with features like taking pictures with a Web camera. In order to get an access to the camera's stream and in an effort to show taken pictures we will use HTML5 tags video and canvas. Basically, my html code looks like the following:

Let's pay attention to the Submit button. Actually, when we click this button, we're going to grab taken picture, send the image to the server and set it as a value of a BLOB entity attribute. So, let's look at the client side first. The code of the button's client listener:

function takePicture(actionEvent)
{ //We are doing all this stuff just in order
// to get access to the inlineFrame's content
var source = actionEvent.getSource();
var ADFiframe = source.findComponent("iframe");
var iframe = document.getElementById(ADFiframe.getClientId()).firstChild;
var innerDoc = (iframe.contentDocument) ?
iframe.contentDocument :
iframe.contentWindow.document;
//Finally we can work with our canvas,
//containing taken picture
var canvas = innerDoc.getElementById("canvas");
//Convert the image into the DataURL string and
//send it to the server with a custom event
AdfCustomEvent.queue(source, "takePicture",
{picture : canvas.toDataURL("image/png")}, true);
}

On the server side we're going to listen to the takePicture event. So, the code of the server listener:

22 Dec 2013

One of the most powerful features of JDeveloper 11gR2 and 12c is the ability of hot redeployment of classes and resources to the integrated WebLogic server. And sometimes it really works, saving a lot of developers' time. You just need to make your changes, rebuild the project, refresh the browser and you are happy. There is no full redeployment of the entire application.
But it doesn't work with ADF libraries. Any modern large ADF application is split into an number of ADF libraries and developers work mostly with code of those libraries. And in order to get their changes applied, developers need to redeploy a library and restart an application. There is pretty powerful tool JRebel, which can make working with ADF libraries much faster and easier. It can be installed as JDeveloper's plugin and it allows hot redeployment of library's classes and resources likewise classes and resources of the target running project. Even better. With JRebel we don't have to rebuild the entire project in case of making changes to class files, we can just rebuild corresponding classes and that's it.
The installation process is pretty easy and well described in this manual. Once the plugin has been installed, we have to generate JRebel configuration files (rebel.xml) for the main target project which we actually run and for each project which is going to be deployed as an ADF library:

For example, for the ViewController project it will generate something like this:

Since the ViewController project is a web project, there is a <web> tag in the file. Actually the same tag is going to be generated for ADF library projects as well, if those projects are web projects containing some task flows. The important thing is that we don't need the <web> tag in the rebel.xml file for ADF library projects. It doesn't work. We have to manually move the public_html dir tag to the <classpath> section:

29 Nov 2013

In this post I'm going to uncover a pitfall to watch for when using ADF Faces selection components such as af:selectBooleanCheckbox, af:selectOneChoice, af:selectOneRadio, af:selectManyCheckbox, af:selectBooleanRadio, af:selectManyChoice, etc.

The default value of TestBean.someBooleanValue is true, so it's going to look like this:

SelectBooleanCheckbox and OutputText are partial targets of the InputText, though the InputText actually does nothing except submitting a request to the server.
For some reason we want to hide the PanelGroupLayout. Let's set the rendered attribute of the PanelGroupLayout to false:

We can see that TestBean.someBooleanValue got false. Why?
Since SelectBooleanCheckbox and OutputText are partial targets of the InputText, the framework is going to process these components during the request along with the InputText.
Very roughly the framework does the following for each component participating in a request:

The root of the evil is in the getSubmittedValue() method. Since selectBooleanCheckbox is not visible (it is even not rendered because it is laying on a panel which is not rendered), there is no any submitted value for it. It just can't be there. But getSubmittedValue() never returns null for selection components. In case of selectBooleanCheckbox it returns false instead of null. If it was an inputText component, it would return null for sure.
The second problem is that the framework checks whether the component is rendered or not, but it doesn't pay attention to its parents.
So, in our case, we have a SelectBooleanCheckbox with "false" submitted value participating in the request. For sure, it will set its model value to false.

How to avoid this pitfall?
We can either set rendered attribute of the selectBooleanCheckbox to false:

17 Nov 2013

Sometimes we need to validate that the date entered in an af:inputDate component is within some range. ADF Faces provides a very convenient approach for that - af:validateDateTimeRange. It is very easy to use and it could look like this in a jspx code:

The error message is absolutely correct since PaymentDate is less than ValueDate.

The value of PaymentDate is equal to ValueDate and it is within the range ValueDate-MaturityDate. So there is no any validation exception.

Ooops! The value of PaymentDate is equal to MaturityDate and it is within the
range ValueDate-MaturityDate. But the validation exception is fired.
We can figure out the reason of this strange behavior in the specification of the maximum attribute of the af:validateDateTimeRange:

"... When binding to Date objects, it is advised to create the Date object
with maximum value for any date-time components that aren't displayed
(usually hours, minutes, seconds, milliseconds) to allow the largest
range of values to be accepted."

So, in order to get it working correctly, it is advised to specify in the maximum attribute of the validateDateTimeRange something like this: "5/24/2012 23:59:59.999".

Let's give it what it wants. In our ViewObject we created a transient oracle.jbo.domain.Date attribute LimitMaturityDate with the following value expression:

The expression actually adds a day (24 hours) to the Maturitydate and subtracts a milisecond, so we're going to get "Maturitydate 23:59:59.999". The new java.sql.Timestamp object is going to be converted into the oracle.jbo.domain.Date by the framework. And let's use this transient attribute as a maximum for the af:validateDateTimeRange:

20 Oct 2013

In this post I would like to thank everyone, who managed to attend the session "Oracle ADF Performance Tuning War Stories" on ADF EMG Sunday at Oracle Open World 2013. I was proud to speak at this session along with Stephen Johnson and Frank Houweling. I hope this session will help ADF developers to feel themselves more confidently and understand better how to tune their applications and JVM.

Since Oracle ADF Essentials has been released it changed the mind of Java EE developers across the world. They started to look at ADF as at the serious alternative to a set of heterogeneous frameworks and technologies the used to build Web applications. They realized that this single powerful framework could provide them with almost everything they needed, and absolutely for free!
Nowadays there are a number of books and various resources providing plenty of information about Oracle ADF. But what could be chosen as a starting point?

Being not a thick book, this resource manages to show the full power of Oracle ADF Essentials on 250 pages only, and the reading is really enjoyable and easy. I would recommend this book as an excellent starting point for those who want to know what Oracle ADF is all about.

17 Sep 2013

Sometimes it can be useful to provide the data collection for a table component by some custom method in the service layer. An example of this technique can be found here. In this case we use methodAction to invoke the method and methodIterator to represent method's return value as a data collection for the table.
Let's say in our EmployeesView view object we've got a method returning some secondary custom ViewObject's row set:

Everything seems to be fine. But, actually, it's not. If we try to sort our data in the table, there will be no any effect. The getManagers method is going to return new row set without any bothering about applied sort criteria. Actually the framework applies the sort criteria to the EmployeesView view object, but not to the row set, returning by the getManagers method. On the other hand, this secondary row set is populated by some internal helper view object, which is called finder view object. And this finder view object has no any idea about changed OrderBy clause. We can fix that overriding ViewObject's method createFinderVO:

31 Aug 2013

Going to attend OOW 2013? Looking for more ADF sessions? There is great news for you!

This year ADF Enterprise Methodology Group has arranged again a full day of ADF sessions. The room has been kindly donated by Oracle Development Tools Users Group (ODTUG).
Come to Moscone West 2003 on Sunday, September 22nd and dive deeply into solid ADF content! ADF only, and nothing else!
The full session list comes up with the following agenda:

19 Aug 2013

Recently I was hunting an interesting bug. The bug was pretty confusing for users because it seemed that some data can be transfered across user sessions. The reason of the bug was very common mistake. Sometimes ADF developers consider Entity definitions (EntityDef) and View definitions (ViewDef) as session scoped objects. They change properties of EntityDefImpl and ViewDefImpl instances, or, which is more likely, properties of AttributeDefImpl and forget that these changes effect all users sessions. There is only one instance of particular EntityDefImpl per application instance. The same is correct for ViewDefImpl as well.
Let's consider a simple task flow:

There is view activity BrowseView representing data in a table and allowing users to create new records. The default activity of the task flow is some method call setDefaultLastName. If we look at its code we'll see the following:

So, when users start this task flow, the default value of the "LastName" attribute of the table becomes their last name. And, after that, when they create new records the value of the "LastName" is populated with their name. Cool! User, whose name is Stogova, entered the task flow, started to create new records and she is happy. So far. Another user, whose name is Smith, did the same. Stogova is still creating new records at BrowseView, and one moment she is realizing that she has become Smith. Cool!

The correct way to implement this use case is to define some groovy expression as the default value of the "LastName" attribute. Something like this:

adf.userSession.userData.lastName

And, for sure, user's last name should be passed somehow to the business service layer. For example, by invoking the following method:

31 Jul 2013

As we know a bounded task flow can be invoked by some URL either directly from a browser or from some external application. This feature is enabled if task flow's property "URL invoke" is set to "url-invoke-allowed" and it is commonly used in integration projects. Usually clients (or invokers) use HTTP GET method and pass their parameters in the URL. Let's consider some simple task flow with one required input parameter:

And it works fine as well. The URL in this case is going to look like this:

http://127.0.0.1:7101/TestApp/faces/adf.task-flow

All other necessary information like task flow id and parameter value is inside POST request. But the problem is that it works fine for R1 only. If we try it out on R2 we will get the following:

ADF_FACES-30179:For more information, please see the server's error log
for an entry beginning with: The UIViewRoot is null. Fatal exception
during PhaseId: RESTORE_VIEW 1.

Why? Because of that:

oracle.adfinternal.controller.application.InvokeTaskFlowException: ADFC-02006: A task flow ID is not found in the URL.
at oracle.adfinternal.controller.util.UrlParams.getTaskFlowInfo(UrlParams.java:144)
at oracle.adfinternal.controller.application.RemoteTaskFlowCallRequestHandler.invokeTaskFlowByUrl(RemoteTaskFlowCallRequestHandler.java:84)
at oracle.adfinternal.controller.application.RemoteTaskFlowCallRequestHandler.doCreateView(RemoteTaskFlowCallRequestHandler.java:63)

All necessary data included task flow id which is supposed to be passed inside POST request is lost. Why? Because of "loopback". If we discover requests sent from the browser to the server on clicking the Submit button we'll see the following:

Instead of one we have two requests. And the first one (POST) is ours. Exploring the response for this request we can see the following:

So, instead of sending the "honest" response, the server sends some "loopback" script which generates "window id" and sends the following GET request with generated window id. Cool! But all post data is gone. The GET request is absolutely empty.
Fortunately, the framework doesn't generate any "loopbacks" if the initial POST request has already some "window id". So, the workaround for our case is to develop a servlet filter, setting the "window id" attribute for our request:

19 Jul 2013

Within passivation/activation cycle of application modules the framework passivates and activates view objects as well. Usually the framework saves information about VO's state, current row, bind variables values and such. But not the data. The VO's query is going to be re-executed and the data is going to be re-fetched after activation of the view object. In most cases the query execution is not performed during or right after the activation phase, but is deferred until the view object is really used. This behavior is quite logical. Let's assume that our application consists of several pages representing data of different view objects. If we send requests to the server from the same page we are going to get VOs executed that are used on that page only. All other view objects, used on other pages, are going to be passivated and activated as well. But they are not going to be re-executed until we ask the framework to do that by navigating to the particular page. And that's cool! It means that we don't perform unnecessary query executions and we don't waste our memory. But there are some cases when the framework performs VO's query execution during the activation phase not bothering whether we really use the VO.
One of these cases is about using of transient VO's attributes. The common recommendation is to not passivate such attributes. But sometimes transient attributes are used to store some custom data and passivation/activation mechanism is used as a convenient way to save this data and keep it alive. Be careful with this approach. If any values of transient attributes are passivated, then the framework will execute the query during the activation of the view object.

Let's consider a sample application with two pages - Employees and Departments.

We use read-only SQL-based view objects browsing data on both pages:

So all VO's attributes are transient and we're not going to passivate them. Application module pooling is disabled:

Exploring the request sent from the Employees page with ODLA we can see the following:

There is no any query execution within application module activation phase. The VEmployees query has been executed in prepare model phase as it was expected.
And now let us change the passivate parameter of one of the VDepartments attributes:

I am going to start the application with the Departments page in order to get the VDepartments VO executed and after that navigate to the Employees page. Sending next requests from the Employees page (for example sorting the table) we are going to get the following picture:

It is obvious that besides execution of VEmployees query the framework executes VDepartments as well. And VDepartments is executed during the activation of the application module. Do we really need that? We are wasting CPU resources for unnecessary query executions and wasting memory to store query collections of unused view objects. The framework demonstrates the same behavior for view objects that have any dynamic attributes and for master view objects with retain view link accessors set on. So, be aware of these features.

30 Jun 2013

Playing with skin selectors of ADF Faces LOV components I found a new selector announced in release notes for 11.1.1.7.0 and 11.1.2.4.0 versions. The -tr-stretch-search-dialog selector enables the feature of resizing LOV's search and select dialog, allowing users to interact with this dialog in more convenient way.

By default the feature is disabled and in order to enable it the source code in the css file for the inputListOfValues component should look like this:

af|inputListOfValues{
-tr-stretch-search-dialog: true;
}

And for the inputComboboxListOfValues it should look like this:

af|inputComboboxListOfValues{
-tr-stretch-search-dialog: true;
}

The cool thing is that when end user is resizing the dialog, it is going to stretch its content as well:

The sample application for this post can be downloaded here. It requires JDeveloper 11.1.2.4.0.

22 Jun 2013

List of Values UI components, such as inputListOfValues and inputComboboxListOfValues have a special facet searchContent. The facet is supposed to be used as an extension point which allows us to build our custom LOV's. The content of the facet is going to be rendered in the LOV's search dialog window. This feature looks pretty attractive, since there are lots of use cases when we would like to modify the search dialog content and functionality. And what is important, we basically don't want to throw away the existing LOV's search engine and build it ourselves from scratch. Our goal is to enhance a little bit the search dialog in terms of look and feel and to inherit the existing functionality.

In order to transform a LOV into the custom one, we've got to implement a couple of listeners and design the content of the searchContent facet. So, there is a LOV:

The facet contains the standard Query+Table form, which is based on the LOV's model. Actually, we can fill free designing the content of the facet. The only requirement is that we should have one query component and one table component within the facet. But, even this restriction is based on the listener's implementation provided in this post. If you want to avoid the requirement, you can rewrite the listeners as you wish.

So, let's have a look at the listeners.
We're going to use the internal framework listener as the query listener of the Query component:

The important thing is that these listeners are generic, they don't depend on any particular use-case and they don't depend on any particular LOV component. These methods can be gathered in some utility bean and used across the entire application.
The result of our work looks like this:

The sample application for this post can be downloaded here. It requires JDeveloper R2.

29 May 2013

Let's consider a page with a region running a task flow. The task flow can invoke some internal task flow and this internal task flow can invoke its internal task flow and so on. After a few navigations of that sort our users are going to get lost. They have no idea how deep they are and how they got there. There is a special component in ADF Faces af:breadCrumbs. Usually it is used to show users their path through the application's menu, so users can know how they got to this page and how they can get back. For example:

Let's use this component to help users in case of a deep task flow stack.In this post I am going to show how we can display the task flow stack with af:breadCrumbs component and how we can use it to stop currently running task flow and allow a user to get back.

The method uses some hierarchical data structure represented by TaskFlowLink class and converts it into a menu model using some internal helper class ChildPropertyMenuModel. The TaskFlowLink class is our custom wrapper of the PageFlowStackEntry internal class. Furthermore, it supports the hierarchical structure by providing the child field.

So, we built a menu model acceptable by the af:breadCrumbs component based on the page flow stack. That's all indeed cool, but it would be better if a user could click on a crumb and return back to the corresponding task flow. For example, clicking on "Task Flow One" I want to abandon currently running "Task Flow Two" and return back to the "Task Flow One". Moreover, I want to return exactly to the same view activity from which I got to the "Task Flow Two".
Alrighty, let's do it! Did you notice that our af:breadCrumbs has a commandNavigationItem within its nodeStamp facet. So, we're going to do something in the commandAction method when we're clicking on the item:

25 May 2013

In this post I am going to show how we can make use of these properties on example of Display Name attribute. Let's consider a region with a running task flow within it. In common case the region is dynamic one, so we don't know in advance which task flow it is going to run. Moreover, the task flaw can invoke another inner task flow, and the inner task flow can invoke its inner task flow, etc. Our goal is to show in the region's title the name of the currently running task flow. Let's assume, that all our task flow definitions have initialized property Display Name with a corresponding name as it is shown on the screenshot above. We can use a managed bean method returning a display name of the currently running task flow:

21 May 2013

Some time ago I blogged about a feature when a VO's attribute can have multiple LOVs and showed how to switch to the desired LOV depending on the value of another VO's attribute. I this post I'm going to use this technique again, but I'm going to choose the LOV for the attribute depending on its value, on the value of the attribute for which the LOV is defined.
Let's consider a simple use-case: We have an input field for a currency code. When a user inputs a currency code, we have to show corresponding currency description near the input field. So, it should look like this:

The implementation of this use-case is pretty obvious - we have to define a LOV for the currency attribute and set autoSubmit=true for the inputText.

Actually besides a symbolic code like USD and EUR a currency has a numeric code like 840 and 978. Sometimes a user prefers to input a symbolic code and sometimes a numeric one. Let's allow users to input whatever they want - either symbolic or numeric code, and we will take care of both and show correct currency description. We are going to add to the VO a transient updatable attribute with two LOVs. A user inputs a value of this attribute and depending on the value's type (string or numeric) we'll use a corresponding LOV. The first LOV looks for the currency description by symbolic code and the second one by numeric code.

The LOV for the symbolic code (Ccy):

And the LOV for the numeric code (Nbuid):

In order to switch between LOVs we use additional transient attribute CcyLovSwitcher:

And the value of the CcyLovSwitcher is going to be some Groovy expression:

The expression adf.object.ccyLovName refers to the method of our custom ViewRowImpl class: