·
Entity Object Create Example
The
following example illustrates an application module method that creates and
inserts a row into the
SuppliersVO
view object. This particular view object is based on the SupplierEOImpl entity
object, so BC4J instantiates this behind the scenes when the row is created.
public void createSupplier()
{
OAViewObject
vo = getSuppliersVO();
Row
row = vo.createRow();
vo.insertRow();
// As specified in OA Framework Model Coding
Standards,
// set the new row state to STATUS_INITIALIZED.
·
View Object Query Examples
This
shows an application module method that queries the SuppliersVO view object using
search criteria passed from the client.
public void query(String supplierName, String onHoldFlag, String supplierNumber)
{
SuppliersExpVOImpl
vo = getSuppliersExpVO();
if (vo == null)
{
MessageToken[] tokens = { new MessageToken("OBJECT_NAME", "SuppliersExpVO")};
throw new OAException("ICX", "FWK_TBX_OBJECT_NOT_FOUND", tokens);
}
vo.initQuery(supplierName, onHoldFlag, supplierNumber);
} // end query()
·
Commit Example
/*
*
Provides a "commit" wrapper so UI controller code doesn't need to get
a handle to the transaction itself which is a violation of the client/sever
tier separation rules.
*/
public void apply()
{
getTransaction().commit();
} // end apply()
·
Modifying Bean Properties
To
modify a web bean's properties, you simply need to find the correct bean in the
hierarchy using its name the ID you assigned in JDeveloper), and call the
appropriate method as shown in the following example.
Warning:
When you get a handle to a web bean, always check whether the value is null
before calling any of the methods. Even if you expect the bean to be included
in the web bean hierarchy, it's possible that a customer may hide it with a
personalization.
processRequest(OAPageContext
pageContext, OAWebBean webBean)
{
// Always call this before adding your own code.
super.processRequest(pageContext, webBean);
OATableBean
table = (OATableBean)webBean.findIndexedChildRecursive("OrdersTable");
if (table == null)
{
MessageToken[] tokens = { new MessageToken("OBJECT_NAME", "OrdersTable")};
throw new OAException("ICX", "FWK_TBX_OBJECT_NOT_FOUND", tokens);
}
// Set the purchase-order specific "control bar"
select text:
// "Select Purchase Order(s) and..."
String
selectPOText = pageContext.getMessage("ICX", "FWK_TBX_T_SELECT_PO", null);
table.setTableSelectionText(selectPOText);
}
Starting
with the controller region's children, the findIndexedChildRecursive(String
name)method searches the entire web bean hierarchy looking for the first
indexed child with a matching name. If the web bean that you want to modify is
a UIX named child (or, if you're not sure whether it is "named" or
"indexed"), use the findChildRecursive(String name) method
instead.
·
processFormRequest( )
Any
code that handles user form submit actions belongs in the processFormRequest()
method.
The
following example is typical of the processFormRequest() code that you will
write. It illustrates how to determine that a particular form submit component
was selected (in this case, a "Go" button), how to initiate a query
in the model code, and how to perform a JSP Forward back to the same page so
web bean properties can be changed in the processRequest() method.
public void processFormRequest(OAPageContext pageContext, OAWebBean webBean)
{
// Always call this before adding your code
super.processFormRequest(pageContext, webBean);
// Pressing the Go button causes the search to be
executed.
If
(pageContext.getParameter("Go") != null)
{
String
orderNumber = pageContext.getParameter("SearchOrder");
String
created = pageContext.getParameter("Created");
String
showMyOrders = pageContext.getParameter("MyOrders");
OAApplicationModule
am = pageContext.getApplicationModule(webBean);
// All parameters passed using invokeMethod() must be
serializable.
Serializable[] parameters = { orderNumber, created, showMyOrders };
am.invokeMethod("search", parameters);
// Now forward back to this page so we can implement UI
changes as a
// consequence of the query in processRequest(). NEVER
make UI changes in
// processFormRequest().
pageContext.setForwardURLToCurrentPage(null, // no parameters to pass
true, // retain the
AM
OAWebBeanConstants.ADD_BREAD_CRUMB_NO,
OAWebBeanConstants.IGNORE_MESSAGES
);
}
} // end processFormRequest();
·
This example shows how to pass request parameters using
the setForwardUrl() method, including how to replace a pre-existing parameter
value (in this case, with "X" which would
be used as an "ignore" value in the
target page).
import com.sun.java.util.collections.HashMap;
import oracle.bali.share.util.IntegerUtils;
processFormRequest(OAPageContext
pageContext, OAWebBean webBean)
{ //
Always call this before adding your code
super.processFormRequest(pageContext, webBean);
String
poEvent = pageContext.getParameter("poEvent");
HashMap
params = new HashMap(2);
// Replace the current poEvent request parameter value
with "X"
params.put("poEvent", "X");
// IntegerUtils is a handy utility
params.put("poStep", IntegerUtils.getInteger(5));
pageContext.setForwardURL("OA.jsp?page=/oracle/apps/dem/employee/webui/EmpDetailsPG", // target page
null, // not necessary with
KEEP_MENU_CONTEXT
OAWebBeanConstants.KEEP_MENU_CONTEXT, // no change to menu context
null, // No need to specify since
we're keeping menu context
params, // request parameters
true, // retain the root
application module
OAWebBeanConstants.ADD_BREAD_CRUMB_YES, // display breadcrumbs
OAException.ERROR); // do not forward w/ errors
}
·
Usefull Code
processFormRequest(OAPageContext
pageContext, OAWebBean webBean)
{
// Check to see if the "Go" button was
pressed...
if (pageContext.getParameter("gButton") != null)
{
// Get the search criteria
String
orderNumber = pageContext.getParameter("SearchOrder");
String
created = pageContext.getParameter("Created");
String
showMyOrders = pageContext.getParameter("MyOrders");
OAApplicationModule
am = pageContext.getApplicationModule(webBean);
// All parameters passed using
invokeMethod() must be serializable.
Serializable[] parameters = { orderNumber, created, showMyOrders };
am.invokeMethod("search", parameters);
}
}
Tip:
Whenever you call invokeMethod() on a server-side BC4J component, any
parameters that you pass must be Serializable. The example above illustrates
the invokeMethod() signature that expects all the parameters to be Strings. If
you need to pass other object types, use the version of invokeMethod() that
takes an array of parameter types. For example:
Class[]
parameterTypes = { String.class, Hashtable.class, Number.class ...};
am.invokeMethod("search",
parameters, parameterTypes);
·
Delete Example
This
example illustrates invoking a delete method on a nested application module
associated with a shared region as opposed to the page's root application
module.
processFormRequest(OAPageContext
pageContext, OAWebBean webBean)
{ if (pageContext.getParameter("DeleteYesButton") != null)
{
// User has confirmed that she wants to delete this
purchase order.
// Invoke a method on the AM to set the current row in the
VO and
// call remove() on this row.
String
poHeaderId = pageContext.getParameter("poHeaderId");
Serializable[] parameters = { poHeaderId };
OAApplicationModule
am = pageContext.getApplicationModule(webBean);
am.invokeMethod("delete", parameters);
}
·
Validation Exceptions
Validation
exceptions are thrown from entity objects and view objects for both row and
attribute level validation failures.
oracle.apps.fnd.framework.OAAttrValException - specialization of OAException
used for attribute level validation failures oracle.apps.fnd.framework.OARowValException
- specialization of OAException used for row (entity) level validation failures
The
OA Framework displays error messages to the user as follows: Attribute-level
exceptions are visually indicated on the error item(s) and at the top of the
page Row-level exceptions are visually indicated on the error row(s) and at the
top of the page Page-level exceptions are visually indicated at the top of the
page
·
OAAttrValException
If
any attribute-level validation fails in a view object row or an entity object,
you can throw an OAAttrValException as shown below.
To
instantiate this exception, you must pass the following information: Source
object type OAException.TYP_ENTITY_OBJECT or OAException.TYP_VIEW_OBJECT) Full
entity definition name or view instance name as appropriate
Primary
key of the entity or row Attribute name being validated Attribute value
that failed validation Error message application short name Error
message name
Entity
Object Example
public void setSalary(Number value)
{
if (value != null)
{
// Verify value is > 0
if (value.compareTo(0) <= 0)
{
throw new
OAAttrValException(OAException.TYP_ENTITY_OBJECT, // indicates EO source
getEntityDef().getFullName(), // entity name
getPrimaryKey(), // entity primary key
"Salary", // attribute Name
value, // bad attribute value
"AK", // nessage application short
name
"FWK_TBX_T_EMP_SALARY_REQUIRED"); // message name
}
setAttributeInternal(SALARY, value);
}
} // end setSalary()
View
Row Example
Also
see the Mapping section below for additional information about raising these
exceptions from a view row.
setDescription(String value)
{
if("XXX".equals(value)
{
throw new
OAAttrValException (
OAException.TYP_VIEW_OBJECT, // indicates VO row source
getViewObject().getFullName(), //View Object full usage name
getKey(), // row primary key
"Description", //attribute name
value, // bad attribute value
"FND", //message application short
name
"ATTR_EXCEPTION"); // message name
}
setAttributeInternal("Description", value);
} // end setDescription()
·
OARowValException
If
any row-level validation fails in a view object row or an entity object, you
can throw an OARowValException as shown below.
To
instantiate this exception, you must pass the following information: Full
entity definition name or view instance name as appropriate Primary key of the
entity or row Error message application short name Error message
name
Entity
Object Example
protected void validateEntity()
{
super.validateEntity();
if(attr1!=attr2)
throw new
OARowValException (
getEntityDef().getFullName(), // entity full definition name
getPrimaryKey(),
// entity object primary key
"FND",
// message application short name
"ATTR_EXCEPTION");
// message name
}
View
Row Example
Also
see the Mapping section below for additional information about raising these
exceptions from a view row.
protected void validate()
{
super.validate();
if(attr1!=attr2)
throw new
OARowValException (
getViewObject().getFullName(),//View Object
full usage name
getKey(),
// row primary key
"FND",
// message application short name
"ATTR_EXCEPTION");
// message name
}
To
display the translated text for a static styled text item,
For
example, simply call its getText() method as shown (remember to always use any
web bean accessor signatures that take OAPageContext as a parameter):
OAMessageStyledTextBean
styledTextBean = (OAMessageStyledTextBean)webBean.findIndexedChildRecursive("itemName");
String
itemText = styledTextBean.getText(pageContext);
Partial
Page Rendering:
Step
5: In the application module that contains your application properties view
object, add a method to set the application property values. For example, in
the ToolBox Tutorial Sample Library we have a method called
handlePoApprovaChangeEvent()
that reads the current value of the PPR event source poplist from the page's
underlying entity object, and sets the appropriate property values as shown:
public void handlePoApproveChangeEvent()
{
// Get the special, single-row application properties and
make the first (only) row current.
OAViewObject
vo = (OAViewObject)findViewObject("SampleBrowserPVO1");
OARow
row = (OARow)vo.first();
// Get the value of the view object attribute with the PO
Approval status.
OAViewObject
poVO = (OAViewObject)findViewObject("PurchaseOrderHeadersVO1");
OARow
poRow = (OARow)poVO.getCurrentRow();
String
status = (String)poRow.getAttribute("StatusCode");
// Set the application property values based on the PO
Approval status value.
if ("APPROVED".equals(status))
{
row.setAttribute("PoApproveRender", Boolean.TRUE);
row.setAttribute("PoRejectRender", Boolean.FALSE);
row.setAttribute("PoApproveReadOnly", Boolean.TRUE);
row.setAttribute("PoApproveRequired", "yes");
}
else if ("REJECTED".equals(status))
{
row.setAttribute("PoApproveRender", Boolean.FALSE);
row.setAttribute("PoRejectRender", Boolean.TRUE);
}
else
{
row.setAttribute("PoApproveRender", Boolean.TRUE);
row.setAttribute("PoRejectRender", Boolean.TRUE);
row.setAttribute("PoApproveReadOnly", Boolean.TRUE);
row.setAttribute("PoApproveRequired", "no");
}
} // end
handlePoApproveChangeEvent()
public void processFormRequest(OAPageContext pageContext, OAWebBean webBean)
{
super.processFormRequest(pageContext, webBean);
OAApplicationModule
am =
(OAApplicationModule)pageContext.getApplicationModule(webBean);
String
event = pageContext.getParameter("event");
// If the user changes the value of the po approval
poplist, call the event handler in the AM to set the appropriate
SampleBrowserPVO values.
if ("poApproveChange".equals(event))
{
am.invokeMethod("handlePoApproveChangeEvent");
}
else if ("supplierSelect".equals(event))
{
am.invokeMethod("handleSupplierSelectionEvent");
}
} // end processFormRequest()
·
You can also explicitly display a message box of any type using
the following code in your controller (this particular example displays a
confirmation message after a successful commit).
processFormRequest(OAPageContext
pageContext, OAWebBean webBean)
{
// Get the purchase order number from the request.
String
orderNumber = pageContext.getParameter("headerId");
MessageToken[] tokens = { new MessageToken("PO_NUMBER", orderNumber)};
OAException
message = new OAException("ICX", "FWK_TBX_T_PO_UPDATE_CONFIRM", tokens, OAException.CONFIRMATION, null);
pageContext.putDialogMessage(message);
}
·
Attribute-Level Validation
As
described in Implementing the View in Chapter 3, whenever an HTTP POST request
is issued for a page with updateable values, OA Framework writes those values
back to the underlying view object, which in turn writes the values to the
underlying entity object(s) by calling its setters.
Since
each attribute's validation should be added to its setters (see the ToolBox
PurchaseOrderHeaderEOImpl's
setHeaderId() method below as an example), the process of calling the entity
object setters executes attribute-level validation.
If
you specify any declarative validation (for example, you indicate in the
JDeveloper Entity Object Wizard that an attribute cannot be updated after it is
saved), this validation is performed in the setAttributeInternal() method that
you should call after executing your own validation logic. It is also checked
in validateEntity().
/*
*
Sets the PO Header Id.
*
Business Rules:
*
Required; cannot be null.
*
Cannot be updated on a committed row.
*/
public void setHeaderId(Number value)
{
// BC4J validates that this can be updated only on a new
line. This
// adds the additional check of only allowing an update if
the value
// is null to prevent changes while the object is in
memory.
If
(getHeaderId() != null)
{
throw new
OAAttrValException(OAException.TYP_ENTITY_OBJECT,
getEntityDef().getFullName(), // EO name
getPrimaryKey(), // EO PK
"HeaderId", // Attribute Name
value, // Attribute value
"ICX", // Message product short name
"DEBUG -- need message name"); // Message name
}
if (value != null)
{
OADBTransaction
transaction = (OADBTransaction)getOADBTransaction();
// findByPrimaryKey() is guaranteed to first check the
entity cache, then check
// the database. This is an appropriate use of this method
because finding a
// match would be the exception rather than the rule so
we're not worried
// about pulling entities into the middle tier.
Object[] headerKey = {value};
EntityDefImpl
hdrDef = PurchaseOrderHeaderEOImpl.getDefinitionObject();
PurchaseOrderHeaderEOImpl
hdrEO = (PurchaseOrderHeaderEOImpl)hdrDef.findByPrimaryKey(transaction, new Key(headerKey));
if (hdrEO != null)
{
throw new
OAAttrValException(OAException.TYP_ENTITY_OBJECT,
getEntityDef().getFullName(), // EO name
getPrimaryKey(), // EO PK 650
"HeaderId", // Attribute Name
value, // Attribute value
"ICX", // Message product short name
"FWK_TBX_T_PO_ID_UNIQUE"); // Message name
}
}
// Executes declarative validation, and finally sets the
new value.
setAttributeInternal(HEADERID, value);
} // end setHeaderId()
Different
"Set" Methods
There
are several different ways of setting values within an entity object. In your
code, you most often call set<AttributeName>() and
setAttributeInternal(). See Entity Object and View Object Attribute Setters for
additional information about all the possible options.
·
Cross-Attribute Validation
Any
validation involving two or more attribute values on the entity should be
included in the validateEntity() method; do not include any
cross-attribute validation in an individual attribute's setter since attribute
values can be set in any (random) order.
You
may reference attribute values from referenced entities in your attribute-level
validation.
Entity
Validation
Whenever
OA Framework sets entity object values during an HTTP POST processing cycle, it
always validates any view object rows that it touches, which in turn calls
validateEntity() on the underlying entity object(s). Furthermore,
entities are validated again prior to posting (up to 10 times in a
composition).
Any
logic which operates at the row level -- and is not particularly sensitive to
being called repeatedly -- should be included in the validateEntity()
method.
The
following PurchaseOrderHeaderEOImpl code illustrates typical entity-level
validation:
/*
*
Performs entity-level validation including cross-attribute validation that
*
is not appropriately performed in a single attribute setter.
*/
protected void validateEntity()
{
super.validateEntity();
// If our supplier value has changed, verify that the
order is in an "IN_PROCESS"
// or "REJECTED" state. Changes to the supplier
in any other state are disallowed.
// Note that these checks for supplier and site are both
performed here
// because they are doing cross-attribute validation.
String
status = getStatusCode();
if ((("APPROVED")Equals(status)) || ("COMPLETED"Equals(status)))
{
// Start by getting the original value and comparing it to
the current
// value. Changes at this point are invalid.
Number
oldSupplierId = (Number)getPostedAttribute(SUPPLIERID);
Number
currentSupplierId = getSupplierId();
if (oldSupplierId.compareTo(currentSupplierId) != 0)
{
throw new OAAttrValException(OAException.TYP_ENTITY_OBJECT,
getEntityDef().getFullName(), // EO name
getPrimaryKey(), // EO PK
"SupplierId", // Attribute Name
currentSupplierId, // Attribute value
"ICX", // Message product short name
"FWK_TBX_T_PO_SUPPLIER_NOUPDATE"); // Message name
}
// If our supplier site has changed, verify that the order
is in an "IN_PROCESS"
// state. Changes to the supplier site in any other state
are disallowed.
Number
oldSiteId = (Number)getPostedAttribute(SUPPLIERSITEID);
Number
currentSiteId = getSupplierSiteId();
if (oldSiteId.compareTo(currentSiteId) != 0)
{
throw new
OAAttrValException(OAException.TYP_ENTITY_OBJECT,
getEntityDef().getFullName(), // EO name
getPrimaryKey(), // EO PK
"SupplierId", // Attribute Name
currentSiteId, // Attribute value
"ICX", // Message product short name
"FWK_TBX_T_PO_SUPSITE_NOUPDATE"); // Message name
}
}
// Verify that our supplier site is valid for the supplier
and make sure it is an active "Purchasing" site.
SupplierEntityExpert
supplierExpert = SupplierEOImpl.getSupplierEntityExpert(getOADBTransaction());
if (!(supplierExpert.isSiteValidForPurchasing(getSupplierId(),
getSupplierSiteId())))
{
throw new
OAAttrValException(OAException.TYP_ENTITY_OBJECT,
getEntityDef().getFullName(), // EO name
getPrimaryKey(), // EO PK
"SupplierSiteId", // Attribute Name
getSupplierSiteId(), // Attribute value
"ICX", // Message product short name
"FWK_TBX_T_PO_SUPSITE_INVALID"); // Message name
}
} // end validateEntity();
·
Calling PL/SQL Functions and Procedures
Even
when writing Java entity objects, you might need to call PL/SQL functions or
procedures.
Note:
Do not use JDBC to perform simple SQL statements. Always leverage view objects
for this purpose. If possible, you should define the view object declaratively.
In
general, to invoke a stored procedure from within an entity object or an
application module, you need to:
1.
Create a JDBC CallableStatement with the PL/SQL block containing the stored
procedure invocation
2.
Bind any variables.
3.
Execute the statement.
4.
Optionally retrieve the values of any OUT parameters.
5.
Close the statement.
The
following application module example shows how to create and use a
CallableStatement in an entity object.
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Types;
OADBTransaction
txn = getDBTransaction();
CallableStatement
cs = txn.createCallableStatement("begin
dbms_application_info.set_module(:1, :2); end;");
try
{
cs.setString(1, module);
cs.setString(2, action);
cs.execute();
cs.close();
}
catch (SQLException sqle)
{
try { cs.close } catch (Exception(e) {}
throw OAException.wrapperException(sqle);
}
This
example illustrates an OUT parameter:
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Types;
import oracle.jdbc.driver.OracleCallableStatement;
DBTransaction
txn = getDBTransaction();
String
sql = "BEGIN :1 :=
FND_MESSAGE.GET; END;";
CallableStatement
cs = txn.createCallableStatement(sql, 1);
String
messageBuffer = "";
try
{
((OracleCallableStatement)cs.registerOutParameter(1, Types.VARCHAR, 0, 2000);
cs.execute();
messageBuffer
= cs.getString(1);
cs.close();
}
catch (SQLException sqle)
{
try { cs.close } catch (Exception(e) {}
throw OAException.wrapperException(sqle);
}
No comments:
Post a Comment