JDEV 11.1.2.1.0: Using router to conditionally set navigation target

Interesting question came up on OTN ADF froum.
You have one page (page2) which is called from two other pages (page1 and page3). The question is how to set up the navigation in page2 so that you have only on button (back) which gets you back to the page the user navigated from to page2?

There is more then one solution to this problem. In this blog entry I show the declarative solution, so no java code is used. Here is adfc-config.xml which shows the navigation:

Router Back Navigation

Router Back Navigation

This is a simple navigation where the user can navigate from Page1 or Page3 to Page2. Page2 uses only one navigation case ‘back’ and let the router decide where to go. To make this happen, the button which navigates from Page1 to Page2 needs to store a hint ‘1’ in pageFlowScope which the router can check to decide where to go to. For this I add a af:setPropertyListener to store the hint in pageFlowScope. You don’t need a bean to store the value as the storage for the value is set up automatically.

                        <af:commandButton text="Page 2" id="cb1" action="page12">
                            <af:setPropertyListener from="#{'1'}" to="#{pageFlowScope.backTarget}"
                                                    type="action"/>
                        </af:commandButton>

The same technique is used in Page3 to store the hint ‘3’ in pageFlowScope

                        <af:commandButton text="Page 2" id="cb1" action="page32">
                            <af:setPropertyListener to="#{pageFlowScope.backTarget}" type="action"
                                                    from="#{'3'}"/>
                        </af:commandButton>

Finally the magic is done in the router. Here the value which is stored in pageFlowScope variable ‘backTarget’ is checked and hte correct navigation target is used for the back navigation. Below is the source of the router, the design view is shown in the first picture.

  <router id="backRouter">
    <case id="__12">
      <expression>#{pageFlowScope.backTarget eq '1'}</expression>
      <outcome>page21</outcome>
    </case>
    <case id="__13">
      <expression>#{pageFlowScope.backTarget eq '3'}</expression>
      <outcome>page23</outcome>
    </case>
    <default-outcome>page21</default-outcome>
  </router> 

When you run the sample you start from Page1 and navigate to Page2 you see the output text which shows the content of the pageFlowScope variable, ‘1’ in this case.

Navigation from Page1 to Page2

Navigation from Page1 to Page2

If the user navigates from Page3 to Page2 the output looks like

Navigation Page3 to Page2

Navigation Page3 to Page2


the output text shows ’3′ in this case.

You can download the sample application which is build using JDeveloper 11.1.2.1.0 from here BlogRouterBackNavigation.zip.
Please rename the file to ‘.zip’ after downloading it!
The sample don’t use any db connection and should be runnable on older JDeveloper versions too.

JDev11.1.2.1.0: Handling images/files in ADF (Part 2)

This blog article is part 2 of a series of posts showing how to deal with images or files in an ADF application. Each of the techniques to do this are described in other blog posts or documents, but I couldn’t find a sample doing it all together in on sample application.
The goal of this series is to provide a sample showing how to upload a file from a client to the server, store the data on the server, make it available for later retrieval and show the data in the user interface (form and table).

    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
    Part 4 backport of the sample to JDeveloper 11gR1
    Part 5 implements a technique to show the uploaded file right after upload without the need to commit first


Uploading, downloading and storing of data in a blob

In this part of the series I show how to upload a file from the client to the server and store the data in a blob column in a db. The tables I’m using are CATALOG and IMAGES. The DML to define the tables and can be found in PART 1 of the series or in the sample workspace at the end of this part.
Lets start with uploading a file from client to the server. ADF rich faces provide the tag af:inputFile to allow uploading of data.

&lt;af:inputFile label=&quot;Select new file&quot; id=&quot;if1&quot; autoSubmit=&quot;true&quot;
              valueChangeListener=&quot;#{ImageBean.uploadFileValueChangeEvent}&quot;/&gt;

