You are on page 1of 20

27

Code checkpoints and performance

Prepared By: Sanjeeb Mahakul

Overview
For any ADF/J2EE Java code, Model and UI layer, here are few points to make code better from writing from performance and standard point of view, that comes from our coding practice and experience. Here I have tried to consolidate a set of checkpoints we should check b4 checking in the source changes into SVN.This ensures making code better, robust, standards compatible and deliver good performant.

JSFF/JSPX code- Checkpoints


Make sure, you have used Resource Bundle wherever its required. For Bounded taskFlows, make sure to use activation as conditional/deferred(Not Immediate) and use active condition EL expression. We will see the implementation later in this slide. Id of the component, length should be <= 7. Make sure, you have removed unwanted PageDef Bindings. This is the most important aspect of improving the performance of the application. We very often ignore this which hits us back in a long run. If af:popup is used, make sure to set the contentDelivery to "LazyUncached". Use partialtriggers cautiously as and when required. Right click->Reformat before checkin. If using JavaScript, can you think to avoid that.

Java Code - Checkpoints

Managed Bean class name should end with "Bean".


Dont use SOP statements. Add Logger statements which can be turned on and off as required. Make sure you have thrown sufficiently Exceptions. Make sure to define the Variables with a name starting with small letter. Do not use underscore (_) in Variable and Method names. Make sure to check for Null condition for all operation that could throw NullPointerException. Ex: CollectionModel, Row, ViewObject, ApplicationModule, String objects etc. Remove the dead codes. Use the scopes objects wisely and use the lesser scopes variable as required. Do not auto bind the page as it creates getters n setters for all components. Bind the components which are required in programmatic manipulation in backing bean. Handle the looping constructs carefully, do that they dont go into indefinite loop and never initialize anything inside the loop unless required. Right click->Organize imports.(removes unwanted imports) Right click->Reformat before checkin.

AM - Check Points
Number of occurances of createRootApplicationModule() or *AMImpl.getInstance() should be minimum. Use the appication module instance wisely.

Entity Object - Check Points


Remove unwanted attributes. Dont extend the impl classes unless required. Make sure you use resource bundle at entity lever so that it can be reused. Its a best practice to use validations at entity level.

ViewObject - CheckPoints
For new Attributes added, make sure you use proper UI hints. If creating a New VO, make sure its is based on an EO,unless required make RO VO. LOVs defined on parent VO shouldn't have "query automatically" checked.It degrades the performance Remove unwanted view accessors. Dont extend the impl classes unless required

Project - CheckPoints
Avoid cyclic dependency. Avoid dependency of the project on itself. Remove unwanted jars if attached.

Fine Tune ADF Faces UI Layer(Performance Improvement)


Use AJAX to boost up the performance of your web pages ADF Faces component trigger Partial Page Rendering (PPR) by default. However action components, by default, triggers full page refresh which is quite expensive and may not be required in most of the cases. Make sure that you set partialSubmit attribute to true whenever possible to optimize the page lifecycle. When partialSubmit is set to true, then only the components that have values for theirpartialTriggers attribute will be processed through the lifecycle.

Avoid inline usage of JavaScript/Cascading Style Sheets (CSS) whenever possible If you need to use custom JavaScript functions or CSS in your application, try using external files to hold the same. Avoid inline usage of JavaScripts/CSS as much as possible. A better idea is to logically group them in external files and embed the required one in the candidate page using tag. If you keep JavaScript and CSS in external files, they are cached by the browser. Don't generate client component unless it's really needed Set clientComponent to true only if you need to access the component on the client side using JavaScript. Otherwise this may result in increased Document Object Model (DOM) size at the client side and may affect the performance of your web page. Prefer not to render the components over hiding components from DOM tree If you need to hide UI components conditionally on a page, try achieving this with rendered property of the component instead of using visible property. Because the later creates the component instance and then hides the same from client side DOM tree, where as the first approach skips the component creation at the server side itself and client side DOM does not have this element added. Apparently setting rendered to false, reduces the client content size and gives better performance as bonus

Fine tune the UI tables(af:table, af:tree, af:treeTable), displayed on your web page Use appropriate content delivery mode Pick up the suitable content delivery mechanism for your UI table to accelerate the performance. Data can be delivered to table either upon rendering the page or lazily as separate Partial Page Request (PPR). This behavior is controlled by the contentDelivery attribute. Possible values for this attribute are:
immediate lazy whenAvailable

If the page contains only the table context or the number of rows displayed are low (say 50 or below) use immediate delivery. You can opt for lazy delivery when the page contains a number of components other than a table or if the number of rows filled is on the higher side.

Pickup right component to display list of values (LOV) ADF Faces provides multiple components or modes to display the 'list of values'. You may need to choose the right one based on your business requirements. Both af:inputListOfValues and af:inputComboboxListOfValues are smart enough to load the list of values on demand(lazy loading) where asaf:selectOneChoice reads the entire list and populates the same when the page renders(greedy loading). You need to me be aware of the performance cost associated with each of these components. As a rule of thumb, consider af:selectOneChoice to display the list of values if the number of elements is less (say 15 or less) .In all other cases consider using either af:inputListOfValues or af:inputComboboxListOfValues, which loads list on demand. we can disable ADF Faces Rich Client animation functionality globally, just by adding one line in trinidad-config.xml file: animation-enabled = false This will help greatly when rendering LOV popups, drawing data tables and etc. By disabling animation, artificial delay of components rendering is removed and this allows to achieve better UI performance.

