Sunday, February 7, 2010

WebCenter Suite 11g and ADF 11g Consulting in Middle East

Recently I was busy in Middle East, consulting and deploying production system based on WebCenter Suite 11g and ADF 11g technologies. This system will have public access, expect URL posted soon ! :-)

Nature is beautiful here - Red Sea coast:

Saturday, February 6, 2010

Custom Attribute to Pass ADF Button Key

I got a question, based on my previous post - CRUD Operations in Oracle ADF 11g Table Using PopUp Component. Blog reader was asking, if its possible to identify ADF button component in Backing Bean without checking component Id. Answer is yes, it is possible - just need to use JSF attribute component. You can declare JSF attribute for ADF button and pass button key through this attribute:


It will be possible to access value passed through JSF attribute in Backing Bean. You just need to specify JSF attribute name and value. In this example, I will use insert value in order to identify Insert button:


In Backing Bean, you will need to access UI Component (ADF button in this case) object, and use getAttributes() function to get a map of available attributes. Retrieve defined JSF attribute using its name:


In a case, if Insert button will be pressed, we will check attribute and will invoke CreateInsert operation:


In other case - row will be opened for editing:


Download sample application - TableDialogEdit3.zip.

Thursday, February 4, 2010

Default Value for Date Field in Query Criteria

I got a question about how to assign default value for Date type field available in Query Criteria. Developer had a requirement to initialize Date type query field with date equal to 10 days before current date. This requirement is very simple for ADF and can be implemented in 5 minutes without writing any code.

Download sample application - DateSearch.zip. This sample returns default value for HireDate attribute on page load automatically:


In order to implement this requirement, open View Criteria definition and assign Bind Variable parameter to HireDate attribute. Its very important, make sure you uncheck Ignore Null Values checkbox:


This will initialize Bind Variable with Null value, when user will try to search with empty HireDate attribute value. Otherwise you will get Missing In and Out parameters SQL error.

For getting correct default date value, you can use Groovy language for Bind Variable default value expression:

Monday, February 1, 2010

Installing ADF/WebCenter 11g on 64-bit Platforms

Today we were creating WebLogic cluster on two machines for ADF/WebCenter 11g application installation. Hardware is 64 bit, each with 8 processor cores and 32 GB RAM - sounds pretty powerful. There was no problems with clustering and deployment, however we faced problem while testing WebCenter Spaces - welcome page just wasn't compiled and was throwing following error, while trying to access it:

Servlet failed with Exception
java.lang.StringIndexOutOfBoundsException: String index out of range: -2

At first, we thought may be WebCenter Suite 11g runtime is not working on 64 bit platforms. So, we uninstalled all servers and did fresh install using only ADF 11g runtime libraries. We deployed simple ADF 11g application and got same exception. It became obvious, that its not WebCenter Suite 11g problem.

After some brainstorming, and couple of tea/coffee breaks, we understood that 64 bit JDK from Oracle (Sun) we were using is newer comparing to that 32 bit JDK packaged together with Oracle WebLogic Server installation. We were using latest jdk160_18, while Oracle WebLogic is packaged with 32 bit jdk160_14 version. So, we downloaded 64 bit jdk160_14 and reinstalled cluster again. This time ADF/WebCenter 11g deployment was working without any problems on 64 bit cluster environment.

Lesson learned: When installing Oracle WebLogic on 64 bit platform, you need to download Oracle WebLogic installation that comes without Java. Make sure you will use same 64 bit Java version, as it is used in packaged Oracle WebLogic installs with 32 bit Java.

Monday, January 25, 2010

Conditional Activation for ADF Regions and Application Availability

In ADF applications, in that case if database is down, user will get error message and site will be broken. If user will open site, when database was already down, user will see 'Loading' message and nothing else. If database will go down, during user activity - most likely NullPointerException will be raised and user will see broken site. Such behavior is not acceptable, enterprise services should be available even when database is not working. Ideally, database related content should be disabled and static content still should be loaded and available.

Today I have developed sample application, where regions are loaded conditionally, based on database availability. Download working sample - ApplicationAvailability.zip.

We will follow such scenario - user is working with Departments and Jobs regions:



Suddenly, database goes down for some unknown reason:



User of course is not aware about database status and press Next button in Departments region:



At this point, ADF will generate Exception, however we can handle it with Error activity registered in ADF Task Flow:



