Monday, September 12, 2016

Modify Row hints on the fly

Scenario - Recently we had a use case where Same View Object is used in 3 different places and the label value of a field should be dynamically calculated based on the context.

Eg: Lets say, In Employee and Departments table,
the in the Employee Entry Form should say

Engineer Name : <Input Text>
HR Name: <Input Text>
GM Name: <Input Text>

based on the chosen Employee type.

Note: the above is just a sample to explain the scenario not the exact use case.

Solution- It can be implemented by EL expressions etc, but it may get clumsy and had to be done in multiple places as employee type grows.

Instead we modified label hints on the fly.

How to do it?

Override the createViewRowAttrHints in ViewRowImpl

    @Override
    protected ViewRowAttrHintsImpl createViewRowAttrHints(AttributeDefImpl attrDef) {
      return new CustomRowAttrHintsImpl(attrDef, this);
    }

Override getLabel in CustomRowAttrHintsImpl as shown below.
You could see there are options to override other hints such as Tooltip,DisplayHeight etc


 import oracle.jbo.AttributeHints;  
 import oracle.jbo.LocaleContext;  
 import oracle.jbo.server.AttributeDefImpl;  
 import oracle.jbo.server.ViewRowAttrHintsImpl;  
 import oracle.jbo.server.ViewRowImpl;  
 public class CustomRowAttrHintsImpl extends ViewRowAttrHintsImpl {  
   public CustomRowAttrHintsImpl(AttributeDefImpl attributeDefImpl, ViewRowImpl viewRowImpl) {  
     super(attributeDefImpl, viewRowImpl);  
   }  
   public CustomRowAttrHintsImpl() {  
     super();  
   }  
   @Override   
    public String getLabel(LocaleContext locale) {   
     if (("EmployeeName").equalsIgnoreCase(getViewAttributeDef().getName())) {   
      String EmployeeCode= (String)getViewRow().getAttribute("EmployeeCode");   
      if (EmployeeCode!= null || !EmployeeCode.equalsIgnoreCase("") || EmployeeCode.equalsIgnoreCase("IT"))   
       return "Engineer";   
      else  if (EmployeeCode.equalsIgnoreCase("HR"))  
       return "HR";   
     }   
     return super.getLabel(locale);   
    }  
   @Override   
    public String getTooltip(LocaleContext locale) {   
     return super.getTooltip(locale);   
    }  
   @Override   
    public String isAutoSubmit(LocaleContext locale) {   
     return super.getTooltip(locale);   
    }  
   @Override   
    public String getDisplayHeight(LocaleContext locale) {   
     return super.getTooltip(locale);   
    }  
   @Override   
    public String getDisplayWidth(LocaleContext locale) {   
     return super.getTooltip(locale);   
    }  
   @Override   
    public String getDisplayHint(LocaleContext locale) {   
     return super.getTooltip(locale);   
    }  
 }  

Hope it helps.. :-)

Wednesday, August 24, 2016

Insert rows at last Index with line numbers

Scenario - In master-child related tables, insert rows in Child Table at the last index  and add line number accordingly.

Solution -

Case 1:
In case you want to persist the line number below code in the child Table's VOImpl works -

    @Override
    public void insertRow(Row row) {
        last();
        next();
        row.setAttribute("LineNumber", getEstimatedRowCount() + 1);
     super.insertRow(row);
    }

Case 2:
If line numbers are just to be used for display purpose, Then in af:Table/af:Iterator
use the varStatus feild to a variable, say rs, and use 

  <af:column headerText="Line Number" id="c25" >

   <af:outputText value="#{rs.index+1}"  id="ot21"/>

</af:column>


Hope it helps :-)

Sunday, July 3, 2016

ADF Performance Analyzer - Part 1

Scenario - In  enterprise level apps there are multiple developers involved in creating different modules and an
  • Untuned select query 
Eg : Select DISTINCT(EMPLOYEE_NAME) from Employees;
Assume Employee table as over 500,000 rows.
  •  Large fetch of rows
Eg :  Table is set to scrollable  - end user scrolls to bottom of table which fetchs all rows  into memory
  •  Frequent inner queries in Groovy.
