JDev & ADF Goodies

13. May 2012

JDeveloper: Controlling which Resources (Files) are Copied into the Projects Output Directory

Filed under: Configuration,JDeveloper — Timo Hahn @ 21:21
Tags: , ,

Some projects need resource files available in the output directory together with the class files. This is a fairly common task, however it’s not obvious how to archive this for all types of resources.

IF you never have had the problem, that a resource file you used in your project did not turn up in the output directory, you probably have used only default resource files like ‘properties’, ‘wsdl’ or ‘XML’ files. These files are copied into the output path by default.

Lets assume you have a resource e.g. a tiff file (*.tiff) or a TrueType font (*.ttf) which you need in your project and finally in the jar or adflib you build from the project. Lets add a dummy file ‘MyFont.ttf’ in a new folder named ‘res’ under the base path of the model projcect ‘de.hahn.blog.controlresourcefiles’. After this the model application looks like

Model Project after adding Font File

Model Project after adding Font File

No problem with this. Now if you compile the model project and check the output path Q:\QT\BlogControlResourceFiles\CRFModel\classes in this sample, you’ll notice that the folder ‘res’ and file ‘MyFont.ttf’ is not in the directory tree

Output Path after Compile

Output Path after Compile

If you check the path configuration of the project, it shows that the folder and the file should have been there

Project Path

Project Path

Well, the problem is an other configuration for the project. If you check the compiler node in the project properties you see that there is a filter which defines which file types are copied into the output path of the project

Project Compiler  Settings

Project Compiler Settings

As you see there is no entry for type ‘.ttf’ which means that files with this suffix are not copied into the output directory. The solution to the problem is to simply add the suffix ‘.ttf’ to the filter and compile the project again. After this the file ‘MyFont.ttf’ can be found in the projects output directory.

If you have any resource of a type (file suffix) you want to automatically copied into the projects output directory, you simple add the missing suffix to the filter.

11. May 2012

JDeveloper 11.1.2.2.0: First trap when installing a new JDeveloper version

Filed under: ADF,Configuration,Installation,JDeveloper — Timo Hahn @ 21:21
Tags: , ,

One of my tasks is to evaluate new JDeveloper versions. I have to say that it’s one of the tasks I really do like as I get the chance to try out new things :) . OK I have to check if current applications are still running first.

I started installing JDev 11.1.2.2.0 on my development machine, checked out the sources of the current applications and started compiling them and building adf libraries. At one point I got the below error message:

Error: An unreported error occurred in Appc. No errors were reported, but the tool returned a failure result code: 1.
Warning: <11.05.2012 16:40 Uhr MESZ> <Error> <J2EE> <BEA-160141> <Could not initialize the library C:\..\..\..\oracle_common\modules\oracle.jsf_2.0\jsf-ri-20.war. Please ensure the deployment unit is a valid library type (war, ejb, ear, plain jar). \..\..\..\oracle_common\modules\oracle.jsf_2.0\jsf-ri-20.war (Das System kann den angegebenen Pfad nicht finden) with : \..\..\..\oracle_common\modules\oracle.jsf_2.0\jsf-ri-20.war>
Warning: <11.05.2012 16:40 Uhr MESZ> <Error> <J2EE> <BEA-160187> <weblogic.appc failed to compile your application. Recompile with the -verbose option for more details. Please see the error message(s) below.> 
Warning: [J2EE:160147]One or more libraries could not be processed. See error above.

Interestingly the message complains about a war file ‘jsf-ri-20.war’ at a location which I never use for JDev. I never install JDev on drive C on a Windows system. All applications are installed on a different drive (P in my case). The reason for this is the the ‘system11.1.2.2.39.61.83.1′ folder was created in my personal ‘application data’ folder which resides on drive C. As this path has spaces on my Windows system I normally move the ‘system11.1.2.2.39.61.83.1′ on drive P. To archive this I set the environment variable JDEV_USER_DIR to ‘P:\jdeveloper\system’. When starting JDev the next time the ‘system11.1.2.2.39.61.83.1′ is generated in the folder ‘P:\jdeveloper\system’.

