ADF Application Module (AM) properties and Performance Tuning:

Performance Tuning:
Programatically created AM Instances must be released after the usage.
ApplicationModule am = Configuration.createRootApplicationModule(amDefName, configName);
//logic
if(am!=null){
Configuration.releaseRootApplicationModule(am, true);
}

AM Properties:

  • The No of AMs that should be kept available during Noraml/ light use: jbo.ampool.minavailablesize
  • The No of AMs that should be kept available during High use: jbo.ampool.maxavailablesize
    [Recommended to keep it 20% more than Noraml usage value]
  • AM Pool clean up frequency is decided by: jbo.ampool.monitorsleepinterval (Default 600000ms or 10 minutes)
  • AM Pool Max inactive age of AM instancce: jbo.ampool.maxinactiveage (Default 600000ms or 10 minutes)
  • AM pool monitor removes all unused AM instances which have been living more than 1 hour: jbo.ampool.timetolive
    If the value set to -1 then removal of AM based on this property will be prevented.
  • property ‘jbo.ampool.maxinactiveage’ will remove the number of Inactive AM instances above the value of ‘jbo.ampool.minavailablesize’
    [if the ‘jbo.ampool.minavailablesize’ value is 10 & assume there are 25 current inactive AM instances, then only 15 inactive AM instances
    will be cleared by AM Pool Monitor]
  • property ‘jbo.ampool.timetolive’ if not set to -1, then it removes all the inactive AM instances (more than 1 hr) irrespective of the
    proeprty ‘jbo.ampool.minavailablesize’

FetchSize: Decides No of records read from DB in one round trip.
Recommended The value of FetchSize should be = Range Size of Interator(defined in page definition) + 3
The Max value of Fetchsize = Max value of Iterator size.
For UI bound View Objects keep fetchsize less than 30.

Maximum FetchSize:  Total no of records that a VO can retrieve from DB.
RangeSize: Decides no of records read into middle tier for a single data access.
——————————-
Popup: [use property contentDelivery=”lazyUncached” in a case that when you open popup enterred values,
click on cancel and reopen popup. Generally the previously entered values will be shown though not submitted.
To get fields cleared every time click on cancel button use proeprty  contentDelivery=”lazyUncached” for a popup].
Every time you raise the popup, lazyUncached will be in place an the data will be fetched from the DB.
——————————-
When you Access a page from browser:
Server recieves the request, Request is intercepted by ADF BindingFilter and Initialses BindingContext
[which is runtime represenation of DataBindings.cpx]

 

Advertisements

ADF Lifecycle & Immediate, Auto Submit, Partial Submit properties behaviour

ADF Cycle is and extended version of JSF Lifecycle. For each request from client to server, application invokes ADF Page lifecycle.

Below are the phases of ADF Page Life Cycle.

1)
Restore View: The component tree for the page will be restored. page URL will be passed to bindingContext object  which will find its page definition file.
Init Context: BindingContainer object will be initialized (which is runtime representation for pageDefinition file).
Prepare Model: Methods in Executables section will be executed whose refresh property set to: ‘Prepare Model’.
And also Input parameters will be applied/evaluated.

2)
Apply Request Values: Input values will be stored to temporary location and initialized.

3)
Process Validation: The input values will be converted to underlying data types [e.g.: string to date] and validations will be applied.

4)
Update Model values: The local values (temp) will be discarded and updated in the Model.
Validate Model updates: updated model values will be validated. (Validation happens on updated values at EO level)

5)
Invoke Application: Action bindings will be executed in this phase.
Commit Metadata: Changes to the runtime metadata will be committed. Also here in this phase runtime changes will be stored using MDS (Meta Data Service)

6)
Prepare Render/ Render Model: Binding Container will be refreshed (So that it allows for any changes that may have occurred in the Apply Request Values or Validation phases).
Render Response: Finally the page will be appeared with updated values.

(If the page is navigating to another page then in this step the phases will be ‘Init context’, ‘Prepare Model’, ‘Prepare Render’ ‘Render Response’)

