JSF Submit-on-Enter forms

It’s not (so far as I know) officially required anywhere, but it’s a generally accepted principle that a form on a web page containing one text field and one submit button should submit itself when you type in text and press the ENTER key. A classic example of this is Google .

In actuality, it isn’t quite that simple. For totally unknown reasons, Microsoft Internet Explorer requires at least two text fields and this apparently goes all the way up to and including IE8 (at least when you upgrade from IE6). Fortunately, the “spare” text field can be invisible and ignored by the application.

JSF is more complicated, and AJAX-aware JSF such as RichFaces compounds the issue even more. Here’s a solution that seems to work for me:

  <h:panelGroup>
     <h:inputText style="visibility:hidden;display:none;"
        disabled="disabled" required="false" />
     <a4j:commandButton id="ask"
        type="submit" styleClass="button1"
        action="#{forgotPassword.doAskQuestion}"
        reRender="pnl1,fpMsg" value="Submit" />
 </h:panelGroup>

I am indebted to Lincoln Baxter for this particular hidden field definition (it’s quite touchy). He’s the person behind the JSF PrettyFaces product (ocpsoft.com).

Note that this is only a kludge, and may not always work. Additionally, it causes the RichFaces a4j:commandButton oncomplete action to misbehave under both IE and Firefox (though in different ways), as of RichFaces 3.4.

Eclipse: Tomcat FileNotFoundException

After happily using the sysdeo Tomcat plugin for years. I’ve finally been pushed into using the Server facility bundled into Eclipse Ganymede’s JEE drop. For some reason, once started, sysdeo cannot be stopped or restarted – it loses track of the logfile classes.

In theory, you just create a new server of your choice in the Eclipse Servers View. In practice, it’s not quite so simple. Here’s why:

Tomcat actually consists of 2 aspects: a sharable codebase (CATALINA_HOME) and a per-instance part (CATALINA_BASE). This allows multiple copies of Tomcat to run on a single server using one codebase. Most of the time, CATALINA_HOME and CATALINA_BASE are the same value, since more often than not, only one copy of a given version of Tomcat is is use – at least on a developer’s machine.

When you create a Tomcat server using the Eclipse Servers facility, however, it clandestinely creates its own CATALINA_BASE, copying selected files – and only those files into a directory owned by the plugin.

I got burned. I was keeping a file of my own in CATALINA_HOME and using a relative reference to it in server.xml. The file didn’t copy and Tomcat didn’t start clean.

The simplest solution was to edit server.xml and replace the relative path to an absolute path, so that the copied configuration would be able to locate the original (and in this case, the only) copy of my file.

Apparently, however, the copying of the CATALINA_BASE data occurs only when you create a new Server definition. I had to delete the old Server definition from Eclipse and create a new one to get the changes to take.

Setter not found for property class

I hate this. Messages like this shouldn’t be permitted. The proper format should be

Setter not found for property “class”

In other words, a JSF tag was coded with a “class=” attribute. So actually, an even more precise rendering should be:

No valid setter method exists for attribute named “class”.

In a civilized world, the element name and line where the offense was committed would be reported as well.

At any rate, the cause of the error is that the attribute should have been “styleClass”, not “class”.

Trac: Permission denied connecting to PostgreSQL Server

Another one of those obscure things that a web search didn’t turn up. Using the “psql” command-line utility, it was possible to connect to and access the PostgreSQL Trac database. However, the webapp failed, with “cannot connect to server: Permission denied”. No amount of tweaking the firewalls or the pg_hba.conf file would help.

It turns out that the permission wasn’t PostgreSQL, it was selinux. It was forbidding psycopg from opening a database connection while running inside Apache. It wants a “allow httpd_t postgresql_port_t:tcp_socket name_connect;”.

A message shows up in /var/log/audit/audit.log – if you think to look there.

PrettyFaces downstream effects

