Tuesday, November 19, 2013

JDeveloper Extension To Suppress Warnings

The JDeveloper auditing framework can be a very valuable tool in delivering high quality code. It not only gives you warnings and errors during development, but can also be run from the command-line on a build server. One thing that always annoyed me is the limited possibilities for suppressing individual warnings. Sure, there is the @SuppressWarnings annotation for Java code. JDeveloper 12c can even use this annotation to suppress any warning, not only the ones supported by the java compiler.

However, much of an ADF (or SOA) application is XML files, not java. JDeveloper 12c doesn't offer a way to suppress warnings in these files. Luckily the auditing framework is highly pluggable and after some inspection how the @SuppressWarning annotation is implemented in the auditing framework, I could create something similar for XML files.

Suppressing a warning in a JSF file

The screenshot above shows how the extension works. See the warning for the value property of the af:outputText component and how it marks this entire document as warning. Simply click the balloon in the gutter of the editor and select to suppress this warning. This adds a comment to the XML file to suppress the warning, very similar to a @SuppressWarnings annotation in java.

Suppressed warning in a JSF file
Notice how the document is now marked green an no more warnings appear. With this extension you can keep the number of warnings down so the real warnings get the attention they need.

I have plans on building a SonarQube extension to run ojaudit (the command line JDeveloper auditing tool) to keep track of your quality. Suppressing warnings can be especially valuable in that situation where you can use SonarQube to keep metrics and track unexpected warnings and errors.

The extension is already live, so simply start JDeveloper 12c and use the Help > Check for Updates feature. Be sure to check "Open Source and Partner Extensions". You should be able to find the "Suppress Audit Warnings" extension. Please leave a comment below if you have any questions or suggestions for a future version.

If you want to see how a custom suppression scheme is built you can download the full workspace or simply browse the subversion repository to look at the source code.

Wednesday, November 13, 2013

Overriding Entity doDML or prepareForDml Causes Locking Issues

It is not uncommon for people to override the doDML or prepareForDml method in an ADF BC Entity to do some additional work just before posting changes to the database. The official documentation even describes this extension point as being an equivalent to the Oracle Forms Post Processing triggers.
Today I discovered this can lead to locking issues in the database when this additional work changes other view objects or entities. The investigation is based on JDeveloper version 11.1.1.7 and this behavior might differ for other versions.

Update Nov 14: The issue doesn't reproduce in ADF 12.1.2.0. Inspecting of the source code seems to indicate (unpublished) bug 11896369 is to blame. Currently working with Oracle support to further investigate and ask for fix backport to 11.1.1.7

Update Jan 2: Oracle development acknowledged this behavior is caused by bug 11896369 and a backport request has been filed to bring the fix to 11.1.1.7.

Update Jan 10: Patch 11896369 is now available for download.

Let's start with an simplified example of an entity mutation another one. Below is the doDML method of the Department entity. Whenever a change happens to a department it sets the commission of its first employee to 99%. Not a very likely business scenario, but enough to demonstrate the issue.

@Override
protected void doDML(int i, TransactionEvent transactionEvent) {
    RowIterator employees = getEmployees();
    EmployeeImpl firstEmployee = (EmployeeImpl)employees.first();
    try {
        firstEmployee.setCommissionPct(new Number(0.99));
    } catch (SQLException e) {
        throw new JboException(e);
    }
    super.doDML(i, transactionEvent);
}

What we also need is a entity level validation on Employee that will be violated by this change. For demonstration purposes I've setup a range validation for CommissionPct to be between 0.00 and 0.50:
Entity-level Validation Rule

Now let's build a very simple ADF page to change a department and try to save the changes to the database. Here is what happens:
Validation Error in ADF Application

Everything appears to be okay. The user is confronted with the validation error as expected. But now let's try to update the same record from a different database session:
Database record locked after validation exception

Friday, November 8, 2013

Vodafone Content Tampering Making Sites Very Slow On Wi-Fi

I've had issues with this blog sometimes being very slow on my iPhone when using Wi-Fi. I finally figured out what is going and it seems like Vodafone (Netherlands) are to blame.

I noticed my browser is trying to download http://1.2.3.50/jsi/flash.php?file=gordon.js&max-age=3600 which never succeeds on Wi-Fi. A whois search seems to indicate the entire 1.2.3.0/24 address block is invalid and shouldn't be used on the public internet. All traffic to this address block is dropped along the route and it takes the browser (or TCP/IP stack) a full minute to give up and continu loading my blog. Strangely enough downloading this script on a Vodafone NL 3G connection does succeed.

But why is my client requesting this bizarre URL? It is actually part of http://googleads.g.doubleclick.net/pagead/blank.html which is used on my blog pages. When requesting this page over a Vodafone NL 3G mobile connection the content of this blank page is:
<html><script src="http://1.2.3.50/jsi/flash.php?file=gordon.js&max-age=3600" language="javascript"></script>
<body style="background-color: transparent"></body></html>

There it is; this blank.html page contains a script tag to load the mysterious resource from 1.2.3.50. When requesting this same blank.html from my Wi-Fi connection I get a trully blank page:
<html><body style="background-color: transparent"></body></html>

You don't really notice the difference while your are on Vodafone NL 3G network. Your browser will download the file from 1.2.3.50 and the site seems to function okay. But what happens when your device (re)connects to Wi-Fi? Google sends response headers with blank.html telling your browser it is okay to cache the page for 24 hours. So your device will simply use the cached (tampered) version of blank.html it retrieved through Vodafone's network. But now you are on Wi-Fi and your device can't load the file from 1.2.3.50 and the site is dead slow.

Okay, this is bad, but let's hope the problem clears after 24 hours. After all your browser is only allowed to cache the tampered blank.html page for 24 hours. Unfortunately the problem doesn't disappear after 24 hours. This is caused by Google sending an ETag response header with blank.html as well. An ETag is an opaque identifier assigned by a web server to a specific version of a resource found at a URL. If the resource content at that URL ever changes, a new and different ETag should be assigned. Google sending an ETag is a good thing, but Vodafone is altering the content so they should also change the ETag. Unfortunately they don't so your browser is caching this altered version under Google's original ETag. So even when the cache expires after 24 hours and your browser is asking for a fresh copy of blank.html it will include the ETag with this request. Whether you are on Wi-Fi or 3G, Google will always respond that blank.html hasn't changed since your request includes their original ETag. This instructs your browser to keep using the (tampered) cached version. In the end, you are stuck with the altered version of blank.html until you clear your browser cache.

Vodafone is altering pages I request from the internet and to make things worse they are altering them in such a way that these pages won't work outside of their network while allowing my browser to cache this crippled content. This really sucks! I want the real internet and not some crippled version! Vodafone support is acknowledging they are injecting javascript through a transparent proxy. They state the only way to get rid of this is to use a different APN setting on your mobile device which first has to be activated for your account through technical support. This sucks big time! Sure I can get my account fixed, but who knows how many more people are running into this issue without ever figuring out what is going on.

Hopefully this rant can help others understand what is going on when they see this failed downloads from the 1.2.3.50 or 1.2.3.4 IP address.

Thursday, November 7, 2013

Decimal Comma with Numeric Keypad as ADF Client Behavior

According to wikipedia 24% of the world's population uses a comma as decimal separator, including The Netherlands where I live. This means entering numeric information with the numeric keypad on the keyboard can be challenging. You can only use it to type a decimal point (.) while we need a decimal comma (,). To make things ADF simply ignores the decimal point in our locale. When a user enters 1.23 it is converted to 123 and wrong information is entered into the system.
Numeric keypad decimal point

We came up with a solution based on a custom ADF Behavior tag. I've recently posted how to create your own ADF (client side) behavior. The first post was a simple version without properties, while the second post expanded this example with properties. Now it is time for the sequel showing how you can handle key presses in an input item and replace any decimal point keystroke with a decimal separator (possibly comma) keystroke. The user can simply use the decimal point on the numeric keypad and when using a European locale it will simply type a comma.

Monday, October 14, 2013

Check for postChanges without commit or rollback in ADF BC

It is not uncommon for an ADF application to invoke DBTransactionImpl::postChanges() to perform database DML without invoking commit (or rollback). This is typically done in environments where we also want to invoke PL/SQL logic in the database that already needs to see these pending changes.

The developer should make sure a commit or rollback is executed in the same JSF request. If this is not done, the database session has pending changes and as we know there is no guarantee a subsequent request by the same user will get the same Application Module and JDBC Connection. It is considered bad practice to have these pending changes survive a single request and today we had a situation where this accidentally happened with all sorts of nasty side-effects. One of the things that happens is that the pending changes also could mean long-lived database locks. We added some code to our ADF BC base classes to detect this and throw an exception so we at least know what is going on and to alert a developer he/she is implementing this bad practice.

First thing we need is to configure our application module to use a custom database transaction class. This is described in the ADF documentation. First we need to create our own DatabaseTransactionFactory so we can use our own subclass of DBTransactionImpl2:
import oracle.jbo.server.DBTransactionImpl2;
import oracle.jbo.server.DatabaseTransactionFactory;

public class MyDatabaseTransactionFactory
  extends DatabaseTransactionFactory
{
  @Override
  public DBTransactionImpl2 create()
  {
    return new MyDBTransactionImpl2();
  }
}

Then we need to make sure this factory class is used instead of the default by setting the TransactionFactory property of the ADF Application Module configuration to the full class name of our own transaction factory:
Set TransactionFactory property of AM Configuration

Next, we can create our own subclass of DBTransactionImpl2 that keeps track of pending postChanges. It sets a flag when postChanges is executed and clears this flag when performing a commit or rollback. We are going to check this flag later on when releasing an Application Module at the end of a request:
import oracle.jbo.server.DBTransactionImpl2;
import oracle.jbo.server.TransactionEvent;

public class MyDBTransactionImpl2
  extends DBTransactionImpl2
{
  private boolean postedChanges = false;

  @Override
  protected void postChanges(TransactionEvent te)
  {
    super.postChanges(te);
    setPostedChanges(true);
  }

  @Override
  protected void doCommit()
  {
    setPostedChanges(false);
    super.doCommit();
  }

  @Override
  protected void doRollback()
  {
    setPostedChanges(false);
    super.doRollback();
  }

  private void setPostedChanges(boolean postedChanges)
  {
    this.postedChanges = postedChanges;
  }

  public boolean isPostedChanges()
  {
    return postedChanges;
  }

}

Final step is to check for pending postChanges at the end of each request. We can do this from our Application Module. This would typically be code you add to your own ADF BC base classes:
import oracle.jbo.ApplicationPoolSvcMsgContext;
import oracle.jbo.JboException;
import oracle.jbo.server.ApplicationModuleImpl;
import oracle.jbo.server.DBTransaction;

public class MyBaseAppModuleImpl
  extends ApplicationModuleImpl
{
  /**
   * This is invoked by the Application Module Pool whenever an 
   * application module is being used, released, removed or recycled
   * from the pool.
   */
  @Override
  public ApplicationPoolSvcMsgContext doPoolMessage(ApplicationPoolSvcMsgContext ctx)
  {
    if (ctx.getMessageType() == 
        ApplicationPoolSvcMsgContext.MESSAGE_TYPE_RELEASING)
    {
      DBTransaction txn = getDBTransaction();
      if (txn instanceof MyDBTransactionImpl2 && 
          ((MyDBTransactionImpl2) txn).isPostedChanges())
      {
        // throwing exception will mark AM as dead and close tainted
        // DBTransaction and JDBC connection
        throw new JboException("Application Module released to the pool with pending posted changes");
      }
    }
    return super.doPoolMessage(ctx);
  }

}

ApplicationModule::doPoolMessage is invoked whenever the pool uses, releases, removes or recycles an application module instance. This can be seen by inspecting ApplicationPoolSvcMsgContext::getMessageType() and comparing to any of the MESSAGE_* constants in ApplicationPoolSvcMsgContext. We check for uncommitted postChanges whenever the application module instance is released to the pool (aka at the end of each request). If these exist we simply throw a JboException. This will not be visible to the end-user as the JSF response has already been completed by then. It will show up in the log for administrators and developers. Because we are throwing an exception during pool management the AM instance will be destroyed together with its JDBC connection. This is actually good as we don't want the AM instance with pending changes, and potential database locks, to linger around.

Update 2 jan: We changed the code to no longer throw an exception thus destroying the applicationModuke, but only log a warning message. Due to an ADF bug we have quite a few AM instances with posted changes at the end of their request. When they get destroyed all ViewObjects loose their where clause and other (or all) records are fetched on the next page request. So until that bug is we fixed we reverted to only logging a warning.

Thursday, August 22, 2013

JDeveloper installer very small on Mac OS X

I have previously installed JDeveloper 11 on my MacBook Pro running Mac OS X Mountain Lion (10.8). Basically you download the generic installer from Oracle and run:
java -jar jdevstudio11124install.jar

Today I tried it again and the installer does start but with a very small screen only showing the exit button:
JDeveloper Installer with only Exit button

As it turns out this is caused by a recent install of JDeveloper 12c on the same machine. That had forced me to install JDK version 7 which is now the default java runtime environment on my machine. Apparently the JDeveloper version 11 installer doesn't like java version 7, at least on Mac OS X.

The solution is rather simple. Run the following commands in a terminal window to start the JDeveloper 11 installer:
wMac:~ wilfred$ /usr/libexec/java_home -v 1.6
/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
wMac:~ wilfred$ /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java -version
java version "1.6.0_51"
Java(TM) SE Runtime Environment (build 1.6.0_51-b11-457-11M4509)
Java HotSpot(TM) 64-Bit Server VM (build 20.51-b01-457, mixed mode)
wMac:~ wilfred$ /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java -jar jdevstudio11124install.jar 
Extracting scripts to /var/folders/vl/qsk0dkgn39b2_4sdngwvcf840000gn/T/
Executing MacOS-specific pre-installation scripts
You may be prompted to enter your Mac OS X password in order to create required directories and symbolic links
Extracting 0%....................................................................................................100%


Line 1 runs java_home to get you the full path to the java version 6 home directory. Line 3 uses this path and adds "/bin/java -version" to run java from that directory to check its exact version. Make sure it is in fact a 1.6.0_xx version. Then finally line 7 uses java from that directory to run the installer. This time it just starts fine:
JDeveloper 11 installer runs fine with JDK 6

Monday, June 17, 2013

Credential Store Framework

Sometimes you have the need for credentials (username/password) in your ADF, or other Fusion Middleware, application. I've seen numerous solutions with property files, web.xml context parameters, deployment plans, etc. Most of these run into problems with SysOps or anyone else worried with security. You don't want these credentials scattered around in plain text files and you don't want developers to know the passwords for each environment. This is better left to configuration by a sys-admin after deployment.

Not everybody seems to know Oracle Fusion Middleware, more specifically Oracle Platform Security Services (OPSS), provides a great solution with the Credentials Store Framework. This is a set of APIs that applications can use to create, read, update, and manage credentials securely.

A credential store is a repository of security data (credentials) that can hold user name and password combinations, tickets, or public key certificates. A credential store can be file-, LDAP- (Oracle Internet Directory), or DB-(Oracle RDBMS)based. A file-based credential store, also referred to as wallet-based and represented by the file cwallet.sso, is the out-of-the-box credential store.

The Credentials Store Framework also limits which application (or components thereof) are allowed to retrieve or modify credentials. This allows for a very secure setup where only trusted libraries that go through extensive auditing are allowed to retrieve credentials.

This post describes the basic steps to get started with the Credentials Store Framework, but more information can be found in the official documentation (Fusion Middleware Application Security Guide):

Wednesday, May 8, 2013

Customizing JDeveloper Preferences

I like to tweak some of the preferences in the Tools menu of JDeveloper. I thought I would document them here for my own reference and in case anyone else is interested. I'll try to list all the settings I typically change from their default. These are ordered and grouped by their panels in the preferences dialog so you should be able to locate them easily.

  • Environment
    • Line Terminator to "Line Feed (Unix/Mac)" especially if you are in a mixed environment with windows and linux/mac developers as it prevents a lot of problems if everyone creates the files in the same way.
    • Encoding to "UTF-8". I have no idea why the default is platform dependent (MacRoman or some obscure windows code page). I like all developers in the team to use the same encoding. This is also used as encoding in XML files you create. Changing it afterwards can be a lot more work as existing files might need recoding
  • Environment > Log
    • Maximum Log Lines to something like 50000. The default of 3000 can be too small if you crank up the logging levels in a development session.
  • ADF Business Components
    • Look at all these settings carefully (and read below). Lots of these settings are used when creating new ADF BC objects so be careful to set these up before you start developing as it can safe a lot of rework later
  • ADF Business Components > Base Classes
    • You can set the default base classes for any ADF BC object you will create in JDeveloper. It is wise to create company wide extension classes for these and configure JDeveloper to use your company extended classes instead of the JDeveloper base ones. You could even  create a layer of extension classes for your project (extending from company classes) and setup the per-project settings to use these application level extension classes
  • ADF Business Components > Packages
    • A lot of developers like to group their ADF BC objects per type in separate sub packages. For instance put all view objects in a subpackage .views or .queries. In stead of remembering to set these sub packages each time you are creating ADF BC objects simply set the defaults here.
  • ADF Business Components > View Objects
    • You could set the default fetching tuning parameters for new view objects here. But in reality they need consideration for each view object you create. One trick we used in the past is to set a ridiculous default value here and then check for that ridiculous value in your extended ADF ViewObject classes. If the developer left the ridiculous initial value simply throw an exception telling the developer to set reasonable values.
  • Audit
    • The JDeveloper Audit framework is under-appreciated. I would advise to tweak the Code Assist Rules that you see while developing. Go over the rules that are disabled by default and see if you want to enable them. My guess is you can enable most of them, especially to warn developers about missing or incorrect javadoc. Also be sure to check the "Audit During Compile" with perhaps a slightly less restrictive set to prevent your developers from violating certain rules. The next step would be to monitor these quality issues from your continuous build server
  • Code Editor
    • I like to enable "Reformat Code Block When Pasting". That is mainly since I tend to keep most of my code auto-formatted so reformatting when pasting someone else's code seems like a good idea.
    • One other thing I like to enable is "Show Total Number of Lines in the Status Bar" just to remind to keep the files small and simple.
  • Code Editor > Code Templates
    • You can add your own code templates here. We've added a bunch to easily use ADFLogger in your Java source code. More on that in a future post.
  • Code Editor > Display
    • Enable Text Anti-Aliasing because it just looks better :-)
  • Code Editor > Line Gutter
    • Enable "Show Line Numbers"
  • Code Editor > Save Actions
    • These are actions that JDeveloper should perform on each file you save. I typically add "Organize Imports", "Trim Trailing Whitespace" and "Clear All Highlighting". I've tried using Reformat as well which is great for Java sources which should always be formatted by a tool for consistency. But JDeveloper will then also reformat all XML files including JSF pages. In those files it is much more common to perform manual formatting and I don't like the always-auto-format of these save actions.
  • Compiler
    • Enable "Clean Project Before Project Rebuild". If you are rebuilding your entire project I see no reason why you don't want to start with a clean project first. Otherwise you might run the risk of keeping compiled artifacts for source objects you have already removed.
  • CSS Editor
    • If you do anything with ADF skinning be sure to set the CSS level to Level 3 (and on JDev 11gR1) enable the ADF Faces Extensions checkbox
  • Debugger
    • Check "Show Action Buttons" to get the debugger buttons (step, continue, etc) also in the log window of JDeveloper.
  • Debugger > Beakpoints
    • Set the scope for new breakpoints to Global. Especially if you are building on a large system with multiple workspaces. With the default setting your debugger will not stop if you set a breakpoint in one workspace and run the application from another workspace. My workflow is to keep the number of breakpoints limited and I frequently clean them. I would like the confidence that a breakpoint is always used.
  • Debugger > Data
    • I personally don't like the new Tree View in the 11gR2/12c debugger where you drill down into objects and have to traverse back up. I prefer the old-style Table View so I change the default view here.
  • Debugger > Smart Data
    • I like to increase the "Number of Lines to Analyze" to something like 5 to show a bit more information in this debugger panel.
    • I personally don't like the new Tree View in the 11gR2/12c debugger where you drill down into objects and have to traverse back up. I prefer the old-style Table View so I change the default view here.
  • Debugger > Watches
    • I personally don't like the new Tree View in the 11gR2/12c debugger where you drill down into objects and have to traverse back up. I prefer the old-style Table View so I change the default view here.
  • File Types
    • I like to change the default editor panel used for certain files. I don't like JSF files to open in design WYSIWYG mode as initializing that editor can be slow. I prefer these to start in source view and I can always switch to the design tab if needed. You can set this in the Default Editors tab of these preferences. I like to set this to "Source" for "ADF Fragment File", "HTML Source", "HTML Template", "JSFF Label", "JSP Segment", "JSP Source", "XHTML/Facelets Source" and "XHTML Source" (not all of these exist in every version of JDeveloper)
  • News (JDev 12c only)
    • Add http://feeds.feedburner.com/RedHeap to the list of News Feeds to get Red Heap posts in JDeveloper :-)
  • Run > WebLogic
    • On 11gR2 only enable FastSwap deployment to you can make more changes to a deployed application without doing a full redeploy. Unfortunately this feature is not available on 11gR1.
  • Web Browser and Proxy
    • If your organisation uses a web proxy be sure to fill in these details so JDeveloper can access the internet for things like checking for updates. You can also set you default web browser here in case that is different from the default browser of your operating system. I like to use Google Chrome as my development browser and sometimes you cannot change the default web browser of your operating system due to administrator restrictions.
    • When using Chrome as your browser be sure to start it in incognito mode. This ensures you start with a clean browser each time you start your application. In JDeveloper 11g you can simply add --incognito to the command line of chrome while JDeveloper 12c allows you to specify --incognito ${URL} as command line parameters.
Some other things I would like to chance with a default JDeveloper installation:

  • Select Tools > External Tools and let JDeveloper create the default external tools when running on Microsoft Windows. This gives you a convenient right-click on all your objects to start a windows explorer in that specific source directory. Something I frequently use, for example to get access to TortoiseSVN on that file. On Mac I like to setup this to run a terminal from the selected directory.
  • Change the memory options in JDEV_HOME/ide/bin/ide.conf. On a 32-bit JVM I like to set both -Xmx and -Xms to 1200M. On a 64-bit JVM you could even go a bit higher, like 1500M or 2000M.
  • When running with non-English regional settings on your operating system, edit JDEV_USER_HOME/system11.x.x.x.x.x.x/DefaultDomain/bin/setDomainEnv.cmd, search for the lines where EXTRA_JAVA_PROPERTIES are set and add a line
    set EXTRA_JAVA_PROPERTIES=-Duser.language=en -Duser.country=US %EXTRA_JAVA_PROPERTIES%
    This enforces WebLogic to use en_US as locale so error messages in the JDeveloper Log window are English and not the language from your operating system. This makes googling for these error messages much easier ;-)
  • While you're already editing JDEV_USER_HOME/system11.x.x.x.x.x.x/DefaultDomain/bin/setDomainEnv.cmd you might just as well increase the memory for WebLogic. Search for the lines where XMS_SUN_64BIT, XMS_SUN_32BIT, XMX_SUN_64BIT and XMX_SUN_32BIT are set. My advice is to change all four to 1024 but you might want to tweak this for your situation.
    When using JDeveloper 12.1.2 you can set memory arguments in JDEV_USER_HOME/system12.1.2.x.x.x.x/DefaultDomain/bin/setStartupEnv.cmd in the section for AdminServerStartupGroup.

