Bolton Carroll Management Consultant ROLTA carrollb@tusc.
com
Agenda
OA Framework Extensions Overview OA Framework Extension vs Personalization OA Framework Extension Examples Some Tips and Techniques Best Practices Questions
OA Framework Overview
OA Framework is a technology stack, which allows extensions to the self-service or html style pages within Oracle E-Business Suite. It is based on the industry standard model-viewcontroller (MVC) architecture and includes the following technologies/tools: UI XML (UIX), Business Components for Java (BC4J), Application Object Library (AOL), Meta Data Service (MDS), and Jdeveloper 9i or 10g. OA Framework was used to build the html web pages in Oracle E-Business Suite for both Release 11i and Release 12, and it is the Oracle recommended technology for customizing or extending the Oracle EBusiness Suite.
Model View - Controller
Model View - Controller
Model-View-Controller is a design pattern which separates an application into 3 basic layers The Model represents the data model and the business logic, which are managed in xml definition files and java classes. The model includes entity objects, view objects, and application modules. These different types of objects are all part of the Business Components for Java (BC4J). The View is what the user sees. The page definition is a hierarchy of web beans, with each web bean corresponding to either a region or an item object. The Controller is a java class file that is tied to either a page or region level, and is responsible for rendering the page or region, handling the user actions, and determining the flow of pages
Key Profile Options
Personalize Self-Service Defn
Yes enables personalization link on all pages
FND: Personalization Region Link Enabled
Yes displays all regional links Minimal displays key regional links
Disable Self-Service Personal
Turn off all personalizations
FND: Personalization Document Root Path
Used for importing/exporting personalizations
Key Profile Options
FND: Diagnostics
Activates the link called About this Page at bottom left of page and allows logging to screen
FND:OA:Enable Defaults
Allows defaulting through personalizations to take place
Fnd Xliff Export Root Path
Sets root path for translation files
Personalizations vs Extensions
Personalizations do not involve the use of JDeveloper Personalizations are for simple modifications to the web pages Personalizations can be accomplished by functional users Extensions involve using Jdeveloper Extensions often involve the use of Personalizations
Personalizations vs Extensions
Most common personalizations are rendering, read only, required, and prompt Custom Views are also considered personalizations and allow changing the display of table data for specific responsibilities Basic Steps for a personalization: Click on Personalize page link, find item, click on personalize icon for the item, select item property to modify, and modify appropriate level with new setting
Personalizations vs Extensions: Buttons
Personalizations can be used to create a button or link with a url as a destination Personalizations can be used to create an export button which allows exporting of table data Personalizations can not create a submit button An extension would be needed to create a submit button and the logic to handle the submit process
Personalizations vs Extensions: Flexfields Personalizations can be used to add flexfields to a page Personalizations can specify which segments of a flexfield to display (independent of the flexfield definition) Extensions are needed to default values in a flexfield Extensions are needed to make specific segments of a flexfield conditionally mandatory, independent of the flexfield definition
Examples of Possible Extensions
Setting properties of flexfield context value or flexfield segments (conditional properties based on other fields or actions on the page) Setting initial properties of any field on the page based on the value of another field on the page Changing properties of a field based on a change to another field on the page Adding a special checkbox which will trigger special validation
Examples of Possible Extensions
Force upper case characters in a particular field Only allow characters and numbers in a particular field Modify an lov on a page Write information to a custom table based on user actions Change the navigation flow, such as skipping over a page or restricting access to a page Combine the information from multiple tabs on a page into one tab on that page
Personalization Example
Step 1: Click on personalize link
Personalization Example
Step 2: Find item to personalize and click personalize icon
Personalization Example
Examples of setting different properties
Personalization Example
Setting default value
Personalization Possibilities
Personalization Possibilities
Personalization Possibilities
Adding a Field To a Page
Through Personalization
When field is already part of VO Just add an item and set VO Name and attribute name
Through an Extension
When field is not part of VO Extend VO to add extra field and modify the sql statement of the VO Add a personalization to display the new field
Adding a Field to a Table
Click on personalize link on the page or region
Adding a Field to a Table
Click About this Page, and then expand all to see all the fields and to determine the name of the View Object for the table
Adding a Field to a Table
In expanded mode, find the View Object for the table where you want to add an extra field (AllReqsVO) In this example, we will add EmergencyPoNum (actually its just hidden at this point, but we are adding it as an example)
Adding a Field to a Table
Find the view object attribute for the field you need
Adding a Field to a Table
Create new item within the table
Adding a Field to a Table
Created item type of message styled text and give a custom name to the id
Adding a Field to a Table
Specify name of View attribute, View Object, and prompt for your new column, then click Apply
Adding a Field to a Table
View results of new field
Extension to Add a Field
Move class file directories needed by page you are modifying from apps server to myclasses directory on your client (e.g. for purchase order you will need $JAVA_TOP/oracle/apps/po directory) Move xml files of pages you are modifying from $Product_TOP/mds/ directory on server to client myprojects directory Move VO xml and class files of VO you are modifying from myclasses directory on your client to myprojects directory on your client Create a new VO as an extension of the original While creating new VO, add extra field as a new attribute and modify SQL statement of VO Create substitution rule in project properties to substitute new VO Set project properties to use substitution rule Add new field to page using a personalization
Extension to Add a Field detailed steps
1. Right click on project and select New, Business Tier, ADF Business Components, View Object 2. Enter or browse for package for custom VO: xxapl.oracle.apps.. 3. Enter name of VO Object xxaplObjectVO 4. Browse for original VO that is being extended 5. Click Next 6. Click Back immediately after (this allows us to change updateable box) 7. Click on checkbox for updateable access 8. Click Next 9. Click Next to get to Step 3 (Attributes) 10. Under list on right, click New button 11. Type attribute name for new field
Extension to Add a Field detailed steps
12. Click Mapped to Column or SQL checkbox 13. Enter Alias and Expression (alias is sql alias, expression is sql database column) 14. Click OK 15. Click Finish 16. Find new VO you created and right click to edit 17. Go to SQL Statement 18. Change sql to add your column (expression and alias must match your attribute) 19. Click Apply 20. Click Attribute Mappings 21. Check to make sure attribute is mapped to sql column 22. Click OK
Extension to Validate a Field
Validation can be done through an Entity Object extension or a Controller extension Entity Object: Advantage is that 1 extension will do validation for any VO accessing that entity object, even if there are multiple VOs Controller: Good way to do extension when there is no entity object on the page and you need to call a sql statement for validation Oracle Developers Guide does not recommend putting validation rules in VO or in Application Module
Entity Object Extension - Validation
Validation can be done on either the field level or record level Field level validation: insert custom code in setter of the specific field Record level validation: insert custom code in validateEntity() method
Entity Object Extension - Validation
Field level validation example (in EOImpl class):
public void setUnitPrice(Number value) { if (value != null) { If (value.compareTo(10000) > 0) { throw new OAAttrValException(OAException.TYP_ENTITY_OBJECT, getEntityDef().getFullName(), // EO name getPrimaryKey(), // EO PK "UnitPrice", // Attribute Name value, // Attribute value "AK", // Message product short name "FWK_TBX_T_PO_PRICE_EXCEEDED"); // Message name } } super.setUnitPrice(value); }
Entity Object Extension - Validation
Record level validation example (in EOImpl class):
protected void validateEntity() { super.validateEntity(); if (condition) {
throw new OARowValException(OARowValException.TYP_ENTITY_OBJECT, getEntityDef().getFullName(), getPrimaryKey(), "AK", // Message product short name,
"FWK_TBX_T_PO_NO_DELETE"); // Message name }
Entity Object Extension - Validation
Import statements that may be needed
import oracle.apps.fnd.framework.OAAttrValException; import oracle.apps.fnd.framework.OAException; import oracle.apps.fnd.framework.OARowValException;
Controller Extension - Validation
Identify the controller that gets called when Apply or Save is pressed (use About this page) If there are multiple controllers, look at Oracles code to see which one handles Apply button Create a new java file which extends the standard controller Create your validation in the processFormRequest method Personalize the page to point to your custom controller
Controller Extension - Validation
Extend the standard controller
public class xxcusBasicInformationCO extends BasicInformationCO {
public xxcusBasicInformationCO() { } public void processFormRequest(OAPageContext oapagecontext, OAWebBean oawebbean) {
Controller Extension - Validation
Logic to put into processFormRequest method
Check for an Apply or Save button action Get a handle on the field Check the value against an expected value If necessary throw an OAException Call super.processFormRequest
Controller Extension - Validation
Example (validate length of a field):
if(oapagecontext.getParameter("Apply") != null) { String longName = oapagecontext.getParameter("LongName"); if (longName != null && longName.length() > 70) { throw new OAException("Error with Long Name: " + longName + " Length: " + longName.length() + " Error: " + longNameError); } } super.processFormRequest(oapagecontext, oawebbean);
Controller Extension - Validation
Adding custom controller through personalization
Setting Default Values
Personalization: Only works for following items: MessageTextInput, MessageLOVInput, MessageCheckBox, MessageChoice, MessageRadioButton, MessageRadioGroup Change property called Initial Value Only works if profile option FND:OA:Enable Defaults is set to Yes In some cases, a default personalization will not take effect due to defaulting logic of Oracle
Defaulting through Personalization
Setting default value
Defaulting Values in Entity Object
Extend EO and override create method in the EOImpl class Call a setter method Example:
import oracle.jbo.AttributeList; .. public void create(AttributeList attributeList) { super.create(attributeList);
// Add or change the default values here. // EXAMPLE: setPaymentTermsCode("NET_60");
}
Defaulting Values in View Object
Extend the VO Add a method to override the insertRow method in the VORowImpl class Use this code:
super.insertRow(); row.setAttribute(<attributename>,<attributevalue>);
Mainly used when there is not an entity object to extend (e.g. when VO is based on OAPlsqlViewRowImpl)
Defaulting Values in Controller
Extend Controller and override ProcessRequest method Find the web bean you want to default Set the value on the web bean using the appropriate set method Include logic so that you are only setting the value when the appropriate button has been pressed (such as a Create Button) Create a personalization to point to the new custom controller
Complex Extension Example
Buyer Work Center: A change to the purchase order line item category should change the line type and the item class automatically. Then the flexfield should automatically change since the item class is the context of the flexfield Solution: Controller extension processFormRequest method:
check the lov input source for a change in category Based on category, find line type and item class Store new values in page parameters Refresh the page
processRequest method:
Check page parameters for new values Populate line type and item class with new values if they exist If item class changed, refresh the flexfield
Tip: Simple SQL Validation
Simple sql lookup in a controller Standard practice would be to
create a custom VO for that sql statement, extend the AM to include the custom VO and an init routine Add an init routine in the controller to call the init routine in the AM
Another option is to dynamically create a VO Advantages:
No need to extend AM No need to create a custom VO All custom code is in a controller, and this can easily be turned off by turning off the personalization that points to the custom controller
Tip: Simple SQL Validation
Steps are:
Define variable to hold query Look for VO, if it does not exist, create it Set where clause parameters Execute query Get result
Tip: Simple SQL Validation (con.)
In processRequest or in processFormRequest String xxcusCatQuery = "select value from ..where id = :1 "; OAApplicationModule am = pageContext.getRootApplicationModule(); ViewObject catVO = (ViewObject)am.findViewObject("xxcusCategoryVO"); if (catVO == null) { catVO = am.createViewObjectFromQueryStmt("xxcusCategoryVO",xxcusCatQuery); } catVO.setWhereClauseParams(null); if (newCategory != null) { catVO.setWhereClauseParam(0,newCategory); catVO.executeQuery(); oracle.jbo.Row row = catVO.first(); if (row != null) { xxcusAttCategory = (String)row.getAttribute(0); }}
Tip: Adding a custom AM
Technique to automatically attach your custom code to the current AM without extending the current AM Steps involved: Create your custom routines in a custom application module Extend the controller
Get handle on current application module Look for the custom application module, if it does not exist create it within the current application module Call your routines in the custom application module
Tip: Adding a custom AM (con.)
if(oapagecontext.getParameter("Apply") != null){ String taskNumber = oapagecontext.getParameter("paElementNumber"); OAApplicationModule oaapplicationmodule = oapagecontext.getApplicationModule(oawebbean); OAApplicationModule nam = (OAApplicationModule)oaapplicationmodule.findApplicationModule("xxcusTabSetupA M"); if (nam == null) nam = (OAApplicationModule)oaapplicationmodule.createApplicationModule ("xxcusTabSetupAM", "oracle.apps.xxcus.pa.util.server.xxcusTabSetupAM"); Serializable aserializable2[] = { taskNumber }; String validResult = (String)nam.invokeMethod("validateCreateTask", aserializable2); if (validResult != null && !"".equals(validResult)) { throw new OAException("Error with Task Number: " + taskNumber + " Error: " + validResult); } } super.processFormRequest(oapagecontext, oawebbean);
Tip: Displaying all the page parameters
Page parameters can be displayed through logging on screen, but that is not always successful Sometimes it is useful to error out a page at time of a submit or save to see all the parameters Parameters can be very useful to determine where the user is coming from and to see some key values
Tip: Displaying all the page parameters (con.)
import java.util.Enumeration; public void processFormRequest(OAPageContext oapagecontext, OAWebBean oawebbean) { if(oapagecontext.getParameter("Apply") != null) { StringBuffer buf = new StringBuffer("Params: "); Enumeration enumer = oapagecontext.getParameterNames(); String key = ""; while ( enumer.hasMoreElements() ) { key = (String) enumer.nextElement(); if( oapagecontext.getParameter( key ) != null) { buf.append("--"+ key+ ":" + oapagecontext.getParameter(key)); } } throw new OAException(buf.toString(),OAException.ERROR);
Tip: Displaying all the page parameters (con.)
Result of throwing error with parameter values
Tip: Using jdr_utils package
Jdr_utils.listCustomizations to show all customizations on a specific page jdr_utils.printDocument to show a page, a region, or a personalization Identify personalizations with listCustomizations and then each personalization can be displayed (in xml format) with printDocument Customizations include personalizations, extensions of BC4J objects, and views (Oracle seeded and your custom views)
Tip: Using jdr_utils package
Example: to see customizations on Purchase Order page jdr_utils.listCustomizations ('/oracle/apps/po/document/order/webui/OrderPG'); Result: /oracle/apps/po/document/order/webui/customizations/re sponsibility/50645/OrderPG Then run jdr_utils.printDocument to see details jdr_utils.printdocument('/oracle/apps/po/document/order/ webui/customizations/responsibility/50645/OrderPG');
Tip: Using jdr_utils package
Result of printDocument on a personalization
<?xml version='1.0' encoding='UTF-8'?> <customization xmlns="http://xmlns.oracle.com/jrad" version="9.0.6.0.0_35" xml:lang="en-US" customizes="/oracle/apps/po/document/order/webui/OrderPG" xmlns:user="http://xmlns.oracle.com/jrad/user" user:responsibilityKey=CUSTOM_RESPONSIBILITY" user:responsibilityAppId="201"> <modifications> <modify element="LinesRN.LinesTableRN" controllerClass="oracle.apps.xxcus.po.document.order.webui.xxcusOrderLinesTable RNCO"/> <modify element="PageLayoutRN" controllerClass="oracle.apps.xxcus.po.document.order.webui.xxcusOrderCO"/> <modify element="HeaderRN.DetailsRN" rendered="true"/> </modifications> </customization>
Tip: Using jdr_utils package
Jdr_utils can be used to see extension of view objects, entity objects, and AM To see an extension on a view object, use the printdocument procedure:
jdr_utils.printdocument('/oracle/apps/pa/structure/s erver/customizations/site/0/CreateTasksVO');
Tip: Using jdr_utils package
Result of displaying a view object extension
<?xml version='1.0' encoding='UTF-8'?> <customization xmlns="http://xmlns.oracle.com/jrad" xmlns:ui="http://xmlns.oracle.com/uix/ui" xmlns:oa="http://xmlns.oracle.com/oa" xmlns:user="http://xmlns.oracle.com/user" version="10.1.3_1305" xml:lang="en-US"
customizes="/oracle/apps/pa/structure/server/CreateTasksVO"> <replace with="/oracle/apps/xxcus/pa/structure/server/xxcusCreateTasksVO"/ > </customization>
Tip: View Log
View log on screen to see request parameters, code that is running and view objects (VOs) on page Displays view object queries, VO parameter values, and order by clauses Requires profile option FND:Diagnostics to be set to Yes Click on Diagnostics link at top right of any page In next screen, select option to show log on screen
Tip: View Log on Screen
Tip: View Log on Screen
Select Log Level and click Go
Tip: View Log on Screen
Log Displays below each page
Tip: Logging Custom Messages
Use OAPageContext.writeDiagnostics method Can be used in controller to log messages Set log level and a custom identifier to easily search
if(pageContext.isLoggingEnabled(1)) { pageContext.writeDiagnostics(this, "xxcus Param xxcusCatAtt: "+ xxcusCatChange, 1); pageContext.writeDiagnostics(this, "xxcusParam xxcusNewLineType: "+ xxcusNewLineType, 1); }
Tip: Logging Custom Messages
Result of custom logging on screen:
Tip: Logging Custom Messages
For AM, VO, and EO use OADBTransaction and writeDiagnostics method
import oracle.apps.fnd.framework.server.OADBTransaction; OADBTransaction oadbtransaction := getOADBTransaction(); if (oadbtransaction.isLoggingEnabled(1)) oadbtransaction.writeDiagnostics(this, "your message", 1);
Tip: Logging to Database
Database logging is controlled by profile options:
FND: Debug Log Enabled FND: Debug Log Level FND: Debug Log Module
Writes data to table fnd_log_messages Can restrict messages to a particular module for ease of troubleshooting
Tip: Migrating Personalizations
Use Functional Administrator, Personalization, Import/Export Exports to directory specified in profile option FND: Personalization Document Root Path Move exported xml file to target server Import into target instance with Functional Administrator
Tip: Migrating Personalizations
Manual creation of a personalization xml file can save time Example: if you have many personalizations on a page tied to one responsibility and you need to include them on 6 other responsibilities Export an xml file for the one responsibility, manually create (through copy and paste) 5 other files for the other 5 responsibilities changing responsibility key in each file Put the new files in appropriate directory structure (based on responsibility id) and import using Functional Administrator
Best Practices
Naming convention:
xxabc/oracle/apps/po/./webui/xxabcOrderCO.java Exception is when using ACP (Oracles tool for migration) oracle/apps/xxabc/po//webui/xxabcOrderCO.java
Root Application Module should not be extended AM Retention: only if next page needs transaction information from first, or if the user may be switching back and forth between pages, not if 2 pages are independent
Best Practices
View Object Performance: Use different VOs for different purposes, dont use VOs with dynamic where clauses if possible View Object Classes: No need to generate View Object Class if you have no custom code, good to generate VORow class for performance purposes. View Object Setter/Getter: use set<AttributeName>, not setAttribute(index), for performance reasons
Best Practices (con.)
VO where clause and parameters should be set in VO, not in controller Business Logic: put business logic in Entity Object whenever possible, not in controller or view object Avoid using JDBC calls directly, use OADBTransaction object to connect to database Avoid Javascript
Reality Sets In
Jdeveloper can be quirky
Example of clicking Next, then Back, to be able to update a property Sometimes its necessary to close Jdeveloper and reopen to see latest changes Sometimes its necessary to modify files on file system and then reopen in Jdeveloper
Oracle does not always follow its own standards (e.g. many examples of OAPlsqlViewRowImpl, which is deprecated) Though Oracle does not encourage extending controllers, this may be the only way to accomplish certain changes
References
Oracle Application Framework Personalization Guide, Release 12 OA Component Reference Oracle Applications Framework Developers Guide, Release 12.1.2 Oracle Tutorials C:\<JDEVinstall>\jdevdoc\index.htm (after you have installed Jdeveloper) Harnessing the Full Power of OA Framework: Personalizations in the E-Business Suite
http://www.ncoaug.org/NCOAUG%20Training%20Day%20Feb% 202010/OAUG2010v3.pdf
Questions
Presenter: Bolton Carroll ROLTA
[email protected]
http://www.linkedin.com/pub/bolton-carroll/1/a87/243
www.tusc.com http://www.roltasolutions.com/