Latest in the ongoing story of why even the simple things take much longer than they should:

I’m working on an app where the menus generate PrettyFaces bookmarkable URLs. However, when I jump to the target page, then click on a commandLink, the secondary target page won’t post properly. When you click on the actionButton, it throws a ViewExpiredException for the target page’s View.

A look at the secondary target page source, however, indicates that the POST URL is the original PrettyFaces URL. NOT the secondary page URL. JSF can be so much fun that way.

The cure is to attach a <redirect/> to the navigator action that dispatches the secondary page. This will cause the correct URL to be used.

UPDATE: It’s a Bug!

Lincoln Baxter, III is the author of PrettyFaces and when he heard about this, he made some mods to PrettyFaces which should remove the need for the <redirect/> workaround. If you’d like to try his fix, it’s in his 1.2.4_PR1 release. Thanks, Lincoln!

Myfaces Extensions Validator and RichFaces (Not yet)

The MyFaces extensions validator package looks like someday it will make life a lot more pleasant when designing JSF backing beans. Instead of cluttering up the markup with cumbersome extra XML, the MyFaces Extensions Validator allows you to annotation the backing bean properties. It even adopts the applicable annotations (such as nullable=false) on JPA model objects.

Unfortunately, when I added it to my RichFaces/PrettyFaces project, all the RichFaces AJAX functions stopped working. Apparently the annotation processor got in the way of the JavaScript downloading process. The AJAX support functions were not found and the Richfaces Calendar stopped responding to popup click requests – Understandably, since the JSF Calendar object was no longer found.

So, I have to do my validations the hard way for the moment.

org.hibernate.PropertyAccessException: could not get a field value by reflection getter of com.mypackage.MyEntity.entityId

There are reports that messages of this sort were due to bugs in one or more Hibernate releases. But this is also a legitimate error.

I wasted a lot of time before it hit me. The original code was:


@SuppressWarnings("unchecked")
public List<State> getStatesForCountry(String countryID) {
    final String SQLCOMMAND =
        "SELECT c " + "FROM "
            + State.class.getSimpleName() + " c "
            + " WHERE c.parentCountry = :countryID"
            + " ORDER BY c.StateName ASC";

    Query query = entityManager.createQuery(SQLCOMMAND);
    query.setParameter("countryID", countryID);
    List<State> results = query.getResultList();
    return results;
}

It should have been:


@SuppressWarnings("unchecked")
public List<State> getStatesForCountry(String countryID) {
final String SQLCOMMAND =
    "SELECT c " + "FROM "
         + State.class.getSimpleName() + " c "
        + " WHERE c.parentCountry = :country"
        + " ORDER BY c.StateName ASC";

    Query query = entityManager.createQuery(SQLCOMMAND);
    Country country = findCountry(countryID);
    query.setParameter("country", country);
    List<State> results = query.getResultList();
    return results;
}

Where findCountry is simply an entityManager.find(Country.class, countryID);

This is a sneaky one because when the database is laid out, you think in terms of foreign keys. But in ORM, you don’t see those keys directly – they translate to object references. So the original version was attempting to compare an object to the key of the object instead of an instance of the object.

I can only plead distraction. The object model in question had been designed by someone else. Instead of accessor methods, it was using direct field access (which I avoid for a number of reasons). Further aggravating the issue was that the fields were all given names starting with an upper-case letter as though they were independent classes instead of properties.

But even without distractions, it’s not too hard to make this mistake.

Writing files into a WAR – Another BAD IDEA

I’ve always recommended against this. For one thing, a WAR is a ZIP file and Java has no builtin support for updating ZIP files.

A lot of people abuse the fact that many JEE servers unpack (explode) WARs into a directory such as Tomcat’s webapps directory. They then proceed to use the ServletContext getRealPath() method to translate a subdirectory in the WAR into an absolute filename path.

