Você está na página 1de 12

ADF Best Practices I.

ADF Coding Standards and naming conventions.

Application name - every app must have a short name or acronym that can be used as part of package names, specific classes and on paths. This should be used in lower case for speed and simplicity (and to save wearing out the shift key). E.g. srdemo, fodemo, um, foobar, speaker refer to ADF Coding Standards_SahajV1.doc Packages should be prefixed by the client or company name, though arguably not a fully qualified path, e.g. oracle.srdemo, veriton.um, ukoug.speaker. refer to ADF Coding Standards_SahajV1.doc Top level BC directories entities, design for diagrams, service for application modules. Note: the views packages typically organised within the individual task flows that use them Backing beans should have the same name as the web page that they are used in, eg. CreateStudentForDept.jspx has a backing bean Eg: CreateStudentForDept. This folder convention is different to what is mentioned in the ADF coding standards. Entity name should suffix with EO, VO name should suffix with VO, read only VO should have suffix as VVO, App Module should have suffix as AM If file name or package name is bigger than 20 characters than use abbreviations for example user dept for department & emp for employee. Refer folder & package structure for more details. Templates are another significant 11g feature. Your application should have one or more templates, though these may be imported from an organization-wide library. Your overall system should be comprised of several Task Flow ADF Application Workspaces, each representing a Task Flow modeling a business process, as well as a single Common ADF Application Workspace. A Master ADF Application Workspace will include each of the separate Task Flow ADF Application Workspaces, in order to meet the overall Application's needs. For security reasons keep your task flow inside the WEB-INF folder. Task flows being an xml file can be opened directly thru the browser and will show the code of your application. Design larger application modules to encompass all of the functionality that a user needs. Nest smaller application modules under a single root application module so that the same database connection can be shared among the nested application modules. Use lazy loading for application modules. In the Application Module tuning section, customize runtime instantiation behavior to use lazy loading. Lazy loading can also be set JVM-wide by adding the following JVM argument:

Adding regions to a page can be a powerful addition to the application. However, regions can be a resource-intensive component on the page. For better performance, consider using regions only when the specific functionality is required. If the application contains static data that can be reused across the application, the cache data can be collected using a shared application module.


View Layer

Use AJAX to boost up the performance of your web pages

Asynchronous JavaScript and XML (AJAX) avoid the full page refresh and minimize the data that being transferred between client and server during each round trip. ADF Faces is packaged with 150+ AJAX enabled components which adds AJAX capability to your applications with zero effort. Certain events on an 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 their partialTriggers attribute will be processed through the lifecycle.

Avoid mixing of html tags with ADF Faces components

Dont mix html tags and ADF Faces components though JSF design let you to do so using <f:verbatim> tag. Mixing row html contents with ADF Faces components may produce undesired output, especially when you have complex layout design for your page. It's highly discouraged to use <f:verbatim> to embed JavaScript or CSS, instead you can use <af:resource> which adds the resource to the document element and optimizes further processing during tree rendering. Avoid long Ids for User Interface components

It's always recommended to use short Ids for your User Interface (UI) components. Your JSF page finally boils down to html contents, whose size decides the network bandwidth usage for your web application. If you use long Ids for UI (User Interface) component, that increases the size of the generated html content. This becomes even worse, if you have many UI elements with long Ids. If there's no Id is set for a UI component explicitly, ADF Faces runtime auto generates Ids for you. ADF Faces let you to control the auto generation of component ids by setting context parameter 'oracle.adf.view.rich.SUPPRESS_IDS' in the web.xml file. The <context-param> entry in the web.xml file may look like as shown below. <context-param> <param-name> oracle.adf.view.rich.SUPPRESS_IDS </param-name> <param-value>auto or explicit </param-value> </context-param> Possible values for oracle.adf.view.rich.SUPPRESS_IDS are listed below.

auto: Components can suppress auto generated IDs, but explicitly set ID will be honored. explicit: This is the default value for oracle.adf.view.rich.SUPPRESS_IDS parameter. In this case both auto generated IDs and explicitly set IDs would get suppressed. 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 <af:resource> tag. If you keep JavaScript and CSS in external files, they are cached by the browser. Apparently, subsequent requests for these resources are served from the cache. This in turn reduces the network usage and improves the performance. Avoid mixing JSF/ADF Faces and JavaServer Pages Standard Tag Library (JSTL) tags

Stick on JSF/ADF Faces components for building your UI as much as you can. JSF component may not work properly with some JSTL tags as they are not designed to co-exist. Relying on JSF/ADF Faces components may give you better extensibility and portability for your application as bonus. Don't generate client component unless it's really needed

ADF Faces runtime generates the client components only when they are really required on the client. However you can override this behavior by setting the attribute clientComponent to true, as shown in the following code snippet. <af:commandButton text="DoSomething" clientComponent="true"> <af:clientListener method="doSomething" type="action"/> </af:commandButton> 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. The following diagram shows the runtime coordination between client side and server side component trees.

