The UKOUG Technology conference in Manchester hosted several very interesting sessions regarding ADF best and worst practices. Some slides are publicly available (see links at the bottom of this blog) but since there where multiple session and speakers I decided to write this blog post and share with you the most prominent do’s and don’t that might even surprise a skillful ADF developer. The topics covered below are certainly not all-encompassing, because one could write a whole book about it, but it does show some topics that may make your say “I wish I had known this a year ago”.
1. Do not prefix all managed bean EL expression with a specific scope.
In some cases, being over explicit is a bad thing when referencing managed beans in EL, for example
Never prefix in case of default Servlet scope, meaning requestScope, sessionScope and applicationScope. By prefixing the scope you bypass the JavaServer Faces managed bean facility. This means it will only look for in-memory objects and does not instantiate managed beans (causing an NPE).
Do prefix in case of ADF specific scope e.g. backingBeanScope, viewScope and pageFlowScope. These are handled by the ADF controller (instead of the standard servlet mechanism) and it takes care of managed bean instantiation (if configuration is available).
In general, you should try to avoid using the default servlet scopes all together and always use the smallest scope possible (this minimizes memory usage). In regards to requestScope and backingBeanScope, note that the backingBeanScope is basically the same as requestScope but when you add the same taskflow twice on one page, they will each have their own backingBeanScope. This is not the case when using request scope!
SessionScope is most suited for storing user context information (e.g. name etc.), do not use sessionScope to pass/reuse values between taskflows, but use TF parameters instead. Also keep in mind that all sessionScope data is shared across browser tabs.
2. Never set immediate=true on an editable components
The most common use case for the immediate property is implementing Cancel/Reset functionality on input forms. In this situation you want to ‘skip’ validation and this is simply achieved by setting the immediate=true property on the commandbutton component, which is fine.
The immediate=true property can also be set on input components such as af:inputText, but this should be avoided whenever possible. You will most likely end up with a page that can never be navigated away from. To fully understand the rationality behind this you must know your ADF lifecycle and ADF optimized lifecycle. I can highly recommend reading this post of Steven Davelaar and his demo-app explaining the JSF/ADF life-cycle.
3. Do not use ADF internal classes (such as FacesCtrlHierBinding and FacesCtrlHierNodeBinding)
Internal Oracle classes have “Internal” in the naming, which should be a clue! ADF Faces, Trinidad and ADF Controller have an API package and an IMPL package. The API package is public and guarantied to remain stable from release to release this is not the case for API’s inside the IMPL package. The FacesCtrlHierBinding and FacesCtrlHierNodeBinding (the Internal ADF Faces component model for tree, table and treeTable) are classic examples of internal class usage. Unfortunately these two internal classes appear in numerous examples throughout the web. To ensure future compatibility, one should instead use the public classes JUCtrlHierBinding and JUCtrlHierNodeBinding.
4. Never cache ApplicationModule references.
Some developers may think that looking up an ApplicationModule is expensive and try to improve performance by caching the ApplicationModule reference in a backingBean. Always keep in mind that ApplicationModules are pooled resources, thus it is never guaranteed that you use the same ApplicationModule instance over a longer period of time. So on a good day caching is a great way to ensure you get an NullPointerException. On a bad day it’s a great way to get stale (or someone elses!) data. Also note that issues related to ApplicationModule caching usually only show itself when the system is under stress.
5. Never store state in your ApplicationModuleImpl.
Storing information in custom fields on the ApplicationModule leads to all sorts of unpredictable application behaviour, such as users being able to see data from other sessions. As mentioned earlier, this is caused by the fact that AM instances are recycled for other users under load.
6. Do not hold references to UI Component in beans (no matter what your scope is).
When you store a reference to a UI Component in a bean, the complete component tree (children and parent) are kept in memory. This causes your ADF application to consume a unnecessary big amount of memory. Unfortunately when you use the auto generation feature for component binding in JDeveloper, it will generates the references as depicted below:
This should be changed using the much more memory efficient ComponentReference class:
7. Do not simply passivate everything
Only passivate transient attributes if you really need it (calculated values such as Firstname + “ ” + LastName do not need to be passivated since they can be recalculated.) Also think carefully before you check the passivate checkboxes in the View Object general settings because this will passivate all transients which impacts performance, since the passivation/activation process will be more time consuming.
8. Avoid using plain text credentials in web.xml or deployment plans.
Sometimes you need to utilise credentials (username/password) from your ADF (or other FWM) applications. Most often the solution involves property files or context parameters in the web.xml and deployment plans. All of which involve plain text password storage, which is a possible security risk. A perhaps less know feature of FMW is that it supplies a credential store framework. This is a set of APIs that applications can use to create, read, update, and manage credentials securely.
The credential store can be accessed via the java API as shown in the example below:
More details regarding this solution can be read on this blog written by Wilfred van der Deijl.
9. Do not forget to use custom framework extension classes for your ADF business components
It is best practice to configure your project to use custom base classes for at least:
This can be easily configured in your application preferences (be sure to do this before you create your application module and business components). Otherwise you may end up doing a lot of refactoring when you decide you need to add functionality like logging/analysing fetch calls made to the database. The latter can be easily achieved (if you have your own base classes) by overwriting the createInstanceFromResultSet() in the VO Impl class (as shown in this blog written by Andrejus Baranovskis).
UKOUG Technology conference – december 2013
18 Invaluable Lessons About ADF Faces Page Lifecycle (Steven Davelaar)
Credential Store Framework (Wilfred van der Deijl)
ADF Anti-Patterns: Dangerouse Tutorials] (Andrejus Baranovskis)
Worst Practices for developing an ADF application (Wilfred van der Deijl)
With special thanks to Duncan Mills and Frank Nimphius.