Archive for the ‘Java EE’ Category

Mixing JPA with JAXB/JAXWS

Friday, April 23rd, 2010

With JavaEE 6, you can publish an SOAP WebService as easy as 1-2-3. It mixes well with JPA, but I give you a small advice: if you need bidirectional ORM mappings, one of them MUST be @XmlTransient. Otherwise, you will receive a com.sun.xml.ws.streaming.XMLStreamReaderException (”unexpected XML tag. expected: {yourns}yourtag but found: {http://schemas.xmlsoap.org/soap/envelope/}Envelope”).

h:selectManyCheckbox with multiple columns/rows

Thursday, April 8th, 2010

If you ever tried to use the <h:selectManyCheckbox> component, you had a bad time figuring out how to split the checkbox on multiple rows - there’s no simple way to do that.

Let’s talk about a feature of the <f:selectItems> tag: it can receive both SelectItem and SelectItemGroup. This means you can create a group of SelectItem easily. Example: if you have a Role list grouped by categories, the List<SelectItem> can have a list of SelectItemGroup and these can have a list of SelectItem with the roles.

Pretty nice, but the items are rendered with the group orientation: this means JSF will render an horizontal table for the groups with nested horizontal tables for the items. Still ugly!

You can solve this using Tomahawk, but I think it’s too much trouble only to get this simple requirement. I prefer using a pure-JSF solution like a new Renderer. Mojarra’s renderer makes this job very easy:

public class MyRenderer
    extends SelectManyCheckboxListRenderer {

  // keeps track of current rendering
  private boolean inner;

  // overriding with synchronized
  @Override
  public synchronized void encodeEnd(
      FacesContext context,
      UIComponent component) throws IOException {
    super.encodeEnd(context, component);
  }

  @Override
  protected void renderBeginText(
      UIComponent component, int border,
      boolean alignVertical, FacesContext context,
      boolean outerTable) throws IOException {
    // are we at the inner table?
    this.inner = !outerTable;
    super.renderBeginText(component, border,
      alignVertical ^ inner, context, outerTable);
  }

  @Override
  protected void renderEndText(
      UIComponent component, boolean alignVertical,
      FacesContext context) throws IOException {
    super.renderEndText(component,
      alignVertical ^ inner, context);
    // reset after inner table is rendered
    this.inner = false;
  }

  @Override
  protected void renderOption(
      FacesContext context, UIComponent component,
      Converter converter, SelectItem curItem,
      Object currentSelections,
      Object[] submittedValues,
      boolean alignVertical, int itemNumber,
      OptionComponentInfo optionInfo)
      throws IOException {
    super.renderOption(context, component, converter,
      curItem, currentSelections, submittedValues,
      alignVertical ^ inner, itemNumber, optionInfo);
  }
}

The trick is pass “alignVertical” parameter XOR inner state. This will change the alignment for the inner table. If you use “pageDirection” as layout, the inner table will use “lineDirection” and vice-versa. Using the “roles” example, the groups will be aligned horizontally and their roles, vertically.

Now, if you don’t want to use groups, you can still benefit - create pseudo-groups for each N elements.  This will give you a matrix-like checkbox list.

Using f:selectItems with JPA entities

Wednesday, April 7th, 2010

It’s a common scenario: you must do a “SELECT e FROM Entity e” with JPA and pass it to a <h:selectOneMenu> or a <h:selectManyList>. Unfortunately, if you google it, you will find a lot of strange solutions.

I’ve tested a simple solution on JavaEE 6. On my managed bean, I can define a property like this:

...
public class MyBean {
  ...
  @PersistenceContext
  private EntityManager em;

  public Converter getConverter() {
    return new Converter() {
      @Override
      public Object getAsObject(
          FacesContext fc,
          UIComponent uic,
          String string) {
        return (string == null)
          ? null
          : em.find(MyEntity.class,
                    Long.parseLong(string));
      }
      @Override
      public String getAsString(
          FacesContext fc,
          UIComponent uic,
          Object o) {
        return (o == null)
          ? null
          : Long.toString(((MyEntity) o).getId());
      }
    };
  }
}

According to JSF specification, only managed beans can be injected. This is why I declared it as an inner class.

This way, the converter allows you to work only with entities, instead of manually storing IDs on the managed bean. This means the page can bind to this property when a conversion is needed:

<h:selectOneMenu value="#{myBean.myEntitySelection}">
  <f:selectItems value="#{myBean.myEntityList}"/>
  <f:converter binding="#{myBean.converter}"/>
</h:selectOneMenu>

One last step: your Entity must have an working “equals” method. If you forget this, you will receive the message “Validation Exception: Value is invalid”.

Usually, a boilerplate, like this one generated by NetBeans will suffice:

@Override
public boolean equals(Object obj) {
  if (obj == null) {
    return false;
  }
  if (getClass() != obj.getClass()) {
    return false;
  }
  final MyEntity other = (MyEntity) obj;
  if (this.id != other.id
      && (this.id == null
          || !this.id.equals(other.id))) {
    return false;
  }
  return true;
}

Works like a charm on JSF 2, but I haven’t tested on JSF 1.2.

BTW, this solution can be refactored to became a more generic: create a base entity class that declares a “getId” method returning Serializable. Then, the converter can be a class receiving an entity manager and the persistent class.

Unit Testing EJBs 3.1 with Glassfish Embedded

Monday, March 22nd, 2010

Pretty simple, indeed. You need the “glassfish-embedded-all-3.0-b74b.jar”, and use the new EJBContainer like this:

MyBean ejb = (MyBean) EJBContainer
    .createEJBContainer()
    .getContext()
    .lookup("java:global/classes/MyBean");
assertEquals(3, ejb.add(1, 2));

And remember that you can use a deployment descriptor on your test classpath to customize both transaction and datasource for your unit testing.

If you are using maven, use this dependency instead of javaee-api:

<dependency>
   <groupId>org.glassfish.extras</groupId>
   <artifactId>glassfish-embedded-all</artifactId>
   <version>3.0-b74b</version>
   <scope>provided</scope>
</dependency>

If you put “javaee-api” as “provided” and GF as “test”, you will receive nasty “Abscent Code” errors.

Conversational Scope on JSF 2.0 (without Custom Scope)

Tuesday, December 29th, 2009

JSF 2.0 is finally out. One thing that you will notice is the absence of a “conversational” scope. That would solve a lot of problems I have, but, unfortunately, I must wait for the next release. Or not?

There’s no silver bullet to solve it, but I found a simple workaround using “view” scoped beans. Works for most cases - unless you need redirection or other advanced requirements.

First, your “conversational” managed bean must be have a “view” scope:

@ManagedBean(name="tbean")
@ViewScoped
public class TBean {
  private String name;
  private String result;

  public String getName() {
    return name;
  }
  public void setName(String name) {
    this.name = name;
  }
  public String getResult() {
    return result;
  }
  public String sayHi() {
    result = "Hi, " + name;
    return "";
  }
}

No big deal: just a POJO with @ViewScoped. The catch is you must return empty on your action. The view is simple, too:

<h:body>
  <h:form rendered="#{empty tbean.result}">
    Name: <h:inputText value="#{tbean.name}"/>
    <h:commandButton value="hi!"
        action="#{tbean.sayHi}"/>
  </h:form>
  <h:panelGroup rendered="#{not empty tbean.result}">
    <h1><h:outputText value="#{tbean.result}"/></h1>
    <h:button value="back" outcome="index"/>
  </h:panelGroup>
</h:body>

Nothing really new: classic JSF 1.0 magic tricks with the rendered attribute. The real catch, although, is the view scope. The bean will remain as long as you keep the current view (by returning empty on your actions). The “back” button clears the form and conditionally rendered components will give the feel of different pages.

This means you can easily have an three-page CRUD (list, view, edit), or an wizard-style page, that will reset when you enter it and keep state as long as you stay on “subpages”.

Your page will grow fast using this method, but, since Facelets support is now native, you can use <ui:include> to keep this solution modular.

Booleans in JPA (the portable way)

Wednesday, October 21st, 2009

If you want to map a boolean value in JPA, you will have a headache if your RDBMS is Oracle. Since it does not support a boolean data type, you usually create a CHAR(1) ‘Y’/'N’ field and use a lot of bad words to describe the feeling you have when you find out that JPA does not support boolean-to-char convertion.

A nice and portable workaround is described here. The trick is to remember why getter/setter encapsulation is a good pratice - you can do a lot more than just plain old get/set:

private char enabled;

public boolean isEnabled() {
  return enabled == 'Y';
}
public void setEnabled(Boolean enabled) {
  this.enabled = (enabled ? 'Y' : 'N');
}

Using JBoss as a remote datasource provider

Monday, July 20th, 2009

After some trial-and-error, I managed to use a JBoss 5 as a JNDI server and a Tomcat as a JNDI client. If you plan to make a JBoss DataSource public, just add a “<use-java-context>false</use-java-context>” to your “<local-tx-datasource>”.

Tomcat is easy to configure. You need to add a resource like this one (”look mom! no password!”):

<Resource name="jdbc/myds"
    auth="Container"
    type="javax.sql.DataSource"
    factory="org.jnp.interfaces.NamingContextFactory"
    URL="jnp://jboss-host:1099/jdbc/mydsOnJboss" />

The “jdbc/mydsOnJBoss” part is the same as the “<jndi-name>” on JBoss datasource. The real trick is the classpath. Go to JBOSS_HOME/client and copy these files:

  • jboss-logging-jdk (or jboss-logging-log4j)
  • jboss-logging-spi
  • jnp-client
  • jboss-client
  • jboss-common-core
  • jboss-integration
  • jboss-remoting
  • jboss-security-spi
  • jboss-serialization
  • jbosscx-client
  • jboss-javaee (optional if your Tomcat has the javax.transation.* already)

The first three (jnp-client, jboss-logging-*) are obvious, since they are explicit dependencies (i.e. you receive a “ClassNotFoundException”). The others are implicit - you don’t receive a CNFE, you get a “ClassCastException” (cannot cast javax.naming.Reference to javax.sql.Datasource). It is evil - no docs, no log, only “-verbose:class” helped me.

With the right libs and the right configuration, you can use @Resource (or Spring’s JNDI lookup) the same way as a locally defined datasource - without any sensitive information exposed.

As a final note, you don’t need the JDBC driver on client.

Using Spring with Mojarra InjectionProvider

Friday, May 22nd, 2009

Are you using SpringBeanFacesELResolver to handle dependency injection on managed beans? It works nice, but your faces-config grows fast with this approach.

Two months ago, I posted about using Spring injection outside application context. I forgot to mention that the same trick can be used to replace ELResolver solution if you are using Mojarra as your JSF provider.

You only need to add a servlet context parameter:

<context-param>
  <param-name>
    com.sun.faces.injectionProvider
  </param-name>
  <param-value>
    mypkg.SpringJSFInjectionProvider
  </param-value>
</context-param>

And the implementation of SpringJSFInjectionProvider is as simple as:

public class SpringJSFInjectionProvider
       implements InjectionProvider {
  private WebContainerInjectionProvider wcip =
      new WebContainerInjectionProvider();

  @Override
  public void inject(Object bean)
         throws InjectionProviderException {
    FacesContextUtils
      .getWebApplicationContext(
         FacesContext.getCurrentInstance())
      .getAutowireCapableBeanFactory()
      .autowireBeanProperties(bean,
         AutowireCapableBeanFactory.AUTOWIRE_NO,
         false);
    wcip.inject(bean);
  }
  @Override
  public void invokePreDestroy(Object bean)
         throws InjectionProviderException {
    wcip.invokePreDestroy(bean);
  }
  @Override
  public void invokePostConstruct(Object bean)
         throws InjectionProviderException {
    wcip.invokePostConstruct(bean);
  }
}

Adding this, you can shrink your faces-context, removing all “managed-property” tags. Your managed beans can look more JavaEE 5 after you change this:

private BO bo;

public void setBo(BO bo) {
  this.bo = bo;
}

To this:

@Resource(name="bean-on-appctx")
private BO bo;

No setter, no ELResolver. This means less code to maintain! If you plan to migrate from Spring to EJB, this means you will only need to promote the BO to an stateless bean and change @Resource to @EJB!

Executable WAR files using Winstone and Maven

Thursday, May 7th, 2009

After a couple of years developing webapps, I’m starting to get problems to design a non-web UI. Not a big deal, since I only use Swing on personal projects. The biggest problem with web projects is the need of at least a servlet container. If you host a lot of projects, Tomcat, JBoss, Glassfish and Geronimo are good choices. But, if you need to host only one “web-container-only” project, Jetty or Winstone are way better.

I’m planning to use maven instead of ant for all of my projects, both personal and professional. It is easier to maintain and more IDE-portable. When I’m developing, I can use “maven jetty:run” to automatically compile and start Jetty (ctrl-c ends the server). The whole process is faster than a “ant dist / deploy / OOM / kill -9″ when using Tomcat. You only need to add jetty plugin to your POM (inside “project > build > plugins”):

<plugin>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>maven-jetty-plugin</artifactId>
  <configuration>
    <contextPath>/</contextPath>
  </configuration>
</plugin>

This is useful to develop, but, when I want to create the “executable WAR”, I prefer using Winstone - it’s even lighter than Jetty. This means I need another plugin:

<plugin>
  <groupId>net.sf.alchim</groupId>
  <artifactId>winstone-maven-plugin</artifactId>
</plugin>

Running “winstone:embed” will create a “xxx-standalone.jar” on “target” folder. This JAR can be run with “java -jar” and your application becames avaliable on “http://localhost:8080/”. This plugin has a lot of configurations, and, using maven, you can configure it to run this goal on package phase. Read its manual for more information.

Password and confirmation with JSF

Tuesday, March 17th, 2009

If you need to validate a field in JSF and the value is dependent of another field (like password/confirmation), BalusC posted a nice tutorial about it. You need to create a JSF Validator and add a <f:attribute/> to your field. Easier than I thought…