Eg : A Groovy expression  which queries multiple tables to get the data is set on a Transient attribute and refreshes frequently. 

can bring down the performance of the applications..

Note - Above mentioned scenarios are not the only cases of performance issues but most important ones.Other scenarios will be covered in next post.

So instead of figuring out the performance bottlenecks once the application is live, It is always good to capture such memory intensive spots in Testing or UAT Phases.

Solution -

Built an ADF Analyzer to monitor such events based on following architecture -


What are features available?
1) Metrics capture can be turned ON / OFF easily.
2) Configurations page to customize the definitions of the parameters used in monitors.

3) DashBoard view 


4) Long running queries -

5) Large Fetches


6) Query Frequency -


















7) Migration function, which will change the extension of current view,entity and app module objects to ADFAnalyzer's extension classes.

8) Metrics capture is light weight and adds a very minimal overhead to your application's performance.

9) In next version, AppModule metrics such as slow activations/passivations, app module performance over long periods of time will be added to the analyzer.   

Note - ADFAnalyzer engine is tested with couple of enterprise level apps so far and outcome is positive. Currently am testing it under complex scenarios, once complete,
I will share the download link and instructions to set it up in your applications.


 Hope it helps :-)


Wednesday, June 29, 2016

Scroll to Fetch with Taskflows

Scenario - Recently we had a requirement to load more than 20 Taskflows in a page and off course the page took over a minute to load.

So designed a way to load task flows lazily based on user scroll, just like how data is fetched in
social websites..

Here is how  the final output looked like -

As you can see, 2 taskflows loads on  page load and next 2 taskflows loads as user scrolls through the page.

This basically reduces the load time of the page to half :-).

How to do it?



Step 1) Few modifications  made to  taskflows that needs to be lazy fetched-




Now we have a taskflows which renders activity when input parameter LazyLoadTF  set to  "TRUE"

Step 2) Here is how the entire flow works -



























-> All the taskflow's input parameter in the  page binding are mapped to a hashmap.
-> Once user scrolls through the window more than 95 percent, a server listener callback changes the next taskflow's input parameter to true.
-> All taskflows are set to refresh ifneeded, so change in input parameter refreshes the taskflow and the actual activity is  rendered this time.
-> Once complete, the server listener issues a notifyComplete to client side javascript using ExtendedServiceKit. The cycle continues as and when user scroll reaches more than 95 percent.

We can build many flavors of this flow,  like to show loading screen while taskflow load or refresh using a contextual event etc.

Workspace used in sample->  ScrollToFetch GitHub, It requires connection to HR Schema.

Hope it helps..:-)












Tuesday, May 17, 2016

Wild card permissions in Jazn-Data.xml

When there are multiple secured resources  in an application it might be a little tough to handle all the permissions in Jazn-data.xml because of its growing size.

There is an easy way to fix this problem. You can make use of wild card feature of OPSS.

Eg: Lets say you have Taskflow1.xml, Taskflow2.xml, Taskflow3.xml, Taskflow4.xml and Taskflow5.xml  used in your application and all of them need to have authenticated role.

Instead of assigning permissions to each of them one by one, you can add a wildcard permission under desired role in source mode of jazn-data.xml -
<permission>        <class>oracle.adf.controller.security.TaskFlowPermission</class>
<name>/WEB-INF/.*</name>
<actions>view</actions>
</permission>

You can use similar approach to any valid resource available.

Hope it helps:-)

ADF Taskflow Transactions Management and Datacontrol scope - Part 3

In our previous post we had discussions about how DataControl Scopes and multiple Application Module Transactions interact with each other.

Lets use the same application used in previous post and discuss more about Taskflow Transactions Management

What is Transaction management in taskflow?
Transactions are managed by the Application Modules, As an application grows we might want to use multiple data controls from different application modules in a single view.

Eg : If we use datacontrol from 3 different application modules (Assuming they are not nested in Data Model) in one taskflow view, then we end up with 3 Root App Modules = 3 Database connections and the important part is we need 3 separate commits to post all changes to DB.

ADF taskflows offer an elegant solution to such problems,  that is to manage Transactions at taskflow level.

Lets see how it works -