As you see the tag has set its autoSubmit property to true to allow direct upload of data. The real work is done in the valueChangeListener which is bound to a backing bean in request scope. The value the event carries allows access to the data and give us the original filename and mime type.

    public void uploadFileValueChangeEvent(ValueChangeEvent valueChangeEvent)
    {
        // The event give access to an Uploade dFile which contains data about the file and its content
        UploadedFile file = (UploadedFile) valueChangeEvent.getNewValue();
        // Get the original file name
        String fileName = file.getFilename();
        // get the mime type 
        String contentType = ContentTypes.get(fileName);
        // get the current roew from the ImagesView2Iterator via the binding
        DCBindingContainer lBindingContainer =
            (DCBindingContainer) BindingContext.getCurrent().getCurrentBindingsEntry();
        DCIteratorBinding lBinding = lBindingContainer.findIteratorBinding(&quot;ImagesView2Iterator&quot;);
        Row newRow = lBinding.getCurrentRow();
        // set the file name
        newRow.setAttribute(&quot;ImageName&quot;, fileName);
        // create the BlobDomain and set it into the row
        newRow.setAttribute(&quot;ImageData&quot;, createBlobDomain(file));
        // set the mime type
        newRow.setAttribute(&quot;ContentType&quot;, contentType);
    }

    private BlobDomain createBlobDomain(UploadedFile file)
    {
        // init the internal variables
        InputStream in = null;
        BlobDomain blobDomain = null;
        OutputStream out = null;

        try
        {
            // Get the input stream representing the data from the client
            in = file.getInputStream();
            // create the BlobDomain datatype to store the data in the db
            blobDomain = new BlobDomain();
            // get the outputStream for hte BlobDomain
            out = blobDomain.getBinaryOutputStream();
            // copy the input stream into the output stream
            /*
             * IOUtils is a class from the Apache Commons IO Package (http://www.apache.org/)
             * Here version 2.0.1 is used
             * please download it directly from http://projects.apache.org/projects/commons_io.html
             */ 
            IOUtils.copy(in, out);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        catch (SQLException e)
        {
            e.fillInStackTrace();
        }

        // return the filled BlobDomain
        return blobDomain;
    }

Please note the I use the Apache Commons IO package in the version 2.0.1 which you need to download from the Apache Software Foundation web side. The use the class IOUtils which allow easy copying of streams.
If your are using an older version of JDeveloper you may need to add the usesUpload property to the af:form tag. In the current JDev version it should work automatically (but please check it).

&lt;af:form id=&quot;f1&quot; usesUpload=&quot;true&quot;&gt;

If you use fragments (as in this sample) you need to check the jspx or jsf page which is holding the af:form tag (Catalog.jsf), as the fragments don’t have a form tag.
By default, Oracle ADF 11g application allows to upload maximum 2 MB size files. This maximum can be configured in the web.xml file if you need to upload files bigger then 2 MB. For this you need to specify the context parameters

    org.apache.myfaces.trinidad.UPLOAD_MAX_MEMORY
    org.apache.myfaces.trinidad.UPLOAD_MAX_DISK_SPACE
    org.apache.myfaces.trinidad.UPLOAD_TEMP_DIR

For more information about the parameters and how they work check the doc Oracle® Fusion Middleware Web User Interface Developer’s Guide for Oracle Application Development Framework.

Now to the download part. This is handled in ADF via the af:fileDownloadActionListener tag. The tag is a client listener tag and is therefor applied to a command ui tag. In the sample I use a af:commandButton:

&lt;af:commandButton text=&quot;Download Data&quot; id=&quot;cb3&quot;
                  visible=&quot;#{bindings.ImageData.inputValue ne null}&quot;
                  binding=&quot;#{ImageBean.downloadButton}&quot;&gt;
          &lt;af:fileDownloadActionListener contentType=&quot;#{bindings.ContentType.inputValue}&quot;
                                         filename=&quot;#{bindings.ImageName.inputValue}&quot;
                                         method=&quot;#{ImageBean.downloadImage}&quot;/&gt;
&lt;/af:commandButton&gt;

The real work is done in the downloadImage method in the managed bean. The signature of the method is

public void downloadImage(FacesContext facesContext, OutputStream outputStream)

This allows you to access to the FacesContext and the output stream which you use to pipe the data to the client.

    public void downloadImage(FacesContext facesContext, OutputStream outputStream)
    {
        BindingContainer bindings = BindingContext.getCurrent().getCurrentBindingsEntry();

        // get an ADF attributevalue from the ADF page definitions
        AttributeBinding attr = (AttributeBinding) bindings.getControlBinding(&quot;ImageData&quot;);
        if (attr == null)
        {
            return;
        }

        // the value is a BlobDomain data type
        BlobDomain blob = (BlobDomain) attr.getInputValue();

        try
        {   // copy hte data from the BlobDomain to the output stream 
            IOUtils.copy(blob.getInputStream(), outputStream);
            // cloase the blob to release the recources
            blob.closeInputStream();
            // flush the outout stream
            outputStream.flush();
        }
        catch (IOException e)
        {
            // handle errors
            e.printStackTrace();
            FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_ERROR, e.getMessage(), &quot;&quot;);
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
    }

This is all you need to do to download a blob from the db and send it back to the client.

I like to mention one other function of the sample application. If you hit the ‘Cancel’ button in the insert or edit image page I use a rollback to get the original data back and remove all changes made in the form. A rollback resets all current row pointers of the iterators. To avoid that the user sees the first row of the catalog table the rollback has to be handled in a special way. You have to save the current row (of the catalog iterator), do the rollback and reset the current row back to the saved one. This is done in the bean method

public String cancel_action() {...}

which you find in the ImageBean class.

This concludes part 2. In part three I implement two techniques to show the data (image) on the user interface (page)

The sample application workspace is build with JDeveloper 11.1.2.1.0 and can be loaded from here BlogUploadDownload_P2.zip
Please rename the file to ‘.zip’ after downloading it!
The Commons IO package in the version 2.0.1 you can download from the Apache Software Foundation apache web side

To be continued…

JDev11.1.2.1.0: Handling images/files in ADF (Part 1)

This blog article is part 1 of a series of posts showing how to deal with images or files in an ADF application. Each of the techniques to do this are described in other blog posts or documents, but I couldn’t find a sample doing it all together in on sample application.
The goal of this series is to provide a sample showing how to upload a file from a client to the server, store the data on the server, make it available for later retrieval and show the data in the user interface (form and table).

    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
    Part 4 backport of the sample to JDeveloper 11gR1
    Part 5 implements a technique to show the uploaded file right after upload without the need to commit first


Overview of the sample application

The sample allows to create and manage catalogs. A catalog has a unique id, a name and may contain files and images which the user can upload into a catalog and download from it. All this is implemented in a simple way, so no fancy layout, only bare functionality. Here is a screen shot of the sample application after part 2 is finished:

Sample app end of part 2

Sample app end of part 2

As you see the UI is nothing I would use in a real world application, but for this sample it does the trick.
To create a new catalog you click the ‘New Catalog’ button and can fill in a name for the new catalog. The id is automatically assigned via a groovy expression which calls a sequence defined in the db. In the catalog screen you see the catalog together with all images added to this catalog. Here you can remove the whole catalog. The image data is deleted too in this case.

Create Catalog

Create Catalog

Once you have a catalog created you can add images or other files to it by using the ‘New Image’ button.

Create Image

Create Image

When adding a new image to a catalog you can specify a name for the image, the content type which will be read from the file once you hit the upload button. The image id is assigned by a groovy expression, the catalog id is populated by the master record, the catalog. As there is no visible image of the data in this version, an output text shows you if data has already been uploaded (Image Data available/not available).
This concludes the short run through the sample application.
The following db diagram shows the two tables involved (CATALOG and IMAGES) and their 1:* relationship. For reference I added the two sequences which generate the primary key for the tables.

DB Diagram

DB Diagram

Next is the DML to generate the two tables and the sequences. You can add the tables to an existing DB or create a new schema and add them their. If you later download the source code you’ notice, that I added the DML to the well known HR schema. If you use an other schema, you have to change the db connection accordingly.

CREATE TABLE CATALOG 
(
  CATALOG_ID NUMBER(12) NOT NULL 
, CATALOG_NAME VARCHAR2(200 CHAR) NOT NULL 
, CONSTRAINT CATALOG_PK PRIMARY KEY 
  (
    CATALOG_ID 
  )
  ENABLE 
);

CREATE UNIQUE INDEX CATALOG_PK ON CATALOG (null ASC);

CREATE SEQUENCE CATALOG_SEQ INCREMENT BY 1 START WITH 100 NOCACHE;

CREATE TABLE IMAGES 
(
  IMAGE_ID NUMBER(12) NOT NULL 
, IMAGE_NAME VARCHAR2(200 CHAR) NOT NULL 
, CONTENT_TYPE VARCHAR2(50 CHAR) 
, IMAGE_DATA BLOB 
, CATALOG_ID NUMBER(12) NOT NULL 
, CONSTRAINT IMAGES_PK PRIMARY KEY 
  (
    IMAGE_ID 
  )
  ENABLE 
);

CREATE UNIQUE INDEX IMAGES_PK ON IMAGES (null ASC);

ALTER TABLE IMAGES
ADD CONSTRAINT IMAGES_CATALOG_FK FOREIGN KEY
(
  CATALOG_ID 
)
REFERENCES CATALOG
(
  CATALOG_ID 
)
ENABLE;

CREATE SEQUENCE IMAGE_SEQ INCREMENT BY 1 START WITH 100 NOCACHE;

Finally here are the task flows which build the first part of the sample application:

Task flows

Task flows

The start page ‘Catalog’ contains a region (catalog-task-flow-description.xml) which is used to add or edit catalogs and to add or edit images for a catalog.

This concludes part 1. In part two I describe in detail how to implement the file upload and download feature and store the data in a blob column in the db.

To be continued…

Save (most of) your changes to the JDeveloper IDE

Under some circumstances you may need to rename or remove your system11.x.x.x folder to overcome errors with the IDE which can’t be solved otherwise. I blogged about this How to find and reset the system11.x.x.x folder for a JDeveloper installation.
However, this means that you loose all of the changes you made to IDE, e.g. connections to DBs, code templates and many more.
In the current version or JDeveloper there is no feature to save all the changes you made with a simple export or click on a button. An ER for this is about to be filed.

Until we see this ER implemented you need to store the changes you made yourself. First of all we need to know all the places were changes can be saved in a file or exported into a file. I put all those files under source control. This makes them available for other developers in the same team and allows to hold different configurations for different or the same JDeveloper version. This blog post lists all the places I know. If you know any other place, please drop a comment so that I can include it here.
To my knowledge the locations below are working for all JDeveloper version from 11.1.1.x up to the current version 11.1.2.1.0.

There are three locations where you can save your changes

  1. Recource Palette
  2. Preferences
  3. File menu

Lets start with the Resource Palette:

Resource Palette 1

Resource Palette 1


This will bring up
Resource Palette 2

Resource Palette 2


This dialog allows you to save all the connection to DBs and Weblogic Servers you have defined as well as Catalogs. All you have to do is to specify a path and a file name to store the information.

Next are the Preferences. Here are a couple of places where you can export your changes.
Audit Profiles:

Audit Profiles

Audit Profiles

Code Editor – Code Style

Code Editor - Code Style

Code Editor - Code Style

Code Editor – Code Templates

Code Editor - Code Templates

Code Editor - Code Templates

Code Editor – Syntax Colors

Code Editor - Syntax Colors

Code Editor - Syntax Colors

Database – SQL Formatter

Database - SQL Formatter

Database - SQL Formatter

Database – SQL Formatter – Oracle Formatting

SQL Formatter - Oracle Formatting

SQL Formatter - Oracle Formatting

Database – SQL Formatter – Other Vendors (each vendor can be saved)

 Database - SQL Formatter - Other Vendors

Database - SQL Formatter - Other Vendors


 Shortcut Keys

Shortcut Keys

Versioning – Comment Templates

Versioning - Comment Templates

Versioning - Comment Templates

Finally the ‘File’ menu which mainly allows to export the connections to the source control system you use

File - Export

File - Export

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.