Sunday, August 30, 2009

LOV execute query many times (Fixed in 11.1.1.3)

Input list of values component has big performance issues, and it seems not suitable for view objects with a lot of data.
Not only you cant use performance tuning since there are bugs if you use range paging:
http://adfbugs.blogspot.com/2009/07/performance-tuning-lovs-and-range.html
and Up to row number:
http://adfbugs.blogspot.com/2009/08/lov-view-object-tuning-only-up-to-row.html

but also because every time you open LOV and select a value it execute query many times.

To test that, i override the method executeQuery for collection and print the query:

@Override
protected void executeQueryForCollection(Object object, Object[] object2, int i) {
System.out.println("EmployeesLOV executes Query :" + this.getQuery());
super.executeQueryForCollection(object, object2, i);
}

when i open the lov and select a value i get the following log:

EmployeesLOV executes Query :Select * from Employees
30-Aug-2009 17:25:04 oracle.adfinternal.view.faces.renderkit.rich.RichRenderKit isNavigating
SEVERE: The original view root was not set.
EmployeesLOV executes Query :SELECT * FROM (Select * from Employees) QRSLT WHERE ( ( ( (EMPLOYEE_ID = :vc_temp_2 ) ) ) )
EmployeesLOV executes Query :Select * from Employees


so the LOV query is executed 3 times !?

If i type a value to fields that many LOV values start with this value then it is executed many times !!!.

EmployeesLOV executes Query :SELECT * FROM (Select * from Employees) QRSLT WHERE ( ( (EMPLOYEE_ID LIKE :vc_temp_2 ) ) )
30-Aug-2009 17:31:34 oracle.adfinternal.view.faces.renderkit.rich.RichRenderKit isNavigating
SEVERE: The original view root was not set.
EmployeesLOV executes Query :SELECT * FROM (Select * from Employees) QRSLT WHERE ( ( (EMPLOYEE_ID LIKE :vc_temp_2 ) ) )
EmployeesLOV executes Query :SELECT * FROM (Select * from Employees) QRSLT WHERE ( ( (EMPLOYEE_ID LIKE :vc_temp_2 ) ) )
EmployeesLOV executes Query :SELECT * FROM (Select * from Employees) QRSLT WHERE ( ( (EMPLOYEE_ID LIKE :vc_temp_2 ) ) )
EmployeesLOV executes Query :SELECT * FROM (Select * from Employees) QRSLT WHERE ( ( (EMPLOYEE_ID LIKE :vc_temp_2 ) ) )
EmployeesLOV executes Query :SELECT * FROM (Select * from Employees) QRSLT WHERE ( ( (EMPLOYEE_ID = :vc_temp_2 ) ) )
EmployeesLOV executes Query :Select * from Employees


Also while you scroll up and down in LOV the query is also executed many times.

Finaly if you type a value that many LOV values start with this value and scroll down then other values that dont start with this value are visible:



And if you select the value then you get a strange error:



Is this a bug?

Is there a way to use LOVs with a lot of data?

Test case:
http://adfbugs.googlecode.com/files/TestPerformance.zip

For the test case i put in Employees table about 100000 rows with the following procedure:

create or replace
PROCEDURE CREATE_EMPLOYEES AS
BEGIN
FOR i IN 1..100000 LOOP
Insert into employees (employee_id,
last_name,
email,
hire_date,
job_id)
select employees_seq.nextval as employee_id,
'auto' i as last_name,
'aut' i '@gmail.com' as email,
sysdate as hire_date,
'IT_PROG' as job_id
from dual;
END LOOP;
COMMIT;
END CREATE_EMPLOYEES;

Wednesday, August 19, 2009

Af:Query bind variable workaround

When you try to enter a page that has af:query with bind variable, after ExecuteWithParams, it always keeps the first value that we first entered the page.
http://adfbugs.blogspot.com/2009/08/afquery-bind-variable-bug.html
Steve Muench said...
Filed bug# 8809022 with your testcase, thanks.
WORKAROUND----------
Rather than using the ExecuteWithParams action as the task flow'sinitial activity, instead write a custom AM method that you publishon the AM's client interface that does the following:
public void initTaskFlowDefinition(Number deptno) {
// Set var value on VO's variable
managergetEmployeesView1().ensureVariableManager().setVariableValue("inDepId",deptno);
// Save the save of the view criteria to "remember"
// the current var values as the ones to be restored
// in the search form.
getEmployeesView1().getViewCriteriaManager().getViewCriteria("EmployeesViewCriteria").saveState();
}
Then, have the task flow's default activity invoke this AMmethod instead to accomplish the task.