Case 3 :
Parent Taskflow
Transaction - Always Begin New Transaction
Data Control Scope - ISOLATED

Child Taskflow
Transaction - Use Existing Transaction if possible
Data Control Scope - SHARED

As we saw in Case 1 and 2, each Application module is created as Root with separate Transactions.
In Case 3 lets make the Parent Taskflow to begin new Transaction and Child to Use the Existing Transaction.

This is how it works internally -






























Key Observations -

1) Parent Taskflow begins a new Transaction at Taskflow level and Child taskflow uses the same.

2) Only  Root Application Module(App module 1) is created and App module 2 is nested inside App Module 1. Hence overall only 1 Transaction and 1 DB Connection is used across different application modules and taskflows.

3) Only one DCFrame is used.

4) A commit/rollback in any iterator will commit the changes to DB since they use one Transaction.
There is also a better way to do it using taskflow return, which we can discuss later in different post.


Check out the flow in a real example, 
Notice that only one Transaction is used in all 4 iterators.







































Similarly we can create multiple cases based on different Transaction management and Datacontrol scope options, But with the above examples you will be able to figure out those combinations pretty easily.

Eg : 
Case 4 :
Parent Taskflow
Transaction - No Controller Transaction
Data Control Scope - ISOLATED

Child Taskflow
Transaction - Always Begin New Transaction
Data Control Scope - ISOLATED

Parent taskflow will use 2 Transactions and Child will use 1.

Case 5 :
Parent Taskflow
Transaction - No Controller Transaction
Data Control Scope - ISOLATED

Child Taskflow
Transaction - Use Existing Transaction if possible
Data Control Scope - ISOLATED

Parent taskflow will use 2 Transactions and Child creates a new Transaction since no new transaction already exists in taskflow layer.

we can go on and on.. 


In my opinion, Don't use Transaction management options unless you absolutely sure of its use.. 
In most cases you needn't use it.

In simple terms - 
Data Control Scope - To manage DC Frames.
Transaction management options - To manage DB Transactions in taskflow layer instead of in the model layer using Application Modules.

You can checkout the application used in these blog posts from
https://github.com/bsatishinbox/FusionSamples/tree/master/TransactionFlows


Hope this helps.. :-) 







Monday, May 16, 2016

ADF Taskflow Transactions Management and Datacontrol scope - Part 2

In previous post we discussed in detail about basics Datacontrol scopes, Transactions and Application Module using single AppModule.

Now lets take it to next level and make it a little complex.

Below picture depicts how sample Parent and Child sample taskflows  used in this post are confgured.

As you can see we have 2 iterators from 2 different Application modules in parent as well as child  taskflow.

Case 1 (Default Taskflow Settings) -

Parent Taskflow
Transaction - No Controller Transaction
Data Control Scope - SHARED

Child Taskflow
Transaction - No Controller Transaction
Data Control Scope - SHARED

This is how it will work internally-






























Key Observations -
Since Datacontrol Scope is set to Shared, Both the Taskflows will share same DC Frame.

Both AppModule1 and AppModule2 will create Root Application Module which eventually means 2 Connections, 2 Separate Commit/RollBack per transaction etc.

In Parent/Child Taskflows, Commit in Employee Iterator 1  will not reflect changes in Employee Iterator 2 and vice versa until new control state is created.

A Commit/RollBack in Child Taskflow's Employee Iterator1 will update changes in Employee Iterator1  of Parent Taskflow and vice versa because they share same Transaction.

A Real Example - Notice the Transaction and AppModule







































Case 2  -
Parent Taskflow
Transaction - No Controller Transaction
Data Control Scope - SHARED

Child Taskflow
Transaction - No Controller Transaction
Data Control Scope - ISOLATED

This is how it will work internally-






























Key Observations -
Since Datacontrol Scope of child is set to Isolated, Both the Taskflows will have separate DC Frames.

Since DC Frames are separate each of iterators will have Transactions of its own so 
2 Taskflows * 2 AppModules = 4 Transactions, 4 Connections(Not good right?)

Commit/RollBack  in any of the iterator will not affect any other.

A Real Example






































Hope this helps:) In next post we can see how  Transaction options modifies the flow.