Tuesday, May 24, 2016

Adf Best Practise & performance Tuning

Application Module

          Disconnect Application Module on Release.
  • ADF will not release database connection back to Data Source by default, which can lead to high connection usage and application may eventually get in to hung situation if you run out of Data Source connections.
  • Setting this option will make sure that connection is released back to Data Source pool and you can keep more number of active application modules in memory without requiring high number of data source connections.

  • Have a purge job to clean up PS_TXN  table frequently

  • Application Module Tuning
    application module settings were tuned to support only 50 concurrent users, 
    but it was working well with 200
    Reference Pool Size :  Number of AM's in the pool that attempts to preserve session affinity for the next request, by default this value is '10' , that you can find in  'Pool and Scalability' section of Application Module, Bump up this value for better performance.

    Maximum Available Pool Size : By default this value is '25', Higher values makes more AM's available and improves performance

    - Idea instance time out : By default this value is 10 Minutes, Bump up this value for better performance, This is strictly based on nature of the users who access the screens, If the nature of application , intented audience access the pages for lesser than 10 minutes for a given instance, then keep this value as it is, If users spends more time on/off on the screen, then increase this value.

    Maximum Instance Time to Live(jbo.ampool.timetolive) : Milli seconds that an application module instance lives in the pool, By default this value is '1hr' , Set this value to '-1' for better performance

  • Entities

  • – Implement entity object sequences consistently 
  •  There are more than 1 way to populate entity object attributes, including with database sequences, via the DBSequence domain type and database triggers, overriding the EntityImpl create() method, or using Groovy expressions.
  •   For your overall application decide the technique to use, apply it consistently across all entity objects and apply it as soon as the entity object is created. 

  • Do not access an application module from an entity object 
  •  entity objects should not access application modules as this makes the entity object only useable within that application module. 

  • - Don't use entity object key ROWID 

  •  By default if ADF BC doesn't find a primary key at design time for an entity object's relating database table, it will generate an additional attribute mapping to ROWID. 
  •  This will continue to work unless an Oracle database Real Application Cluster (RAC) is used where across database partitions different ROWIDs can be returned for the same row.  Therefore attempt to avoid using the ROWID attribute and instead select a combination of existing attributes as the primary key. 

         Avoid using the entity object validateEntity() method for validation

         do not override an entity object's EntityImpl validateEntity() method.Rather code any business logic as a declarative method validator for the entity object itself. This comes with the added advantage all validations are visible in the entity object's business rules page. 
           
        Avoid entity object attribute validation in accessors

        do not write code to validate an attribute in its setter accessor within the associated EntityImpl class for the entity object. Rather create a declarative method validator for the attribute.

        Do not call postChanges unless you can guarantee a commit or rollback at the end the HTTP request 
         Typically the EntityImpl postChanges method is called by the ADF BC lifecycle upon a commit operation. However you can also programmatically call this method. As the postChanges method changes the state of the associated EntityImpl which then assumes the changes have been committed to the database, this can leave your entity object in a dirty state. As such only call the postChanges method directly if you know that at the end of the HTTP request you will commit or rollback the transaction.

---------------------------
ViewObject

Use view criteria over editing view object where clauses
 - Rather than customizing a view objects where clause which makes the use of the view object less flexible, use a viewcriteria instead.

 Avoid read only view objects for speed benefits alone

- Older ADF manuals recommended using read only view objects as there was a minor speed benefit. Since JDeveloper 11g this is no longer true as the caching mechanism has been improved. Today read only view objects should be reserved for complex queries such as those with set operations (e.g. UNION, MINUS, INTERSECT) and connect by queries. All other view objects should be based on entity objects. If the view object needs to be read only, unselect the "Updateable" property when the entity object is mapped to view objects.

Use createRowSetIterator() for view object programmatic iteration 
- if in code you need to programmatically iterate over the rows provided by a view object, use the createRowSetIterator() and closeRowSetIterator() methods to manage a separate RowSetIterator to the default provided by the view object, as the default may be bound to the user interface

Consider view object fetch size and access mode 

- Consider the view object tuning options for how the view object will be used. If the view object is used to display a page of 10 records for example, set the Batch/Fetch size of the view object to 10 + 1 too.

- Make sure in VO->General->Tuning-> Batches

 Make sure to have unique/Primary key defined on every View Object

always create and use custom base classes for at least 

- ApplicationModuleImpl
- EntityImpl
-ViewObjectImpl
-ViewRowImpl

- dont generate impl classes without a need , keep code base size reasonable 

Managed Beans

1- 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:

RichInputText nameField;
public void setNameField(RichInputText nameField)
{
  this.nameField = nameField;
}
public RichInputText getNameField()
{
  return nameField;

}
his should be changed using the much more memory efficient ComponentReference class:



private ComponentReference nameField;
public RichInputText getNameField()
{
  if (nameField!=null)
  {
    return (RichInputText) nameField.getComponent();
  }
  return null;
}
public void setNameField(RichInputText nameField)
{
  this.nameField = ComponentReference.newUIComponentReference(nameField);
}

  • - Ensure each backing bean/Manage bean should implements java.io.Serializble interface.
  • - Remove unused VOIterators on JSFF Page definitions.
  • - on Buttons use "blocking=true" for and to avoid multiple clicks on submit buttons.
  • - While using tree or table components, set correct fetch size(this determines the number of rows to be sent to the client in one round trip) value.
  • - Never use getRowCount() unless if it is really needed