Avoid repetitive coding by improving the reusability Use Page templates Declarative components ADF task flows Page Fragments Use resource bundles intelligently If the size of your resource bundle is huge, logically split that into multiple resource bundles. While splitting, please make sure that a single page doesn't need to look in to multiple bundles to get the localized strings. Dont over engineer your product by caching the ResourceBundle in your managed bean or through a custom way, it's already cached for you by design.

ADF UI - Performance Tip: Lazy load task flows for better performance
Before discussing the performance improvement by implementing lazy loading for the task flows, let us go through the task flow basics.

How task flows are loaded normally? If you're dropping task flow as a region in your jsff, the task flow binding will be added in the pagedef file as an executable. So, anything under executables section including the task flows in pagedef file will be loaded by default when the jsff page is loaded.

How it impacts the performance?


As ADF loads all the task flows that are inlcuded in a page, even if they are not rendered by default, it'll be a performance hit as we're loading the task flows which are not needed by default. Examples below: Popups: Task Flows on a popup should be loaded only when user clicks on Pop-up link but ADF loads them during the page invocation itself and hence reduce the perfomrance of the page . Hidden Taks Flows or Conditionally Rendered Task Flows: ADF page could have some of the task flows that are hidden based on a condition. In this scenario as well ADF loads the task flows during page loading even if those task flows are hidden and the model content in that will get executed during the page loads hence results in lower performance of the page. Panel Tabs: Page could have multiple tabs on a page with respective task flows , ADF loads all the task flows even though only one tab will be showed at a time.

So, What is lazy loading and how it improve the performance?


Lazy loading means loading the task flows only when they are required to be rendered. i.e., we won't load the task flows that are included inside popups, and those hidden initially, and the ones that are present in other than the default tab. We'll load them only when the popup is invoked, when the task flow region is unhidden/shown, on clicking the tab that has the task flow respectively.

How to implement lazy loading for the task flows?


For task flows in popups i. Define a af:setPropertyListener of type 'popupFetch' and set some constant to one pageFlowScope variable. Jsff containing taskflow: <af:popup id="popup1" contentDelivery="lazyUncached"> <af:dialog id="dialog1" type="okCancel" title="Employee Details" inlineStyle="width:340px; height:125.0px;"> <af:panelGroupLayout id="panelGroupLayout1"> <af:region value="#{bindings.EmpDetailsTaskFlow1.regionModel}" id="r2"/> </af:panelGroupLayout> </af:dialog> <af:setPropertyListener to="#{pageFlowScope.popupFetched}" type="popupFetch" from="EMP_DETAILS"/> </af:popup>

ii. In the pagedef, set 'Activation' property for task flow binding to 'Conditional' and 'Active' property to above defined pageFlowScope variable with EL expression which evaluates to true when the popup is fetched.

2. For the hidden or conditionally rendered task flows: i. Conditionally rendered task flows will have the 'rendered' property set to some condition defined as EL expression based on which the region will be hidden or shown. You need to specify the same condition for the 'Active' property of the task flow binding in the pagedef. And, don't forget to set the 'Activation' property for task flow binding to 'Conditional'. Jsff containing taskflow: <af:showDetailHeader text="Emp Details" disclosed="true" id="sdh3"> <af:region value="#{bindings.ShowHideTaskFlow1.regionModel}" id="r2" rendered="#{pageFlowScope.showHideCondition==true}"/> </af:showDetailHeader>
The task flow in the corresponding pagedef file: <taskFlow id="ShowHideTaskFlow1" taskFlowId="/com/demo/taskflows/ShowHideTaskFlow.xml#ShowHideTas kFlow" activation="conditional" xmlns="http://xmlns.oracle.com/adf/controller/binding" active="#{pageFlowScope.showHideCondition==true}"/>

3. For panel tabs (af:panelTabbed) components i. Add a af:setPropertyListener of type 'disclosure' in each af:showDetailItem under af:panelTabbed and set some constant value to a pageFlowScope variable. You need to set value to the same pageFlowScope variable in each tab. On reading the pageFlowScope variable value, you should be able to tell in which you're currently in. Jsff containing taskflow: <af:panelTabbed id="pt1"> <af:showDetailItem id="showDetailItem1" text="Basic Details"> <af:region value="#{bindings.BasicDetailsTaskFlow1.regionModel}" id="region1"/> <af:setPropertyListener to="#{pageFlowScope.tabClicked}" type="disclosure" from="BASIC_DETAILS"/> </af:showDetailItem> <af:showDetailItem text="MainDetails" id="showDetailItem2"> <af:region value="#{bindings.MainDetailsTaskFlow1.regionModel}" id="region2"/> <af:setPropertyListener to="#{pageFlowScope.tabClicked}" type="disclosure" from="MAIN_DETAILS"/> </af:showDetailItem> <af:showDetailItem text="Other Details" id="showDetailItem3">

You might also like