After this change I tried again and got the same error, only this time the path started with ‘P’. The path to the jar file C:\..\..\..\oracle_common\modules\ made me think again. This path is normally part of the ADF Runtime installation on a WLS server. In this case the integrated WLS which comes with JDev.

Well, at the time I tried to compile a project containing an ADF Task-Flow into an adf library. Interestingly the rebuild process somehow needs access to the ‘jsf-ri-20.war’. Problem is that I had not created the integrated WLS. This is done the first time you start the integrated WLS (debug or normal).

After starting the integrated WLS the first time the path gets created and my ADF Task-Flow compiles OK.

I installed JDev in various version hundreds (more or less) of times but never stumbled upon this.

9. May 2012

Patch Numbers for ADF Runtime Libraries Update to 11.1.2.2.0

After the release of the new JDev version 11.1.2.2.0 I ask support for the patch numbers for the ‘Sherman Update 2′, which seams to be the official name.
Support just answered my question:

The 2 patches are :

Patch 13656274: SHERMAN UPDATE2: RT BASED ON JDEVADF_11.1.2.2.0_GENERIC_120418.2212.6183.1
Patch 13656372: SHERMAN UPDATE2: WEBCENTER COMPOSER PATCH FOR SHERMAN UPDATE 2

But I need confirmation if it can be installes on top of WLS 10.3.5.0
as from the crertification matrix it is only certified on top of WLS 10.3.6.0 :
Oracle JDeveloper Certification Information

So lets hope we can somehow update the WLS 10.3.5 server with installed ‘Sherman Update 1′ :)

UPDATE May-10-2012:
Got this from support regarding upgrade of an existing WLS 10.3.5 server:

There was a confusion if 11.1.2.2.0 could be installed on top of WLS 10.3.5.0 as per the cerfification matrix

http://www.oracle.com/technetwork/developer-tools/jdev/jdev11gr2-cert-405181.html#Application_Servers

11.1.2.2.0 is only certified for WLS 10.3.6.0.

I got confirmation that ADF 11.1.2.2.0 requires the Application Development Runtime 11.1.1.6.0 libraries.
ADR 11.1.1.6.0 can be installed on WLS 10.3.5 or WLS 10.3.6
So 11.1.2.2.0 can be installed on top of WLS 10.3.5.0

UPDATE May-19-2012:

I got some more info about the possible upgrade path from Oracle I like to share:

Q1) Are the ADF 11.1.2.2.0 ADF Runtimes certified against WLS 10.3.5?

Yes and we’ve updated the cert matrix to reflect this: http://www.oracle.com/technetwork/developer-tools/jdev/jdev11gr2-cert-405181.html

Q2) Is there a patchset to move from 11.1.2.0.0 or 11.1.2.1.0 to 11.1.2.2.0?

No. As you’ve correctly identified, the only way is to install the 11.1.1.6.0 Runtimes then apply the 11.1.2.2.0 patch.

The release notes do highlight this fact, but do not mention that there isn’t a patch from 11.1.2.0.0/11.1.2.1.0 to 11.1.2.2.0: http://www.oracle.com/technetwork/developer-tools/jdev/11gr2update2-1592225.html#deploy. I’ll seek to get a clarification put in the release notes.

Q3) If 11.1.2.2.0 is a patch on top of 11.1.1.6.0 are all of the 11.1.1.6.0 features available to 11.1.2.2.0?

No. The 11.1.2.2.0 patch overrides functionality in 11.1.1.6.0 so customers should not assume this.

The answer to Q3) is probably the interesting one as it makes clear that even as we update from 11.1.1.6.0, we don’t get the features introduced with 11.1.1.6.0 in JDev 11.1.2.2.0 :-(
One other implication is that you can’t run applications from both versions on one WLS 10.3.6 server.

18. April 2012

JDeveloper & ADF: Multiple Cascading Tables

In a former blog post JDeveloper 11.1.2.1: Cascading Tables I showed how to cascade two tables. Lately I saw a couple of request on the OTN JDeveloper & ADF forum on how to do this with multiple tables.
This blog extends the sample given in the old post to show how to add another cascading table. For this we need to add an other entity view object pair to the project, build the needed association and view links to the existing entity and view object, change the data model of the application module and finally change the UI to show the new cascadeing table.

Lets start to add the new JobHistory entity and JobHistoryView view object. For this you can open the ‘New Business Components from Tables…’ wizzard on the existing business components node in the application

Add new Business Objects

Add new Business Objects


Follow the wizard…
Select new Table

Select new Table

Select new ViewObject

Select new ViewObject

Don't add new ApplicationModule

Don't add new ApplicationModule

The result of this operation should look like this:

Result of the Wizard

Result of the Wizard

Now that we only added one table, the framework did not pick up the foreign key relationship between the Employees and the JobHistory entities. We have to build the needed association and view link ourself…

Build New Association

Build New Association

... Name it ...

... Name it ...

... Select the Attributes ...

... Select the Attributes ...

... Remove the not needed Navigation from JobHistory to Employee ...

... Remove the not needed Navigation from JobHistory to Employee ...

Step to the end of the wizard and click ‘Finish’, save your work. Next we create the ViewLink based on just created EmpJhistFkAssoc…

Create ViewLink ...

Create ViewLink ...

... Name it ...

... Name it ...

... Select the EmpJhistFkAssoc for both ViewObjects  ...

... Select the EmpJhistFkAssoc for both ViewObjects ...

At this point you can click ‘Finish’ as no other change need to be made in this wizard. After this we add the new JobHistoryView to the application modules data model as a dependent ViewObject (on EmployeesView). Open the BCTAppModule application module and select the ‘Data Model’ node

Open BCTAppModule and select the ViewObjects...

Open BCTAppModule and select the ViewObjects...

… and hit the shuttle arrow to put the JobHistoryView under the EomployeesView3…

Final Data Model

Final Data Model

Save your work and compile the model project. Next we change the UI to show the job history for the selected employee. If you open and refresh the data model of the ViewController project you see the new JobHistory1 under the EmployeesView3…

Data Model in ViewController...

Data Model in ViewController...

Now we open the existing Dep.jsff page fragment to add an other af:panelCollection under the existing two

...add af:panelCollection ...

...add af:panelCollection ...

drop the JobHistoryView1 from the data control onto the new af:panelCollection as ‘Read-Only Table’…

... Drop JobHistoryView1 into panelCollection as Read-Only Table ...

... Drop JobHistoryView1 into panelCollection as Read-Only Table ...

... Setup Table as 'Single Selection' and allow Sorting ...

... Setup Table as 'Single Selection' and allow Sorting ...

Finally we need to setup the partial triggers for the JobHistroy table so that the table reacts of changes of the departments and employees table…

Setup Partial Triggers...

Setup Partial Triggers...

... React on Department and Employee changes...

... React on Department and Employee changes...

Save your work and run the application. That should open the Page with three cascading tables visible. If we change the department to e.g. ‘Sales’ and select the employee with the id 176 we should see

Final Cascading Table Application

Final Cascading Table Application

You can download the sample workspace, build with JDev 11.1.2.1.0 and depending on hte HR db schema, from here: BlogCascadingTableV2.zip
Please rename the file to ‘.zip’ after downloading it!

13. April 2012

JDeveloper & ADF: Use the Application Module Tester (BC4J Tester) to Test all your BusinessLogic

This blog post describes how to use the Application Module Tester provided together with JDeveloper to test all your business logic without having to write or design the client UI (view controller part of a Fusion Web Application).
I consider this a ‘best practice’ to do this in each project. It allows the developer(s) of the business logic to run, debug and test all business logic before the designers have worked out the UI. Changes to interfaces can be done without an impact to the UI this way.

One other advantage of using the Application Module Tester is that it starts up really fast compared to the long init phase the full web application needs.

Before going into detail lets talk about what this blog shows and how it’s implemented. A sample work space build in JDeveloper 11.1.2.1.0 using the HR schema as DB can be downloaded using the link provided at the end of the blog.
First of all you can test the data model you designed into the application module, meaning that you can execute the VO and walk over the result set or show the result as table

Data Model of the Application Module

Data Model of the Application Module

The application module can implement service methods which your later use in the UI to archive a business need. In the sample the application module defines just one service method ‘howManyEmpEarnMoreThen’ which returns the number of employees who are earning more (or equal) to the given amount.

Service Method 'howManyEmpEarnMoreThen'

Service Method 'howManyEmpEarnMoreThen'

and the implementation of this method

    public oracle.jbo.domain.Number howManyEmpEarnMoreThen(oracle.jbo.domain.Number aSalary)
    {
        _logger.info("Call with salary: "+aSalary);
        EmployeesViewImpl lEmployeesView1 = this.getEmployeesView1();
        oracle.jbo.domain.Number n = lEmployeesView1.countEmpWihtSalaly(aSalary);
        return n;
    }

Next a VO might have some ViewCriteria attatched which you also want to test

ViewCriteria to Test

ViewCriteria to Test

and the last thing to test are service methods which are exposed in the VO instead of the application module (‘countEmpWihtSalaly’ in the sample)

Exposed Methods in a View Object

Exposed Methods in a View Object

and the implementation of the method

    public Number countEmpWihtSalaly(Number aSalary)
    {
        RowSet lCreateRowSet = this.createRowSet("counterView");
        ViewCriteriaManager lCriteriaManager = this.getViewCriteriaManager();
        String[] lAvailableViewCriteriaNames = lCriteriaManager.getAvailableViewCriteriaNames();
        for (String vcName :lAvailableViewCriteriaNames)
        {
            this.removeApplyViewCriteriaName(vcName) ;
        }
        lCreateRowSet.ensureVariableManager().setVariableValue("bindSal", aSalary);
        ViewCriteria lCriteria = this.getViewCriteria("EmpSalaryVC");
        this.applyViewCriteria(lCriteria);
        lCreateRowSet.executeQuery();
        long count = lCreateRowSet.getEstimatedRowCount();
        _logger.info("Count Emp wiht salay > " + aSalary + " = " + count);      
        lCreateRowSet.closeRowSet();    
        return new Number(count);
    }

Now let start up the the Application Module Tester and debug the business logic. To start the tester in debug mode, right click the application module facade and select ‘Debug’

Start the Application Module Tester in 'Debug' Mode

Start the Application Module Tester in 'Debug' Mode

which shows the tester like

Running Tester

Running Tester

A double click on a ViewObject (e.g. EmployeesView1) opens one record in form mode. You can navigate the result set using the icons in the header

Navigate Result Set

Navigate Result Set

One of the icons (the field glass) allows you to specify one or more of the available view criteria and hitting the ‘Find’ button after selecting a view criteria opens a dialog to enter bind variables

Specify View Criteria

Specify View Criteria

Specify Bind Variables

Specify Bind Variables

The result of this is again shown as a result set with navigation. If you like to see the result a table you can right click on the VO and select ‘Show Table’.

Show Result as Table

Show Result as Table

So how do we execute the ‘countEmpWihtSalaly’ method which is exposed in the client interface of the VO?
If you look at the image above you’ll see the option ‘Operations’ which will open a new tab showing all available operations which are exposed to the client interface of the VO.

Available Operations

Available Operations

After selecting the method you can hit execute and the method is executed

Result of Operation

Result of Operation

To access the public available methods from the application module you right click on the application module and select ‘Show’. After that you see a tab like the one for the VO operation.

Application Module Operations

Application Module Operations

Result of Operation

Result of Operation

This might not look as much to you, but the advantage of the Application Module Tester is that you can debug the code in the application module methods or view object operation easily. You can set needed variables when calling the methods and use the outcome of the operations in calls to other operations. This way you can easily test the whole business logic without the need to have an UI present.

For more information you can check the Oracle® Fusion Middleware Fusion Developer’s Guide for Oracle Application Development Framework 11g Release 2 (11.1.2.1.0)

You can download the sample workspace, build with JDev 11.1.2.1.0 and depending on the HR db schema, from here: BlogBC4JTester.zip.doc
Please rename the file to ‘.zip’ after downloading it!

5. April 2012

JDeveloper: Case Insensitive Search and Performance

A couple of days ago Frank Nimphius published a new ADF Insider Essential video about Search Forms Customization where he also showed how to implement case insensitive searches. While the tip how to do this is fine, he did not mention the bottleneck involved in doing so. Yesterday, while writing up this blog I came across this blog ‘ADF ViewCriteria performance impact’ by Raman Nanda who summarized the same issue. The last statement in his blog is the starting of this blog:

Note:Also don’t choose to ignore null values for predicates that are required and create proper indexes on the table structure depending upon how you filter results. For ex: If predicate is upper(ename)=upper(:bvar) then create a index on upper(ename) .

Lets start with a look on a view criteria definition in JDeveloper 11.1.2.1.0. the image below shows the definition of a simple view criteria to search for employees who’s names start with a given bind variable. When you first add items to the view criteria both check boxes ‘Ignore Case’ and ‘Ignore NULL Values’ are checked.

ViewCriteria Definition: Ignore Case and Ignore Null

ViewCriteria Definition: Ignore Case and Ignore Null


A close look at the ‘View Object Where Clause’ part reveals that the ‘Ignore Case’ part of the query is not visible in JDev 11.1.2.1.0. This is a bug which I’m going to file in the near future. Before going into detail with the query lets uncheck the ‘Ignore NULL Values’ to see the final criteria:
ViewCriteria only 'Ignore Case'

ViewCriteria only 'Ignore Case'


Running the application module in the tester reveals the final query as (copied from the log window)
[104] SELECT Employees.EMPLOYEE_ID,         Employees.FIRST_NAME,         Employees.LAST_NAME,         Employees.EMAIL,        
             Employees.PHONE_NUMBER,         Employees.HIRE_DATE,         Employees.JOB_ID,         Employees.SALARY,         
             Employees.COMMISSION_PCT,         Employees.MANAGER_ID,         Employees.DEPARTMENT_ID,         
             Employees.ACTION_COMMENT 
             FROM EMPLOYEES Employees 
             WHERE ( ( ( (UPPER(Employees.LAST_NAME) LIKE UPPER( :bindLN || '%') ) ) ) )
[105] Bind params for ViewObject: [de.hahn.blog.vcinsesitivesearch.model.dataaccess.EmployeesView]VCISAppModule.EmployeesView1
[106] Binding param "bindLN": K

Here you see that the ‘Ignore Case’ results in calling SQL UPPER’(…) on the bind parameter as well as on the row attribute. When you copy this query and run it in a SQL worksheet it returns the right results. However, in this bog we are more interested in the execution plan of the query. This is shown in the below image:
Execution Plan Without Index

Execution Plan Without Index


The interesting thing is that the result is reached by a full table scan, which you see as the option is ‘FULL’ for table access. This is not a problem if the table contains only a small number of rows, but if you work on large tables with 10000+ rows it’ll take ages (OK, it’s notable longer then you would expect) to execute.
If you only have defined the normal index on the LAST_NAME column
create index normal_ln_idx on employees (last_name);

the plan doesn’t change at all. This is exactly what Raman Nanda meant in his blog. You need to create a function based index on the LAST_NAME column. Here is the SQL to do so:
create index upper_ln_ix on employees (UPPER(last_name));

Running the query again after creation of the new index results in
Execution Plan with UPPER Index

Execution Plan with UPPER Index


As yo ucan see the table now is accessed via the ‘upper_ln_ix’ index we created. This speeds things up in large tables.

To summarize this blog: you should, as part of your testing, check the execution plans of the queries executed by your application. This can result in a huge improvement of the performance. You should ask your DBA to help you with this task. There are tools readily available to the DBA to help getting information about the queries executed by your application.

31. March 2012

Changing OTN Notification E-Mail Address (aka Username)

Filed under: Uncategorized — Timo Hahn @ 22:22

Lately my old web provider told me that he discontinued his service. So I was forced to change my OTN notification e-mail address or username which still used this old provider.
After reading some thread about this, I was not exactly thrilled to do this. Well, there was nothing I could do about it so I decided to ask support how I could minimize the risk of loosing my identity. You find the OTN account help here. It’s hidden in the ‘GETTING HELP ON LOGIN ISSUES’ section as link ‘Submit a help request’.
Now that it seams that the change went well for myself I like to share the procedure given from the ‘Oracle Profile Helpdesk’:

You may update/change the email address associated to your Oracle account by following the steps below:

1) Delete browser cookies, Close and re-open a new browser window.
2) Go to https://myprofile.oracle.com/EndUser/faces/profile/sso/updateUser.jspx, which will take the user to Single Sign On page. Login using your account credentails.
3) Click “Change Username” link on the top right hand corner of the page and a pop up box will appear.
4) Now Type the password of the account for Current Password field, type the new email address (which you want the account to be associated) for New Username field and Similarly type the same email address for Confirm New Username field and Click “Change” button.

