Case Study: Backporting a JDeveloper Project from11gR2 to 11gR1

I got a couple of queries to backport my file and image handling sample, which was built using JDeveloper 11.1.2.x version, to JDeveloper 11.1.1.x version. This I have done and like to share the steps on how to do this.

Here are the general steps:

  1. copy the workspace from 11gR2 into a fresh folder which you should onöy access with 11gR1. It’s essential to don’t open one workspace with different workspaces as this might change descriptors and or files.
  2. open the ‘.jsw’ file in 11gR1. If you get a message if you want to migrate answer ‘yes’
  3. recompile the model project.
  4. make the necessary changes to the viewController project files: ui pages and descriptors
  5. Test the application

As base for this case study we use the sample BlogUploadDownloadV2.zip which is the final sample from the Part 3.

1) unzip the sample into a fresh folder. We use the same folder names from the zip archive, but use a different base directory (backport in this case)
2) The images below show the steps to take after copying the files into the backport folder and opening the ‘.jws’ file. Don’t be fooled by the wizard which tell you that the files are converted from jsf1.0 to jsf1.2. Somehow hte wizard only knows that that the files are not jsf1.2 so it assumes that they are jsf1.0.

3) The database project don’t need any attention. The model project can just be recompiled. Here are the last lines after the rebuild. If you like you can test application module using the application module tester

...
Validating Business Component: de.hahn.blog.uldl.model.businessobjects.Catalog
  copying de/hahn/blog/uldl/model/businessobjects/Catalog.xml to output directory
Updated file:/Q:/backport/BlogUploadDownload/ULDLModel/classes/META-INF/adfm.xml
[7:11:42 PM] Successful compilation: 0 errors, 0 warnings. 

4) Now we have to make some obvious changes to the ViewController project. Fist we have to check if the ui pages are built using JSPX pages of JSF pages. A look into the public_html folder reveals that there is only one page (Catalog.jsf) which was built as JSF page. In a first step we rename the file to Catalog.jspx. Fragments have the suffix ‘.jsff’ in both versions, but are based on different schemas. However, we don’t need to rename the fragments.
Now we refresh the viewController project to see the new jspx file.

Refresh Project

Refresh Project


When we open the file we’ll see an error which is hte result that we tried to open a jsf (renamed only to jspx) page in 11gR1.
Error opening the Catalog.jspx

Error opening the Catalog.jspx


We ignore the error and continue our work. To fix the error we have to look into the file (source) and see that the jsf page uses a different root element:

<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">

whereas a jspx page uses

<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
  <jsp:directive.page contentType="text/html;charset=UTF-8"/>
<f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">

After changing this root element and adding the close tag, the whole page look like

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
    <jsp:directive.page contentType="text/html;charset=UTF-8"/>
    <f:view xmlns:f="http://java.sun.com/jsf/core" xmlns:af="http://xmlns.oracle.com/adf/faces/rich">
        <af:document title="Catalog.jspx" id="d1">
            <af:form id="f1" usesUpload="true">
                <af:panelStretchLayout topHeight="50px" id="psl1">
                    <f:facet name="top">
                        <af:outputText value="Upload Download Test" id="ot1" inlineStyle="font-size:xx-large;"/>
                    </f:facet>
                    <f:facet name="center">
                        <af:region value="#{bindings.catalogtaskflowdefinition1.regionModel}" id="r1"/>
                        <!-- id="af_one_column_header_stretched"  -->
                    </f:facet>
                </af:panelStretchLayout>
            </af:form>
        </af:document>
    </f:view>
</jsp:root>

We still see red marks in the right side gutter of the file. These are because we have not jet changes the libraries used by the project. After removing the JSF2.0 library we use the ‘Code Assist’ function of JDeveloper to add the correct JSF1.2 tag libs and libraries.


You may have to close JDeveloper and reopen it again to get rid of the red marks. After this you can open hte Catalog.jspx file in design mode:
Migrated Catalog.jspx

Migrated Catalog.jspx


The next step is to look into the ‘.jsff’ fragments. These too are using a different schema. This is the JSF2.0 fragment which uses a tag:

<?xml version='1.0' encoding='UTF-8'?>
<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
                xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
                xmlns:f="http://java.sun.com/jsf/core">

The JSF1.2 fragment uses a jsp:root element instead:

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:af="http://xmlns.oracle.com/adf/faces/rich" xmlns:f="http://java.sun.com/jsf/core">

Changing the ui:component tag to the jsp:root tag (don’t forget to change the end tag) the fragments can be opened in design mode too. Depending on the components you have used in your may have to change some ui components to get your page to work.
Next step is to adjust the Databindings.cpx which still holds a link to the Catalog.jsf page.

Old Databindings.cpx

Old Databindings.cpx


Open the file in source mode and change the ‘Catalog.jsf’ to ‘Catalog.jspx’. Next we have to check the ‘adfc-config.xml’ which holds a reference to the ‘Catalog.jsf’ page. This we change to ‘Catalog.jspx’.
Now we are ready to try to run the backported app the first time. We check the DB connection first, then run the application.

<20.05.2013 20:58 Uhr MESZ> <Error> <J2EE> <BEA-160197> <Unable to load descriptor P:\jdeveloper\system\system11.1.1.7.40.64.93\o.j2ee\drs\BlogUploadDownload/META-INF/weblogic-application.xml of module BlogUploadDownload. The error is weblogic.descriptor.DescriptorException: Unmarshaller failed
	at weblogic.descriptor.internal.MarshallerFactory$1.createDescriptor(MarshallerFactory.java:161)
	at weblogic.descriptor.BasicDescriptorManager.createDescriptor(BasicDescriptorManager.java:323)
	at weblogic.application.descriptor.AbstractDescriptorLoader2.getDescriptorBeanFromReader(AbstractDescriptorLoader2.java:788)
...
	at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)
Caused by: com.bea.xml.XmlException: weblogic.descriptor.BeanAlreadyExistsException: Bean already exists: "weblogic.j2ee.descriptor.wl.LibraryRefBeanImpl@eadc995c(/LibraryRefs[[CompoundKey: adf.oracle.domain]])"
	at com.bea.staxb.runtime.internal.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:54)
	at com.bea.staxb.runtime.internal.RuntimeBindingType$BeanRuntimeProperty.setValue(RuntimeBindingType.java:539)
...

This error points to one of the descriptors we did not check up to now. The ‘/LibraryRefs[[CompoundKey: adf.oracle.domain]]’ is defined in the weblogic-application.xml file which we find ‘Application Resources’->’Descriptors’->’META-INF’ node.

weblogic-appliaction.xml

weblogic-appliaction.xml


Here we see that there are multiple entries for the same listeners and library-ref entries. These entries are getting duplicated each time you open the project (or restart JDeveloper). The reason for this is that the ‘xsi:schemaLocation’ is pointing to the wrong version ’1.1′ (and location) in this case. The correct version for the 11gR1 is ’1.0′. We replace the wrong schema with the correct one and remove the duplication entries.

<weblogic-application xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                      xsi:schemaLocation="http://www.bea.com/ns/weblogic/weblogic-application http://www.bea.com/ns/weblogic/weblogic-application/1.0/weblogic-application.xsd"
                      xmlns="http://www.bea.com/ns/weblogic/weblogic-application">

Before we run the application again we check need to check the web.xml which contains a couple of entries which are not needed using 11gR1.
There ‘context-param’s javax.faces.PARTIAL_STATE_SAVING, oracle.adf.view.rich.security.FRAME_BUSTING, javax.faces.FACELETS_VIEW_MAPPINGS, javax.faces.FACELETS_SKIP_XML_INSTRUCTIONS, javax.faces.FACELETS_SKIP_COMMENTS, javax.faces.FACELETS_DECORATORS and javax.faces.FACELETS_RESOURCE_RESOLVER should be removed.
After these changes the application is ready to run.
5) Test run the application

Running Backported Application

Running Backported Application

If you like to use hte new skyros skin you neet to alter the trinidad-config.xml to:

<?xml version="1.0" encoding="UTF-8"?>
<trinidad-config xmlns="http://myfaces.apache.org/trinidad/config">
  <skin-family>skyros</skin-family>
  <skin-version>v1</skin-version>
</trinidad-config>

The last things to check is the ‘transaction isolation level’ of the task flows and the ‘ChangeEventPolicy’ of the iterators. The default ‘ChangeEventPolicy’ has been changed for 11gR2 applications to ‘ppr’ whereas it was ‘none’ for 11gR1. This change might not be visible at first, but you may notice some flicker in the table of the sample. This is the result of the new ‘ChangeEventPolicy’. If you check it back to none, you have to app the partial triggers to the components yourself. This is done in the sample which comes with Part 4 of the file and image handling sample.

There sure are more things to change, which I did not mention. This is because I did not need to change them ot did not find them. If you come across suhc a missing thing, please drop me a note so that I can add this to this article.

Handling images/files in ADF (Part 4)

This the a continuation of my already three part series about handling files and images in JDeveloper. The first three parts guided through the hole process:

    Part 1 gives an overview of the sample application I’m going to build and how to set it up
    Part 2 shows how to upload a file, store it and download it back to the client
    Part 3 implements two techniques to show the data (image) on the user interface

There is one missing part, which is that the whole sample was built using JDeveloper 11.1.2.1.0 using JSF2.0 components. Running the sample in newer JDeveloper 11.1.2.x versions in no problem (tested up to 11.1.2.4.0). However I got a couple of questions asking hoe to run it using JDeveloper 11.1.1.x version.
The shown techniques are all version independent, so that you can used them in your own application, but have to build your own UI.

I decided to backport the sample to run under 11.1.1.x too.

    Part 4 Sample build to run with JDeveloper 11.1.1.x.

The sample can be downloaded from the ADF EMG Sample side BlogUploadDownload._R1V3.zip.

JDeveloper 11.1.2.4.0 First Impressions