Without closing browser, user can refresh site, and if database still will be down - only static content will be loaded, database related regions will be disabled (I will describe how you can achieve this after few steps):



This allows to present at least static content, which is much better comparing to Error page, I'm even not talking about visible exception.

New users, who will open site while database is still down, will get static content rendered as well:



Finally, when database will be back to life again:



It will be enough just to refresh browser (no need to close it and open again), regions will be activated automatically and dynamic content will be rendered:



Now I will explain how it is done. Thanks to ADF Regions functionality , we can activate them conditionally:



When we use conditional region activation, activation condition must be provided. In this case, I'm calling managed bean (request scope) where check is done for Application Module status:



Its enough to acquire Application Module instance reference, if database will be down, Application Module will be unavailable and exception will be thrown. We can catch this exception and deactivate regions:



Finally, Error activity should be defined in ADF Task Flow in order to handle exception, when database is going down during active session:


Friday, January 22, 2010

Demystifying ADF BC Passivation and Activation

It happens to face exceptions in production environment, even if during development and testing everything was working good. In most of the cases, this strange behavior will be related to wrong transient attribute usage, transient attribute which value is not passivated and then its lost after activation. You can test your code, if it contains any bad practice implementations, by disabling application module pooling. Most of ADF developers know this, however only few really understand what is happening. Today I will present sample case, where bad practice is demonstrated practically.

Let's say developer decided to store temporary values in VO transient attribute and created new DummyAttr attribute in Employees VO:



Developer thinks - since I already have my temporary value in VO, why not to use it for another, this time permanent, attribute. And he calls transient attribute from permanent attribute getter method:



Thats it, Model is implemented. Next step, transient attribute should be somehow initialized. Its easy in ADF, we can use af:setActionListener component and initialize attribute directly from ViewController:



In our case, DummyAttr will be assigned with DepartmentName value:



At this point, functionality is implemented and can be tested. On runtime, transient attribute will be initialized in Departments page:



Employees page will be successfully opened:



Everything works good during testing. In production, when there will be high workload and many concurrent users, ADF will start to passivate Application Module instances and we will face a problem with such implementation. Production environment can be simulated by disabling Application Module Pooling:



User will open Departments page and will set transient attribute value:



Will try to open next page - Employees, and will get java.lang.NullPointerException. Why? Let's find an answer in detail log. When there is not enough space in the pool (during next submit in our test case), and Application Module instance is passivated, transient DummyAttr attribute value was not passivated and this means it was simply lost:



There is nothing to activate for transient DummAttr attribute, and since this attribute is called, exception is raised.

You should avoid such use cases as I just described and develop proper quality ADF code. In worst case scenario, which is not recommended anyway, you can force transient attribute passivation on attribute level:



Or even on VO level:



Then you can see that transient attribute will be passivated as well:



This means, code will work without exception, because activation will be done successfully. However, in my opinion, you should avoid this approach and use it only when you are really forced.

Download sample application, where Application Module Pooling is disabled and described bad practice is reproduced - AppModulePooling.zip.

Monday, January 18, 2010

Storing/Accessing Objects in ADF BC UserData Map

While implementing one of the requirements for View Criteria, I faced an issue when there was a request to filter View Criteria Item based on user language. Well, its trivial when you want to filter choice list defined for attribute - just specify bind variable value in View Accessor. Its a bit more tricky for View Criteria Item choice list, mainly because View Criteria can't access value from VO row. This means, if we want to filter View Criteria Item choice list, we need to use Groovy language script in order to retrieve value for View Accessor bind variable. In my case it was user language. What I did - I have read Example #154 from Steve Muench blog - Not Yet Documented ADF Sample Applications, and decided to store user language in UserData map, in order to access it from View Accessor Groovy.

If you will read Steve post, you will understand there are two approaches to access from your Model data available in ViewController layer. I prefer approach when UserData is set from custom Application Module method and then it can be accessed through Groovy.

Download sample application - UserDataGroovy.zip, where LocationId choice list is filtered based on user language. When browser works with English locale, LocationId brings locations from US:



When its set with French locale, LocationId is filtered again and shows French speaking countries:



As I already mentioned, there should be always clear separation between Model and ViewController. I'm storing user language value in UserData by calling ADF Task Flow Method Call:



This Method Call is invoking Application Module custom method, where current language is stored in UserData map:



You should see, language is stored in UserData map with currentUserLanguage ID. Same ID is used to access current language from View Accessor - adf.userSession.userData.currentUserLanguage: