Blog

Spring-Applikation in einem JEE Server (JBoss AS5)

Spring ist ein modernes Baukastenframework, das als Alternative zum JEE-Stack entstand und für ähnliche Problemklassen eingesetzt wird. Üblicherweise werden Spring-Anwendungen auf Apache Tomcat ausgeliefert, was auch eine gute Idee ist. Versucht man nämlich, Spring auf einem vollwertigen JEE-Server einzusetzen, muss mit einigen Überraschungen gerechnet werden. Im Folgenden werden die Anpassungen beschrieben, die nötig sind, um eine Anwendung auf dem JBoss-Applikationsserver zum Laufen zu bringen.

Die Anwendung

Als Beispiel wird die folgende Anwendungskonfiguration verwendet:

  • Spring 3.0
  • JPA mit Hibernate 3.4.0 GA und MySQL 5.1.13
  • Java Server Faces (JSF) 2.0.3

Die resultierende WAR-Datei ist 24MB groß und enthält vor allem ein paar Bibliotheken, die nicht ohne weiteres im JEE Server deployed werden dürfen.

Die Auslieferung

Damit die WAR-Datei überhaupt erfolgreich für einen JEE-Server ausgeliefert werden kann, müssen die folgenden JARs aus dem WAR entfernt werden:

  1. ejb3-persistence-1.0.2.GA.jar
  2. hibernate-annotations-3.4.0.GA.jar
  3. hibernate-commons-annotations-3.1.0.GA.jar
  4. hibernate-core-3.3.0.SP1.jar
  5. hibernate-entity-manager-3.4.0.GA.jar
  6. javassist-3.4.GA.jar
  7. jta-1.1.jar
  8. xml-apis.jar
  9. jsf-api-2.0.3.jar
  10. jsf-impl-2.0.3.jar
  11. el-api-2.0.3.b01.jar
  12. el-impl-2.0.3.b01.jar
  13. mysql-connector-java-5.1.13.jar

Hibernate-Bibliotheken dürfen nicht deployed werden, weil sie bereits Teil des JBoss AS sind und eventuell in anderer Version vorliegen. Daraus resultieren oft ClassCastExceptions. Das Gleiche betrifft JTA, die ein Teil von JEE ist und XML-APIs, die zu ClassCastExceptions bei Konfigurationsdateien führen. Die DB-Treiber sollten nicht innerhalb vom WAR deployed werden, wenn die Datasource im Server konfiguriert ist. Daher sollte der MySQL-Treiber ins /server/default/lib kopiert werden. Ein besonders komplizierter Eingriff ist aber notwendig, damit JSF 2.0 funktioniert. Ein JEE Server muss laut Spezifikation eine JSF-Unterstützung haben. JBoss AS 5 ist JEE-compliant und liefert JSF 1.2 als Implementierung mit aus. JSF 1.2 ist aber nicht binärkompatibel zu JSF 2.0, und deshalb müssen Teile vom JBoss ersetzt werden. In /server/default/deploy/jbossweb.sar/jsf-libs müssen JSF-JARs ersetzt werden. JSF 2.0 verwendet Expression Language 2.2, und so muss in /common/lib/ die vorhandene el-api.jar durch die neuere API samt Implemenetierung ersetzt werden. Als Ergebnis bleibt eine nur 12 MB große WAR-Datei, die deployed werden kann.

Die Konfiguration

Im Unterschied zu einer Apache Tomcat-Konfiguration, in der JPAs Persistence Unit im RESOURCE-LOCAL funktioniert, muss im JEE-Server der JTA-Modus verwendet werden. Dazu richtet man zunächst eine Datasource im JBoss Server ein (kopiert /docs/examples/jca/mysql-ds.xml ins /server/default/deploy) und ändert die Einstellungen entsprechend. Wichtig ist das jndi-name-Attribut (z.B. myDataSource). Als nächstes muss in der persistence.xml die Konfiguration auf JTA umgeschaltet werden:

<persistence-unit name='myPU' transaction-type='JTA'>
  <jta-data-source>java:myDataSource</jta-data-source>
  <class>...</class>
</persistence-unit>

Dann muss in der spring-config.xml die Entity Manager Factory konfiguriert werden.

<bean id='entityManagerFactory'
     class='org.springframework.orm.jpa.
       LocalContainerEntityManagerFactoryBean'>
 <property name='jpaVendorAdapter'>
   <bean class='org.springframework.orm.jpa.
           vendor.HibernateJpaVendorAdapter'>
     <property name='showSql' value='true' />
     <property name='generateDdl' value='true' />
     <property name='databasePlatform'
               value='org.hibernate.dialect.MySQL5Dialect' />
   </bean>
 </property>
 <property name='jpaProperties'>
   <props>
     <prop key='hibernate.transaction.factory_class'>
       org.hibernate.transaction.JTATransactionFactory
     </prop>
     <prop key='hibernate.transaction.manager_lookup_class'>
       org.hibernate.transaction.JBossTransactionManagerLookup
     </prop>
   </props>
 </property>
</bean>

Als letztes muss die Datasource so konfiguriert werden, dass sie auf die Server-Datasource verweist und dass schließlich der Transaktionmanager, der von Spring verwendet wurde, zu der Entity Manager Factory passt.

<jee:jndi-lookup id='dataSource' jndi-name='java:myDataSource'
 cache='true' resource-ref='true' lookup-on-startup='true'
 proxy-interface='javax.sql.DataSource'/>
<bean class='org.springframework.transaction.jta.
 JtaTransactionManager' id='transactionManager'/>

Fazit

So konfiguriert, funktioniert die Spring-Anwendung in einem JEE Server. Es sei jedoch die Frage erlaubt, warum man nicht gleich auf Spring verzichtet und mittels EJB 3.1 die Businesslogik implementiert. Schließlich wurde es genau dafür entwickelt und kommt mit deutlich weniger Konfiguration aus. Manchmal werden aber Rechnungen von Kunden bezahlt, die bereits eine Architekturauswahl getroffen haben und nicht mal eben auf EJB 3 umsteigen können.

Über den Autor

Simon Zambrovski

Simon Zambrovski ist als Senior Berater der Holisticon AG in Hamburg, BPM-Craftsman, Arhictekt und Entwickler in IT-Projekten unterwegs. Er entwickelte maßgeblich eine Methodologie zur Durchführung von agilen BPM Projekten. Sein aktuelles Interesse gilt der Automatisierung von Geschäftsprozessen, den Event-Driven Microservices und dem Enterprise Architektur Management.

Antwort hinterlassen