That’s easy enough and worked out OK.

18. March 2012

JDeveloper: Preventing return of large row sets on page load of VO using bind variable

Back in 2009 Andrejus Baranovskis blogged about how to prevent the execution of a (default) query when ADF loads a page here. This is sometimes necessary if the query defined for a page consumes a lot of time or return a lot of rows.
Lately some users reporting that the solution provided in the blog mentioned does not work. I have to confess, that I did not try out the method, so I can’t really comment on that.
In this blog I show a different way to archive this. The idea I implement is to add a part to the where clause of the VO which, when executed, return no rows. So I don’t prevent the execution but ensure that no row is returned.
To archive this I add the following where clause:

1 = 0

Now, if I add this as is, the query never will return any row. Instead I use a bind variable
1 = :bindDummy

This allows to use the bind variable to enable the query or in fact disable it. The full query defined in the VO looks like
SELECT Employees.ACTION_COMMENT, 
       Employees.COMMISSION_PCT, 
       Employees.DEPARTMENT_ID, 
       Employees.EMAIL, 
       Employees.EMPLOYEE_ID, 
       Employees.FIRST_NAME, 
       Employees.HIRE_DATE, 
       Employees.JOB_ID, 
       Employees.LAST_NAME, 
       Employees.MANAGER_ID, 
       Employees.PHONE_NUMBER, 
       Employees.SALARY
FROM HR.EMPLOYEES Employees
WHERE 1=:bindDummy

The next challenge is to control the bind variable from the UI. Here ADF Task Flows comes to help. A bounded task flow has a start activity which is executed whenever the bounded task flow is started. I use this start activity to set the bind variable to ’0′ to prevent the return of any row. Then, on the page I have a button which sets the bind variable to ’1′ and execute the query. This time I get the desired result.

adfc-config.xml

adfc-config.xml

I use the EWPTest ViewId to start the sample. On this page I add a button ‘Show Emplyoees’ which navigates to the bounded task flow ‘show-emp-bft’. In this task flow the start activity is ‘ExecuteWithParams’ which sets the bind variable to ’0′.

Bounded Task Flow 'show-emp-bft'

Bounded Task Flow 'show-emp-bft'

Here is the page def file for the start activity. As you see this method call activity call ‘ExecuteWithParams’ and sets the bind variable to ’0′ thus preventing the return of any row from the query.

Start Activity in Task Flow 'show-emp-btf'

As a result the next page only shows an empty table.

Show Employees after entering the page

Show Employees after entering the page

In the toolbar I placed a button ‘Execute with bindDummy set to 1′ which calls the executeWithParams’ method, this time with the bind variable set to ’1′

ExecuteWithParams bind variable set to 1

