Sunday, July 31, 2011

How To Handle Web Browser Buttons in ADF/WebCenter Applications

ADF/WebCenter technology typically is used to implement transactional logic and transfer desktop applications functionality into web browser. Based on this, many questions can be asked, for example - what will happen if user press browser Refresh button during pending transaction or what will happen if browser will be closed at all during transaction. We are not asking same questions for pure web type applications, but ADF/WebCenter is different case.

There is no 100% working option to control web browser buttons and to disable them from inside of our application, this would break browser security and allow hackers to lock users into specific web site. We can try to clear browser cache, etc. - but this is not working with ADF/WebCenter applications. However, there is option to inform user proactively about browser related even, that can potentially break application functionality, for example - browser will be closed, page will be refreshed by Refresh button, etc. We can catch these events and warn user from ADF/WebCenter application. I will describe in this blog post, how to implement such warning.

Download sample application for this post - EnterprisePortalApp_v5.zip.

Sample application is based on WebCenter 11g navigation model, it loads ADF task flows and external resources:


When authentication is succeeded, default home page is loaded. Browser Back button becomes active, because it indicates user can go back to login page. We would like to avoid this, so we can inform user with warning implemented by sample application:


This is standard browser warning dialog and is supported by all browsers. Two options are given - to stay or to continue browser navigation. If user will choose to stay on current page, will be able to continue his work. If "Leave this Page" option will be selected - we can't guarantee correct application behavior.

This warning works well when navigating between pages. However, it behaves a bit different with ADF dynamic regions or when WebCenter navigation model is loading ADF task flows, external resources into internal frame. Let's load external resource by clicking on WebCenter menu:


Make sure you have noticed that "Reuters Global News" menu item was selected. Now press browser Back button - page content remains the same, but menu item selection moves and makes previously selected menu item as current:


This is logical, because we were not using separate page to display "Reuters Global News", but it was rendered inside frame - sample application didn't catch any change in navigation. However, if we press browser Back button one more time, it would try to navigate away from home page and we would receive navigation warning:


Press - "Stay on this Page" and open another menu item - "Jobs". Try to close browser, same navigation warning dialog will appear and ask user to confirm his action. This is good, because user is warned before closing page without doing actual logout:


Navigation warning doesn't affect internal navigation between ADF regions, because this navigation doesn't change current page - press Edit button:


Another ADF region will be opened, without giving any navigation warning:


But if user will press "Administration" link, this will invoke navigation to new physical page, user will be warned:


"Logout" link also navigates to another physical page, however it will not give navigation warning - I will explain how to handle this with JavaScript:


Let's do one more test and press browser Refresh button, while "Departments" menu item is opened. Press "Leave this Page" when navigation dialog will be opened:


ADF/WebCenter application will reload, but will fail to render correct data - it will show "Fetching Data..." message constantly. Also menu item selection becomes wrong. If user would choose to "Stay on this Page", it would work well - it's user responsibility to choose action. Now user would need to press previously selected menu item "Departments", but all pending data will be lost:


It works to control navigation in this way with all browsers, or at least with those I have tested - IE, Firefox, Google Chrome. IE test:


Firefox test:


I will explain now, how to enable such navigation warning dialog. We need to invoke JavaScript function, during application home page load. In ADF/WebCenter applications we can invoke onload JavaScript function, simply by calling it from main af:form binding method:


I'm loading JavaScript from navigation-renderer.jspx page, because ADF/WebCenter application is using this page to load page content into frame. You are free to do the same from your home page.

Form binding method, programmatically loads window.onbeforeunload JavaScript function. This function allows us to control browser navigation, and is loaded only once - on home page initialization. If we want to skip navigation check for some page, we should leave function body empty (if check for logoutAction == 0):


If we need to skip navigation check for specific link, we can add af:clientListener method and set JavaScript variable flag:


Flag value will be set through JavaScript and later evaluated from window.onbeforeunload method (see above):


Friday, July 29, 2011

Presenting Red Samurai at Oracle User Group in Japan

I was giving session today about Red Samurai during Oracle User Group in Japan. You can read more about Oracle community initiative (Oracle Lovers) in Japan on Facebook. Thanks to Mototaka Yoshida Oracle ACE for inviting me to speak - it was really fun and I enjoyed a lot.



Audience in the room, watching Red Samurai session in Oracle Japan Aoyama Center 13F S2:


Session topic was - why our company is called - Red Samurai?

The answer is:
  1. Our Motto - Killing Bugs
  2. Oracle Specialized - We are Red
  3. Always Fix Problems, or We Are Dead - Samurai
  4. If You Have Problem and No One can Help (even Oracle) - Call Us, We Will Fix it in No Time

These are not just words, but proven by Oracle Awards:


ADF Code Corner Article - 087. How-to improve LOV performance with shared AM in ADF BC

I have started to publish articles on ADF Code Corner hosted on Oracle OTN and managed by Frank Nimphius. You can read my first post there - 087. How-to improve LOV performance with shared AM in ADF BC.


Stay tuned, more articles to come !

Saturday, July 23, 2011

Configuring Oracle UCM 11g Access Control List Security - Missing Steps

If you are working with Oracle UCM 11g, I can imagine you may encounter hard times, when thinking about content security architecture design. But really, its not so complex - as it looks first, just there are lots of confusion between Security Groups, Accounts and Access Control Lists (ACL). For your reference, in Oracle UCM its not enough to define security groups to protect content - Understanding Oracle UCM 11g and Oracle ADF 11g Security Integration. One of the recommended ways is to use security Accounts in combination with Security Groups to protect RWDA permissions for files and folders. However, while this approach is recommended - is not so practical. Idea of using Security Groups and Accounts combination is hardly acceptable by customers, because first is hard to understand, second is hard to maintain. Its hard to maintain, because from administration point there is no difference between Security Group and Account, but it matters for UCM.

We prefer to use Access Control List (ACL) functionality to implement content security in Oracle UCM 11g. ACL was available in previous versions of UCM, before 10g and returned back in 11g. This suggests ACL being simple to understand and preferred solution to protect content security - 5.6 Access Control List Security.

Goal of this post is to describe few missing steps from Oracle UCM 11g documentation, related to ACL configuration.

Let's follow 5.6.1 Configuring Access Control List Security section and define UseEntitySecurity=true together with AllowQuerySafeUserColumns=true properties:


This should be enough to enable ACL support, as per documentation.

We can see now that two additional fields became available - User Access List and Group Access List (out of scope for this post) for folder/file configuration. Type redsa into Add User box, auto-suggest list with matching users will appear:


Assign RWD permissions to redsam for the 266 folder. You should keep in mind, this folder is enabled with Security Group called - Proposal :


Make sure that Force Folder Security is set to True - this will ensure ACL list propagation to child folders or files:


For example, if we upload new file into 266 folder, this file will inherit ACL list:


Another folder - 267, is assigned for user redsam1 with RWD permissions:


Let's do a test now, logically thinking folder 267 should not be visible for user redsam because of ACL setup:


Its still visible, both folders are visible, when it should be visible only one:


What was missing in UCM 11g ACL configuration guide, is SpecialAuthGroups property. From WebCenter Administrator's Guide 11.2.2.2 Configuring Oracle Content Server 11g to Support Item Level Security in All WebCenter Applications:

SpecialAuthGroups is a comma separated list of security groups that contains the content on which ILS can be specified. If in a WebCenter Spaces application users are to be provided ILS support, then the security group in which all Spaces content is created must be one of the SpecialAuthGroups. For WebCenter Spaces, the security group is named the same as the Document Spaces Property's application name. (For WebCenter Portal applications, the applicationName is the name of the security group in which content is created.)

In our case, we are using Proposal group for ACL enabled folders and files, it can be any other custom Security Group:


Make sure this group is included into ACL configuration:


It works now as expected, user redsam will see only those folders allowed through ACL - it works:


Folder 267 is not accessible for redsam, when going directly through URL as well, as it should be:


Major difference between UCM 10g and 11g, in 11g it runs directly integrated into WebLogic. This simplifies lots of administration and configuration tasks, for example UCM security is synchronized with WebLogic security providers. This means its enough to define Active Directory security provider for WebLogic, it will be visible for UCM as well.

UCM 11g is fetching users from WebLogic security provider automatically:


UCM role is mapped with roles from WebLogic security provider automatically as well, for example ProposalRole from UCM:


Can be used directly inside WebLogic security provider or fetched from Active Directory, etc.:


Saturday, July 16, 2011

ADF View State Tuning for Large WebCenter 11g PS3/PS4 Applications

While running large ADF/WebCenter 11g PS3/PS4 applications in stress test or production environment, users can experience random errors related to ADF view state token. For example such errors can be observed in the log: StateManagerImpl restoreView Could not find saved view state for token -ejrgnqgsv.

We can refer to section 8.2 Oracle ADF View Performance from Oracle Fusion Middleware Performance and Tuning Guide. It describes org.apache.myfaces.trinidad.CLIENT_STATE_MAX_TOKENS property and instructs how to tune performance by reducing the size of state token cache. By default, for ADF application tokens size is set to 15 (I personally would recommend to set it to 25 and then measure application performance, if no performance issues, its better to keep available tokens value higher), it can be tuned to 2. When it is set to 1, ADF application will return error after browser Back button click. When we create new WebCenter application in JDeveloper, org.apache.myfaces.trinidad.CLIENT_STATE_MAX_TOKENS is set to 3, this means WebCenter application would keep only three tokens in memory. Number of tokens is set to 3, probably to reduce memory usage for heavy WebCenter applications.


We have noticed, when Web session timeout is set to default 30 minutes, after 10-15 minutes of user inactivity - could not find saved view state for token error is be reported randomly. This is unexpected behavior, because user is not pressing browser Back button, but still gets error during inactivity, even before timeout.

This means org.apache.myfaces.trinidad.CLIENT_STATE_MAX_TOKENS = 3, as it set for WebCenter 11g PS3/PS4 applications, looks like not enough. When this value was increased to 25, state token error was not reproduced anymore.

Hope this hint will help you, in case of unexpected error will be encountered for missing view state during user inactivity.

Monday, July 11, 2011

Unique Key Validation for LOV Based on Reference Attribute

While ago I was blogging how to Define LOV on a Reference Attribute in Oracle ADF 11g. Such type of LOV's are defined on description text, not on key. This approach works well, however there are some limitations when applying Unique Key business rule for such type of LOV's. Because LOV is based on read-only reference attribute, and Unique Key business rule is applied for LOV key, updated in the background - Unique Key business rule is not fired correctly for LOV based on reference attribute. I have tested this with JDev PS3, PS4 and R2 releases - same behavior is reproduced - Unique Key business rule is not working for such type of LOV's. User requirement is a must, and I will describe today how to implement Unique Key validation for LOV based on reference attribute, may be not exactly following ADF best practices.

Download sample application - UniqueKeyADFSample.zip. This sample is not using LOV based on a reference attribute approach described from the blog post mentioned above. Instead, it is using calculated attribute - DepartmentName, by default this attribute is populated through SQL expression and is updateable (which is very important):


This attribute must be set as updateable, otherwise in case of validation error - user still will see previous value. Control Hints for DepartmentName define Auto Submit = true property:


Persistent LOV key attribute - DepartmentId, is defined to be dependent on DepartmentName:


This means, whenever DepartmentName will be changing, DepartmentId value will be updated as well.

Let's return now to Unique Key business rule. This rule defines pair of attributes - DepartmentId and PhoneNumber to be unique for every row:


Business rule - Unique Key Validator, is created based on EO alternate key:


LOV is defined on calculated DepartmentName attribute and additionally returns value for DepartmentId persistent attribute:


In this scenarion, because Unique Key business rule is defined on EO level, and we are changing DepartmentId by selecting another value for DepartmentName - Unique Key business rule is not fired on UI side (it works in ADF BC tester utility).

One of the ways to force business rule execution, is to call validate method for current transaction - method is implemented inside AM implementation class:


We would need to invoke this method from UI, this means declare it inside Page Definition and call after LOV value will change:


When you will look through sample application, you will wonder why there is additional hidden button available - Helper:


This is not accidental. If we would come back to the beginning of this story, we would remember that Unique Key business rule is defined on EO level. This means business rule is fired only on submit, but not on auto submit for attribute (at least this is true for LOV attribute). It would be not convenient for user to press button, just to perform validation. So, we create hidden button and invoke it programmatically. Hidden button properties:


Hidden button calls AM method to validate current transaction.

LOV is defined with Value Change Listener and invokes hidden button action - once LOV value is changed, hidden button will be invoked and validate current transaction:


This trick allows to invoke EO level validation rule, when changing only attribute value. You may think, why not to invoke AM validate method from Value Change Listener itself - its simply still not working.

Its not the end of the story yet. When transaction is validated and validation error is reported, this error is attached only with attribute from Unique Key business rule. So, even this business rule is invoked on EO level, it reports validation errors for individual attributes - tricky. So, we need to highlight failed attribute by ourselves. We can do this by referencing attribute from Unique Key business rule, just point to errors property - this would tell us about validation status and we could copy it and display for LOV:


For row.bindings.DepartmentId.errors to work, make sure DepartmentId is declared inside tree bindings:


We can simulate Unique Key validation error:


Selected duplicate value is highlighted, validation error message is shown as well: