Weblog

Commons Annotations

In the previous post Tom pointed to an article discussing the use of some EJB 3.0 annotations in JSF applications: Using EJB Annotations Outside of EJB. The annotations discussed are @PostConstruct and @PreDestroy. The first annotation indicates a method to be called during creation, the other indicates a method to be called during destruction.

His post didn’t mention another interesting topic discussed: Common Annotations (JSR-250). This JSR aims to create a library with generally usable annotations. According to Ed Burns, the annotations @PostConstruct and @PreDestroy, should be part of Commons Annotations.

Commons Annotations contains some interesting annotations, as mentioned in this article on TSS: JSR 250: Common Annotations for the Java Platform in early draft. For example, the annotation @Generated, which indicates that the object or class was not hand-written.

I’m currenlty working with a lot of generated code: some generated using castor, some using JDeveloper’s visual swing editor, some using JDeveloper’s BC4J wizards. The @Generated annotation could be useful to indicate to tools like PMD, FindBugs and Checkstyle that the code does not need to be inspected. I’m sorry to say, but the code generated by JDeveloper causes these tools to generate a lot of warnings. Fortunately, most of the issues are no big deal: non standard naming, hard coded numbers, etc.

Share EJB annotations

Today, I read an interesting posting on Ed Burn’s Blog. In his posting he explains how two usefull annotations from the EJB3.0 scope are made available in the JSF scope.

It sounds like an interesting development that usefull annotations for EJB3.0 are properly made available in other parts of the Java world. This makes the live of a programmer more easy and flexible.

New releases

Oracle has released a couple of updates this week:

Succesful Deployment, or ?

Small but irritating bug in BPEL PM. Deployment of a process seems to go succesfull, but the process never shows up in the BPEL Console Dashboard. This usually happens when there’s a problem with the accessibility of the WSDL (either for the originating proces or for corresponding processes/webservices). Even a manual deployment will not help you at all.

The trick is to bypass the Dashboard just once! Try to access the process by using the following url:


http://servername:7782/BPELConsole/default/displayProcess.jsp?processId=processname&revisionTag=1.0&mode=manage

When you’ve done this once, the process shows up in the Dashboard, and you can see the exception that has occurred while deploying (even though you got the ‘Succesfull deployed’ message).

Software Configuration Management patterns

It seems like more and more people who are currently developing Oracle database software using Oracle Designer or editors like Toad are recognizing that version control could benefit their development process. When you first start using a version control system like cvs or subversion you run into a lot of questions. How do we use branches? When do we commit changes? How do we create a production release? The Software Configuration Management patterns page has some usefull advice, or patterns as they call it, for using version control and software configuration management.

Update:
Forgot to mention that these patterns are discussed in the following book: Software Configuration Management Patterns: Effective Teamwork, Practical Integration.

JComboBox automatic completion and Oracle ADF

Thomas Bierhance has written an excellent article on implementing automatic completion for JComboBoxes: Inside JComboBox: adding automatic completion.

Unfortunately, when you try to use it with Oracle’s ADF you’ll notice that it doesn’t work. I’ve modified Thomas’s AutoCompletion class to make it work with ADF. The code requires two changes.

First, when you are using ADF, the ComboBoxModel contains Row objects. A row object can have multiple attributes and you need to determine which attribute needs to be matched with the entered text. You can get this info from a UIModel.

Second, empty rows in the ComboBoxModel aren’t displayed when you use ADF. I think this is a bug, but it means that you can’t select an empty value in the JComboBox. You can work around this problem by setting the selected item to null if the entered string is completely selected and the delete key is pressed.

You can download the modified code here: AdfAutoCompletion.java.

The following is a small example using the autocompletion code. The example demonstrates how you can build a JPanel using ADF, based on a POJO model. Most examples on the Oracle site show you how to do this with ADF Business Components, but you can also use POJO’s.

First create an Emp object. The JComboBox we will display on the panel will display a list of Emp objects:

package model;
public class Emp {
    private Integer id;
    private String name;

    public Emp() {
    }

    public Emp(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public String toString() {
        return name;
    }
}

Next we need a model service. This class contains an id attribute. You’ll be able to change the value of id using the combobox. The model service also contains a method to get the array of objects which need to be displayed by the combobox.

package model;
public class AutoCompletionModelService {
    public static Integer id;
    public static Emp[] emps;

    public AutoCompletionModelService() {
    }

    public Emp[] getEmps() {
        if (emps == null) {
            emps = new Emp[] {
                    new Emp(null, ""),
                    new Emp(new Integer(1), "Robby"),
                    new Emp(new Integer(2), "Pete"),
                    new Emp(new Integer(3), "Jason"),
                    new Emp(new Integer(4), "Dave"),
                };
        }

        return emps;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public Integer getId() {
        return id;
    }

    public void printSelectedEmp() {
        System.out.println("selected emp id: " + id);
    }
}

When you have these two classes, create a Data Control for AutoCompletionModelService. You do this by right clicking on AutoCompletionModelService.java in the Applications navigator. This will create some xml files which describe the classes in your model package.

Now we can start building the GUI. You don’t need much manual coding here. First create a new JPanel for ADF, and then drag and drop a label (from the Swing component palette), and a combobox on the panel. To drop the combobox on the panel you select the id attribute of the AutoCompletionModelSerice data control from the data control palette. Then you specify that you want to drop it as a combo box. Now drag the id attribute on your panel.

Data control palette

Your panel will look something like this (I’ve also dragged the printSelectedEmp method as a button on the panel):

JPanel

Next you need to specify what data to display in the combobox. You do this by selecting the id binding in the panel UIModel, as displayed below.

UIModel

When you edit the binding you see the following binding editor. First specify ‘LOV Mode’ for the List Binding Mode. Next you specify the source of the lov data, i.e., emps, and the destination of the selected data, i.e., AutoCompletionModelServiceDataControl. You also need to specify which attribute provides the value you select (id), and which attribute should be displayed in the lov (name).

List Binding Editor

The only line of coding required is the code to enable autocompletion. Add the following line in jbInit:

AdfAutoCompletion.enable(employeeComboBox,panelBinding,"id");

That’s it. You can now run the panel and the following window will be displayed:

JPanel with autocompletion enabled jcombobox

File definition for form is not valid

You may get the following error in jDeveloper when creating an empty Panel for ADF: File definition for form is not valid. This is a cryptic message telling you to specify a package name for the Panel.

How to: using ant to deploy to OC4j (dp4)

In a comment to my posting Deploy task bug in oc4j 10.1.3 dp4, art_usa asked for some help deploying to oc4j using ant. The following example works for me.

First the Ant build.xml file itself:

<?xml version="1.0" encoding="windows-1252" ?>
<project default="all" xmlns:oracle="antlib:oracle"
         xmlns="antlib:org.apache.tools.ant"
         xmlns:ivy="antlib:fr.jayasoft.ivy.ant">
  <property file="build.properties"/>
  <!--
    ============================================================================
    == properties
    ============================================================================
    -->
  <!-- directories -->
  <property name="src.dir" value="src"/>
  <property name="classes.dir" value="classes"/>
  <property name="log.dir" value="log"/>
  <property name="web.dir" value="public_html"/>
  <property name="deploy.dir" value="deploy"/>
  <property name="doc.dir" value="doc"/>
  <!-- deliverables -->
  <property name="webjar.file" value="${app.name}-web.jar"/>
  <property name="war.file" value="${app.name}-web.war"/>
  <property name="ejbjar.file" value="${app.name}-ejb.jar"/>
  <property name="ear.file" value="${app.name}.ear"/>
  <!--
    ============================================================================
    == class path
    ============================================================================
    -->
  <path id="class.path">
    <fileset dir="lib">
      <include name="**/*.jar"/>
    </fileset>
    <pathelement path="${classes.dir}"/>
  </path>
  <!--
    ============================================================================
    == init
    ============================================================================
    -->
  <target name="init">
    <tstamp/>
    <mkdir dir="${log.dir}"/>
    <mkdir dir="${classes.dir}"/>
  </target>
  <!--
    ============================================================================
    == compile
    ============================================================================
    -->
  <target name="compile" depends="init">
    <javac srcdir="${src.dir}" destdir="${classes.dir}"
           classpathref="class.path"/>
    <copy todir="${classes.dir}">
      <fileset dir="${src.dir}">
        <include name="**/*.xml"/>
        <include name="**/*.properties"/>
      </fileset>
    </copy>
  </target>
 <!--
    ============================================================================
    == war
    ============================================================================
    -->
  <target name="war" depends="compile">
    <war destfile="${deploy.dir}/${war.file}" webxml="${web.dir}/WEB-INF/web.xml">
      <fileset dir="${classes.dir}">
        <include name="**/*.class"/>
        <exclude name="test/**/*.class"/>
      </fileset>
      <fileset dir="${web.dir}">
        <include name="**/*.jspx"/>
        <include name="**/*.html"/>
        <include name="WEB-INF/*.xml"/>
      </fileset>
      <lib dir="lib">
        <exclude name="ivy-1.1.jar"/>
        <exclude name="ejb.jar"/>
        <exclude name="ejb30.jar"/>
        <exclude name="junit.jar"/>
        <exclude name="oc4jclient.jar"/>
      </lib>
    </war>
  </target>
  <!--
    ============================================================================
    == ejb jar
    ============================================================================
    -->
  <target name="ejb" depends="compile">
    <jar destfile="${deploy.dir}/${ejbjar.file}">
      <fileset dir="${classes.dir}">
        <include name="**/model/**/*.class"/>
        <exclude name="test/**/*.class"/>
      </fileset>
    </jar>
  </target>
  <!--
    ============================================================================
    == Ear
    ============================================================================
    -->
  <target name="ear" depends="war,ejb">
    <ear destfile="${deploy.dir}/${ear.file}"
         appxml="${classes.dir}/META-INF/application.xml">
      <fileset dir="${deploy.dir}/" includes="${war.file}"/>
      <fileset dir="${deploy.dir}/" includes="${ejbjar.file}"/>
    </ear>
  </target>
  <!--
    ============================================================================
    == deploy
    ============================================================================
    -->
  <target name="deploy" depends="init">
    <oracle:deploy moduletype="ear" host="${oc4j.host}"
                   port="${oc4j.admin.port}" userid="${oc4j.admin.user}"
                   password="${oc4j.admin.password}"
                   file="${deploy.dir}/${ear.file}"
                   deploymentname="${app.name}"
                   logfile="${log.dir}/deploy-ear.log"/>
    <oracle:bindWebApp host="${oc4j.host}" port="${oc4j.admin.port}"
                       userid="${oc4j.admin.user}"
                       password="${oc4j.admin.password}"
                       deploymentname="${app.name}" webmodule="${web.name}"
                       websitename="${oc4j.binding.module}"
                       contextroot="/${app.name}"
                       />
  </target>
  <!--
    ============================================================================
    == clean
    ============================================================================
    -->
  <target name="clean">
    <delete quiet="true">
      <fileset dir="lib" includes="**/*.jar" excludes="**/ivy-1.1.jar"/>
      <fileset dir="${classes.dir}" includes="**/*"/>
      <fileset dir="deploy" includes="*"/>
    </delete>
  </target>
  <!--
    ============================================================================
    == deploy
    ============================================================================
    -->
  <target name="all" depends="clean,ear,deploy"/>
</project>

Next the build.properties file:

app.name=test1
web.name=test1-web

oc4j.binding.module=default-web-site
oc4j.admin.port=23791
oc4j.admin.user=oc4jadmin
oc4j.http.port=8888
oc4j.admin.password=admin
oc4j.host=localhost

java.home=c:\\Program Files\\Java\\jdk1.5.0_01
oracle.home=c:\\programs\\oracle\\oc4j1013-dp4

And finally a shell script to start ant.

set JAVA_HOME=c:\Program Files\Java\jdk1.5.0_01
set ANT_HOME=c:\programs\oracle\oc4j1013-dp4\ant
set ORACLE_HOME=c:\programs\oracle\oc4j1013-dp4

set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%PATH%

%ANT_HOME%\bin\ant %1 %2 %3

RIM vs Good.com

Recently, I was passed a whitepaper about the mobile products of Good company. Good is a young company from Redmond (US) and wants to beat RIMs blackberry on its market share in the mobile technology market. Good offers a variety of interesting products: GoodLink for agenda and e-mail, GoodAcces for behind-firewall apps and GoodAdmin for several admin and security features across the previous products. Those products has the huge benefit above the Blackberry that they are independent of the platform (Symbian, Windows CE) and the network (CDMA, GPRS enz) of the mobile device they run on.
According to Forbes Good is now gaining rapidly market-share over Blackberry. Also Microsoft is taken advantage of Good’s products, because they also run on Windows CE devices.

In my opinion, this is another hint that the mobile market is evolving and has become an interesting market for commercial products.

Oracle doc search plugin for Firefox

Eddie Awad has created a plugin for Firefox which lets you search the Oracle documentation. Read his posting: Oracle Firefox search plugin. Have a look at the plugin, adding a search engine to Firefox is amazingly simple. It’s not even a real plugin, it’s just some lines of javascript code.

Technology
Ben jij slim genoeg voor IT-eye