ExecuteWithParams bind variable set to 1

As the result I get the desired result

Result after ExecuteWithParams with bind variable set to 1

Result after ExecuteWithParams with bind variable set to 1

The ‘Back’ button in the toolbar return from the task flow to the first page. If I hit the ‘Show employees’ again the bind variable is set to ’0′ again and the query again does not return any row.

You can download the sample workspace, build with JDev 11.1.2.1.0 and depending on the HR db schema, from here: BlogExecWithParams_V2.zip.doc
Please rename the file to ‘.zip’ after downloading it!

11. March 2012

JDeveloper & ADF: Reset Form Fields

In the last couple of weeks I saw some posts on JDeveloper & ADF forum asking how to reset form fields when the user had changed some or all fields of an input form and wants to undo the changes. This is a typical use case when you work with forms to enter or change data.

In this blog I summarize the different possible solutions build in the ADF framework. The sample provided for you to analyze is build using JDeveloper 11.1.2.1.0 and uses the HR schema. A link to download the workspace is provided at the end of the blog post.

Before I go into the different solutions, I like to point out that all solutions can only reset values to the last data model state if they are not submitted. After a value is submitted the reset operation will show the same value as in the UI. If you e.g. navigate to the next record all values are submitted to the data model (not the db). Calling reset after you go back to the previous record you’ll see no change as the values are already submitted.
As an implication you need to make sure that the action component (button, listener…) uses the immediate property set to ‘true’. If the immediate property is set to ‘false’ the action first updates the model after which no reset is possible. In this case you can only rollback the transaction to get the old values back.