Refresh Condition: For Executables like Iterators, methods if the default ‘Refresh’ condition is ‘Deferred’ which means only the required will executed at ‘Render Response’ phase which have UI Dependency.
If you set Refresh property forcefully to ‘Prepare Model’ or ‘PrepareRender’ then always that method will be executed during that phase. (irrespective of UI dependency)

First time page load: When the page is loaded for the first time, it’ll go through first phase which is ‘Restore View’, in this phase the view state of the current page will be checked and as the page is loaded for the first time, there won’t be any view state. If there is no view state, then it skips next phases and directly enters ‘Render Response’ state, as it is not required to validate/update anything. From the next subsequent requests from this page, it’ll go thought first phase ‘restore view’ where the current view state will be compared with the previous view state, and if there is a difference between view states then it’ll go though all the phases. Otherwise it’ll again directly enters Render Response phase.

Immediate:

On Command Button: [If you set for Command button it skips validations]

  • When Immediate=”true” property is set for a command button, it means that the action/action listener for that button will be executed immediately. (generally if you won’t set, then all the input fields and other component values present in the page will be validated and updated through multiple phase of Life cycle).
  • So by keeping the Immediate property value to ‘true’ then action/actionListener will be invoked during second phase (Apply request values) and it skips all other phases (3,4,5) and only ‘Restore view’, ‘Apply Request Values’, ‘Render Response’ phases will be invoked.
  • A general real time example would be setting ‘Immediate’ property to true for ‘Cancel’ button for a form. As when cancel is invoked actually we won’t bother about validation of entered input values.

On Input Component:

  • If you set the Immediate property to Input field component, then what happens? One line answer would be the local format conversion and validation will happen during second phase ‘Apply Request Values’ instead in the third phase ‘Process Validation’ to make the values available for button’s action/actionListener methods whose Immediate property is true [those methods executed during second phase when Immediate is true for buttons, and values of input fields will not available by then in this phase if immediate for input fields is not set to True].
  •  Let’s take InputA whose autoSubmit property is not set to ‘true’, CommandBtnB whose Immediate property is set to ‘true’. Enter some value into InputA and click on CommandBtnB then as Immediate property is set action Listener will be invoked during second phase ‘Apply Request Values’ and it skips the next steps process validation, Modal Updates, Invoke Application. Suppose if you want to get the value of InputA in the actionListener, it will not be available by then as InputA value will be converted& validated in the Third phases ‘Process Vlidation’ which is getting skipped because of Immediate property on ComandBtnB.  When you give ‘Immediate’ property to true for InputA, then that component value is converted and validated during the second phase ‘Apply Request Values’. So the entered value of InputA will be available in the actionListener method when Immediate property for InputA is set to ‘true’.
  • This property is Available to both Command Button and Input field components.

Auto Submit:

  • When AutoSubmit=”true” property is set for an input text field, then only that component will go through the Life Cycle event when curser is removed/ tab out from that input text field. Though other fields have values entered and which are not valid, it won’t throw any error.
  • So when this property is set for a field, that filed value will be submitted, validated and updated in the Model and finally component will be refreshed.
  • If you set the partialTriggers property for other components pointing to this command component whose AutoSubmit is true then those properties will also under go validation and re render phases.
  • E.g.1 : InputA whose autoSubmit is ‘true’ & InputB which has required validation as ‘true’. Now on entering value to InputA and tab out, will not give any validation error on InputB though the value of InputB is null.
  • E.g.2 : InputA whose autoSubmit is ‘true’ & InputB which has required validation as ‘true’ & partialTriggers property point to InputA comp Id. Now on entering value to InputA and tab out, will give validation error on InputB. 
  • This property is Available only for Input components to get validated and post their data to model. This property is NOT available to command button component.

ValueChangeListener:

  • If you want to call a method and execute some java code when the value of a filed is changed, then you just need to set the ‘ValueChangeListener’ property’s value for that field to required method.
  • ValueChangeListener event is triggered during the 3rd phase of ADF Life cycle (Process Validations phase)

Partial Submit:  [To avoid full page refresh]

  • If you set PartialSubmit property to a command button in form then entire form will be submitted. All the fields will under go validations. And entire page will NOT be refreshed.
  • If don’t set this property value to ‘true’ then entire page will be refreshed. Instead by setting this property we can avoid refresh of the page. If you want to refresh any component then you can do it by using partialTriggers property.
  • This property is Available to only Command Button. And is NOT Available to Input field components as similar property to it, autoSubmit is available to them.

PartialSubmit vs AutoSubmit:

  • PartialSubmit property will be given to command buttons. Which generally used to submit the form and to avoid full page refresh after that.
  • AutoSubmit property will be given to Input component which will validate, model update & re render that component on tab out from that component. It doesn’t care about other components.
  • Now similarity is If you set these properties to respective components [PartialSubmit to command button, auto submit to Input text], then these will refresh the other components which uses partialTriggers property pointing these component Ids.
  • So you can also call autoSubmit for input component as partial submit as it does the same functionality.

 

lifecycle.png

 

More info: http://krishnaprathi.blogspot.in/2015/08/adf-life-cycle.html

 

 

JPA vs ADF-BC(BC4J)

In ADF, for creating Business services related to DB we generally use ADF – BC (EO, VO, AM), but we can also use JPA(Java Persistence API) Entities. Which option to choose is completely your choice as there won’t be any difference if you create data controls out of them in terms of performance. But you can note few points that ADF-BC provides default List of Values and validations options. If you are familiar with using Hibernate (But not with ADF-BC) then you are good to go with using JPA Entities.

JPA Entity:

JPA

You can find the below sample JPA entity created for Departments table.


package model;

import java.io.Serializable;

import java.util.List;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;

@Entity
@NamedQueries({ @NamedQuery(name = "Departments.findAll", query = "select o from Departments o") })
public class Departments implements Serializable {
private static final long serialVersionUID = -1771169464233198257L;

@Id
@Column(name = "DEPARTMENT_ID", nullable = false)
private Integer departmentId;

@Column(name = "DEPARTMENT_NAME", nullable = false, length = 30)
private String departmentName;

@Column(name = "LOCATION_ID")
private Integer locationId;

@ManyToOne
@JoinColumn(name = "MANAGER_ID")
private Employees employees1;

@OneToMany(mappedBy = "departments", cascade = { CascadeType.PERSIST, CascadeType.MERGE })
private List<Employees> employeesList1;

public Departments() {
}

public Departments(Integer departmentId, String departmentName, Integer locationId, Employees employees1) {
this.departmentId = departmentId;
this.departmentName = departmentName;
this.locationId = locationId;
this.employees1 = employees1;
}

public Integer getDepartmentId() {
return departmentId;
}

public void setDepartmentId(Integer departmentId) {
this.departmentId = departmentId;
}

public String getDepartmentName() {
return departmentName;
}

public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}

public Integer getLocationId() {
return locationId;
}

public void setLocationId(Integer locationId) {
this.locationId = locationId;
}

&nbsp;

public Employees getEmployees1() {
return employees1;
}

public void setEmployees1(Employees employees1) {
this.employees1 = employees1;
}

public List<Employees> getEmployeesList1() {
return employeesList1;
}

public void setEmployeesList1(List<Employees> employeesList1) {
this.employeesList1 = employeesList1;
}

public Employees addEmployees(Employees employees) {
getEmployeesList1().add(employees);
employees.setDepartments(this);
return employees;
}

public Employees removeEmployees(Employees employees) {
getEmployeesList1().remove(employees);
employees.setDepartments(null);
return employees;
}
}

 

Applying ViewCriteria dynamically

If you want to Apply ViewCriteria by passing a parameter and then execute the VO query the following methods you can choose based on the requirement.