So i do it according to Steve workaround, but i didnt want to use bind variables since they have other issues:
http://adfbugs.blogspot.com/2009/07/jdeveloper-11-r1-cascading-lov-bugs.html
http://adfbugs.blogspot.com/2009/07/view-criteria-with-exists-optional-bug.html

So i used the following code:
public void initialSettings(oracle.jbo.domain.Number depId) {
EmployeesViewImpl emp = (EmployeesViewImpl)this.getEmployeesView1();
ViewCriteria vc = emp.getViewCriteria("EmployeesViewCriteria");
vc.first().setAttribute("DepartmentId", depId);
emp.getViewCriteriaManager().getViewCriteria("EmployeesViewCriteria").saveState();
}

i use this method in the task flow before entering the page and it seems to work fine.
Test Case:
http://adfbugs.googlecode.com/files/TestViewCriteria.zip

Friday, August 14, 2009

Range Paging in Master Detail bug. (Fixed in 11.1.1.3)

When i thried to set Range Paging in some view objects in our application i had the following exception:


oracle.jbo.InvalidOperException: JBO-25011: Rowset Employees_Departments1_EmpDeptFkLink_DepartmentsView_0 is forward only. at oracle.jbo.server.ViewObjectImpl.validateRangeSizeForRangePaging(ViewObjectImpl.java:13522) at oracle.jbo.server.ViewRowSetIteratorImpl.setRangeSize(ViewRowSetIteratorImpl.java:529) at oracle.jbo.server.ViewRowSetImpl.setRangeSize(ViewRowSetImpl.java:2633) at oracle.jbo.server.ViewObjectImpl.doCreateViewLinkAccessorRS(ViewObjectImpl.java:13534) at oracle.jbo.server.ViewObjectImpl.createViewLinkAccessorRS(ViewObjectImpl.java:13624) at oracle.jbo.server.AssociationDefImpl.get(AssociationDefImpl.java:405) at oracle.jbo.server.ViewAttributeDefImpl.get(ViewAttributeDefImpl.java:773) at oracle.jbo.server.ViewRowStorage.getViewLinkAccessorResult(ViewRowStorage.java:1365) at oracle.jbo.server.ViewRowStorage.getAttributeInternal(ViewRowStorage.java:1579) at oracle.jbo.server.ViewRowImpl.getAttributeValue(ViewRowImpl.java:1795) at oracle.jbo.server.ViewRowImpl.getAttributeInternal(ViewRowImpl.java:783) at model.EmployeesViewRowImpl.getMasterDepartment(EmployeesViewRowImpl.java:522)

This happens if you use a master Accessor in a detail view object.
So i reproduced in a simple test case:


I have a simple Departments Employees master detail relation.

In Employees view object i create a transient Attribute IsDepartmentManager that i want to check if the employee is the manager of the department.

To do that i need the department assecor in Employees. so i do that from the View link.


In the getter of transient attribute i get the attribute of master :
public Boolean getisDepartmentManager() {
Object depManager = this.getMasterDepartment().getAttribute("ManagerId");
return depManager != null && depManager.equals(this.getEmployeeId());
}

When i Run application, everything is working fine:


But if i set Range Paging on tuning of Departments View and run again :


Is this a bug?

Am i missing something?

Test case:
http://adfbugs.googlecode.com/files/TestRPMasterDetail.zip

Wednesday, August 12, 2009

Table Filter Bug

I create a default ADF table with filter from Employees views.

If i put an invalid value in date filter then i correctly have a validation error.


Also if i press rollback the value is cleared

If i put invalid value in a number filter then i get a ppr exception.


is this a bug?

Generally rollback (and resetActionListener) does not clear filters of table.

Is there a way to clear values and reset query for table filters?

Sunday, August 9, 2009

Af:Query bind variable bug (Fixed in 11.1.1.3)

We have noticed in our application a bug that when we enter a page that has af:query with bind variable, after ExecuteWithParams, it always keeps the first value that we first entered the page.

I reproduced this bug in a simple Departments Employees Test case:

In Employees View object i have a query criteria for DepartmentId = :inDepId. In the taskflow that opens the Employees query page i first run ExecuteWithParams for the task flow input paramter.



When i run application in the main page i select a department and then i pass DepartmentId as input value to the Employees task flow.



The first time i call Employees task flow everything works fine. The value of input parameter is set in the criteria and Employees of that department are queried:



But when i return to departments and select an other department and go to Employees again, the bind Variable in Query criteria is still the same, Even though the input parameter and the results have changed for the new department.


Isn't this realy strange?

If i change value and press reset it allways return to the first value that af:query is executed.
I tried in bindings refresh conditions and TrackQueryPerformed="Page" with no luck.

Is this a bug?

Is there a workaround?

Test case:
http://adfbugs.googlecode.com/files/TestViewCriteriaBug.zip

Saturday, August 8, 2009

Page with Region Validations bug

In the same test case of previus post i put commit actions.

I noticed that if i have a validation errors in region i cannot submit or commit page.


In the contrary if i have validations on page i can do submit and commit on retion.


These problems are easily fixed if you put partial trigger in page components from region

But even though validations fire, if i dont have validation errors when i commit the region also the page changes are commited. but the page does not know it. The commit button is not becoming disabled.

In order to be more obvious i also added a field from Jobs in the main page.
Then if i change value in the region and press commit in the region the value is returned to the value of the main page.



Is this a bug?

If not, how can i refresh data of main page when i make a change in the region?

Thursday, August 6, 2009

Region and dialog return bug

I create a simple application with Departments and Jobs entities and view objects.

I put Departments as a simple form in a page and Jobs as a simple form in a page fragment and task flow that i add as a Region in the first page. I also create a dummy dialog with a return button.


But when i return from dialog and try to navigate inside the region i get the following error:



java.lang.IllegalStateException: ADF_FACES-60058:Attempt to re-register component with different model. at oracle.adfinternal.view.faces.activedata.PageDataUpdateManager._registerComponent(PageDataUpdateManager.java:256) at oracle.adfinternal.view.faces.activedata.PageDataUpdateManager.registerComponentForPPR(PageDataUpdateManager.java:161) at oracle.adf.view.rich.activedata.ActiveComponentContext.popActiveComponent(ActiveComponentContext.java:371) at oracle.adf.view.rich.render.RichRenderer.encodeAll(RichRenderer.java:1191) at org.apache.myfaces.trinidad.render.CoreRenderer.encodeEnd(CoreRenderer.java:335) at org.apache.myfaces.trinidad.component.UIXComponentBase.encodeEnd(UIXComponentBase.java:751) at org.apache.myfaces.trinidad.render.CoreRenderer.encodeChild(CoreRenderer.java:415)

After that the page is no longer functional.

Is this a bug?

Test case:
http://adfbugs.googlecode.com/files/RegionAndDialogTest.zip

P.s. This bug was found by 2 female colegues (Roula and Nota) in our application. It was working befor r1 of jdev11.

Wednesday, August 5, 2009

LOV criteria bug.

Some times after using search criteria inside an LOV we get a strange exception:

java.sql.SQLException: Attempt to set a parameter name that does not occur in the SQL: vc_temp_2
at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapping.java:70)
at oracle.jdbc.driver.DatabaseError.newSQLException(DatabaseError.java:133)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:199)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:263)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:271)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectAtName(OraclePreparedStatement.java:11158)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObjectAtName(OraclePreparedStatementWrapper.java:815)
at oracle.jbo.server.OracleSQLBuilderImpl.bindParamValue(OracleSQLBuilderImpl.java:4617)
at oracle.jbo.server.BaseSQLBuilderImpl.bindParametersForStmt(BaseSQLBuilderImpl.java:3807)
at oracle.jbo.server.ViewObjectImpl.bindParametersForCollection(ViewObjectImpl.java:18278)
at oracle.jbo.server.QueryCollection.buildResultSet(QueryCollection.java:1035)
at oracle.jbo.server.QueryCollection.executeQuery(QueryCollection.java:815)
at oracle.jbo.server.ViewObjectImpl.executeQueryForCollection(ViewObjectImpl.java:5892)
at oracle.jbo.server.ViewRowSetImpl.execute(ViewRowSetImpl.java:1021)
at oracle.jbo.server.ViewRowSetImpl.execute(ViewRowSetImpl.java:889)


It is not easy to reproduce but when it happens you cannot open the LOV again and you cannot set a value to the LOV field, even from diferent row or from diferent session.

I managed to reproduce it in a simple test case of Employees form with simple Department LOV.
The steps to reproduce are:


1.Select an existing department

2.open department LOV add a criterion and press search.


3.Close LOV without selecting row and type a non existing value and press Tab. LOV automatically opens and even though it doesnt have values in criteria only the previus results are visible.