Friday, March 15, 2013

ADF Faces Client Behavior with Attributes

Last month I posted about the basics of creating custom ClientBehavior in ADF Faces. Now it is time to take the next step and enhance that example with ways to set attributes on the JSP client-behavior tag, pass these on to the client-side javascript implementation and use them in the actual functionality.

We'll take the (simplified) example of the previous post that could show a javascript alert and adopt it to get the message from an attribute which we specify in the JSF page using the component. We'll also make sure we can use an EL expression to specify this values (this is the tricky part). We will be able to do something like:
<af:forEach begin="1" end="5" varStatus="vs">
  <af:commandButton text="click to see message #{vs.index}" id="cb">
    <redheap:showAlertBehavior message="This is message #{vs.index}"/>
  </af:commandButton>
</af:forEach>

Saturday, February 2, 2013

Custom ADF Faces Client Behavior 11.1.1 JSP tag

This post will show how to create your own ADF Faces client behavior JSP tags which makes them suitable for ADF version 11gR1, also known as version 11.1.1, and version 11gR2 (11.1.2) when not using Facelets.

ADF Faces client behavior tags provide declarative solutions to common client operations that you would otherwise have to write using JavaScript, and register on components as client listeners.

Using tags makes behavior much more reusable. All a page developer has to do is drag-and-drop the client behavior tag on the appropriate component and not worry about writing JavaScript and attaching the appropriate client listeners. ADF Faces 11gR1 has a number of client behavior tags and a couple more were added in version 11.1.2. Some examples are the af:showPopupBehavior to disclose a popup or the af:scrollComponentIntoViewBehavior to scroll the page.

Wouldn't it be great if we can create our own client behavior tags for things that ADF doesn't support out of the box? There are a number of blogs out there that describe something like that, such as placeholder watermarks by Duncan Mills and setting the initial focus component by Donatas Valys. Unfortunately those blogs describe how to do this with facelets which requires JDeveloper 11.1.2 We needed a solution for JDeveloper 11.1.1 and thus JSP tags.

Update: A follow-up post is available that explains how to add support for attributes to your custom client behavior.

Friday, February 1, 2013

Deploy a simple ADF application to Oracle Cloud

I write sample applications to accompany blog posts. You can typically download the project as a zip file or get access to the subversion repository. But I also wanted to make it as easy as possible for people to see the running application. This where the Oracle Cloud comes in. I currently still have a free trial java cloud and this posts explains how I deployed one of the sample applications to that cloud.

First thing you need is the latest version of JDeveloper 11.1.1.6. If you already have JDeveloper installed be sure to check Help > About for the version number. For reasons beyond my comprehension Oracle decided to give the JDeveloper version with cloud support the same version number. The one you need is build 6229 and not the original build 6192:

Wednesday, January 30, 2013

Performance diagnostics with ADFLogger