In the above diagram, you can see that no client side component is generated for the server component whose clientComponent attribute is set to false. 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. Prefer to use click-To-Edit over edit-All mode for tables

The click-To-Edit mode table lets the end user to edit the selected rows in a lockstep fashion, one row at a time. Advantages of using click-To-Edit mode are listed below.

In a click-To-Edit, non editable rows are rendered as output components which tend to generate less HTML than input components. Client components are not created for the read-only rows.

Validation phase is also optimized to handle one row at a time. Request and Response data is significantly lower in this mode as data relevant to the current editable row alone is being transferred between client and server. Really a good option if the table has large number of rows. Fine tune the UI tables, 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: o immediate o lazy o 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.

Use suitable fetch size Data fetch size for a table plays critical role in deciding the performance of the containing pages. The attribute fetchSize decides the number of rows needs to be retrieved during each server round trip. You may need to ensure that value specified for this attribute is good enough to fill the displayed table rows to avoid further server round trips.

The above discussion is applicable for tree and tree table as well. 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. List Type Input Text with List of Values Combo Box with List of Values Choice List, Combo Box, List Box, Radio Group Component af:inputListOfValues af:inputComboboxListOfValues af:selectOneChoice

Both af:inputListOfValues and af:inputComboboxListOfValues are smart enough to load the list of values on demand(lazy loading) where as af: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. Use customized Skins to style your pages

If you need to specify custom styles (look and feel) such as height, width, font size etc. for components on a page, then use ADF Faces skinning solution. Though you can do this by overriding inline style for each component, this may not be a viable solutions if this style needs to be applied across pages. ADF Faces always lets you to override the default look and feel for a component by creating custom skins. Skinning let you to override the look and feel of UI components across application. If you need to apply the style to a specific group of components alone, then you can create a style class with standard selector(s), and apply them by setting the styleClass attribute of the component to the desired style class. Choose the right layouts to design your pages

While lay outing components on page, choose the right layout component that meets your requirement. If you dont want stretch-to-fit layout, then dot use them at all. A stretch-to-fit layout is not as good performant as fixed height-width layouts. Situation becomes worse, if you have nested containers with many child UI components inside. Apart from these geometry management components, there are certain attributes which may need special attention on the same context. You may need to be measured while opting for columnStretching property for a table to stretch the column to fit the available width. The columnStretching adds extra overhead on the client side at runtime. When the table is a complex one with large number of columns and rows, this becomes very expensive operation. The same point is applicable for table with frozen columns (frozen=true), they are also expensive on the client side. Avoid repetitive coding by improving the reusability

When you build an application, avoid replicating the same piece of code or component definitions across pages. ADF Faces is built focusing on maximum reusability and minimal boiler plate code. Consider one of the approaches explained below, to improve the reusability in your application.

Page-templates Page template helps you to keep generic page definition in one place and reuse the same as basis for building pages and page fragments. New pages generated based on the page template inherit the layout defined for the page template and these pages can add the custom contents in the place holders provided by the template. You may need to be cautious while choosing layout for page template as this repeats across multiple pages in your application. Try to keep the layout simple and efficient. Declarative-components The declarative components follows composite design pattern, where you can assemble individual UI components into one composite reusable component. The same can be used declaratively in multiple pages. This really helps you to build complex reusable UI by composing multiple components. Declarative components can also be used in page templates.

ADF-task-flows Task flows provide a modular approach for defining control flow in an application. If you have use case which involves multiple tasks that needs to be carried out in a step by step manner, apparently that turns out to a perfect candidate for a 'task flow'. Task flow encapsulates business logic, process flow, and UI components all in one package, which can then be consumed by multiple teams declaratively. Page-Fragments If you page is cluttered with huge chunk of UI components and the same repeats across pages in your application, try considering creating reusable page fragments and later consume them from the client pages. A page fragment, as the name stands represents portion of page embedded inside <jsp:root> tag. Use resource bundles intelligently

Success of a product depends on its marketability across the globe. Obviously, localization of messages and labels play a very vital role in this context. As you use Java for building fusion web application, you may need to use java.util.ResourceBundle to store locale specific objects like messages or labels. A couple of points on the effective usage of ResourceBundles are listed below.

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. Be bold enough to bypass the JSF lifecycle phases as and when needed

The JSF lifecycle is not trivial; each request is routed through definite stages before rendering the page. However there are scenarios where you can bypass certain phases and leverage some performance bonus. While navigating from one page to another, using navigation components, there is no need to stick on the full JSF life cycle. You can short circuit the lifecycle phases by keeping immediate=true for navigation/action components. You can see this in the following diagram that life cycle execution skips to RenderResponse phase when immediate property set as true for an action button.

Please note that, you can skip to the RenderResponse phase by calling javax.faces.context.FacesContext::renderResponse() from any phase of execution. Always design your Managed Bean for High Availability