Oracle released a new version of JDeveloper Release 2 aka 11.1.2.4.0 on May 2nd, 2013. Great news as the planned update of the OTN forums has been postponed for four weeks. Think about a new version and no forum to ask questions!

Well, a look into the release notes reveals that there is not much new in this version beside a new version on the ADF Mobile development framework (1.1). This update gets us push notifications, file content display (Android), badging API support (iOS only), application archive support and infrastructure updates. These are performance enhancements, iPhone5 and iPad mini form factors support (needed for the iStore), migration of PhoneGap 1.0 to Cordova 2.2 and updated Xcode and Android SDK support.
I have not tested the new mobile stuff as I’m currently busy with other urgent stuff. Let’s take a close look to the new features of the 11.1.2.4.0 version beside the mobile update:
Start of List

End of List
Yes there is no official new feature in this version, only bug fixes. However, the list of bug fixes can’t be found by clicking the link in the release notes, Somehow the link does not work (at least not for me). To find the list of fixed bugs click on the link for the 11.1.2.3.0 bug fixes and scroll up a couple of pages.
Most fixes are for mobile, a couple of the fixes are for IE. Check the whole list at JDeveloper 11g Release 2 (11.1.2.4.0).
The JDK 1.7.0 bug (see issue ADFEMG-120). The backport did not make it into the 11.1.2.4.0 version!
So you still have to run this version on a JDK 1.6.0. Be sure to install an JDK 1.6.0_35 or higher as you otherwise get an error

“Java version 1.6.0_24 not supported. The minimum version required is 1.6.0_35.”

For more information about this refer to this thread on the (still old) OTN forum.

To install the new ADF Runtime for a standalone WebLogic Server you need two patches which are only available via Oracle support. The patch numbers are 16273810 (ADF) and 16156149 (WebCenter). Both patches need to be applied. For detailed information on how to apply the patches read the release notes.

UPDATE 13-05-2013
Chris Muir pointed out that the issue with the bundeld JDK 1.6.0_24 has been fixed in the meantime.
Apparently I missed this information as it’s not made overly public. I knew Oracles worked on a fix for the JDK problem, but just adding a ‘.1′ to the build number,which is build 6436.1 now, did not get my attention. Checking the documentation did not reveal much more. First hint I found in the release notes:

Introduction
Oracle JDeveloper and Application Development Framework 11g Release 2 (11.1.2.4.0) is a minor update to 11.1.2.4.0. For a list of new features in 11g Release 2, and specific customer bugs fixed in the update release see the What’s New document on OTN.

Note the versions mentioned? I’m not sure this is by intention, but further searching the release notes I found the info under the ‘Installation’ topic. It may help to add this info on the front page of the documentation.
—END UPDATE—

OTN Forum Update posponed to June 2013

Oracle just announced that the planned update of the OTN forums to a new modern version has been posponed to June 2013.

Quote:

UPDATE – launch delayed for four weeks, into June. 

In a last minute decision we have delayed launch so that we can establish thread level redirects across the site.  I am very happy with this outcome and expect a much smoother transition when we do make the switch.

Good move!  Better wait until all links can be migrated than update and many links are broken.

Bye, Bye Good Old OTN Forums

Starting May 3rd 2013 the good old OTN forum software get it’s desperately needed live-cell therapy. Only a few people know how the new forum software looks like and how it works (I’m none of them).

A couple of things are already known, e.g. some new terminology (spaces instead of forum), more colorful or modern (so better targeted for the facebook generation?), we hopefully get a search which really searches what we are looking for and performance should be better too. You can read for yourself on this OTN thread.

There are some things which are not clear to me, like how all the links posted in threads are handled. From the discussion in the thread above we learn that hopefully all links are migrated. Well, this reminds me when Oracle reorganized its websites. Nothing was reachable any more. There are still link which are broken, forcing us to dig deep in the WWW to get the information back. So let’s hope this will work this time.
However, this adds a lot of work to all the links which are stored in blogs and wikis pointing to interesting information in OTN threads. I’ll lose about 30% of my personal knowledge store and have to update some links here in this blog too.

I don’t want to start a new discussion about the dammed reward system (yes, the points are meant), as they do not alter the system at the moment. Interesting is that there are plans to get real-world rewards at some point in the future (do I get rich?:)).

For sentimental reasons I put a couple of screenshots of the old look and feel in this blog. In a couple of month or years, when dust has settled, we can look back at them and decide if the live-cell therapy has rescued the patient.

Master Detail Insert/Delete Sample

In the last couple of weeks a question on the OTN JDeveloper & ADF forum about how to insert and delete in a master-detail szenario was asked frequently. There are some threads in the forum talking about this, but apparently no solution which answers all the questions. This post tries to fill in the gap.

Use case
The use case we implement in this blog is as follows: we have a master detail relationship defined by a foreign key in the detail table. We use the REGION and COUNTRIES tables of the HR DB schema. There is a 1..* relationship between the REGION and the COUNTRIES tables. When you look at the REGIONS table only four regions are defined. We want to be able to create a new region and add some new countries into the detail table COUNTRIES before committing the whole transaction. Likewise we want to delete a region together with the countries attached to it, but also a country by itself without deleting a region.

Implementation
The insert part is pretty simple as the ADF framework does it automatically for you. You only have to use the right view objects from the data control and the framework does all the magic of propagating the FK to the child table when you insert a new row into the child table. This even works if you just added a new row to the master without committing it before inserting new child records.
The cascading delete part is not as obvious as the framework offers some help, but delegates the real work to the DB. If the DB knows about the cascading delete it works out OK. However, when you build the business components from the DB tables, the framework does not tell the DB that you want the cascading delete to happen. So without a small change the use case won’t work without us manually deleting all child rows ourselves.

In this blog we build a sample which shows how this use case can be implemented with the help of the DB. In an OTN Harvest post What happens when you choose cascade delete on an association Frank Nimphius talked about what it means if we choose the cascade delete option on an association. Here is a quote from the article:


One of the configuration options in the visual editor is Implement Cascade Delete that is located in the
Relationship menu under the Behavior header. Selecting this option indicates that all detail rows that are
associated with a parent entity should be deleted when the parent entity is deleted.
However, ADF Business Components does not itself perform the cascade delete, but expects a database
constraint to be defined for this. All that the Implement Cascade Delete does is to change the delete
command issued by ADF Business Components to the database.
To quote the “Oracle Fusion Middleware Fusion Developer’s Guide for Oracle Application Development
Framework”

” … When selected, this option allows the composing entity object to be removed unconditionally together with any composed
children entities. If the related Optimize for Database Cascade Delete option is deselected, then the composed entity objects
perform their normal DELETE statement at transaction commit time to make the changes permanent. If the option is
selected, then the composed entities do not perform the DELETE statement on the assumption that the database ON
DELETE CASCADE constraint will handle the deletion of the corresponding rows.

In summary, the article tells us what to do to make the cascading delete work. We need to make the foreign key constraint aware of that by setting it’s delete action to ‘CASCADE’. This we can do from within JDeveloper by using the DB Navigator. Open the HR connection and then open the ‘Tables’ node. Here we select the COUNTRIES table and edit it:

Change FK Constraints on the DB Table COUNTRIES

Change FK Constraints on the DB Table COUNTRIES


Select ‘CASCADE’ in the ‘On Delete’ drop down box in the Foreign Key dialog box:
Set Constraint to CASCADE

Set Constraint to CASCADE


After this change the rest of the use case is just setting up the UI.

Setting up the UI
First we take a look at the ‘Data Controls’ where we see the master detail relationship between the Regions and Countries:

Data Controls

Data Controls


The UI is build in on fragment ‘SchowMasterDetail.jsff’ which consists of a vertical splitter. In the upper part we put the master (Region) as a form and in the bottom part the detail (Countries) as editable table.

<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1" xmlns:af="http://xmlns.oracle.com/adf/faces/rich" xmlns:f="http://java.sun.com/jsf/core">
  <af:panelStretchLayout id="psl1">
    <f:facet name="center">
      <af:panelSplitter id="ps1" orientation="vertical" splitterPosition="150">
        <f:facet name="first">
          ...
        </f:facet>
       <f:facet name="second">
         ...
       </f:facet>
      </af:panelSplitter>
      <!-- id="af_one_column_stretched"   -->
    </f:facet>
    <f:facet name="bottom"/>
  </af:panelStretchLayout>
</jsp:root>

To get the master data into the form we drag the Region view object from the data controls on the first splitter facet and drop it as form with submit and navigation buttons. After this we add another panelGroupLayout where we put some additional buttons which we use to create a new region, delete a region, rollback the changes and commit the changes.

For the detail we use the Countries view object from the data controls and drop it as table (editable) on the center facet of a panelStretchLayout which we put on the second facet of the panelSplitter. We mark the table singe selection and sortable. As we did for the regions we add some buttons to the bottom facet which we use to create a new country, delete a country, rollback the changes or commit them. Rollback and commit are for the whole transaction. Even if we click the rollback in the detail part, the whole transaction is rolled back.

Final Page Layout

Final Page Layout


The image above shows the final page layout. Only two things are left to do. We change to the bindings tab of the ShowMasterDetail.jsff and set the ‘ChangeEventPolicy’ for both iterators (Region and Countries) to ‘ppr’. This spares us to update the input fields and the table after each click on one of the navigation buttons. If you are using 11.1.1.7.0 or 11.1.2.x this is the default for newly created iterators. For older versions you have to do it yourself.
Set ChangeEventPolicy to PPR

Set ChangeEventPolicy to PPR

Set ChangeEventPolicy to PPR

Set ChangeEventPolicy to PPR


Running Application
The images below are showing the running sample. We start by verifying that no countries for attached to region id 5 are present, then create a new region with the id 5. Without committing the new region we create some new countries for the fresh created region 5. Finally we commit the transaction and verify that the new data is present in the DB.