There are 4 problems with that idea.

  1. If the server doesn’t explode the WAR, there won’t be a real path. So the pathname returned will be null and the code will probably throw an exception. This can be a problem when transporting the application to a different vendor’s server or when the configuration of the current server is changed.
  2. It’s generally good practice to keep executable code, forms, and other potentially-hackable constructs in a write-protected location. Plop down a writable directory in the middle of the WAR and you’ve opened up a potential exploit.
  3. If you write “permanent” files to the WAR directory, a redeployment may nuke the entire WAR substructure, losing the files forever. I’ve always preferred to explicitly erase a WAR before updating it anyway, since otherwise old stale stuff hangs around and pollutes the application. Sometimes with unfortunate results.
  4. If you hardcode the write directory relative to the WAR, what do you do when the disk fills up? Unix and Linux provide a special directory tree (/var) to hold things that may grow, but there’s no fixed relationship between the WAR directory and the /var directory. Coding an absolute path can work, but it’s not very flexible, either.

What to do? I normally get my writable directory location via JNDI lookup. For example: “java:comp/env/wardata”. The advantage of this is that I can relocate the directory any time I want. I put the default location in the web.xml resource definitions, but in Tomcat I can override this. Which is convenient when testing.

JSF/Facelets/RichFaces – and Maven

SF itself is fairly straightforward. Getting it functional in an appserver is another matter. Originally, I used MyFaces and Tomahawk. More recently, I’ve replaced MyFaces with the Sun JSF Reference Implementation (RI). Tomahawk, although a MyFaces library works just fine with the RI.

The JSF-impl jar is part of the server for JEE-compliant servers, such as recent versions of JBoss. For Tomcat, it has to be explicitly linked into the WAR (?). At any rate, it has to be put into the application’s classpath, and everyone seems to be putting it into the WAR and not the server lib directory. Since there are possible threading implications, I’m doing likewise.

Tomcat5 also needs the EL-ri JAR placed in its classpath. Tomcat6 includes the required classes as part of the base distribution.

For the whole set of dependencies, see the Maven POM for my sandbox project: here

OpenJPA/Spring/Tomcat6

Oh, what a tangled web we weave…

In theory, using JPA and Spring is supposed to make magical things happen that will make me more productive and allow me to accomplish wonderful things.

Someday. At the moment, I gain tons of productivity only to waste it when deployment time comes and I have to fight the variations in servers.

JPA allows coding apps using POJOs for data objects. You can then designate their persistence via external XML files or using Java Annotations. The Spring Framework handles a lot of the “grunt” work in terms of abstract connection to the data source, error handling and so forth.

But that, alas, is just the beginning.

First and foremost, I had to build and run using Java 1.5. OpenJPA 1.2 doesn’t support Java 6.

Tomcat is not a full J2EE stack. To serve up JPA in Tomcat requires a JPA service – I used Hibernate-entitymanager.

JPA requires a little help. Specifically, I used the InstrumentationLoadTimeWeaver to provide the services needed to process the annotations.

The weaver itself requires help. And to enable the weaver in Tomcat, I needed the spring-agent.

To the Tomcat6 lib directory I added:

  • spring-tomcat-weaver jar
  • spring-agent jar

But that’s not enough! The agent won’t turn itself on automatically. So I need to add a “-javaagent” to Tomcat’s startup. The easiest way to do that was to create a CATALINA_BASE/bin/setenv.sh file:

#!/bin/sh
CATALINA_BASE=/usr/local/apache-tomcat-6.0.18
JAVA_OPTS=”-javaagent:$CATALINA_BASE/lib/spring-agent-2.5.4.jar”

Tomcat 5

I think this all works more or less the same in Tomcat5, except that there are 3 library directories instead of the one library that Tomcat6 uses so the location for the spring suport jars is different. common/lib seems to work, although I’m not sure it’s the best choice.

That’s half the battle. Next up: JSF/RichFaces – and Maven

1 2 3 4 5