1) Getting VO from AppModule Instance Programmatically and Applying VC on it: Simply create a java class and register it as a managed bean and then inside the method get the AppModule instance and from which get VO  then apply VC and execute. [This method is not preferable as this might lead to creation of multiple AppModule instances]. shortcut to get the skeleton code is type bc4j and then press Ctrl+Enter inside java method.
Note: You need to close the AppModule instance connection at the end. Generally this will be placed in the finally section.

ApplicationModule am = null;
String amDef = &quot;test.TestModule&quot;;
String config = &quot;TestModuleLocal&quot;;
am = Configuration.createRootApplicationModule(amDef, config);
ViewObject vo = am.findViewObject(&quot;TestView&quot;);
// Work with your appmodule and view object here [Apply ViewCteria and execute VO]
finally {
if (null != am) {
Configuration.releaseRootApplicationModule(am, true);
am = null;
}
}

2.  Getting VO from Bindings programmatically and Applying VC on it: Simply create a java class and register it as a managed bean and then inside the method get the Iterator bindings [bindings should present in the page from which method is getting called] from which get VO then apply VC and execute. This is better method than previous method but still not much code efficient.


BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding itrBind = (DCIteratorBinding)bindings.get(&quot;EmployeesView1Iterator&quot;);
ViewObject empVO = itrBind.getViewObject();
empVO.clearCache();
ViewCriteriaManager vcm = empVO.getViewCriteriaManager();
ViewCriteria vc = vcm.getViewCriteria(&quot;EmployeesViewCriteria&quot;);
empVO.applyViewCriteria(vc);
empVO.setNamedWhereClauseParam(&quot;DeptId&quot;, 100);
empVO.executeQuery();

 

3. Create a method in AppModuleImpl class in which apply VC on VO and execute it before calling the page using Taskflow:

Generate AppModuleImpl class and then create a method inside the class and once coding is done then go to Client Interface of AppModule and move the created method to the client interface, so that it is visible in the data controls section of the AppModule and can be used in Taskflow or can be used in JSPX page also.

public void applyVC(){
ViewObject empVO = this.getEmployeesView1();
ViewCriteriaManager vcm = empVO.getViewCriteriaManager();
ViewCriteria vc = vcm.getViewCriteria(&quot;EmployeesViewCriteria&quot;);
empVO.applyViewCriteria(vc);
empVO.setNamedWhereClauseParam(&quot;DpetId&quot;, 100);
empVO.executeQuery();
}

Now all we need to do is execute the above method using Taskflow before the page is being called as we have to apply VC on VO and the results we have to display on the page.

 

 

 

‘RangeSize’property in ADF

If you want to get all the rows and show in a table or Iterator you need to set the property ‘RangeSize = -1‘ for the VO Iterator in the binding section and also you have to set the value of ‘rows’ property for the Table or Iterator being used to EL expression which points to ‘rangesize‘ of Iterator.

Eg:

 rows="#{bindings.EmployeesView1.rangeSize}"

By default the VO Iterator rows property will be set to 25 that means the rows from DB are fetched in a batches of 25. When you scroll down the table for every 25 rows you can see some delay and also a message showing like fetching rows. It is good to fetch and display only the rows how many are needed to show instead of fetching all the rows at once. If the table row count is small then you can set RangeSize = -1.

3

 

2

1

 

 

 

 

 

 

 

 

 

af:table component structure in ADF

<af:table value="#{bindings.treename.collectionModel}"  var="row"
varStatus="vs">
<af:column headerText = "#{bindings.treename.hints.FirstName.label}"
sortable="true" filterable="true"
sortproperty = "#{bindings.treename.hints.FirstName.name}"
Editable tab- <af:inputText value = "#{row.bindings.FirstName.inputValue}" />
Readonly tab- <af:outputText value = "#{row.FirstName}" />
</af:column>