Now we delete the new region 5 with all countries created.

The sample was built using JDeveloper 11.1.1.7.0 and uses the HR DB schema. It should be work with JDeveloper 11.1.1.5.0, 11.1.1.6.0 and JDeveloper 11.1.2.3.0 too. You can download the sample from the ADF-EMG Sample Project ‘BlogMasterDetail.zip’

How to Add New Choice to an af:selectOneChoice at Runtime

A question on the JDeveloper and ADF OTN forum asked for help on how to add a new choice to an af:selectOneChoise on the page during runtime. The selectOneChoice is based on is a table in the DB.
This sample shows how to do this using the HR DB schema. The workspace is built using JDev 11.1.1.7.0 but should work without a problem using 11.1.1.4.0 and higher too. You may be asked if you want to migrate, which you should answer with ‘Yes’. The sample can be downloaded using the link provided at the end of this blog.

As this is a real simple data model it only uses the REGIONS table from the HR DB schema. As we want to add new values to the regions table we need to generate entity and view object for the Regions table. We name the VO RegionsLov to make clear that we use this VO as base for a LOV in the UI. To add a new row into this table we implement a public method in the application module which we expose through the client interface of the am. This method isn’t needed as we could simply use createWithParams method from the VO, but the use case asked on the forum did use a method in the application module too.

    public void insertRegion(Integer id, String name) {
        if (id == null || name == null)
            throw new JboException("No Data!");
        Row row = getRegionsLov().createRow();
        row.setAttribute("RegionId", id);
        row.setAttribute("RegionName", name);
        getRegionsLov().insertRow(row);
        // commit is used here only because of the use case from the forum!
        this.getTransaction().commit();
    }

You see that the method uses a commit statement, which I prefer not to do. The reason for this is that you can’t reuse this method in other cases where no commit is allowed because there are other pending changed which you don’t want to commit at the moment. We can remove the commit and call the commit from a bean or directly from a button in the UI to make the method reusable.

We use the VO as dynamic list in the UI so we don’t need to add ViewAccessors or list attributes on the VO. Before we built the UI we add three temporary variables into the variables iterator of the pageDef file. Refer to Creating Variables and Attribute Bindings to Store Values Temporarily in the PageDef for information about how to do this. One variabel ‘RegionId’ (as Integer) is used to store the selection of the LOV we build, the other two ‘newRegionId’ (as Integer) and ‘newRegionName’ (as String) are used to create a new region row in the REGIONS table.
The LOV is built from a af:selectOneChoice which we generate by dragging the RegionsLov’s RegionId attribute onto the page and drop it as SelectOneChoice. The image below shows the binding as dynamik list

Define af:SelectOneChoise

Define af:SelectOneChoise


The whole UI looks like
Final UI

Final UI


Here we see the form with the two inputText components which store their values in temporary pageDef variables ‘newReginId’ and ‘newRegionName’. Here is the full pageDef file for reference:

<?xml version="1.0" encoding="UTF-8" ?>
<pageDefinition xmlns="http://xmlns.oracle.com/adfm/uimodel" version="11.1.1.64.93" id="StartPageDef" Package="de.hahn.blog.addvaluesoc.view.pageDefs">
  <parameters/>
  <executables>
    <variableIterator id="variables">
      <variable Name="region" Type="java.lang.Integer"/>
      <variable Name="showregion" Type="java.lang.Boolean" DefaultValue="false"/>
      <variable Name="newRegionId" Type="java.lang.Integer"/>
      <variable Name="newRegionName" Type="java.lang.String"/>
    </variableIterator>
    <iterator Binds="RegionsLov" RangeSize="-1" DataControl="BAVSOCAppModuleDataControl" id="RegionsLovIterator"/>
  </executables>
  <bindings>
    <list IterBinding="variables" id="RegionId" DTSupportsMRU="true" StaticList="false" ListIter="RegionsLovIterator" NullValueId="PLEASE_SELECT"
          NullValueFlag="start">
      <AttrNames>
        <Item Value="region"/>
      </AttrNames>
      <ListAttrNames>
        <Item Value="RegionId"/>
      </ListAttrNames>
      <ListDisplayAttrNames>
        <Item Value="RegionName"/>
      </ListDisplayAttrNames>
    </list>
    <attributeValues IterBinding="variables" id="newRegionId1">
      <AttrNames>
        <Item Value="newRegionId"/>
      </AttrNames>
    </attributeValues>
    <attributeValues IterBinding="variables" id="newRegionName1">
      <AttrNames>
        <Item Value="newRegionName"/>
      </AttrNames>
    </attributeValues>
    <methodAction id="insertRegion" InstanceName="BAVSOCAppModuleDataControl.dataProvider" DataControl="BAVSOCAppModuleDataControl" RequiresUpdateModel="true"
                  Action="invokeMethod" MethodName="insertRegion" IsViewObjectMethod="false">
      <NamedData NDName="id" NDValue="" NDType="java.lang.Integer"/>
      <NamedData NDName="name" NDType="java.lang.String"/>
    </methodAction>
  </bindings>
  <ResourceBundle>
    <PropertiesBundle xmlns="http://xmlns.oracle.com/adfm/resourcebundle" PropertiesFile="de.hahn.blog.addvaluesoc.view.BAVSOCViewControllerBundle"/>
  </ResourceBundle>
