Sunday, May 17, 2009

Parent Action Activity in ADF Task Flow

Recently I have faced a problem, when was trying to navigate to ADF Task Flow Call activity. The problem was, that I was initiating navigation from inside the region and navigation flow was defined not in bounded region ADF Task Flow, but inside parent bounded page ADF Task Flow. This means, navigation outcome from parent ADF Task Flow was simply invisible for button I have created inside region. But as usual in most of the cases, ADF provides very elegant solution to solve problem of external navigation from inside the region. I will describe it in this post.

The problem is, that I have bounded ADF Task Flow, however main page is using region and this region can't see declared navigations from this ADF Task Flow:


Region is used on main page, this region provides table of Countries, user can select any country and navigate to Location ADF Task Flow:


And here is the answer for described problem - in order to navigate from region using navigation rule from parent ADF Task Flow, you can use Parent Action activity inside region ADF Task Flow:


Only one thing you need to do is to define parent-outcome property, or in other words - navigation outcome from parent ADF Task Flow you want to use. In my case it is child navigation outcome:


Defined parent outcome will navigate to ADF Task Flow call activity and will open locations page.

On runtime, when user will press Location button implemented in region component, navigation from parent ADF Task Flow will be triggered:


Correct list of locations is returned:


You can download sample application for this post - ADFRegionNavigation.zip.

Useful hint, when user will return to Countries table, in order to show previously selected record, set DisplayRow = selected for af:table component:

Saturday, May 16, 2009

Inheritance Feature in Oracle ADF BC - Part 2

My today post is second post that describes inheritance functionality support in ADF BC. I will describe how you can use inheritance in View Objects. In previous post I was describing inheritance in Entity Objects - Inheritance Feature in Oracle ADF BC Part 1. Inheritance on View Object layer adds more object abstraction, you can operate not only different sets of data based on discriminator, but implement polymorphism for View Row classes. For more information, you can read 35.7.5 Working with Polymorphic Rows section from ADF Developer Guide.

I have developed sample application - ADFBCInheritance2.zip, based on application from previous post - ADFBCInheritance.zip. Updated sample contains additional View Objects, extended from Country. Those new View Objects are CountriesAfricaView and CountriesEuropeView:


In the View Row class of CountriesView, I have defined calculateProfit method. This method will be overridden in extended View Objects:


I will create only two overridden View Objects from possible four - for Africa and Europe discriminator values. CountriesAfricaView inherits calculateProfit method:


And CountriesEuropeView inherits same calculateProfit method:


I have defined Row Class for both extended View Objects, in those classes I'm overriding calculateProfit method from parent Row Class of CountryView:


For example, in CountriesEuropeViewRowImpl class I'm setting profit value to 500, while in CountriesAfricaViewRowImpl class to 200 and finally in CountriesViewRowImpl to 700. This means rows that belong to Asia and America discriminator value, will get 700 value for Profit attribute:


Last step, when enabling inheritance in View Objects layer, you need to set Subtypes in Application Module for polymorphic View Object - CountriesView in our case:


Press Subtypes button and and choose available View Object that extends parent:


In View layer, from Backing Bean, I'm scrolling through all rows from CountriesView and invoking calculateProfit method. Through implemented polymorphism, this method will be invoked for specific row based on its discriminator type, we dont need to specify it directly:


During runtime, I will invoke method from Backing Bean, by pressing Set Profit button:


To test that polymorphism really works, go to Europe section and check that Profit value is set to 500, as it was specified in overridden method:


Then go to Asia section, and check that Profit is set to 700, as it was specified in the Row Class of parent CountriesView:


Spanish Summary:

El post anterior, mostró como aplicar el concepto de Herencia en las Entidades. Sin embargo el mismo principio puede ser aplicacion a los componentes View Object. En este post, Andrejus nos muestrá, de manera práctica como aplicar herencia entre Vistas.

Sunday, April 26, 2009

Inheritance Feature in Oracle ADF BC - Part 1

When building large applications with Oracle ADF, you can consider to use inheritance in Oracle ADF BC layer. This can reduce Model complexity in terms of size and relationship. I will split inheritance topic into two parts - today I will describe inheritance with ADF BC Entities, and in my next post with ADF BC View Objects. I recommend to read Oracle ADF Developer guide related topic - 34.7 Using Inheritance in Your Business Domain Layer. In ADF BC you can implement inheritance layer for Entities and create View Objects with polymorphic Entity usages. This means Oracle ADF supports abstraction on both - components and data.

You can download sample application - ADFBCInheritance.zip where I have implemented inheritance between Entities and created View Object based on polymorphic Entity usage.

I have generated Countries Entity in order to use it as Base Entity in an inheritance hierarchy:


Four Entities - CountriesAfrica, CountriesAmerica, CountriesAsia and CountriesEurope are created as Subtype Entities from Countries Entity in inheritance hierarchy.

While creating Base Entity, I have declared discriminator attribute - RegionId. This attribute will allow us to perform polymorphic queries:


I have left discriminator value as empty by default, this means if View Object will not include any subtype, empty rowset will be returned:


Subtype Entities are created by extending Base Entity and overriding its attributes:


In Subtype Entity we need to set corresponding value for overriden discriminator attribute - RegionId:


For example, in CountriesAfrica Entity I have set this attribute discriminator value to 4:


In CountriesAmerica, CountriesAsia and CountriesEurope it is set to 3, 2 and 1 accordingly. Of course, there is no point to create inheritance hierarchy just for fun, in most of the cases its useful to have it when implementing different validation rules for example. In my sample, I have implemented different validation rules for transient Profit attribute. In CountriesAfrica Entity validation rule is implemented as range between 100 and 1000:


In CountriesAsia Entity, with discriminator value set to 2:


Same type validation rule is implemented with different constraints set to 300 and 1200:


Finally, when View Object is created based on Base Entity - Countries:


You need to include Subtypes of Base Entity you wish to use in your View Object. If you will not include any of Subtypes, View Object will return empty rowset (remember we have set empty default value for discriminator in Base Entity). In my sample, View Object will work with all four Subtypes, so I'm declaring this:


Even my View Object is based on all four Subtypes, I will want to limit rows to expected Enity Subtypes. We can do this, simply by adding discriminator into WHERE clause and declaring Bind Variable, however I have noticed if to implement it in such way - View Accessors from any Detail View Objects will not work. However, everything works fine, if to declare and use View Criteria:


This View Criteria is really simple, it just includes discriminator attribute filtering:


At this point, inheritance in ADF BC Entities is finished. Let's add some more complexity and define association relationship. I will define it between Countries entity with discriminator attribute and Locations:


Based on this association its possible to define Master-Detail relationship through View Link:


Its cool that, you can use Detail View Object - Locations in relationship with Master View Object - Countries just in standard way, even we know that Countries is based on Entity Subtypes. In order to test and prove this, I have created transient attribute in Locations View Object - CountryName. This attribute gets value through accessor from its Master - Countries:


We have following Master-Detail relationship exposed to View-Controller layer:


In View-Controller I have created navigation flow to pass discriminator value into Bounded ADF Task Flow through a call:


In Bounded ADF Task Flow I'm doing ExecuteWithParams in order to set Bind Variable value and opening main page with already filtered values by provided discriminator:


Rowset is pre-filtered by activating View Criteria on page load. View Criteria is activated by referencing Query Model, read more in my previous post - ADF Query Component Usage with ADF Panel Stretch Layout.

On runtime, select any of regions, this will set discriminator value:


Let's select Asia and set Profit value to 350. Remember, CountriesAsia Entity implements validation 300 - 1200, so no error is shown and value is accepted:


Now let's select Europe and set Profit value to the same 350. Remember, CountriesEurope Entity implements validation 400 - 1300, validation error will be shown:


Spanish Summary:

En este post, Andrejus nos entrega un ejemplo de como aplicar mecanismos de herencia entre entidades de Business Components. En una entrega posterior nos mostrará la manera de implementar herencia entre View Objects.

Tuesday, April 14, 2009

Workaround for LOV on Primary Key Attribute in Create Mode

In February, I was blogging about - Workaround for LOV on Primary Key Attribute. Provided workaround and sample application was working nicely, but it was working only in edit mode, when already existing row was updated. There was a need in my project, to update previously developed workaround in order to have working functionality when current row is in create mode.

I'm posting updated sample application, you can download it - LOVPrimaryKeyCreate.zip. This sample implements workaround for LOV on Primary Key for both cases - edit and create modes. Most probably you will face described problem in current JDeveloper/ADF builds (5188 and 5205).

One specific with create mode is that Primary Key usually have database constraint - Mandatory:


This means, on runtime - when user will try to create new row and will do commit - validation error will be generated for LOV attribute. Its because value from dummy attribute will not be copied into real attribute, validation will fire first for empty real attribute value:


Its possible to solve this problem, by simply updating previously described workaround. Idea is to initialize real key attribute with some dummy value when create is invoked. In my sample, I'm using main key negative value retrieved from DBSequence. I'm assigning this value in overriden create method:


This means, validation will not be fired anymore and dummy value will be changed with a real one in doDML() method (same as in original version of workaround):


With described update, workaround works well for newly created row:


Spanish Summary:

Este post es una actualización de un post anterior en el que Andrejus muestra como evitar un bug que se produce cuando queremos trabajar con una Lista de Valores (LOV) sobre un campo de una tabla. El post anterior solo consideraba el uso de LOV cuando la tabla estaba en modo de consulta, sin embargo esta actualización considera las tablas en modo creacion y lectura.

Thursday, April 9, 2009

WebLogic In-Memory HTTP Replication for Oracle ADF Applications

In my previous post - WebLogic Load Balancing for Oracle ADF Applications, I have described how to setup cluster environment with a set of WebLogic Managed Servers together with separate WebLogic domain for Load-Balancing. Today I will describe, how to enable In-Memory replication in cluster environment.

Load-Balancing allows to distribute user sessions across cluster elements, based on current server load. However, if one of Managed Servers from cluster will go down, all the sessions on this server will be destroyed and users will loose their work. In order to avoid this, WebLogic server allows to enable replication between Managed Servers in cluster. In this blog I'm describing In-Memory HTTP replication.

You can enable session replication, basically by adding one parameter into weblogic.xml file. You should edit weblogic.xml available in your Oracle ADF application, if you don't have this file - create it in WEB-INF folder:


Specify PersistentStoreType parameter and set replicated as value:


All required configuration is done, now you can deploy application on WebLogic cluster. Here I'm accessing ADF Faces Rich Client page through Load-Balancing domain:


Load-Balancing domain have redirected to a second Managed Server, I have pressed Save button on application page couple of times, you can see it from the server log:


I have killed second Managed Server:


I didn't closed my browser and have pressed Save button again - without replication I would get server error, however now my session is successfully transferred to the next available Managed Server from cluster environment - its third server:


You can see from the log - Save operation was successfully done. User didn't lost his session and can continue work:


Spanish Summary:

En post anteriores, Andrejus nos había mostrado como configurar nuestras aplicaciones hechas con ADF para poder soportar el balanceo de carga en los servidores WEB Logic. En esta oportunidad, se muestra como mejorar esta configuración y permitir el aseguramiento de las sesiones de las aplicaciones (en balanceo de carga) ante una caida en uno de los servidores.