Web.xml

Consider web.xml settings for development and testing 
– there are a number of web.xml settings that can be set to assist the process of debugging during development and testing: 

oracle.adf.view.rich.ASSERT_ENABLED=true
org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT=true org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION=true oracle.adf.view.rich.LOGGER_LEVEL=true 

Be aware that you might not want to have these set for all testing systems such as user acceptance testing and performance and stress testing, where the perception of speed to your users is paramount. 


Deployment to Production Systems The following guidelines apply to deploying your application to a production environment: 
– Ensure web.xml settings for production – ensure that the following context parameters are set for a production environment: 

oracle.adf.view.rich.automation.ENABLE=false [default value] oracle.adf.view.rich.ASSERT_ENABLED=false [default value] org.apache.myfaces.trinidad.CHECK_FILE_MODIFICATION=false [default value] org.apache.myfaces.trinidad.COMPRESS_VIEW_STATES=true
org.apache.myfaces.trinidad.DEBUG_JAVASCRIPT=false
org.apache.myfaces.trinidad.DISABLE_CONTENT_COMPRESSION=false[default value] oracle.adf.view.rich.libraryPartitioning.DISABLED=false [default value] oracle.adf.view.rich.LOGGER_LEVEL=false [default value] javax.faces.STATE_SAVING_METHOD=client

Pages  
Use JSPX rather than JSP for 11gR1 applications - If using a JDeveloper 11gR1 release (which doesn’t use Facelets), use JSPX XML compliant files rather than JSP. 

Don't hardcode human readable text - Do not hardcode human readable text in your pages/fragments. Rather store any hardcoded text in a resource bundle and refer to the keyvalue pair instead.

  Avoid inline HTML use - Embedded HTML in JSF pages is often responsible for breaking the behavior of the ADF Faces Layout components. Additionally HTML embedded in a JSF page assumes that the page is indeed being rendered in a conventional browser and may link the application to a particular subset of browsers. 

Consider command partialSubmit=true - Command components such as af:commandButton by default when pressed cause a complete page refresh with the server. If not navigating between pages, consider using partialSubmit=true which will result in only components with their partialTriggers set to be processed. 

Avoid long component ID lengths - Avoid long component ID names as this has a performance hit. 
Use rendered=false over visible=false if possible - If you wish to hide a component use rendered=false over visible=false when possible as the first results in the server skipping the processing of the component and sending it over the wire to the browser, while the 2nd requires the server to process the component, send it over the wire, the browser to process it then hide it.

   Make Id's value as small as possible, This will avoid too much HTML to the browser.

  PanelTabbed Child Creation - Use 'childCreation="lazyUnCached" ' or 'childCreation="lazy" ' to defer taskflow execution of all tabs until the tab is opened.

  - For Popups, use  'childCreation="deferred" 

Never rely on UI side validation - Never solely rely on UI (browser) validation alone as this can be easily exploited by hackers. As example a selectOneChoice on the browser provides an allowable list of values the user can select from, but doesn't validate that the user hasn't submitted a different value not in the list. Always back UI side validation up with server side validation to catch such workarounds.

Bindings 

 Only interact with the business model through the binding layer 
- Accessing the underlying business model (e.g. an application module) via the dataprovider can have multiple negative effects such as causing memory and connection leaks, getting the wrong sessions data and breaking the auto PPR functionality.

  Don’t reference #{data} - The #{data} expression root is not guaranteed to provide access to the required data. Success will depend on the state of the cache. If data is needed in a particular view / method then create an explicit binding in that scope


 Avoid business logic in bean methods - complex business logic that manipulates model layer data should not be placed in the ViewController layer. Consider placing such code in the model layer instead and making one programmatic call from the bean. 

Java 

 Don't use System.out.* or System.err.* - Do not use functions like System.out.println.for debugging and do not leave this unnecessarily in your code. 
 Use the ADFLogger- Make use of ADFLogger in your ADF applications.
ex: 
 private static ADFLogger _logger = 
            ADFLogger.createADFLogger(MainPageBackingBean.class); 

 public MainPageBackingBean() {
        super();
        _logger.info("Creating a new instance");
        if (BindingContext.getCurrent() == null) {
            _logger.warning("Injected Data-Binding Reference is null");
        } else {
            try {
                doSomethingComplex();
            } catch
            weirdAppException waex;
            {
                _logger.severe("Unexpected exception doing complex thing",
                               waex);
            }
        }
    }

 Consider user level logging in production – Enterprise manager now supports user level tracing which allows you to lower the log level for a single session. Traditionally turning on logging on production systems would result in a flood of information for all sessions making the reason to write logging in the first place less than useful. However with the ability to turn logging on for a specific user this makes the implementation of logging more useful. 

 Always reformat code - All code should be reformatted before check in to assist readability.

 Remove commented out code - Do not leave commented out code in your source code upon check in.