JDeveloper 12.2.1.2 is out

Aside

Today October, 19th 2016 JDeveloper 12.2.1.2 was released. From the first look at it it’s only a maintenance release.  There is currently no ‘What’s new’ document, only a release notes are available.

The release notes show only some bug fixes and some deprecation. Noteworthy are some changes in the REST runtime. One of them is that ADF REST HTTP PUT is deprecated functionality. From the doc

ADF REST HTTP PUT is deprecated functionality

Oracle has deprecated the functionality for executing HTTP PUT methods on ADF REST resource requests. In the current release, the describe for ADF REST resources continues to display PUT actions when the backing view object has the Update operation enabled (the operation enables both PUT and PATCH methods); however, ADF REST service clients should avoid making PUT requests (replace all items of the view row) as this functionality will be desupported in a future release

Another change in the REST department is that adf date and datetime attributes are no longer described as string but as date and datetime. Interesting if you work with ADFbc and Oracle JET.

There are some other small bug fixes and deprecation’s of oracle.domain data types and the dvt:stockGraph. You should use dvt:stockChart instead.

Let’s wait if Oracle releases an ‘What’s new’ document in hte near (?) future which will spear us some time searching for new stuff 🙂

Developer Cloud Service: Continuous Integration with JDeveloper 12.2.1

The last blog showed that the Oracle Developer Cloud Service is now available for JDeveloper and ADF 12.2.1 (Developer Cloud Service with JDeveloper 12.2.1 available). The missing part is the connection of the DCS to the newly created JCS for version 12.2.1. This we show in the blog.

The ground work, how to set up a build system for the DCS has been shown in Fasten your seat belts: Flying the Oracle Development Cloud Service (3 – Take Off – ROTATE). We now have to find out which environment variable to use for the 12.2.1 installation. At the time I wrote the mentioned blog there where only environment variables for 11.1.1.7.1 and 12.1.3.0 available. Looking at the documentation Using Hudson Environment Variables we find that the variables

  • ORACLE_HOME_SOA_12_2_1=/opt/Oracle/MiddlewareSOA_12.2.1/jdeveloper
  • MIDDLEWARE_HOME_SOA_12_2_1=/opt/Oracle/MiddlewareSOA_12.2.1
  • WLS_HOME_SOA_12_2_1=/opt/Oracle/MiddlewareSOA_12.2.1/wlserver

Are the right ones (and the only ones which point to 12.2.1). In the application.properties file (from the ‘… Take Off…’ blog) we exchange

# Don't change anything below!
 oracle.home=${env.ORACLE_HOME_12C3}
oracle.commons=${env.MIDDLEWARE_HOME_12C3}/oracle_common
middleware.home=${env.MIDDLEWARE_HOME_12C3}
install.dir=${env.ORACLE_HOME_12C3} 

with

# Don't change anything below!
oracle.home=${env.ORACLE_HOME_SOA_12_2_1}
oracle.commons=${env.MIDDLEWARE_HOME_SOA_12_2_1}/oracle_common
middleware.home=${env.MIDDLEWARE_HOME_SOA_12_2_1}
install.dir=${env.ORACLE_HOME_SOA_12_2_1} 

This change will use the JDeveloper 12.2.1 to run ojdeploy and configure the application to run on a WebLogic Server 12.2.1. This should do the trick and we can use the DCS build system to create application using ADF 12.2.1. As the application I used for the ‘Fasten your seat belts…’ blog series was pretty simple I like to show the result using the application I used for a presentation at the DOAG DevCamp2016, named AppsClouUIKit. You can read all about this application in a blog I wrote here DOAG DevCamp2016.

The application was build using JDeveloper 11.1.1.9.0 and has been migrated during the DevCamp to 12.1.3. This was the DCS version which was available at the time of the DevCamp. The first task is to migrate the source to 12.2.1 by creating a new branch in the GIT repository for the new 12.2.1 version.

We Clone the repository and create a new branch 12_2_1 which we use to build the AppsCloudUIKit for 12.2.1. As we are now running JDeveloper 12.2.1 we can use the Team-Server to get the sources from the DCS GIT repository

But we can use any other GIT client to get it. As this is covers in other blogs I’ll skip the details here. In the end we have this branch tree

Where the green marked local branch 12_2_1 is the one we are working on.

After changing the application.properies as shown above we can run the build using ant on the local machine

By selecting the ‘deploy’ target.

The result is an EAR file in the deploy folder

Setting up the build job

Let’s check-in the changes and setup the build in the DCS. Here are the steps for the build job

With this we can build the application to get the result

Setting up the Deployment

The final task is to set up the deploy task to deploy the application on the JCS_12_2_1. When we select the ‘Deploy’ tab we see the existing deployment configuration for the 12.1.3 JCS.

For the JCS 12.2.1 we created a new JCS instance with a different IP (public). Before we can create a new configuration for the 12.2.1 JCS instance we have to allow the Hudson user access to the JCS. This process is described in detail at Deploying an Application from Oracle Developer Cloud Service to Oracle Java Cloud Service

It’s absolutely necessary to get the Oracle Developer Cloud Service SSH public key and add this key to the JSC 12.2.1 instance as authorized key. Please follow the instructions given in the link above to do so.

After this is done we can create a new deployment configuration

Start filling in the dialog by giving the configuration a name. Next we create a new ‘Deployment Target’

In the dialog fill in the public IP address from the new JC 12.2.1 and select SSH Tunnel. The user name and password is the one you selected when you created the JCD instance. Test the connection and close the dialog by clicking ‘Use Connection’

Finally we can complete the Deployment dialog

We choose ‘On Demand’ here which let us specify which job/Build and artifact to use. A click to ‘Save and Deploy’ closes the dialog and the artifact will be deployed to the JCS 12.2.1. The URL to open the application is AppsCloudUIKit 12.2.1

And we should see

Good News: ADF and IE11 working together again

Aside

Yesterday (Jan 15th, 2014) Oracle support came up with a patch for JDeveloper in concern of running ADF applications using IE11.
Form Article Id 1599898.1:

Below is a list with available patches for IE11 issues. The list will be updated once more patches become available. However this does NOT mean IE11 is certified but the patches allows you to access the application IE11:

patch 17236592 – IE11 SUPPORT: ADF APPS DON’T LOAD WITH IE11
Patch to avoid the popup shown above from appearing.
Versions: 11.1.1.6.0, 11.1.1.7.0

You need a support contract to get the patch.

JDeveloper 11.1.1.6.0: Escape QBE Operators in Filterable Tables

You may not have noticed that some words like ‘and’ and ‘or’ do have a special meaning if you use them in a filterable af:table. If a column of a db table contains some text which you like to filter via the Query by Example (QBE) feature of the af:table, you’ll notice that you can’t filter for  ‘and’ and ‘or’. These words are used as SQL operands for character columns,  like  ‘>’ or ‘<‘. There is no property to escape these words do that they are treated as normal words. For a full list of QBE operands check the Table 27-2 Query-by-Example Search Criteria Operators.

In this post we learn how to implement such an escape mechanism. The sample work space, which used the HR DB schema, can be down loaded using the link provided at the end of the post.

The solution for the problem is implemented on the vo the table is based on. Surprisingly no change is needed in the view controller. We only need to overwrite one method on the ViewObjectImpl which is used to generate the where clause part out of the filter criteria.

Before we go into the details let’s look at the running application, the problem, and it’s solution.

Running Test Application

Running Test Application

To show the problem without the need to change to much in the HR db we use the FirstName and the LastName column of the employees table. Here we change one or more entries do that they contain the word ‘and’ and ‘or’. In the image the changed lines are EmployeeId 202 and 203.

Filter for 'Pat and John'

Filter for ‘Pat and John’

As you see in the image above you get no row if you enter e.g. ‘Pat and John’ into the filter column of the first name. The reason is that the QBE feature build two where clause parts out of the one filter value as down in the output below.

FINE: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: Employees.FIRST_NAME value: Pat%
INFO: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: Employees.FIRST_NAME value: Pat%
FINE: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: Employees.FIRST_NAME value: John%
INFO: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: Employees.FIRST_NAME value: John%
FINE: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: FirstName value: Pat%
INFO: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: FirstName value: Pat%
FINE: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: FirstName value: John%
INFO: 17.02.2013 15:36:33 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 15 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: FirstName value: John%

As mentioned before this is a feature and not a bug. However, the are use cases where we need to filter for the words which are treated as operands.
We use a trick to escape the operands. We surround the operands by ‘_’. Then they are not treated as special words any more but as normal text.

Filter for 'Pat_and_ John'

Filter for ‘Pat_and_ John’

To make it work we have to remove the ‘_’ in the ViewObject before the query is executed. The output from the method now looks like

 
FINE: 17.02.2013 16:07:22 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 11 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: Employees.FIRST_NAME value: Pat _and_ John
INFO: 17.02.2013 16:07:22 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 11 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: Employees.FIRST_NAME value: Pat and John
FINE: 17.02.2013 16:07:22 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:66) - 11 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Before matching - Column: FirstName value: Pat _and_ John
INFO: 17.02.2013 16:07:22 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl.getCriteriaItemClause(EmployeesViewImpl.java:80) - 11 - de.hahn.blog.qbe.model.vo.EmployeesViewImpl
  Column: FirstName value: Pat and John

For this we overwrite the ‘public String getCriteriaItemClause(ViewCriteriaItem vci)’ method in the ViewObjectImpl.

 
    /**
     * Build the where clause for the criteria item 
     * @param vci
     * @return null if we use hte default where clause, the where clause part if we want to change the default.
     */
    @Override
    public String getCriteriaItemClause(ViewCriteriaItem vci) {
        if (vci != null) {
            AttributeDef attrDef = vci.getAttributeDef();
            String attrName = attrDef.getName();
            // for string attributes check for the '_xxx_' sequence and remove the '_' around hte operator
            if ("java.lang.String".equals(attrDef.getJavaType().getName()) && vci.getValue() != null) {
                String colName = vci.getViewCriteria().isCriteriaForQuery() ? vci.getColumnNameForQuery() : attrName;
                String operator = vci.getOperator();
                String filterVal = (String)vci.getValue();
                _logger.fine("Before matching - Column: " + colName + " value: " + filterVal);
                int i = filterVal.indexOf("_");
                while (i > -1) {
                    int k = -1;
                    String subFilter = null;

                    k = filterVal.indexOf("_", i + 1);
                    if (k > -1) {
                        filterVal = filterVal.replaceFirst("_", "");
                        filterVal = filterVal.replaceFirst("_", "");
                    }
                    i = k;
                }

                _logger.info("Column: " + colName + " value: " + filterVal);
                // handling for STARTSWITH operator
                if (JboCompOper.OPER_STARTS_WITH.equals(operator)) {
                    int columnsValue = vci.getUpperColumnsValue();
                    // check if hte parameters are uppercase
                    String sql = "(%s like '%s%%')";
                    if (columnsValue != -1)
                        sql = "(UPPER(%s) like UPPER('%s%%'))";
                    String clause = String.format(sql, colName, filterVal);
                    return clause;
                }
                // handle other operators here
            }
        }
        return super.getCriteriaItemClause(vci);
    }

As the method is called for every criteria item we have to check if the current criteria is of type string as only string criteria react on the operands.
Then we need to create the where clause part for the criteria our self. The method implements this only for the ‘startswith’ operand!
If you need this for other operators too, you have to add the code to build the where clause at the commented point.

The workspace can be loaded from ADF EMG Samples Project. The sample uses the HR db schema and was developed using JDeveloper 11.1.1.6.0

JDeveloper 11.1.1.6.0: The Git Experience (Part 2)

End of November Oracle released a new JDeveloper version 11.1.1.6.0 Build 6229 (What’s new 11.1.1.6.0) which introduces Git support as one of the new features.
Part 1 showed how to setup and use git integration in JDeveloper
In part 2 of the series I show how branching and merging are done using the git integration in JDeveloper.

Let’s start with a picture of the current git repository:

Repository at Start

Repository at Start

Here is the first missing part in JDeveloper’s git integration. There is no visual representation of the whole repository available as shown in the image above. To get such a representation we need to install a third party tool (msysGit in my case, or Tortoise Git which can run in parallel on a Win7 machine). JDeveloper only allows you to see the history of one file via the ‘Version History’ menu. The images of the repository we’ll see in this blog are done with msysGit.

As we see there is only one branch named ‘Master’ and we see a straight line of dots, each representing a commit to the ‘Master’ branch. We start by adding a new branch to the repository named ‘AddCalcuatorClass’. The name of the branch can be almost anything, as long as it doesn’t contain spaces. We choose the name of a branch so that it reminds us later why we created the branch, or what it’s used for. As the name of the branch indicates we add a class to the project which implements a simple calculator.

Create New Branch

Create New Branch

Name the new branch ‘AddCalcuatorClass’

Name Branch

Name Branch

The ‘Application Navigator’ did not change, but the new branch is visible in the ‘Version Navigator’ in JDevelpoer

Version Navigator

Version Navigator

the same from the view of msysGit:

msysGit Repository after adding new Branch

msysGit Repository after adding new Branch

We need to play close attention to the different views and what they tell us. In JDeveloper we still see ‘[master]’ behind the project name. This tells us that we are still working on the ‘master’ branch and not the new created branch ‘AddCalculatorClass’. The msysGit image shows the same as the ‘master’ branch is printed in bold (which it does for the current branch).
To switch to the new branch we need to checkout the branch.

Checkout Branch

Checkout Branch

then click the ‘Select Branch’ button in the dialog to get to the available branches and select the ‘AddCalculatorClass’ and click ‘OK’, finally close the dialog by clicking ‘OK’ again.

Select Branch

Select Branch

After that we are working on the ‘AddCalculatorClass’ branch, only we don’t see it right away. We need to refresh the project (e.g. clicking the refresh button) to see the ‘[AddCalculatorClass]’ right to the project name.

Now working on 'AddCalaculatorClass' Branch

Now working on ‘AddCalaculatorClass’ Branch

Again the msysGit image:

msysGit: new active Branch

msysGit: new active Branch

Now we add a new class ‘Calculator’ to the project. For this we add the new class from the ‘Candidate’ tab and then commit the new file by committing it

Add new Class to Project and Repository

Add new Class to Project and Repository

Add new File

Add new File

Commit

Commit

Commit dialog

Commit dialog

Repository after adding new File

Repository after adding new File

Now we add an other method in the calculator class which should multiply to parameters and return the result. After that we commit the change and the repository looks like:

Repository after Change of Calculator Class

Repository after Change of Calculator Class

Let’s assume that we have to fix a bug in the main development path, which is ‘master’. We have to switch back to the ‘master’ branch. This is done by checking out the ‘master’ branch again. The procedure is the same we already saw before. The result in JDeveloper looks like:

Back on Branch 'master'

Back on Branch ‘master’

msysGit: Back to 'master'

msysGit: Back to ‘master’

As we see the new class ‘Calculator’ is not part of the project as it was not added in the ‘master’ branch. Back to the ‘master’ branch we add another class ‘Stack.java’ and add some lined to the existing class. After committing the changes, in multiple commit cycles to get a better visibility of the different branches, the repository look like:

Repository after change to 'master'

Repository after change to ‘master’

Let’s switch back to the ‘AddCaclulatorClass’ branch to finish the work on this class by adding two more methods to subtract and divide to parameters. After this work is done the repository look like:

Repository after more work don in 'AddCalculatorClass' Branch

Repository after more work don in ‘AddCalculatorClass’ Branch

A requirement is that we need the changes done in the ‘master’ branch now need in our current branch ‘AddCalculatorClass’. For this we need to merge the branch ‘master’ to the current branch ‘AddCalculatorClass’. This is easily archived by opening the ‘Version Navigator’, open the node of the project and then the open the ‘Branches’, ‘Local’node. Here we see the currently available branches ‘master’ and ‘AddCalculatorClass’. The same can be archived by right clicking the Project and select ‘Versioning->Merge…’.

Merge 'master' Branch

Merge ‘master’ Branch

Merge

Merge

After Merge

After Merge

Don’t forget to refresh the project to see the added class. The resulting repository now looks like

Repository after Merge

Repository after Merge

with all changes made to the branch ‘master’ including the new class Stack. We could have done the merge the other way around. Then we had to checkout branch ‘master’ and then merge branch ‘AddCalculatorClass’. This would give us a repository looking like:

Merge 'AddCalculatorClas' to 'master'

Merge ‘AddCalculatorClas’ to ‘master’

The difference at this moment is, that the changes are visible in the ‘master’ branch and which branch is active after the merge. We can create another branch from every other tag or branch currently present in the repository. Let’s make a new branch ‘DoCalcDifferent’ from the ‘master’ branch. Remember that we are currently in branch ‘AddCalculatorClass’. Still we are able to create the new branch. We can also create a branch based onany other branch like ‘AddCalculatorClass’ which we call ‘AddCalc2’. A look at the repository after all this:

Branch Festival

Branch Festival

We see it’s easy to create new branches, switch between them to do some work, merge the different branches without problems. Make yourself familiar with the technique and how to use it. This is especially true after some wild changes to different branches. We may end up with a confusing repository like

Complex Repository after some changes

Complex Repository after some changes

where it’s not obvious which change created which node in the repository. It may take a while, but in the end it’s much easier then it looks and it’s more productive then SVN or CVS.

Learning to use git the integration into JDeveloper is a good start. However, we need some of the other git commands (e.g. cherry pick) or representations (gitk to view the whole repository) integrated into JDeveloper to make it really a great tool integration.

I have planned a third part for this series, but can’t really tell when it is going to happen. This 3rd part covers remote git repositories which add a new dimension to the git picture. Right now I don’t have a remote git repository available. I’m looking into this issue in the next couple of days/weeks and hopefully get one installed and running.

JDev 11.1.2.1.0: Dealing with ADF_FACES-60003 Error: Component with ID: r1:1:cb1 not registered for Active Data.

The last couple of weeks I saw some questions on OTN JDev forum dealing with file and image handling in ADF applications. All of the needed information to do this is already published in various blog posts and tutorials, still I did not find a post covering all aspects with a single demo application.

I’m in the progress of writing a mini series about file handling (upload and download) and image handling in ADF applications providing exactly this demo application. If you are interested in this stay tuned, as the first part is almost ready to publish.

Now, while I assembled the demo application I stumbled upon this error:

java.lang.IllegalStateException: ADF_FACES-60003:Component with ID: r1:1:cb1 not registered for Active Data.
	at oracle.adfinternal.view.faces.activedata.PageDataUpdateManager.unregisterComponent(PageDataUpdateManager.java:600)
	at oracle.adfinternal.view.faces.context.RichPhaseListener.handleStartAndStopActiveData(RichPhaseListener.java:502)
	at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl._executePhase(LifecycleImpl.java:479)
	at oracle.adfinternal.view.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:204)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:312)
	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:300)
	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:173)
	at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
	at oracle.adfinternal.view.faces.webapp.rich.RegistrationFilter.doFilter(RegistrationFilter.java:122)
	at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:468)
	at oracle.adfinternal.view.faces.activedata.AdsFilter.doFilter(AdsFilter.java:60)
	at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl$FilterListChain.doFilter(TrinidadFilterImpl.java:468)
	at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl._doFilterImpl(TrinidadFilterImpl.java:293)
	at org.apache.myfaces.trinidadinternal.webapp.TrinidadFilterImpl.doFilter(TrinidadFilterImpl.java:199)
	at org.apache.myfaces.trinidad.webapp.TrinidadFilter.doFilter(TrinidadFilter.java:92)
	at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
	at weblogic.servlet.utils.FastSwapFilter.doFilter(FastSwapFilter.java:66)
	at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
	at oracle.security.jps.ee.http.JpsAbsFilter$1.run(JpsAbsFilter.java:111)
	at java.security.AccessController.doPrivileged(Native Method)
	at oracle.security.jps.util.JpsSubject.doAsPrivileged(JpsSubject.java:313)
	at oracle.security.jps.ee.util.JpsPlatformUtil.runJaasMode(JpsPlatformUtil.java:413)
	at oracle.security.jps.ee.http.JpsAbsFilter.runJaasMode(JpsAbsFilter.java:94)
	at oracle.security.jps.ee.http.JpsAbsFilter.doFilter(JpsAbsFilter.java:161)
	at oracle.security.jps.ee.http.JpsFilter.doFilter(JpsFilter.java:71)
	at weblogic.servlet.internal.FilterChainImpl.doFilter(FilterChainImpl.java:56)
	at oracle.dms.servlet.DMSServletFilter.doFilter(DMSServletFilter.java:136)
	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.wrapRun(WebAppServletContext.java:3715)
	at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3681)
	at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
	at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
	at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2277)
	at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2183)
	at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1454)
	at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
	at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)
...

It happened when I used a af:fileDownloadActionListeneron a detail page fragment and navigated back to the master page fragment. As I never saw the error before and did not use ‘Active Data’ anywhere in my demo, I started digging.

There are some members of OTN hitting the same error (may be not under the exact same conditions) as this thread shows.
The thread points to an older post which mentions that this is caused by the bug 9218151 and is fixed in JDev 11.1.2.0.0. As I use JDev 11.1.2.1.0 this should not happen, or I see a regression of the bug in JDev 11.1.2.1.0. The bug database did not help either, as there is very little information on the bug itself.
The solution given in the thread to use a custom error handler (and ignore the error) did not seem right to me. I did not try the other solution to write a custom tag either, as it looks like overkill to me.

The normal debugging of this problem didn’t get me further to a solution. I tried a couple of things and even was able to get around the error with some hacks I will not publish here.

Luckily I met Frank Nimphius at the DOAG2011 and ask him about this bug (that’s what such events are for :)). He gave the right pointer to solve the problem.
With JDev 11.1.2.0.0 a new default ‘change event policy’ was introduced to the iterators and components. Now the policy is ‘ppr’ and not ‘none’ as before.
Jobinesh had blogged about the new ‘change event policy’ and its meaning here.

As I couldn’t reproduce this behavior in JDev 11.1.1.5.0 Franks suggestion was to set the change event policy back to none. After doing exactly this the error is gone, the application runs as expected.

The new policy can be changed (back to the old behavior) on a global level for applications you are building new under JDev 11.1.2.x. To do this open the adfc-config.xml file from the ‘Application Resources:

adfc-config.xml

adfc-config.xml

change to the ‘Overview’ tab and select the ‘Model’. Here you remove the selection from the check box:

adfc-Config.xml Change Event Policy

adfc-Config.xml Change Event Policy

If you already have done some work in your project, e.g. used some views on an UI page, you have to change the iterators one by one. For this open the bindings of the page and select an iterator:

Change Event Policy on Iterator

Change Event Policy on Iterator

You may let the default ‘change event policy’ be ‘ppr’ if you like, as there are some advantages (there must be a reason why Oracle changed it in the first place). Only if you hit the error you can change the policy for the iterators involved. Keep in mind, that changing the policy later may have some side effects to your existing pages. It’s up to you to decide and test this.

I’ll file an SR for this just to make sure that Oracle looks into this again. For me it looks like a bug as I don’t understand why I get an error at all.

JDev: How to reset a filter on an af:table

In my last blog entry “How to reset or undo a af:table sort” I showed how to clear a sort on a column of an af:table.

Chris Muir asked me to do a follow up showing how to do the same for a filter an an af:table. A short research about this question did not turn up anything. If somebody already has bloged about this, please drop me note and I’ll mention you for reference.

************
OK, just 5 minutes after first publishing I found Steve Muenchs sample #146 at http://blogs.oracle.com/smuenchadf/resource/examples. More to come?
************

You can download a sample workspace, which was set up using JDeveloper 11.1.2.1.0 and the HR schema as DB connection, using the link at the end of the blog.

The use case for the blog is

  1. A use has a filterable af:table on a page. At some point he fills in one or more filter criteria and executes the query.
  2. Now he wants to clear the filter criteria to show all rows again.