</pageDefinition>

Now we look at the running application:


Here we see that originally are only four regions present in the selectOneChoice, and we add a new one with the Id=5 and the name ‘aaaaaaaa’ which is inserted with a click on the ‘Insert New Region’ button. The button calls a method in a managed bean

    public void insertRegionListener(ActionEvent actionEvent) {
        // GET A METHOD FROM PAGEDEF AND EXECUTE IT
        // get the binding container
        BindingContainer bindings =
            BindingContext.getCurrent().getCurrentBindingsEntry();
        // get an ADF attributevalue from the ADF page definitions
        AttributeBinding attrId =
            (AttributeBinding)bindings.getControlBinding("newRegionId1");
        Integer id = (Integer)attrId.getInputValue();
        AttributeBinding attrName =
            (AttributeBinding)bindings.getControlBinding("newRegionName1");
        String name = (String)attrName.getInputValue();
        // get an Action or MethodAction
        OperationBinding method = bindings.getOperationBinding("insertRegion");
        if (method == null) {
            FacesMessage msg =
                new FacesMessage(FacesMessage.SEVERITY_ERROR, "Method insertRegion not found!",
                                 "");
            FacesContext.getCurrentInstance().addMessage(null, msg);
            return;
        }

        // if there are parameters to set...
        Map paramsMap = method.getParamsMap();
        paramsMap.put("id", id);
        paramsMap.put("name", name);
        // execute the method
        method.execute();
        List errors = method.getErrors();
        if (!errors.isEmpty()) {
            Exception e = (Exception)errors.get(0);
            FacesMessage msg =
                new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(),
                                 "");
            FacesContext.getCurrentInstance().addMessage(null, msg);
            return;
            // handle errors here errors is a list of exceptions!
        }

        // Get a attribute value of the current row of iterator
        DCBindingContainer dcBindings = (DCBindingContainer)bindings;
        DCIteratorBinding iterBind =
            (DCIteratorBinding)dcBindings.get("RegionsLovIterator");
        iterBind.executeQuery();

        // gat the form for refresh
        UIComponent ui = (UIComponent)actionEvent.getSource();
        ui = ui.getParent();
        ResetUtils.reset(ui);
        attrId.setInputValue(null);
        attrName.setInputValue(null);

        // PPR refresh a jsf component
        AdfFacesContext.getCurrentInstance().addPartialTarget(ui);

    }

The method first gets the entered parameters for the new region id and name, then calls the method to insert the data in the AM (insertRegion) and finally requires the iterator which is used for the selectOneChoice in the UI (RegionsLovIterator).

You can download the sample workspace which was built with JDev 11.1.1.7.0 and which uses the HR schema from the ADFEMG Sample Project BlogAddValueSOC.zip page.

Make Disclosed Row the Current Row when using a Detail Facet of a Table

A question on the OTN JDeveloper & ADF forum asked for help on a use case using a table with an active detail facet. The problem is that when you disclose a row to see the detail, the current row is not changing to the disclosed row.

To make this work we add a RowDisclosureListener where we get the row which should be disclosed and make the row the current row.

The sample, which you cam download using the link provided at the end of the post, uses the HR schema. The master table show the employees and the detail facet is used to show details of the current job the employee has.

Running Application

Running Application


The data model looks like
Data Model

Data Model


The tabel is build by dropping the Employees table onto a page as read only table. The detail facet is build by dropping the JobsDetail as read only form onto the facet. The resulting page code looks like

        <af:table value="#{bindings.Employees.collectionModel}" var="row" rows="#{bindings.Employees.rangeSize}"
                  emptyText="#{bindings.Employees.viewable ? 'No data to display.' : 'Access Denied.'}" fetchSize="#{bindings.Employees.rangeSize}"
                  rowBandingInterval="0" selectedRowKeys="#{bindings.Employees.collectionModel.selectedRow}"
                  selectionListener="#{bindings.Employees.collectionModel.makeCurrent}" rowSelection="single" id="t1"
                  rowDisclosureListener="#{ShowEmployees.rowDiscloseListener}">
...
          <f:facet name="detailStamp">
            <af:panelFormLayout id="pfl1" partialTriggers="::t1">
              <af:panelLabelAndMessage label="#{bindings.JobId.hints.label}" id="plam3">
                <af:outputText value="#{bindings.JobId.inputValue}" id="ot10"/>
              </af:panelLabelAndMessage>
              <af:panelLabelAndMessage label="#{bindings.JobTitle.hints.label}" id="plam1">
                <af:outputText value="#{bindings.JobTitle.inputValue}" id="ot7"/>
              </af:panelLabelAndMessage>
              <af:panelLabelAndMessage label="#{bindings.MinSalary.hints.label}" id="plam2">
                <af:outputText value="#{bindings.MinSalary.inputValue}" id="ot8">
                  <af:convertNumber groupingUsed="false" pattern="#{bindings.MinSalary.format}"/>
                </af:outputText>
              </af:panelLabelAndMessage>
              <af:panelLabelAndMessage label="#{bindings.MaxSalary.hints.label}" id="plam4">
                <af:outputText value="#{bindings.MaxSalary.inputValue}" id="ot9">
                  <af:convertNumber groupingUsed="false" pattern="#{bindings.MaxSalary.format}"/>
                </af:outputText>
              </af:panelLabelAndMessage>
            </af:panelFormLayout>
          </f:facet>