Lets start with a picture of the running application:

Running Applicaiton

Running Applicaiton

As you see it’s just the employees table dropped as adf form on a jsf page with navigation buttons and an other row of buttons to demonstrate the different possible solution for the use case. First I show how to use java code in a bean to reset the changes made in the form. Next I use a command button with an af:resetActionListener attached. Then there is the new af:resetButton which was introduced in JDev 11.1.2.0.0 and is essentially like the previous solution. As a variation I added two buttons which I use to queue an action from inside a bean method to the second and third buttons. Finally there is cancel button which does a rollback of the transaction. This rollback undo changes even if you navigate back and forth over the row set.

1. Reset field from a java bean

The button ‘Reset Form Fields by Bean’ uses an action listener to call a method in a request scope bean. This method then resets the form fields using the ResetUtils.reset(UIComponent start); method to do the work.

    public void resetFormFieldsListener(ActionEvent actionEvent)
    {
        // check if hte action has a component attatched
        UIComponent uiComp = actionEvent.getComponent();
       
        if (uiComp == null)
        {
            // if not we use the button which we bound to this bean
            uiComp=getButtonResetByBean();
            _logger.info("reset fields: buttonID = " + uiComp.getId());
        }
        else
        {
            _logger.info("reset fields: CompID = " + uiComp.getId());
        }
        // pass component inside the UIForm, UIXForm, UIXSubform, UIXRegion, UIXPopup, RichCarousel
        // or RichPanelCollection which holds the components to reset
        ResetUtils.reset(uiComp);
    }

The ResetUtils.reset(UIComponent start) method walks up the component tree to find the first UIForm, UIXForm, UIXSubform, UIXRegion, UIXPopup, RichCarousel or RichPanelCollection component. Any one of this components are used as container elements for input components (inputText, inputDate …) which are reset to the values stored in the model data. This allows to only reset part of the input components on a page. So passing the right start component to the reset method is essential. In the simple layout I used in the sample it’s OK to use the button which has the actionListener attached. The af:form is the container found by the ResetUtils.reset(UIComponent start) method.
The ResetUtils.reset(UIComponent start); can be used from other bean code too. In this case you need to set a component as start component. Which component you use depends on your page layout.