This post will show how to use the ADF Logger for performance analysis and how to instrument your own code so it shows up in this analysis. Every ADF developer should know, or learn, about the ADF Logger. If you are new to the logger than read up on it at the official documentation or the great Adventures in Logging series by Duncan Mills.

Configuring Oracle Diagnostic Logging

First thing we need to do is to configure the proper ADF Logger levels as the default levels will only show warning and errors. Run your application so the integrated WebLogic server starts. The log window in JDeveloper will have an Actions pull down menu where you can opt to configure Oracle logging:
configuring Oracle Diagnostic Logging

This will open an editor to the logging configuration file at DefaultDomain/config/fmwconfig/servers/DefaultServer/logging.xml which is typically in JDEV_USER_HOME/system11.1.1.6.38.61.92

SyntaxHighlighter at Blogger

Running a tech/developer blog means I will be posting source code and other technical text. This requires proper syntax highlighting and use of monospaced fonts. Unfortunately blogger.com doesn't really support this out of the box so we need to resort to 3rd parties. Alex Gorbatchev created an awesome syntax highlighter purely in javascript. This means it doesn't need a server side component and we can easily integrate it into blogger.

To integrate SyntaxHighlighter into blogger you have to edit the HTML of your template:
how to get to editing your blogger template

Tuesday, January 29, 2013

Global DateTimeConverter without separators

We are developing an application where data processing speed is important and users have to enter a lot of dates into the system. This is replacing a legacy Oracle Forms system where people were used to entering dates without any separators. For example they want to enter 120613 for June 12th 2013 (or December 6th 2013 if you're from the US).

ADF Faces (and MyFaces Trinidad) has its own DateTime converter that is already pretty advanced and lenient. You can give it a pattern and it will try to parse any input in several variations of the supplied pattern. For example, both "Jan/4/2004" and "01.4.2004" will be parsed with a pattern of "MMM/d/yyyy". For months it will try MMM, MM and M and it will try any of the separators - or . or /

But we wanted the converter to also try a pattern without any separators. You could specify a secondary pattern for a converter and it will also try to parse any input with this secondary pattern while still using the primary pattern for displaying the date/time. But I don't like the idea of manually setting a secondary pattern on each and every date field in the application.

Tuesday, January 22, 2013

Welcome back!

I've been away from blogging for too long. My old blog succumbed to spam way back. It just got too bad and I ended up shutting down my blog.

I am now putting my faith back in modern anti-spam technology and giving it another try with Google's Blogger. There's just so much stuff going on in my daytime job that is perfect for a blog. Sometimes you spend a couple of hours or days on a technical issue and I want to share it with the world. It's also a great reference for myself because you frequently need a solution you figured out months/years ago and a blog can be a very valuable reference.

For people that don't know me personally: I am Wilfred van der Deijl from The Netherlands. I have been working with Oracle development tools since 1995 with a strong focus on ADF in the last 7 years. I am an Oracle Fusion Middleware ACE and an independent contractor working on projects in the Netherlands and occasionally abroad. Last year I did smaller jobs in Denmark, Belgium, Canada and the Cayman Islands. I am also the creator of OraFormsFaces, a toolkit to seamlessly integrate legacy Oracle Forms modules into a web application. I try to present as much as possible at different Oracle events, such as OpenWorld, ODTUG Kaleidoscope, UKOUG, etcetera.

So here I am again. A fresh new blog about ADF and other Oracle Fusion Middleware topics. I am still thinking whether I should import the content of my old blog or I should get a clean start.

There are some nice ADF goodies coming in future posts. Examples are a global DateTimeConverter that allows the entry of dates without any separator (eg. 311212 or 12312012), a custom ClientBehavior to replace the decimal point on the numerical keyboard with a comma as you type, and some experiences building an ADF Mobile application that we hope to publish in both the Apple App Store and Google Play Store.

If this sounds interesting then please subscribe to the feed, or follow me on twitter (@wilfreddeijl) or Google+.