Here is the code for a table with filtering enabled. As you see the filter is implemented as a filterModel (line 06: filterModel=”#{bindings.ImplicitViewCriteriaQuery.queryDescriptor}”).

                        <af:table value="#{bindings.EmployeesView1.collectionModel}" var="row"
                                  rows="#{bindings.EmployeesView1.rangeSize}"
                                  emptyText="#{bindings.EmployeesView1.viewable ? 'No data to display.' : 'Access Denied.'}"
                                  fetchSize="#{bindings.EmployeesView1.rangeSize}"
                                  rowBandingInterval="0"
                                  filterModel="#{bindings.ImplicitViewCriteriaQuery.queryDescriptor}"
                                  queryListener="#{bindings.ImplicitViewCriteriaQuery.processQuery}"
                                  filterVisible="true" varStatus="vs"
                                  selectedRowKeys="#{bindings.EmployeesView1.collectionModel.selectedRow}"
                                  selectionListener="#{bindings.EmployeesView1.collectionModel.makeCurrent}"
                                  rowSelection="single" id="resId1" styleClass="AFStretchWidth"
                                  binding="#{ResetTableFilterBean.empTable}"
                                  columnStretching="multiple">
                            <af:column sortProperty="#{bindings.EmployeesView1.hints.EmployeeId.name}"
                                       filterable="true" sortable="true"
                                       headerText="#{bindings.EmployeesView1.hints.EmployeeId.label}"
                                       id="resId1c1">

From the javadoc

getFilterModel

public final java.lang.Object getFilterModel()

    Gets the model used for filtering of data in the table. This attribute must be bound to an instance of FilterableQueryDescriptor class.

we see that the filterModel needs to be casted to a FilterableQueryDescriptor. A look into the javadoc shows that the class has a method to get a map of all criteria entered into the filter fields of a table. Here’s the javadoc for the FilterableQueryDescriptor.getFilterCriteria() method:

getFilterCriteria

public abstract java.util.Map<java.lang.String,java.lang.Object> getFilterCriteria()

    Gets the filter criteria associated with the query descriptor. Filter Criteria are generally useful for filtering data in the table.

    Returns:
        Map<String, Object> containg the filterCriteria

Clearing this map clears the filter fields of the table. Finally we queue an query event to the table to refresh it. Here is the bean code:

public class ResetTableFilterBean
{
    private RichTable empTable;

    public ResetTableFilterBean()
    {
    }

    public void resetTableFilter(ActionEvent actionEvent)
    {
        FilterableQueryDescriptor queryDescriptor =
            (FilterableQueryDescriptor) getEmpTable().getFilterModel();
        if (queryDescriptor != null && queryDescriptor.getFilterCriteria() != null)
        {
            queryDescriptor.getFilterCriteria().clear();
            getEmpTable().queueEvent(new QueryEvent(getEmpTable(), queryDescriptor));
        }
    }

    public void setEmpTable(RichTable empTable)
    {
        this.empTable = empTable;
    }

    public RichTable getEmpTable()
    {
        return empTable;
    }
}

In the following picture we see a page holding the query panel with a table with filter enabled. A search for employees with last name starting with ‘K’ has been executed and the result has been filtered for last name starts with ‘Ki’.

Query Panel with Filterable Table

Query Panel with Filterable Table

After a click an the ‘Reset Table Filter’ button clears the filter and shows the result for the query only.

Filter reset

Filter reset

The sample workspace uses JDeveloper 11.1.2.1.0 but the bean code should work in older JDeveloper version 11.1.1.x too. The sample used the HR schema as DB connection. You can download the sample workspace from BlogResetTableFilter.zip
After downloading the file rename it to ‘BlogResetTableFilter.zip’!

The sample also contains an other page showing the same for a simple table without the query panel.

ADFLogger: Using a Custom Formatter Class to Print Log Messages

Based on some posts on the OTN JDeveloper forum this article shows how to implement a custom fdormatter class to use with ADFLogging and how to integrate it with the embedded WLS instance in JDeveloper. Sample workspace for the custom logger is available at the end of the article.
For this post I assume you now your way around java.util.logging. I show how to implement a custom formatter class to format the log messages with more information and a different style. The picture below shows the general java logging model:

General Logging Model

General Logging Model


As the model shows the formatter is used by the log handler which gets a log record and processes it by piping the record through a filter and then through a formatter to finaly pass it to the attached output target. In most cases the output target is a file, a db table, a system log or a stream. For the console logger its most often a stream (e.g. stdout and/or stderr).

A typlical JDev log message from the ConsoleFormatter looks like this:

<AdfcAppInitializer> <loadDebugFacades> ADFc: Initializing ADF Debugger

I’ll change this to:

FINE: 22.09.2011 13:18:17 - de.hahn.blog.popupregion.backingbeans.pageflow.SelectionBean$beaVersion0_39.selectionListenerEmp(SelectionBean.java:92) - 15 - de.hahn.blog.popupregion.backingbeans.pageflow.SelectionBean
  Selected: oracle.jbo.Key[105 ]

The general layout of the log message is

data in [] is customizable, data in {} is printed only if available
level: date time [- threadId] [- class] [- method] [- message] {- throwable.message}
These parameters configure which information to print
       t = thread
       n = logger name
       l = line number; if 'l' is selected 'c' and 'm' are not used
       c = class name
       m = method name

As you see there is more information printed, e.g. source and line number and log level. As this creates long log lines I made this customizable. How the parameters are passed to the logger is shown later.

First of all I implement a class DebugFormatter which extends java.util.logging.SimpleFromatter as this class is an implementation of the abstract class java.util.logging.Formatter the base of all formatter attached to a log handler. The key part of this class is the method

public String format(LogRecord record) {...}

which gets a log record and returns a string of the information which send to the handler for further action. The format method checks the parameters given and returns a string according to them.

To wire things up I modify the logging.xml file which can be reached from the ‘Application Server Navigator’. Right click on the integrated WLS and select ‘Configure Oracle Diagnostic Logging for …’. This will open a nice graphical overview

Logging.xml

Logging.xml


Now I add a new logger by clicking the green ‘+’ sign and specifying the log level and the name of the logger, which is actually the part of the class path the logger reacts on.
Add  Logger

Add Logger


this creates a new line in the logging.xml file looking like
Added Line

Added Line


Next I set up a new log handler in the logging.xml file which uses my DebugLogger class as formatter. Together with the log handler I specify the parameters which configure the output format of the string. The DebugLogger is not used directly, but instead a wrapper class WLSConsoleFormatter used which specifies default parameter set to the DebugFormatter. This way you can omit the parameters in the setup. Below is the resulting log handler entry in the logging.xml file:

        <log_handler name='blog-console-handler'
                     class='de.hahn.blog.consoleformatter.logger.BlogConsoleHandler' level='ALL'
                     encoding='UTF-8'>
            <property name='formatStyle' value='tnlcm'/>
            <property name='formatter'
                      value='de.hahn.blog.consoleformatter.logger.WLSConsoleFormatter'/>
        </log_handler>

To add this you need to change to the source view for the logging.xml file.
Finally I change the added logger to use the new handler

        <logger name='de' level='TRACE:1' useParentHandlers='false'>
            <handler name='blog-console-handler'/>
            <handler name="odl-handler"/>
        </logger>

I have to set the useParentHandlers to false to prevent that the messages get printed multiple times. To be able to analyze the messages with the log analyzer I add the ODL handler too. Now all log messages are printed to the console and to the ODL logger.

Now that the logger are setup in the logging.xml all I need to do is to make the classes available to the WLS instance. For this I build a jar from the project and put the resulting BlogConsoleFormatter.jar in a folder where WLS picks it up while starting. There a a couple of folder, but I choose <ide.system.dir>/DefaultDomain/lib folder. ide.system.dir is also known as the systemfolder of your JDeveloper installation. If you don't know where to find it check this blog. You can either copy the jar into the folder or setup the deployment profile to generate the jar in this folder.

Sample Oiutout

Sample Oiutout

The picture above show a small code sample with the generated output from DebugFormatter. As you see the log lines are marked as links. If you click on such a line you see that you are transfered to the code location of the message.

You can download the source code for the BlogLogConsoleFormatter.zip and a BlogPopupRegion.zip using the ADFLogger to generate messages in different log levels. After downloading the files you need to remove the ‘.doc’ suffix and rename them to ‘.zip’ as the files are normal zip files.
The sample workspaces are developed with JDeveloper 11.1.2.0.0, BlogPopupRegion uses the HR schema as DB connection.

JDeveloper Versions vs. Weblogic Server Versions

UPDATE 21-Dec-2012: added info for JDev 11.1.2.x running on WLS 10.3.5 to match the Certification Matrix
UPDATE 29-Nov-2012: added note for new JDev 11.1.1.6.0 Build 6229 released Nov-2012
UPDATE 13-Jul-2013: added info for JDev 12c released 10-Jul-2013
UPDATE 26-Jun-2014: added info for JDev 12cR1 (12.1.3) released 26-Jun-2014

The last couple of days more people are trying to run ADF applications build with JDeveloper of version X on a Weblogic Server with a different ADF Runtime version Y installed.

To make it clear, this will not work!

You need to make sure that the ADF Runtime versions of  JDeveloper and Weblogic Server match. Next thing is that you can’t install the ADF Runtime on any Weblogic Server you like. The ADF Runtime will only work with a specific Weblogic Server. As each JDeveloper version comes with its own ADF Runtime version, there is a direct connection between JDeveloper and Weblogic Server.

To help you to use the right combination use the below table:

JDeveloper (ADF Runtime) Weblogic Server Info
11.1.1.2.0 10.3.2
11.1.1.3.0 10.3.3
11.1.1.4.0 10.3.4
11.1.1.5.0 10.3.5
11.1.1.6.0 10.3.5, 10.3.6 Integrated WLS is 10.3.5, stand alone WLS can be 10.3.5 or 10.3.6 (see Chris Muir on adf runtime 11.1.1.6.0)
Important Note: there are two releses of JDev 11.1.1.6.0 out. The first one release Feb 2012 (Build 6192.1) and the second one Nov 2012 (Build 6229). Both use the same ‘ADF Runtime Installation’ so there in no new ‘ADF Runtime’ installation available or needed. Read Release Notes for more information on this.
11.1.1.7.0 10.3.5, 10.3.6 Integrated WLS is 10.3.5, stand alone WLS can be 10.3.5 or 10.3.6 (see Chris Muir on adf runtime 11.1.1.6.0)
11.1.2.0.0 10.3.5 + Sherman patch Only available via MOS: patch  #12611176 and  patch #12556632; requires ADF 11.1.2.x patches onto Application Development Runtime 11.1.1.5.x
11.1.2.1.0 10.3.5 + Sherman patch UPDATE1 Only available via MOS: patch #12979653 and patch #12917525; requires ADF 11.1.2.x patches onto Application Development Runtime 11.1.1.5.x
11.1.2.2.0 10.3.5 + Sherman patch UPDATE2; 10.3.6 + Sherman patch UPDATE2 Only available via MOS: patch #13656274 and patch #13656372 (see Patch Numbers for ADF Runtime Libraries Update to 11.1.2.2.0 for more info); running on WLS10.3.5 requires ADF 11.1.2.x patches onto Application Development Runtime 11.1.1.6.x
11.1.2.3.0 10.3.5 + Sherman patch UPDATE3; 10.3.6 + Sherman patch UPDATE3 Only available via MOS: patch #14582286 (ADF) and patch #14582309 (WebCenter); running on WLS10.3.5 requires ADF 11.1.2.x patches onto Application Development Runtime 11.1.1.6.x
11.1.2.4.0 10.3.5 + Sherman patch UPDATE4; 10.3.6 + Sherman patch UPDATE4 Only available via MOS: patch #16546129 (ADF) and patch #16546157 (WebCenter); running on WLS10.3.5 requires ADF 11.1.2.x patches onto Application Development Runtime 11.1.1.6.x
12.1.2.0.0 12.1.2.0.0 WLS 10.3.5+ can be used if no ADF is used in the application!
Running a standalone WLS12.1.2.0.0 needs a Oracle DB 11.1.0.7+, Oracle DB 11.2.0.3+ or Oracle DB 12.1.0.1+
12.1.3.0.0 12.1.3.0.0 WLS 10.3.5+ can be used if no ADF is used in the application!
Running a standalone WLS12.1.3.0.0 needs a Oracle DB 11.1.0.7+, Oracle DB 11.2.0.3+ or Oracle DB 12.1.0.1+

There is no backward or forward compatibility!

You don’t need to try, I’ve tested most but not all combinations and run into trouble whenever I mixed versions.

For my tests I used used a small ADF application based on the HR schema.The UI consists of an af:query with a panelCollection for the result table and abounded task flow for editing a row in a popup.

The application was build on JDeveloper under Window 7, the resulting ear file was deployed (using the WLS console) on the Weblogic Server on a Linux box.

The ADF Runtime  installed on the WLS was downloaded from here. The WLS  installed on the Linux box was downloaded from here. I used the “Oracle WebLogic Server 11gR1 (10.3.5) + Coherence – Package Installer” and installed the WLS without  Coherence. After installing WLS the ADF Runtime installation was applied.

Three ways to delete a row while navigate over a RowSet

An OTN user ask how to delete a row while navigation a row set. This question and the problem the user got with implementing this leads to this sample. Shay Shmeltzer mentioned a pending bug #12671112 in JDev 11.1.2 which may cause trouble deleting a row while navigation a row set. As far as I understand only the first method (direct delete via data control) is affected by the bug.

The are a couple of ways to archive this task. This sample uses the declarative way of doing this. So no bean code is involved. I’m using the HR schema and the departments table to show the techniques. Be sure to save the content of the DEPARTMENTS table as the deletion will remove some rows if you commit the operation. For this you can e.g. export the table content as SQL insert statements to a file.

You can download the sample code from here
You need to remove the suffix ‘.doc’ as the file itself is a zip archive.

The sample shows three approaches to the problem, all declarative.
First I use the ‘Delete’ method from the DataControl ViewObject to delete the currently selected row.
The second approach uses a custom method in th e VO which gets the department id to remove as a parameter.
Finally the third approach uses a task flow method call to the above mentioned method to archive the deletion of the row which is identified by the passed department id.

Final application

Final application

The application consists of a ADF form together with the navigation buttons, commit and rollback button and one button to activate each of the three solutions.

1. Solution

The delete button is bound directly to the ‘Delete’ method of the VO of the DataControl:

<af:commandButton actionListener="#{bindings.Delete.execute}"
    text="Delete" immediate="true" id="cb9"/>

and the binding

Delete Binding

Delete Binding


As mentioned above the solution might cause trouble. For more info read this thread.

2. Solution

The second approach uses a custom method which is implemented in the DepartmentViewObject. The method receives the department id to delete as parameter, uses a viewCriteria to find the row and deletes the row if found. The method is exposed in the client interface of the VO to make it accessible on the UI layer.

    /** Delete the department row with the department id aDepId
     * Search the department via its id and if found delete the row without committing
     * @param aDepId Id of the department to delete
     */
    public void deleteDepartmentById(Number aDepId)
    {
        this.setWhereClauseParams(null);
        this.setWhereClause(null);
        this.setbindDepId(null);
        ViewCriteria lCriteria = this.getViewCriteria("DepartmentByIdCriteria");
        removeApplyViewCriteriaName(lCriteria.getName());
        this.applyViewCriteria(lCriteria);
        this.setbindDepId(aDepId);
        this.executeQuery();
        Row row = this.first();
        if (row != null)
        {
            row.remove();
            mLogger.info("Row with DepId " + aDepId.toString() + " deleted (not committed yet)!");
            removeApplyViewCriteriaName(lCriteria.getName());
            this.executeQuery();
        }
        else
        {
            mLogger.info("Row with DepId " + aDepId.toString() + " not found!");
        }
    }

The button ‘deleteDepartmentById’ binds this method to the button

<af:commandButton actionListener="#{bindings.deleteDepartmentById.execute}"
    text="deleteDepartmentById"
    disabled="#{!bindings.deleteDepartmentById.enabled}"
    id="cb7" immediate="true"/>

and the binding of the method

Binding DeleteDepartmentById

Binding DeleteDepartmentById


In this case the selected department id is passed to the method directly in the binding dialog (which is opened when you drop a method which needs a parameter onto the page:
Edit Action Binding of DeleteDepartmentById

Edit Action Binding of DeleteDepartmentById

3. Solution

The final approach used the same method mentioned in the 2nd approach, but uses a task flow method call to execute it.

Task Flow Method Call

Task Flow Method Call


The Button uses a af:setPropertyListener to pass the selected department id to the method in pageFlowScope variable ‘#{pageFlowScope.depId}’

<af:commandButton text="Delete Row via TaskFlow" id="cb8"
    action="delete" immediate="true">
    <af:setPropertyListener from="#{bindings.DepartmentId.inputValue}"
        to="#{pageFlowScope.depId}"
        type="action"/>
</af:commandButton>

The task flow method call was dropped from the dataControl onto the bounded task flow. The picture below shows the pageDef file which was generated by the framework:

PageDef of Method in TaskFlow

PageDef of Method in TaskFlow


This time the parameter is read from the pageFlowScope variable ‘#{pageFlowScope.depId}’.

All three solutions are doing the same in the end: they delete a row from a row set. Solutions 2 and 3 can be used when the table you use to select the row is based on an other (e.g. read only) VO then the VO you use to delete the row.
The same technique can be used for other methods defined in the VO too, e.g. to select a row in a read only table and edit the row in a ADF form (using a method which find the row ba id).