4.Press cancel again and type an existing value and press Tab. Then the error apears

It seems that LOVs Love bugs.

Tuesday, August 4, 2009

LOV view object Tuning: 'Only up to row number' bug (Fixed in 11.1.1.3)

Since we can not use Range paging on LOVs for performance Tuning due to bug 8722958 :
http://adfbugs.blogspot.com/2009/07/performance-tuning-lovs-and-range.html

I try the 'Only up to row Number' option in a simple employees form with Input List of values for DepartmentId.

so when i open the LOV only 10 rows apear:





Bug1: if i try to type number 110 that is a valid value but does not exist in the range, the value just disapear without even opening the LOV.


Bug2: If i type the number 20 then since both 20 and 200 exist it opens the LOV to select 1. but if i select cancel and after that i type the number 200 the value is set back to 20 and i get a stange error:



Is this a bug?
Or we should not use Tuning: 'Only up to row number' for LOV view objects?

Test case:
http://adfbugs.googlecode.com/files/TestLimitedLov.zip

Monday, August 3, 2009

Table Validations Bug.

In a simple Departments Entity i also put 2 transient attributes for this test case reasons.

Then i add some entity and attribute validations.


Then i create a simple ADF Table with submit and commit buttons


I put values in a row so that Entity compare validation should fail. I press submit but nothing happens. I press commit and it seems that data is commited, but they are not!!!

Validation error only shows up if i navigate to an other row by clicking.


but again if i press submit or commit all validation errors disapear!!!?

If i navigate to next row by pressing Tab, again no validation errors!!!



Is this a bug?

Is there any way that these validation errors do not disapear when i press any button?
Test Case:

Sunday, August 2, 2009

Returning from dialog to a page that has f:verbatim tag bug

We had a bug in application that when we return from dialog page the page was brocken, bindings were lost, and exceptions apeared in the log.

I managed to reproduce it in a simple test case:
I create a simple page with default oracle template and a dialog page.
I click on header facet and just typed something (test)





I run application i open dialog but when i return from dialog i have exception:


