Overview

Struts2 Interface and EJB issues

No Comments

Today I want to write about an issue that occurred to me with Struts2, but it is also valid for other scenarios. Ill first give an example:

Elections in the States are coming close, so we are going to make a favorite poll.

First implement a service that has three methods:

public interface ElectionFavorite {
  public List getFavs(int userId);
  public List getChoices();
  public void setFavs(int userId, List);
}

Looks pretty straightforward. Our choices are a list of top candidates, including Homer Simpson, Dilbert and Captain Kirk for possible presidents.

To make our poll we write a small Struts2 based application and use the CheckboxList to display the choices. We use the two getters from the an EJB implementation of this interface to obtain the possible choices and the made selections in case the guest is changing its vote.

The application works fine, we make our choice and save.

NoClassDefFoundException: com.opensymphony.xwork.util.XWorkList not found

How come? Well Struts2 does some conversion magic. It converts the returned selections from the page, which are HTML arrays, into this type, for whatever reason they think it is appropriate. But when we passing this List instance to the EJB that List implementation is most likely not on the classpath. Depending on your classloading setup when trying this, it might work, but when the EAR the EJB is in has no access to struts/xwork jars from the Web Application you will be getting this error.

To fix this there are some options on the client side. One might be to implement a proxy that converts the List:

setFavs(List favs){
  this.favs = new ArrayList();
  this.favs.addAll(favs);
}

And now the general learning from this exercise: Using interfaces in APIs is great, because it allows the usage of different implementations. But when the chosen implementation is not found on the receiver’s classpath bad things can happen. There are three options to resolve this:

  1. Make sure that all client classes are available on the service classpath
  2. Make a project convention that only JDK implementations are passed
  3. Don’t use Interfaces in Service APIs

Neither one is an easy pick, I must admit. Feel free to post better ideas into the comments.

(Option 3 doesnt work in Struts2 due the magic involved when converting request parameters)

Comment

Your email address will not be published. Required fields are marked *