Zur Zeit wird gefiltert nach: jboss
Filter zurücksetzen

30.06.2011
14:46

Was ist eigentlich Rückwärtskompatibilität?

Was ist eigentlich Rückwärtskompatibilität?

Roman Seibold, Senior Consultant und technischer Leiter der Schulungsabteilung von aformatik

von Roman Seibold

Ein furchtbar schwer auszusprechendes Wort, mehr nicht, wie ich dieser Tage erfahren musste. Hintergrund war die "schnelle und einfache" Umstellung eines Servers, auf dem bislang JBoss 5.1 betrieben wurde. Bei der Umstellung sollte gleich die JBoss-Version auf die aktuelle 6.0 migriert werden.

Auf JBoss 5.1 lief eine Anwendung, die seit vielen Jahren auf div. Servern u.a. auch auf JBoss 5.0, Tomcat 5.x und IBM WebSphere Application Server 5 und 6, gelaufen ist. Zu Beginn als reine Web-Anwendung, seit der Migration auf JBoss 5.x auch als echte 3-Tier-Applikation mit EJBs.

Nie, ich betone "nie", gab es Probleme bei der Migration. Einfach neuen Server installieren, konfigurieren (Datasources, Queues usw.) und Anwendung deployen, fertig. Jetzt, mit JBoss 6, wurde alles anders.

Das Kernproblem war, dass die Anwendung, schon leicht in die Jahre gekommen, das damals sehr populäre Struts 1 verwendet. Und Struts 1 läuft in unveränderter Form nicht auf JBoss 6. Ja, Sie haben richtig gelesen. Da Struts 1 nicht mehr weiterentwickelt wird und Struts 2 jetzt nicht wirklich einfach eine aktuellere Version ist, sondern schon etwas anderes, gibt es da auch keinen Migrationspfad.

Symptom, dass die Anwendung nicht mehr läuft, sind Deployment-Errors, die auf nicht korrekte URIs hinweisen (z.B. in bsf-2.3.0.jar). Es wird von JBoss 6 moniert, dass "http://java.sun.com/j2ee/dtds/web-jsptaglib_1_1.dtd" nicht existiere. Das ist im Grunde genommen auch richtig, denn der URI in der Taglibrary-Definition sollte "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd" heissen (d.h. "jsptaglibrary" statt "jsptaglib"). Allerdings fragt man sich, wieso so etwas bislang auf allen Servern anstandslos gelaufen ist und nur der neue JBoss hier Probleme bereitet. Angeblich, weil JBoss etwas strikter im Umgang mit XML-Validierung geworden ist.

Die Lösung für dieses Problem ist zwar einfach, aber irgendwie nicht akzeptabel:
man extrahiert bsf-2.3.0.jar, editiert unter META-INF/taglib.tld die Datei und
ersetzt den obigen String mit seiner korrekten Version. Danach packt man das JAR wieder zusammen und ersetzt das alte. Fehler beseitigt.

Danach wird sich herausstellen, dass die Applikation wieder startet, aber nicht in allen Fällen funktioniert. Es kommt zu JSP-Compile-Fehlern. Nach längerem, scharfen Hinsehen entdeckt man, dass einige Struts-Tags in den JSPs das Problem verursachen. Nämlich solche Kandidaten wie <html:select> oder <html:option>.
Diese Tags haben Inhalt (aka "body-content"), bei option z.B. die Beschriftung, wenn sie denn nicht aus einem Ressource-File kommt. In der TLD dieser Tags fehlt aber der Hinweis auf den "body-content". Wenn man zu diesem Konfigurationseintrag etwas näher in der JSP-2.1-Spezifikation stöbert, kommt man zu dieser Stelle (S. 3-37, JSP-Spec 2.1):

"body-content: Specifies the format for the body of this tag. The default in JSP 1.2 was 'JSP' but because this is an invalid setting for simple tag handlers, there is no longer a default in JSP 2.0."

Das heißt, weil in der Tag-Library-Angabe der body-content fehlt, quittiert die JBoss 6-JSP-Runtime diese Tags mit einem Compile-Fehler, allerdings ohne sinnvolle Fehlerangabe. Man sieht nur NullPointerExceptions.

Die Lösung ist auch hier so simpel wie unverzeihlich: analog zum oben erwähnten Vorgehen bei der bsf.jar muss man die Datei struts-taglib-1.3.10.jar (Struts 1.3.10 vorausgesetzt natürlich) von Hand ändern, genauer gesagt die Datei META-INF/tld/taglib.tld, und überall wo der Autor dieser Datei davon ausging, wenn er body-content nicht angibt, dass dann der Default "JSP" zieht, ein explizites

<body-content>JSP</body-content>

einfügen. Das wars "auch schon". Man muss nur darauf kommen.

Abschließend kann man eigentlich nur resignierend resümmieren, dass es ja schön ist, wenn JBoss sich an die Spezifikationen hält und dass es natürlich nicht schön von Sun/Oracle ist, Defaults nachträglich zu entfernen. Aber es ist schon komisch, dass sich beispielsweise die letzte JBoss-Version 5.1, die auch schon JSP 2.1 implementiert hat, daran nicht störte.

Ist das vielleicht auch der Unterschied zwischen Open-Source-Software und den (oftmals teuren) Produkten großer Hersteller?

Zurück

11.11.2009
16:00

Nur mal kurz...

Roman Seibold, Senior Consultant und technischer Leiter der Schulungsabteilung von aformatik

...einen JAX-WS WebService mit JBoss 5.1 erstellen.

von Roman Seibold

Vorgeschichte: der WebService

"Nur mal kurz" geht in der IT gar nicht. Musste ich neulich wieder feststellen. Eigentlich ging es hauptsächlich überhaupt nicht um einen WebService, aber ich brauchte einen, um etwas anderes tun zu können. Ist ja jetzt ganz einfach, mit Java EE 5 und JAX-WS. Dachte ich. Der WebService, als POJO nicht als EJB, ist mit JAX-WS tatsächlich schnell geschrieben. Hier, auch was den Rückgabetyp betrifft, sehr vereinfacht dargestellt:

import javax.jws.WebMethod; 
import javax.jws.WebService;


@WebService
public class WebService
{
@WebMethod
public String getContent()
{
return "Juhu, tut!";
}
}

Das ist schon alles. Mit @WebService erkläre ich die Klasse zum Web-Service, mit @WebMethod wird klar, was als Operation für den Service im WSDL verfügbar wird.

Deployment

Jetzt beginnt der proprietäre Teil. Ein Java-EE-compliant Application- Server ist nur verpflichtet, einen Web-Access-Point für JAX-WS zur Verfügung zu stellen. Wie ist nicht gesagt. Das macht jeder Server anders, z.B. indem er einen automatisch aktivierten WebService- Router zur Verfügung stellt, wenn JAX-WS-Services erkannt werden. JBoss verfährt so nicht. Es gibt verschiedene Möglichkeiten, mit WebServices umzugehen. Mein POJO-WebService wird nur von außen erreichbar, wenn ich ihn als Servlet (!) definiere. Das sieht im Deployment-Deskriptor so aus:

<servlet>

<servlet-name>JaxWSServlet</servlet-name>

<servlet-class>
com.aformatik.biblio.service.BiblioAccessService
</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>JaxWSServlet</servlet-name>

<url-pattern>/BiblioAccess</url-pattern>

</servlet-mapping>

Das war schon die erste, nicht ganz intuitive Hürde. Weiterhin ist mein Projekt folgendermaßen - eigentlich recht simpel - strukturiert:

WebServiceEAR.ear 
+-- WebServiceWeb.war


Das heißt, dass der WebService in einem Web-Modul definiert ist, das einem EAR-Modul zugeordnet ist. Das ganze schnell auf einen JBoss AS 5.1 deployed. Fehlerfrei. Gut.

Nur noch kurz...