<af:column headerText = "#{bindings.treename.hints.departmentId.label}"
sortable="true" filterable="true"
sortproperty = #{bindings.treename.hints.departmentId.name}
<f:facet name="filter">
<af:inputDate value="#{vs.filterCriteria.HireDate}"/>
</f:facet>
Editable tab- <af:inputDate value="#{row.bindings.HireDate.inputValue}" />
Read only tab-  <af:outputText value="#{row.HireDate}" >
</af:column>

<af:column headerText = "#{bindings.treename.hints.departmentId.label}"
sortable="true" filterable="true"
sortproperty = #{bindings.treename.hints.departmentId.name}
<f:facet name="filter">
<af:selectOneChoice value="#{vs.filterCriteria.DepartmentId}"
inlineStyle="width:100px" autoSubmit="true">
<af:forEach items="#{bindings.DepartmentsView1.rangeSet}"
var="listRow">
<f:selectItem itemValue="#{listRow.DepartmentId}"
itemLabel="#{listRow.DepartmentName}"/>
</af:forEach>
</af:selectOneChoice>
</f:facet>
Editable tab- <af:inputText value="#{row.bindings.DepartmentId.inputValue}">
Read only tab- <af:outputText value="#{row.DepartmentId}">
</af:column>
</af:table>

 

Result: This code displayes the updatable/read only table. In the top input text as default filter for all columns and date or LOV or customized component for the columns which use <f:facet name =”filter” />. The default implementation of the table filter cell renderer is an af:inputText field.

Front end display will be like below:

table

Note: If you want to add a filter like we have done it here for Department Id column you need place the filter component in the filter facet of a column. Here we have added LOV filter (SelectOneChoice) and inside that we have placed foreach to which bindings we’ve given for DepartmentsVO . There is no need to be any relationship between employees and departments to create in adf. Just Department Id should present in both VOs that is enough. And your page should contain both the VOs tree bindings. No need to do any child relationship like that just drag two VOs datacontrols as tree bindings to the page.

BPEL Creation with DB Adapter usage and consuming it in ADF application as webservice

Story of Project:  We are going to pass the employee id from the ADF web application to SOA BPEL, which fetches more details of an employee from the database and returns them to ADF which are then shown on the ADF page. Tool used for this project is JDev 12.1.3

This Post includes the following

  • SOA Application creation
  • DB Adapter Configuration (for connecting to Database)
  • BPEL Creation (WSDL generation)
  • ADF Application Creation
  • Consuming the WSDL and create data controls
  • Test from the ADF Application

SOA Application Cretion:

Create a SOA Application with name ‘SOA_fetchDBdataApp’

Snap2

Create a Project ‘FetchEmpDataProj’ and select the Composite With BPEL Process while project creation

Snap3

Create a BPEL with the name ‘fetchEmpDetailsBPEL’ and select Template as Synchronous BPEL Process and then click OK

Snap4

The BPEL will be created with receiveInput and replyOutput as default schema components.

Snap17

Navigate to Databases tab and create a new Database Connection with the name with which we created in console

Snap21

Now Navigate the Database Adapter to the bpel flow

Note: Before proceeding from this step you should configure your DB Adapter in the console first. Please go through the DB Adapter configuration steps given at the end of the post.

Snap22

Give the dbreference name and click on Next

Snap23

Click on Search Icon and select the created Database Connection and click on Copy Connection

Snap24

Check only Select check box as we are doing only select operation in this example and click on Next

Snap25

Click on Query button to select the existing table in DB and move it to the selected area by clicking on right single row.

Snap26

Now remove the unneccessary  relationships by selecting each and clicking on remove button

Snap27

Click on Add button for creating a bind variable to the query which basically used to pass a variable dynamically. Generally to apply where condition its been used

Snap28

Click on Edit button beside to query click on Add button and then Check the Parameter option and select the created parameter ’empId’ from dropdown

Snap29

You can observer the modified SQL query

Snap30

Click on Next and finally Click on Finish

Snap31

Drag and drop the Invoke BPEL Constructor below to input and map to the dbreference

Snap34

Configure the Input and Output for this DB adapter. Click on + symbol and give names to the input and output variables.