Solution 1 ResetUtils.reset(...)

Solution 1 ResetUtils.reset(...)

2. Command button with attached resetActionLitener

This was the default solution in JDev 11.1.1.x.0. You attach an af:resetActionListener to an other command component and when an action is triggered the reset take place. See solution 4 for a variation.

        <af:commandButton actionListener="#{bindings.Rollback.execute}"
            text="Cancel" immediate="true" id="cb6">
              <af:resetActionListener/>
        </af:commandButton> 

Solution 2: af:resetActionListener

Solution 2: af:resetActionListener

3. af:resetButton
This component was introduced with JDev 11.1.2.0.0 and works like a command button with an attached af:resetActionListener. Advantage is that you have only the button, nothing attached which makes it more clear to understand.

resetButton

resetButton

<af:resetButton text="Reset Form Fields" id="rb1" binding="#{BRFFBean.buttonResetButton}"/>

Solution 3: af:resetButton

Solution 3: af:resetButton

4. Queue an action to a button with attached af:resetActionListener

This solution is a combination of the first one using java code which then queues an action on an existing button on the page. If this button has an af:resetActionListener attached it resets the form fields as if the user had hit the button itself. On the page I use a button with an actionListener simply to get to a bean method (an actionListener in this case)

<af:commandButton text="Queue Action1 " id="cb9"
                  actionListener="#{BRFFBean.queueAction1Listener}"
                  immediate="true"/>

and in the bean I queue an action to the button with the attached af:resetActionLisener. This button is bound to a bean property to keep things simple.

    public void queueAction1Listener(ActionEvent aEvent)
    {
        _logger.info("Queue action for button wiht af:resetActionListener");
            
        ActionEvent actionEvent = new ActionEvent(this.getButtonResetActionListener());
        actionEvent.queue();
    }

Solution 4: Queue action to existing button with af:resetActionListener

Solution 4: Queue action to existing button with af:resetActionListener

5. Queue an action to a af:resetButton

Like in solution 4 I use an existing button (the af:resetButton in this case) and queue an action on this button using java code in a bean.

<af:commandButton text="Queue Action2" id="cb10"
                  actionListener="#{BRFFBean.queueAction2Listener}"
                  immediate="true"/>

and the code in the bean looks like in solution 4, only the button the action is queued on differs.

    public void queueAction2Listener(ActionEvent aEvent)
    {
        _logger.info("Queue action for af:resetButton");
        ActionEvent actionEvent = new ActionEvent(this.getButtonResetButton());
        actionEvent.queue();        
    }

Now, if you carefully look at the result of this action you’ll notice that nothing has happened. I filed an SR for this, resulting in bug 13802277 ‘QUEUEING AN ACTION EVENT ON AN RICHRESETBUTTON DOESN’T WORK’.

Solution 5: Queue action on af:resetButton

Solution 5: Queue action on af:resetButton

6. Cancel action with rollback

This solution just call the rollback of the data control. This give you the values back which are stored in the DB. This allows even to reset changes which where submitted to the data model, but where not persisted in the db.

You can download the sample workspace, build with JDev 11.1.2.1.0 and depending on the HR db schema, from here: BlogRestFormFields.zip.doc
Please rename the file to ‘.zip’ after downloading it!

5. March 2012

Got my present for 10.000+ points on OTN forum… well no, but still a present :)

Filed under: Uncategorized — Timo Hahn @ 23:23
Tags:

Today I received a surprise package, or better the notification of the parcel service, that there is one waiting for me at my neighbors.
You know the game we start to play: Do we expect a package?
Who send the package?
What’s in it?

It turned out that the package was send by Oracle. Still no clue what’a in.
Finally, unpacking…

Trophy

Trophy

… something for my trophy case

Thank you all

Next Page »

Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 67 other followers