Struts2 Interfaces und EJB Probleme

Keine Kommentare

Heute schreibe ich über ein Problem welches mir kürzlich mit Struts2 begegnet ist. Es ist allerdings auch gültig für viele andere Szenarien. Hier ein Beispiel:

Die Wahlen in den Staaten nähern sich, deshalb wollen wir heute eine kleine Vorabstimmung machen.

Wir bauen dafür einen Service, welcher 3 Methoden enthält:

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

Sieht doch ganz einfach aus. Unsere Auswahl sind mehrere Top Kandidaten, unter anderem Homer Simpson, Dilbert und Captain Kirk. Ich denke diese wären wohl alle eine gute Wahl.

Als Oberfläche für die Abstimmung schreiben wir eine kleine Struts2 Anwendung und benutzen die CheckboxList um die Wahlmöglichkeiten darzustellen. Die beiden Getter des Interfaces, welches wir als EJB realisieren, verwenden wir um die Möglichkeiten zu laden und falls vorhanden auch eine bereits getätigte Auswahl eines Users anzuzeigen.

Die Anwendung funktioniert prima, bis wir speichern:

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

Wie kann das passieren? Nun Struts2 muss einiges an Konvertierungsmagie für uns durchführen. Der HTML Request liefert leider nur ein HTML Array der Auswahl ab, wir wollten aber eine Liste haben. Also baut Struts2 uns eine Liste. Reichen wir diese Liste nun weiter an unsere Implementierung des ElectionFavorite findet sich diese Liste wahrscheinlich nicht auf dem Classpath. Je nach Classpathkonfiguration kann das Beispiel noch funktionieren, aber spätestens bei einem getrennten Service EAR und der Webapplikation in einem WAR ist dann auch Schluss.

Um das ganze ans Laufen zu bekommen, muss man auf Clientseite in der Struts2 Action z.B. einen Proxy verwenden welcher die Liste umwandeln kann:

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

Die Moral dieser Geschichte ist, dass Interfaces eine tolle Sache für APIs sind, weil es die Benutzung verschiedener Implementierungen erlaubt, aber wenn genau diese Implementierung nicht überall vorhanden ist können Probleme entstehen. Es gibt grob gesagt 3 Möglichkeiten dieses Problem zu lösen:

  1. Stellt sicher dass alle Klassen von Clients auch auf Serviceseite verfügbar sind
  2. Eine Konvention für das jeweilige Projekt nach der nur JDK Implementierungen für Interfaces übergeben werden dürfen
  3. Benutzt keine Interfaces in Euren Service APIs

Keine dieser Optionen ist eine einfache Wahl. Leider. Vielleicht hat ja jemand eine viel bessere Idee?

(Möglichkeit 3 funktioniert durch die Magie innerhalb von Struts2 leider auch nicht)

Fabian Lange ist Lead Agent Engineer bei Instana und bei der codecentric als Performance Geek bekannt. Er baut leidenschaftlich gerne schnelle Software und hilft anderen dabei, das Gleiche zu tun.
Er kennt die Java Virtual Machine bis in die letzte Ecke und beherrscht verschiedenste Tools, die JVM, den JIT oder den GC zu verstehen.
Er ist beliebter Vortragender auf zahlreichen Konferenzen und wurde unter anderem mit dem JavaOne Rockstar Award ausgezeichnet.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.