Snap36

Now drag and drop the Assign Constructor below to input

Snap37

Double click on Assign which opens a Edit Assign popup in which map the input variable value to input of database adapter and click on Apply and OK

Snap38

Now assign the output of DB Adapter to the reply output of BPEL.  For that use Assign constructor.  Here the output of DB adapter has many fields so create as many outputs in the schema also to map from DB Output to BPEL output.

Open the schema file (.xsd file) and add the the required inputs and outputs in its source view

Snap35

Now drag and drop the Assign Constructor to below to DB adapter to  map the output of DB Adapter to BPEL output.

Snap40

And then double click on it for mapping. a popup window opens where map the output of DB adapter to output variable of BPEL. Map all fields directly. There is field named ‘EmpName’ at the output section for which the input should be from two fields (firstname, lastname) so drag and drop the Expression icon to the output field ‘EmpName’

Snap41

On Drag of Expression onto field a popup opens where click on concat and then click on first name and last name. The format should be concat(val1, val2) which combines the output of these two fields  and stores in EmpName field.

Snap42

Finally click on Apply and OK

Snap43

Deployment:

Save the project and right click on project-> Deploy

Snap44

Click on Deploy to Application Server.

Check the box Overwrite any existing composites with the same revision ID. which basically useful for generating same wsdl url for every deployment. Click on Next

Snap46

Click on Integrated weblogic server. Here you can add any server and deploy to that.

Select the domain (Default Server) and click on Finish which finishes the deployment.

Snap47

Open Enterprise Manager on browser. Select the project and click on Test

Snap51

Copy the WSDL to clipboard. Give the input as 102 and click on Test Web Service

Snap52

It opens the Response tab with the result. you can Launch Flow Trace to view the complete step by step response

Snap63

ADF Application Creation:

Create ADF Fusion Web Application ‘ADF_SOA_App’ keep the default names for the project.

Snap64

Create a custom project ‘consumeEmpWS’

Snap65

Right click on the created project -> New -> Select Web Service Client and Proxy

Snap66

Paste the copied WSDL URL in the WSDL Document URL field and click on Next and proceed by keeping default settings and Finish.

Right click on the WSDL and click on Test Web Service which opens a Http Analyzer.

Snap69

Give the input and click on Send Request which returns Response at right side.

Snap70

Now right click on the WSDL file and click on Generate Data Controls which generates the data controls which can be used on in the ADF page.

Snap72

You can see the updated data Controls Section

Snap73

Now Create a jspx page under View Controller Project.

Snap74

Check the JSP XML and name it ‘getDetails.jspx’

Snap79

Go to Source code of the page and then drag and drop the web service data controls on to the center facet of the page and select the option as ADF Parameter Form.

Snap76

Now right click on the page and click on Run

Snap77

In the page pass the Employee Id and you can see the more details which are fetched through BPEL and displayed on the page.

Snap78

DB Adapter Configuration:

This includes creation of Data Source, DB Adapter Outbound Connection Creation, mapping created Outbound Connection Creation with created data source.

Open Console and Create Data Source for connecting to the database.

Snap11

Create a New Generic Data Source

Snap13

Give the connection name as ‘HRConn’ and JNDI name as ‘jdbc/HRConnDS’ for the data source

Snap14

Give the Database Connection details and click on Next

Snap15

Click on Test Configuration which shows a success message for the successful connection. Click on Finish.

Snap16

Click on DbAdapter from the deployments

Snap5

Click on Configuration -> Outbound Connection pools -> New and then create an outbound connection

Snap7

Click on Next

Snap8

Give the JNDI name for the Outbound connection as eis/DB/HRConn

Snap20

Click on the Created Outbound Connection Pool

Snap9

Give the property  value for XA Data Source name as with earlier created DataSource jndi name ‘jdbc/HRConnDS’ and click on save

Snap61

Now again go to deployments and select DbAdapter and click on update which ends the DB Adapter Configuration.

Snap62