The problem now is, that if we click on the disclose arrow on the left hand side we see the detail information of the current employee row (the master row). The disclosure of a row doesn’t set the current row to the disclosed row.
The solution is to make the disclosed row the current row. For this we add a rowDisclosureListener to the table which points to a method in a bean. The code of hte listener look like

    /**
     * Disclosure event
     * @param rowDisclosureEvent
     */
    public void rowDiscloseListener(RowDisclosureEvent rowDisclosureEvent) {
        RowKeySet addedSet = rowDisclosureEvent.getAddedSet();
        Object object = rowDisclosureEvent.getSource();
        // iterate over the disclosed row (hopefully only one)
        for (Object obj : addedSet) {
            List<Key> rowKeys = (List<Key>)obj;
            // make the disclosed row the current row
            this.makeDisclosedRowCurrent(rowDisclosureEvent,
                                         (Key)rowKeys.get(0));
        }
    }

    /**
     * Synchronizes the table UI component row selection with the
     * selection in the ADF binding layer
     * @param rowDisclosureEvent event object created by the table
     * component upon row selection
     */
    public static void makeDisclosedRowCurrent(RowDisclosureEvent rowDisclosureEvent,
                                               Key key) {
        RichTable _table = (RichTable)rowDisclosureEvent.getSource();
        //the Collection Model is the object that provides the
        //structured data
        //for the table to render
        CollectionModel _tableModel = (CollectionModel)_table.getValue();
        //the ADF object that implements the CollectionModel is
        //JUCtrlHierBinding. It is wrapped by the CollectionModel API
        JUCtrlHierBinding _adfTableBinding =
            (JUCtrlHierBinding)_tableModel.getWrappedData();
        //Acess the ADF iterator binding that is used with
        //ADF table binding
        DCIteratorBinding _tableIteratorBinding =
            _adfTableBinding.getDCIteratorBinding();

        //get the row key from the added rowdisclosure event
        Key _rwKey = key;
        _tableIteratorBinding.setCurrentRowWithKey(_rwKey.toStringFormat(true));
    }

The method rowDiscloseListener is used to get the key of the disclosed row and the method makeDisclosedRowCurrent is used to make the row the current row and synchronise the binding layer to reflect this.

You can download the sample thos the ADFEMG Sample side BlogTableDetail.zip
The sample uses the HR schema and was built with JDev 11.1.1.7.0 but works works with 11.1.1.4.o and higher too.

Using one ViewObject for Global Lookup Data (Part 2)

Based on the other post ‘Using one ViewObject for Global Lookup Data’ I got an other question on how to use this approach in a way, that a LOV is initalized with an area of lookup data before the page in shown to the user.
This can be done, all declarative without the need to write java code e.g. in an onLoad() method. The solution is to use a bounded task flow which initializes the LOV before navigation to the page the LOV is used.
To show this we create a simple navigation model in the adfc-config.xml like

Navigation Model

Navigation Model

‘Generic Lookup’ is used to show how to do this inside a page, where the lookup is presented in a region, the ‘LookupInitPosition’ shows how to preset an area for the lookup data (POSITION in this case) before showing the page in a region too.
Before we go into detail on how to setup the UI we need to add another view object to our data model which we use the acquire the lookup data

VO to get Lookup Data

VO to get Lookup Data


The ‘GeneralLookup’ view object is the same we used in part 1 to get the lookup data of an area, only this time we don’t specify lookup area but a dummy value (’1′ in this case) for the area. This dummy value is set so that we don’t get any result back. If the ‘GeneralLookup’ view is executed without an area given from the outside, we don’t get any result. Keep this in mind when we are looking at the running sample later on.

Back to the UI. As both use cases uses a region it’s a nice sample how a bounded task flow (btf) can be reused in different use cases. The bounded task flow itself looks like

Navigation Model Bounded Task Flow

Navigation Model Model Bounded Task Flow

Bounded Task Flow to Show preselected Lookup Data

Bounded Task Flow to Show preselected Lookup Data


As you see the bounded task flow uses a method call (ExecuteWithParams) as it’s start activity. A task flow parameter is used to pass the name of the lookup area we want the LOV to initially show.
The name of the input parameter does not really matter, what you have to note down is the value part ‘#{pageFlowScope.selectedType}’ as this is the the variable we use to set the bindType parameter of the method call activity ExecuteWithParams.