Managed Beans are very essential elements for a JSF based application. They act as back up for UI component model and can hold view specific custom business logic as well. There are six types of scopes available for managed beans in a fusion web application as listed in the below diagram.

You may need to take care of following points in regards to managed bean while developing a high available fusion web application.

Keep the managed beans in the lowest possible scope While defining managed bean always try to keep them in the lowest possible scope, which reduces the runtime overhead associated with state replication across nodes in a clustered environment. Keep the getters/setters of your managed bean (data model) lightweight You may need to understand that getters and setters for a managed bean used in a page may

get called multiple times during the life cycle. Always make sure that assessors specified for the data model doesn't have any complex logic. Use managed bean only to store book keeping information, business logic should reside in your business service layer. Bean should be serializable If the managed bean scope is higher than request, then its state needs to be serialized and copied to other nodes at the end of each request. Obviously beans need to implement java.io.Serializable interface. Note that, member variable of you class should also be serializable, or marked as transient if their state does not need to be replicated at the end of a request. Mark ADF scopes as dirty to enable state replication ADF optimizes state replication of ADF scoped beans to avoid the blind copy of the state at the end of each request. So you may need to ask for state replication by marking them as dirty, based on bean mutation state. Use the below API to ensure the state replication for viewScope or pageFlowScoped bean if its modified for any request. ControllerContext.getInstance().markScopeDirty(viewScope/pageFlowScope); Log your debugging messages smartly with ADFLogger

It's a bad practice to use System.out.println() to log your debugging or diagnostic messages. There is no easy way to turn off or control these logs when your application goes for production. This may dump all unwanted logs in your application server, adding extra overhead for your system administrator. If the numbers of logs statements are large in number, this may affect your system's runtime performance too. For fusion web application, it is recommended to use oracle.adf.share.logging. ADFLogger to log all debugging messages which gives more control on the logging part. You can easily change log levels (turn off or customize) of ADFLogger using the configuration parameters present in logging.xml. Feel free to override the default rules set for JavaScript Partitioning

Almost all html based web frameworks make use of heavy JavaScript based libraries to set up the basic infrastructure at the client side. Apart from these core run time libraries, an enterprise application may have its own custom JavaScript libraries. ADF Faces provides a way to group (partitions) the JavaScript source files logically and down load each partition on demand. The default partitioning provided by ADF Faces may not be ideal for your application in all cases; it depends upon the combination of UI components used to build pages and usage pattern of the pages. ADF Faces allows you to tune the JavaScript library footprint to meet the needs of their application. You can override the default partition rules (that come with ADF Faces) by creating your own adf-js-partitions.xml in the WEB-INF directory. Speed up your web application by caching static contents

Caching static contents such as images, JavaScript, css etc. improves performance of the system. ADF Faces is packaged with oracle.adf.view.rich.webapp.AdfFacesCachingFilter (servlet filter) which marks the application resources for caching at external Web Cache and/or user-agents (browsers). ADF Faces comes with set of default rules for caching static contents; however developers can override the default caching behavior with application's adf-config.xml file. This file is located under your web application's WEB-INF folder. Following diagram shows the syntax for defining caching rules in adf-config.xml. <?xml version="1.0" encoding="windows-1252" ?> <adf-config xmlns="http://xmlns.oracle.com/adf/config"

xmlns:adf="http://xmlns.oracle.com/adf/config/properties" xmlns:sec="http://xmlns.oracle.com/adf/security/config"> <adf-faces-config xmlns="http://xmlns.oracle.com/adf/faces/config"> <caching-rules> <caching-rule id="cache js"> <cache>true</cache> <compress>true</compress> <duration>99999</duration> <agent-caching>true</agent-caching> <cache-key-pattern>*.js</cache-key-pattern> </caching-rule> <caching-rule id="cache jpeg"> <cache>true</cache> <compress>false</compress> <duration>99999</duration> <agent-caching>true</agent-caching> <cache-key-pattern>*.jpeg</cache-key-pattern> </caching-rule> </caching-rules> </adf-faces-config> </adf-config>

III. Model Layer

1. Do attribute validations at EntityObject instead of in backing bean If you have a new validation which is not available in your validation list in EntityImpl, create a new validation rule class as mentioned in the below screen. It can be reused at various places

2. Usage of groovy expression for primary key generation Use groovy expression in entity for primary key generation using database sequence instead of doing this in EntityImpl create / prepareForDML or doDML methods.

3. Prefer Declarative SQL Mode View Objects SELECT list "pruned" at runtime based on data required on current page A "wide" VO with joined referenced information gets "trimmed" to exclude unreferenced tables "Selected In Query" property determines attributes which should never be pruned

4. Prefer One View Object with Many View Criteria No longer necessary to create separate Vos that only differ by WHERE filter Single, consistent row structure everywhere you use it, regardless of which criteria are applied Apply view criteria declaratively when defining view accessors and AM data model instances