Some March 2014 Notes/Tips

1) List of implicit JSF EL objects:

http://balusc.blogspot.sg/2011/09/communication-in-jsf-20.html#ImplicitELObjects

2) Performance issue caused by Oracle DB bind variable peeking

Encountered an strange performance issue, the ADF VO query is very slow, though the same query could finish in other sql tools within seconds. In the end it’s due to oracle bind variable peeking, different execution plan is used by the query optimizer, some references:

http://blog.tanelpoder.com/2010/02/02/bind-variable-peeking-execution-plan-inefficiency/

http://dba.stackexchange.com/questions/51558/query-gets-slow-when-bind-peeking-is-turned-on

http://scn.sap.com/community/oracle/blog/2013/06/13/oracle-db-optimizer-part-vi–effects-of-disabled-bind-variable-peeking-adaptive-cursor-sharing-and-cardinality-feedback-on-the-cbo-in-sap-environments

http://stackoverflow.com/questions/7839907/no-more-data-to-read-from-socket-error/7844985#7844985

3) how to find query block identifier for oracle sql hint

explain plan then run:

</p>
<p>SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY(NULL, NULL, 'typical alias -rows -bytes -cost'))</p>
<p>

http://jonathanlewis.wordpress.com/2007/06/25/qb_name/

4) Set all VO fetch size to 25, I feel it has more benefits than drawbacks

Default fetch size is 1 which is Ok since when drag drop to page as table, it will set fetch size to 25. But sometimes, we iterate on the table/iterator data without displaying it on UI, this setting will often missed out. If the SQL is slow, performance is even more affected obviously. I felt change this to 25 in all VO has more benefits than drawbacks.

5) ADF Error page

http://biemond.blogspot.sg/2008/04/exception-page-with-adf-taskflow.html

But it seems need some special handling for view expired exception (should redirect to login instead of this page? pending test this)

6) ADF dynamic component, some hacking to show filter and sort properties

http://andrejusb.blogspot.sg/2013/11/creating-adf-bc-view-object-instances.html

Used above as a starting point but forced to add sorting and filtering, fortunately most columns are just String type, otherwise more work needs to be done. Following is in Jdev11.1.2.4, I think higher version will be much easier to do this since it’s more JSF2.x compatible.

Step 1: Add following phase listener to the dynamic table page:


    public void phaseListener(PhaseEvent evt) {
        try {
            if (PhaseId.RENDER_RESPONSE.equals(evt.getPhaseId())) {
                evt.getFacesContext().getViewRoot().subscribeToViewEvent(PreRenderComponentEvent.class, new SystemEventListener() {
                        @Override
                        public void processEvent(SystemEvent evt) {
                            if (evt.getSource() != null && evt.getSource() instanceof DynamicTable) {
                                DynamicTable dtt = (DynamicTable)evt.getSource();
                                if (dtt != null && dtt.getChildCount() > 0) {
                                    RichTable t = (RichTable)dtt.getChildren().get(0);
                                    Iterator<UIComponent> itr = t == null ? null : t.getFacetsAndChildren();
                                    while (itr != null && itr.hasNext()) {
                                        UIComponent col = itr.next();
                                        if (col != null && col instanceof RichColumn) {
                                            ((RichColumn)col).setSortable(true);
                                            ((RichColumn)col).setSortProperty(((RichColumn)col).getHeaderText());
                                            UIComponent filter = col.getFacet("filter");
                                            List<UIComponent> children = ((RichColumn)col).getChildren();
                                            boolean filterable = true;
                                            if (children != null && children.size() > 0) {
                                                if (children.get(0) != null && children.get(0) instanceof RichInputDate) {
                                                    ((RichColumn)col).setFilterable(false);
                                                    filterable = false;
                                                }
                                            }
                                            if (filter == null && filterable) {
                                                UIComponent f = new RichInputText();
                                                ((RichColumn)col).setFilterable(true);
                                                FacesContext context = FacesContext.getCurrentInstance();
                                                f.setValueExpression("value",
                                                                     context.getApplication().getExpressionFactory().createValueExpression(context.getELContext(),
                                                                                                                                           "#{vs.filterCriteria." +
                                                                                                                                           ((RichColumn)col).getHeaderText() +
                                                                                                                                           "}", String.class));
                                                ((RichColumn)col).setFilter(f);
                                            }
                                        }
                                    }
                                }
                            }
                        }

                        @Override
                        public boolean isListenerForSource(Object o) {
                            return o != null && o instanceof DynamicTable;
                        }
                    });
            }
        } catch (Throwable e) {
            logger.severe("before phase", e);
        }
    }