Setup of the ExecuteWithParams Method Call

Setup of the ExecuteWithParams Method Call

After executing the query with the new set bindType we navigate to to page to show the result:

Region View1 which shows the LOV with the Preselected Lookup Data

Region View1 which shows the LOV with the Preselected Lookup Data


We see the LOV as af:selectOneChoice which stores the selected value in an attribute from the variable iterator (see Creating Variables and Attribute Bindings to Store Values Temporarily in the PageDef for more info on this). The input text below the LOV can be used to change the area parameter used for the LOV. If we enter e.g. WEEKDAY and click the ‘Refesh’ button, the input value is read and transferred to the parameter (#{pageFlowScope.selectedType}) for the executeWithParameter method via a af:setPropertyListener. This allows to change the LOV on the fly from within the region.
The LOV source is a dynamic list generated from the Generallookup VO as seen in the next image
Setup LOV for af:selectOneChoice

Setup LOV for af:selectOneChoice

After we know how the region (the bounded task flow) works, we can build the GenericLookup.jspx page. This page allows to enter the name of an ares into an input text field and then to refresh the bounded task flow, which we put on the page as region.

The final use case is to navigate to a page with with a preselected lookup area, POSITION in this case. For this we use the button ‘goto Page with init on POSITION’ at the bottom of the page.

You can download the sample workspace which was build JDeveloper 11.1.1.7.0 and using the HR schema from the ADF EMG Samples side BlogStaticVOLov_V3.zip. You can open the workspace using JDev 11.1.1.6.0 without a problem. If you are asked if you like to migrate the workspace to 11.1.1.6.0 answer with Yes.

Installing JDeveloper 11.1.1.7.0 from the Generic Installer Jar on 64bit Windows System

If you have installed JDev 11.1.1.7.0 lately, which I strongly recommend, you may have noticed, that the windows installer jdevstudio11117install.exe still ships with jdk160_24. Please don’t ask why Oracle don’t includes a JDk 1.7, I don’t know.
Well, it’s time to use JDK1.7 on my WIn7x64 system so I loaded hte jdevstudio11117install.jar which is a lot bigger (1.9GB) but comes without a bundeld JDK. As I have already installed JDK 1.7.0_17 on my system I pointed the installation to this jdk when I asked during the installation.
Everything went smooth and i took only a couple of minutes to install JDev and generate the embedded WLS 10.3.5 instance.

However, when I tried to start the embedded WLS instance I got the following error message

*** Using port 7101 ***
r:\jdeveloper\system\system11.1.1.7.40.64.93\DefaultDomain\bin\startWebLogic.cmd
[waiting for the server to complete its initialization...]
.
.
JAVA Memory arguments: -Xms256m -Xmx512m
.
WLS Start Mode=Development
.
CLASSPATH=...
.
PATH=...
.
***************************************************
*  To start WebLogic Server, use a username and   *
*  password assigned to an admin-level user.  For *
*  server administration, use the WebLogic Server *
*  console at http:\\hostname:port\console        *
***************************************************
starting weblogic with Java version:
<strong>Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
Unrecognized option: -jrockit</strong>
Starting WLS with line:
...
Process exited.

Hm, ‘Unrecognized option: -jrockit‘, how’s that? I’m running Sun JDK!
Right at the beginning of the server start we see the command used to start the server (the path may be different on your system)
r:\jdeveloper\system\system11.1.1.7.40.64.93\DefaultDomain\bin\startWebLogic.cmd
A look into this command shell reveals that another command shell script is called
r:\jdeveloper\system\system11.1.1.7.40.64.93\DefaultDomain\bin\setDomainEnv.cmd
In this script we find the problem

...
set BEA_JAVA_HOME=C:\Program Files\Java\jdk1.7.0_17

set SUN_JAVA_HOME=


if "%JAVA_VENDOR%"=="Oracle" (
	set JAVA_HOME=%BEA_JAVA_HOME%
) else (
	if "%JAVA_VENDOR%"=="Sun" (
		set JAVA_HOME=%SUN_JAVA_HOME%
	) else (
		set JAVA_VENDOR=Oracle
		set JAVA_HOME=C:\Program Files\Java\jdk1.7.0_17
	)
)
...

As you see hte BEA_JAVA_HOME is set and if you put an
echo %JAVA_VENDOR%
before the if statement you see that the vendor is null. This sets the JAVA_HOME correct, but sets the JAVA_VENDOR to ‘Oracle’. This then adds the wrong option -jrockit to the command line later on in the startWebLogic.cmd script.

Now that we know that the solution is to make a small change to the
r:\jdeveloper\system\system11.1.1.7.40.64.93\DefaultDomain\bin\setDomainEnv.cmd
script. We only have to set the SUN_JAVA_HOME and set the JAVA_VENDOR to ‘Sun’

set BEA_JAVA_HOME=

set SUN_JAVA_HOME=C:\Program Files\Java\jdk1.7.0_17
set JAVA_VENDOR=Sun

After this change the embedded WLS server starts without a problem.