Jetzt "nur noch kurz" den Client dazu... Geht eigentlich auch einfach. Man importiert das vom Server gemäß JAX-WS generierte WSDL-File und lässt sich die entsprechenden Client-Klassen erstellen und arbeitet damit. Die Frage ist nur: wo ist denn das WSDL-File? Angeblich gibt es bei JBoss eine URL unter der die deployten Services erreichbar sind. Bei mir sollte dies http://localhost:8080/jbossws/services sein. Tatsächlich, da ist auch was. Wenn man aber auf den Link zum Service klickt, dann kommt "Not Found". Hmmm...

Nach längerer Zeit wurde ich im "data"-Verzeichnis des Servers fündig, da liegt das generierte WSDL ebenfalls. Na gut, dann nimmt man halt das. Auf dieser Basis den Client generiert - und nichts tat. Not found. Ich habe also ein WSDL für einen Service, der angeblich verfügbar ist, aber nicht auf Zugriff reagiert. Das stimmte mich miß. Hier schloß sich nun eine längere Zeit für Recherche und Tests an. Offenbar war ich einem Problem begegnet, das noch niemand so hatte. Es ließ sich jedenfalls nicht auf die Schnelle im Internet etwas finden. Macht keiner WebServices, oder nicht mit JBoss, oder (noch) nicht mit JAX-WS?

Die Lösung

Auf einer einzigen, etwas versteckten JBoss-JIRA-Bug-Tracking Webseite, die eigentlich einen Bug im Zusammenhang mit JBoss ESB thematisierte, wurde ich fündig: die JBoss-native WebService-Implementierung hat einen Bug in der ausgelieferten Version 3.1.2. Der Bug kommt aber nur zur Geltung, wenn eine WAR-Datei, die einen Web-Service definiert, in einem EAR deployt wird. War bei mir ja der Fall. Lösung: die neuere Implementierung der WebServices 3.2.0 verwenden. Leider, leider ist die neueste Server-Version, die man von JBoss herunterladen kann, die 5.1 GA. Punkt. Kein Service-Release, kein sonstwas. Ist aber vom Mai, jetzt haben wir November. Haben die kein Release-Management? Na gut, dann basteln wir uns eben einen gepimpten Server. In einem Blog  fand ich, wie man eine andere WebService-Implementierung ("Metro") aktualisiert. Ich wollte aber die JBoss-native. In diesem Beitrag ist die Download-Adresse der Metro-Implementierung angegeben, wenn man aber versucht, einfach mal ins Verzeichnis zu schauen, um nach den anderen Implementierungen zu suchen, dann klappt das aus Berechtigungsgründen nicht. Man muss den Dateinamen schon wissen! Jetzt hilft mal wieder nur "inspiriertes Raten" und es klappte mit dem URL http://jboss.org/file-access/default/members/jbossws/downloads/jbossws-native-3.2.0.GA.zip. War jetzt auch nicht so schwer. Danach die Steps ausgeführt, die der Kollege mit dem unaussprechlichen Namen "Prakashbabu" vorschlägt, und - voila - JBoss bootet noch (!) und zeigt im Log:

JBoss Web Services - Native Server 
3.2.0.GA


Und, oh Wunder, jetzt tut sofort alles, wie beschrieben. Unter http://localhost:8080/jbossws/services/WebService?wsdl ist mein WSDL verfügbar, der Eclipse-Testclient und ein generierter Client-Code können sofort auf den Service zugreifen. Super! War ja auch ganz einfach. Naja, JAX-WS schon, nur der konkrete Teil mit Produkten und Versionen, der war mal wieder unschön.

Komisch aber schon, dass dieser Fehler kein größeres Echo hervorgerufen hat und dass die seit Mai verfügbare Download-Version von JBoss AS 5.1 immer noch diesen Bug beinhalten darf und dass es keine aktualisierte gibt. Das lässt schon den Verdacht etwas keimen, dass JAX-WS-WebServices noch nicht so verbreitet sind. Oder dass niemand die native Implementierung verwendet. Oder...

Zurück