Step 2: Add phase listener to page:

<f:view beforePhase="#{pageFlowScope.xxxBean.phaseListener}">

In page def file, besides the iterator, also need to add this search criteria binding for filtering:

</pre>
<searchRegion Criteria="__ImplicitViewCriteria__" Customizer="oracle.jbo.uicli.binding.JUSearchBindingCustomizer" Binds="MyVO1Iterator"
 id="ImplicitViewCriteriaQuery" InitialQueryOverridden="true" Refresh="always"/>
<pre>

7) For ViewObject, need to run executeQuery before insertRow (if it’s not executed)? otherwise hv activation/passivation problem

8) In IE, tabbing out of autosubmit input fields inside af:table is not working perfect if event policy is ppr

In IE, if event policy is ppr, for a table of input text fields, if it’s autosubmit & other fields have partial trigger on it, when user tab out to the next field (assume there’s existing text inside all input fields), the highlighted text status of the next input text field will be lost, it’s a problem for those head down input users

env: Jdev 11.1.2.4 & IE8; it’s working fine in Chrome.

9) Transient View Object In-memory sorting behavior

If all attributes of the view object are transient attributes (I didn’t have time to test sql/entity based VO), In-memory sorting feature works however after the sorting, all inserted rows will disappear after passivation/activation. One possible workaround is that executeQuery in scan db table mode and insert sorted rows again :(

It seems this was a bug and already fixed but I still encounter it in 11.1.2.4.

Reference: https://community.oracle.com/thread/656745?start=0&tstart=0

10) ADF IE 11 Support:

Workarounds like filter are there but seems official way is to use following patch:

https://blogs.oracle.com/jdeveloperpm/entry/oracle_jdeveloper_and_adf_patches

11) Add own searhc fields to af:query 

http://www.jobinesh.com/2011/03/retrieving-viewcriteria-from-custom.html

I used above reference as a starting point of some af:query hacking (I do this only when I don’t have a choice): Adding some semi-colon delimited search fields.

Step 1: Change the VO sql, add some new column like this ‘$$$_’ || COLUMN1 searchField, mark it as queriable

Step 2: Manipulate search criteria in  VO’s “executeQueryForCollection” method, so it always evaluated to true.


...

ViewCriteria vc = this.getViewCriteria("__ImplicitViewCriteria__");
 Object v = null;
 if(vc!=null && vc.size()>0){
ViewCriteriaRowImpl r = (ViewCriteriaRowImpl)vc.get(0);
if(r!=null){
r.setOperator("searchField", "<>");
}

...
 }
 super.executeQueryForCollection(object, object2, i);

Step 3: in the af:query’s query listener, execute a AM’s method binding to query the VO by converting the semicolon field to its where clause (or maybe using a VC if you like) before processing query event via EL invokation. The submitted af:query search field could be obtained:

public void onSearch(QueryEvent evt) {
   QueryDescriptor desc = evt.getDescriptor();</pre>
for(Criterion c : desc.getConjunctionCriterion().getCriterionList()){
if( "SearchFeild".equalsIgnoreCase(((AttributeCriterion)c).getAttribute().getName())){
 searchField= (String)((AttributeCriterion)c).getValues().get(0);
 }

...
<pre>

Lastly, I need to hide the search criteria operator for the newly added fields, following tip is very helpful: http://andrejusb.blogspot.sg/2014/04/hide-all-search-operators-for-adf-view.html However, on jdev11.1.2.4, I notice that the jdeveloper view object attributes will disappear in the VO configuration design View, workaround is to remove the added tag in source view and get the attributes shown and add the tag in source view again.

12) Encounter issue: RowID truncated during table scrolling

Forced to use RowID as PK and display records inside af:table however when scrolling and select the row, the row key in selection event which is the RowID is truncated so the RichTable.getRowDate(key) will fail to return current row.