INFO: unable to dispatch JSP page: The following exception occurred:.java.lang.NullPointerException at oracle.adfinternal.view.faces.taglib.region.IncludeTag$RelocatedFacet.restoreFacet(IncludeTag.java:816) at oracle.adfinternal.view.faces.taglib.region.IncludeTag.doStartTag(IncludeTag.java:192) at oracle.adfinternal.view.faces.taglib.region.DynamicIncludeTag.doStartTag(DynamicIncludeTag.java:109) at oracle.jsp.runtime.tree.OracleJspBodyTagNode.executeHandler(OracleJspBodyTagNode.java:50) at oracle.jsp.runtime.tree.OracleJspCustomTagNode.execute(OracleJspCustomTagNode.java:257) at oracle.jsp.runtime.tree.OracleJspClassicTagNode.evalBody(OracleJspClassicTagNode.java:87) at oracle.jsp.runtime.tree.OracleJspBodyTagNode.executeHandler(OracleJspBodyTagNode.java:58) at oracle.jsp.runtime.tree.OracleJspCustomTagNode.execute(OracleJspCustomTagNode.java:257) at oracle.jsp.runtime.tree.OracleJspClassicTagNode.evalBody(OracleJspClassicTagNode.java:87) at oracle.jsp.runtime.tree.OracleJspBodyTagNode.executeHandler(OracleJspBodyTagNode.java:58) at oracle.jsp.runtime.tree.OracleJspCustomTagNode.execute(OracleJspCustomTagNode.java:257) at oracle.jsp.runtime.tree.OracleJspClassicTagNode.evalBody(OracleJspClassicTagNode.java:87) at oracle.jsp.runtime.tree.OracleJspBodyTagNode.executeHandler(OracleJspBodyTagNode.java:58) at oracle.jsp.runtime.tree.OracleJspCustomTagNode.execute(OracleJspCustomTagNode.java:257) at oracle.jsp.runtime.tree.OracleJspNode.execute(OracleJspNode.java:76) at oracle.jsp.runtimev2.ShortCutServlet._jspService(ShortCutServlet.java:88) at oracle.jsp.runtime.OracleJspBase.service(OracleJspBase.java:29) at oracle.jsp.runtimev2.JspPageTable.service(JspPageTable.java:416) at oracle.jsp.runtimev2.JspServlet.internalService(JspServlet.java:722) at oracle.jsp.runtimev2.JspServlet.service(JspServlet.java:646) at javax.servlet.http.HttpServlet.service(HttpServlet.java:820) at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292) at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at oracle.adf.library.webapp.LibraryFilter.doFilter(LibraryFilter.java:159) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at weblogic.servlet.internal.RequestDispatcherImpl.invokeServlet(RequestDispatcherImpl.java:500) at weblogic.servlet.internal.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:248) at com.sun.faces.context.ExternalContextImpl.dispatch(ExternalContextImpl.java:410) at org.apache.myfaces.trinidad.context.ExternalContextDecorator.dispatch(ExternalContextDecorator.java:44) at org.apache.myfaces.trinidad.context.ExternalContextDecorator.dispatch(ExternalContextDecorator.java:44) at org.apache.myfaces.trinidad.context.ExternalContextDecorator.dispatch(ExternalContextDecorator.java:44) at org.apache.myfaces.trinidad.context.ExternalContextDecorator.dispatch(ExternalContextDecorator.java:44) at org.apache.myfaces.trinidadinternal.context.FacesContextFactoryImpl$OverrideDispatch.dispatch(FacesContextFactoryImpl.java:267) at com.sun.faces.application.ViewHandlerImpl.executePageToBuildView(ViewHandlerImpl.java:473) at com.sun.faces.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:141) at javax.faces.application.ViewHandlerWrapper.renderView(ViewHandlerWrapper.java:189) at org.apache.myfaces.trinidadinternal.application.ViewHandlerImpl.renderView(ViewHandlerImpl.java:193) at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._renderResponse(LifecycleImpl.java:685) at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase(LifecycleImpl.java:261) at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:193) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:266) at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:227) at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:125) at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:292) at weblogic.servlet.internal.TailFilter.doFilter(TailFilter.java:26) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at oracle.adf.model.servlet.ADFBindingFilter.doFilter(ADFBindingFilter.java:191) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at oracle.adfinternal.view.faces.webapp.rich.RegistrationFilter.doFilter(RegistrationFilter.java:85) at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:420) at oracle.adfinternal.view.faces.activedata.AdsFilter.doFilter(AdsFilter.java:54) at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:420) at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:247) at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:157) at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at oracle.security.jps.wls.JpsWlsFilter$1.run(JpsWlsFilter.java:96) at java.security.AccessController.doPrivileged(Native Method) at oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:313) at oracle.security.jps.wls.util.JpsWlsUtil.runJaasMode(JpsWlsUtil.java:146) at oracle.security.jps.wls.JpsWlsFilter.doFilter(JpsWlsFilter.java:140) at oracle.security.jps.ee.http.JpsFilter.doFilter(JpsFilter.java:70) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at oracle.adf.library.webapp.LibraryFilter.doFilter(LibraryFilter.java:159) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at oracle.dms.wls.DMSServletFilter.doFilter(DMSServletFilter.java:202) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at weblogic.servlet.internal.RequestEventsFilter.doFilter(RequestEventsFilter.java:27) at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56) at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3588) at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321) at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:121) at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2200) at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2106) at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1428) at weblogic.work.ExecuteThread.execute(ExecuteThread.java:201) at weblogic.work.ExecuteThread.run(ExecuteThread.java:173)

and the page is no longer functional.

If i remove f:verbatim tag the page and dialog work nomraly.

So is this a bug?

If we should not use f:verbatim on ADF pages, why it is set automaticaly when you type something on the page?

Test case:
http://adfbugs.googlecode.com/files/TestDialogReturn.zip

Saturday, August 1, 2009

Range Paging Last operation, bug workaround

As i posted in previus post when you use Range Paging on a view object then Last operation throws an error.
http://adfbugs.blogspot.com/2009/07/performance-tuning-range-paging-last.html

As Steve suggested i created a method that takes you to the last row:

private Row rangePagingLast() {
int pagesCount = getEstimatedRangePageCount();
scrollToRangePage(pagesCount);
Row lastRow = getRowAtRangeIndex(getRowCountInRange()-1);
setCurrentRow(lastRow);
return lastRow;
}

This method actually gets you to the last row even though Range Paging is set on a view object
It is also much faster than scrolling down to a table component or Last operation of a view object that has Scrolling as Action Mode.
So i overide my base View Object Implementation Class and the Last operation to support Last operation even if Range Paging is set.

@Override
public Row last() {
if (getAccessMode()==ViewObjectImpl.RANGE_PAGING) return rangePagingLast();
return super.last();
}

It seems to work fine.



Test case:

http://adfbugs.googlecode.com/files/TestRangePaging.zip