JDeveloper 11gR1 Bug in Tuning Node of ViewObject

Today I came across a bug in the tuning node of ViewObjects in JDeveloper 11gR1 (meaning all 11.1.1.x versions). For a prove of concept I played with the tuning options available for ViewObjectes in JDeveloper. The following image shows the the default tuning node of a ViewObject (it doesn’t matter if it’s based on an EntiyObject or not):

Default Tuning Node

Default Tuning Node

As I tested some options I eventually switched to the ‘Only up to row number’ radio button which enables the input field for the number of rows:

Tuning for '...up to row number'

Tuning for ‘…up to row number’

Nothing special there. Now if you delete the number (default is 10)

Delete Number from Field

Delete Number from Field

and ‘tab’ out of the input field, or click on any other field, you get an error dialog telling you that ‘(null) is not a valid fetch size value’.

Error Dialog

Error Dialog

OK, this is correct, but if you hit the OK button or the ‘x’ to close the dialog to put the number back in the dialog stays open, you can’t close it. You don’t get a chance to put the number back into the field. A first I had to kill JDeveloper through the task manager (I did that a couple of times ;)) until I found the following workaround:
            hit the Esc key
you may need to do this multiple times, but the dialog closes eventually and the last number is back in the input field.

This bug is fixed in the current JDeveloper 11gR2 (11.1.2.3.0) version!

Advertisements

JDev: Custom selectionListener for ViewObjects in ‘RangePaging’ mode

Lately a question on the Oracle JDev forum came up, asking for a solution for a problem with a ViewObject in ‘RangePaging’ mode and a single selection af:table defined on this ViewObject. The problem is to get the current selected row in such a case. Under some circumstances (which are not always reproducible) using the default

#{bindings.YOUR_VIEWNAME.collectionModel.makeCurrent} 

doesn’t mark the selected record and a call in a bean to get the selected record returns null:

BindingContext lBindingContext = BindingContext.getCurrent();
BindingContainer lBindingContainer = lBindingContext.getCurrentBindingsEntry();
DCBindingContainer bindingsIte = (DCBindingContainer) lBindingContainer ;
DCIteratorBinding dciter = bindingsIte.findIteratorBinding("YOUR_VIEWNAMEIterator");
Row row = dciter.getCurrentRow();
if (row == null) {
    return null;    // no current row
}

For ViewObjects in ‘Scrollable’ mode you get the selected record without any problem. ViewObjectes in ‘RangePaging’ mode are mostly used for tables which contain many rows and the use case doesn’t allow to filter the result set to a reasonably number. The ‘RangePaging’ option is a tuning parameter in the ViewObject definition

Set a ViewObject to 'RangePaging' mode

Set a ViewObject to 'RangePaging' mode


I run into this condition myself and use the following work around:

  1. remove the current selectionlistener from the table (#{bindings.YOUR_VIEWNAME.collectionModel.makeCurrent})
  2. define a new selection listener (use the small arrow on the right side) in a bean of your choice. The scope of the bean has to be view or pageflow depending on where you need access to the selected row
  3. in the new selectionListener you get the selected row from the event, get the key of the row and store it in a bean attribute
  4. when you need the selected row you use the stored row key and work with this. If you need attributes from the row you have to query the row again, as you only have the key

If you only need the key of the row you can e.g. pass this key to a service method defined in the application module or the ViewObject. Here is a sample of such a selection listener:

public void singleSelectionListener(SelectionEvent selectionEvent) {
        RowKeySet rksAdd = selectionEvent.getAddedSet();
        if (rksAdd.isEmpty())
            return;  // no selection
 
        Object[] it = rksAdd.toArray();
        // as this is for single selection there should only be one, but...
        for (Object obj: (List) it[0]) {
            mLogger.fine("Selected :" + obj);  // log selected row
            Key k = (Key) obj;   // the object is the row key
            Object[] kv = k.getKeyValues();  // get the key value for later
            // strore the key value in a bean attribute: mLastSelectedOID is defined in the bean
            mLastSelectedOID = (Integer) kv[0]; // store the key value (if the key has multiple parts you need to store them all)
        }
    }

The variable mLastSelectedOID is defined in the bean. The type of the attribute depends on the type the primary key of the table has. If you like you can generate getter/setter methods for the attribute and use them instead of assigning the value directly.

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

ADF News Session – ADF Logging

Am 01.10.2010 fand die ADF Newssession zum Thema “Logging in ADF Anwendungen” statt. Wie in der Session besprochen werde ich in diesem Eintrag die verwendeten Workspaces bereitstellen.

Der Workspace SCMDebugLogging beinhaltet den in der Session verwendeten ConsoleHandler, die angesprochene Wrapperklasse WLSConsoleHanndler sowie den DebugFormatter.
Die Klassen sind in Code dokumentiert.

Damit JDeveloper die Klassen verwenden kann, müssen sie als JAR verpackt werden und entweder in den CLASSPATH aufgenommen werden, oder in ein Verzeichnis kopiert werden, welches der im JDeveloper integrierte WLS beim Starten automatisch durchsucht.

Ich verwende die zweite Methode und dazu das Verzeichnis
‘WLSHome’/system11.1.1.3.37.56.60/DefaultDomain/lib
‘WLSHome’ ist dabei durch das auf ihrem System entsprechende Verzeichnis zu ändern.

Dieses Verzeichnis ist im Deployment-Descriptor des Workspace angegeben und muss auf Ihre Installation angepasst werden, oder Sie kopieren das JAR von Hand.

Der Workspace PopupRegion enthält die Beispielanwendung, die auf dem HR Schema von Oracle beruht.

Hier noch die Zusätze zur logging.xml innerhalb des JDev:

 <log_handler name='smc-console-handler' class='de.smc.common.logger.SMCConsoleHandler' level='ALL' encoding='UTF-8'>
  <!-- t = thread
       n = logger name
       l = line number; falls angegeben werden c und m nicht berücksichtigt
       c = class name
       m = method name
  -->
   <property name='formatStyle' value='tnlcm'/>
   <property name="formatter"
             value="de.smc.common.logger.WLSConsoleFormatter"/>
  </log_handler> 
  
  <logger name='de' level='TRACE:1' useParentHandlers='false'>
   <handler name='smc-console-handler'/>
   <handler name="odl-handler"/>
  </logger>  

Viel Spaß bei Probieren…

Folien der Session als PDF:
Logging in Web-Anwendungen

SMCDebugLogger (bitte mit ‘Link speichern unter…’ laden und nach ‘.zip’ umbenennen!):
SMCDebugLogging_ThuSep30170446CEST2010.zip

PopupRegion (bitte mit ‘Link speichern unter…’ laden und nach ‘.zip’ umbenennen!):
PopupRegion_ThuSep30170502CEST2010.zip

Logout with confirmation dialog

A question on OTN (http://forums.oracle.com/forums/forum.jspa?forumID=83) leads to this short article.

The use case requires to ask for a confirmation before logging out of the application.  This can easily implemented using a OK/Cancel dialog  which we show on a button click.

My simple test page looks like this:

On a click on the logout button we show a confirmation dialog as popup:

The dialog uses a dialog listener to catch the user input.  For an OK/Cancel dialog only the click on the OK button is passed to the listener. Closing the dialog or clicking cancel never calls the dialog listener. Clicking on OK navigates to a logout page:

Looks pretty simple,  still we need  a few things to mention. The code for the logout button and popup  looks like:

<af:panelGroupLayout id="pgl1">
  <af:commandButton text="Logout" id="cb2">
    <af:showPopupBehavior popupId="p1" triggerType="action"/>
  </af:commandButton>
  <af:popup id="p1">
    <af:dialog id="d2" dialogListener="#{LoginLogout.dialogLogoutListener}" title="Confirmation">
    <af:outputText value="Do you want to logout?" id="ot2"/>
    </af:dialog>
  </af:popup>
 </af:panelGroupLayout>

The real work is done in the dialog listener in the managed bean (here called LoginLogout). The dialog listener checks if OK was clicked, and then calls the logoutTarget method with a parameter which is the target page after invalidating the session. This page is a normal html page just showing the user that his session has ended. On this page you can put a link back to the application as shown above.

public String logoutTarget(String aTarget)
{
  ExternalContext ectx = FacesContext.getCurrentInstance().getExternalContext();
  HttpServletResponse response = (HttpServletResponse) ectx.getResponse();
  String url = ectx.getRequestContextPath() + aTarget;
  HttpSession session = (HttpSession) ectx.getSession(false);
  //close session
  session.invalidate();
  try
  {
    response.sendRedirect(url);
    FacesContext.getCurrentInstance().responseComplete();
  }
  catch (IOException e)
  {
    e.printStackTrace();
  }
  return null;
}

public void dialogLogoutListener(DialogEvent dialogEvent)
{
  if (dialogEvent.getOutcome() == DialogEvent.Outcome.ok)
  {
    logoutTarget("/ByBy.html");
  }
}

If you use a jspx page which is part of  your application, the session gets invalidated but you see that url rewriting stuff is still part of the url you see in the browser.

http://127.0.0.1:7101/LoginLogout/faces/Logout.jspx?_afrWindowMode=0&_afrLoop=10962072683890&_adf.ctrl-state=10eyn0547w_4

I like it if the url looks like

http://127.0.0.1:7101/LoginLogout/ByBy.html

so I use a normal html page.

Feel free to play with this. You only have to change the parameter in the logoutTarget(…) method call to

logoutTarget("/faces/Logout");

if you have a page Logout.jspx in your application.

FATAL ERROR when upgrading to WLS 10.3.3

In one of my last posts (https://tompeez.wordpress.com/2010/05/01/upgrade-an-existing-wls-10-3-2-to-wls-10-3-3/) I talked about the process of upgrading an existing WLS 10.3.x server to version 10.3.3.
One minor bug or glitch came up when I tried the procedure on one of the customers WLS servers.
Right befor the upgrade process starts we got a ‘FATAL ERROR’ from the installer. No log where written, nothing unusual I could think of.
After trying it out a couple of times, the last try I used JRockit instead of the configured Sun JDK and bingo I got an error message too. The big difference this time it told me that the free space on one of the partitions was too small.
Removing some old stuff from the partition solved the problem.

Upgrade an existing WLS 10.3.2 to WLS 10.3.3

Since JDev 11.1.1.3.0 is out we have to think about where to deploy the apps to which are developed with the new version. Bad new is, that you can’t use existing WLS 10.3.2 and just delpoy application compiled or developed with the new JDev 11.1.1.3.0 version. Good news is, that you don’t have to setup a whole new WLS 10.3.3, at least if you have a valid support contract.

Log in to MOS and download the upgrade installer for WLS 10.3.3 (from the patch and update section) and the ‘Oracle Application Development Runtime 11g Patch Set 2’ (from E-Delivery)

In this short post I’ll just describe the ease routine of updating an existing WLS 10.3.2 :

  1. remove all your applications running on WLS 10.3.2 (first stop them, then delete them)
  2. stop WLS 10.3.2
  3. make a backup of all the files in WLS you have changed. The upgrade process does this for only a barely minimum of files.
  4. run the upgrade installer for WLS 10.3.3: this is just pointing to the existing ‘Middleware’ folder (the folder you installed the WLS 10.3.2 to) and let the installer do the rest of the work
  5. run the ADF runtime installer patch to 11.1.1.3.0: this is patch installer, so you need to have ADF 11.1.1.2.0 installed, otherwise you’ll get an error. The only thing to do is to point to an existing domain in the now upgraded WLS.
  6. start WLS now 10.3.3
  7. deploy your apps (compiled with JDev 11.1.1.3.0) again

That all you need to do. For more complex scenarios like clusters  and/or WLS installation which have been adopted to special needs you my have to do some more work. This is all well documented in the README.TXT file you get together with the upgrade installer.