Archiv der Kategorie: JEE-Prototype

JMX, Spring und Glassfish – Wie cool ist das denn?

Hallo zusammen,

da ich leicht erkältet bin, verbringe ich den Abend heute zu Hause – und was gibt es besseres, als sich ein wenig mit Glassfish zu beschäftigen;).

Ich habe ein wenig mit meiner Demoanwendung experimentiert (für das Aufsetzen und Auschecken am besten mal kurz diesen Eintrag lesen). Ziel war es, MBeans im Glassfish zu registrieren und diese zunächst über die jvisualvm sichtbar zu machen.

Die Architektur aktuell sieht so aus, dass die EJBs durch eine SessionFacade vom Frontend gekapselt sind.

Es genügt also vorerst, eine MBean für diese SessionFacade zu erstellen.

Hierfür erzeuge ich zunächst im EJB-Modul folgende Klasse:


@ManagedResource(objectName="md:name=ServiceFacadeMBean")
@Service("ServiceFacadeMBean")
public class ServiceFacadeMbean  {

 @Inject
 @Named("sessionFacade")
 private SessionFacade facade;

 @ManagedOperation(description="Load all Contacts")
 public List<Contact> getContact(){
 return facade.loadAllContacts();
 }
}

Zunächst mal ist es unbedingt notwendig, dass eine MBean auch als Spring-Service deklariert wird. D.h. eine MBean benötigt zwingend die @Service-Annotation. Weiterhin habe ich es mir einfach gemacht, indem ich die @ManagedResource-Annotation verwende, hierüber kann Spring die Bean automatisch als MBean identifizieren und registriert diese im MBean-Server des Glassfish (oder auch fast jedes anderen AS).

Im Spring-Kontext selbst wird folgendes deklariert:


<context:mbean-export />
 <context:component-scan base-package="de.md" />
 <context:annotation-config />

Über das Element mbean-export wird Spring angewiesen, alle MBeans soweit möglich direkt im AS zu registrieren.

Eine Alternative hierzu wäre die Deklaration einer MBeanExporter-Bean im Spring-Context. Das könnte ungefähr so aussehen:


<!-- Exporting Mbeans -->
 <bean id="exporter" lazy-init="false">
 <property name="beans">
 <map>
 <entry key="md:name=WebJMX" value-ref="sessionFacadeMBean" />
 </map>
 </property>
 </bean>

Das wars prinzipiell schon, fährt man jetzt den Glassfish hoch, kann man im Anschluss die jvisualvm-konsole hochfahren

(einfach in der Konsole jvisualvm eingeben). Glücklicherweise funktioniert das bereits Adhoc und Spring erkennt eine lokal laufende Glassfish Instanz.

Viel Spaß damit!;)

Advertisements

Deployment mit Maven 2, Cargo und Glassfish

Hallo zusammen,

da ich schon lange keine richtig guten Technischen Beiträge hier im Blog verfasst habe, wirds allerhöchste Zeit.

Die regelmäßigen Leser wissen, dass ich ein kleines Spielwiesenprojekt habe, in dem ich immer wieder mal neue Sachen ausprobiere, heute hatte ich ein wenig Zeit, und ich habe mir vorgenommen, das ganze Projekt (ein EAR) mittels Maven und Cargo deploybar zu machen.

Cargo ist eine sehr einfache Java-API mit folgendem Ziel:

Cargo is a thin wrapper that allows you to manipulate Java EE containers in a standard way.

Das schöne ist, dass Cargo auch über ein Maven-Plugin verfügt, und da mein Demo-Projekt zufälligerweise auch auf Maven basiert, kann mit Hilfe des Cargo Plugins problemlos ein Deployment in eine installierte ApplicationServer-Instanz vorgenommen werden.

Um das Ganze in Aktion zu sehen, empfehle ich dringend, das Demoprojekt auszuchecken, und zwar von hier mit Hilfe des Befehls :

git clone git://github.com/dilgerma/wicket-ejb-maven-prototype.git git-project

Um das Projekt starten zu können sollte man sich einen Glassfish-AS V3 lokal installieren. Einzige Anpassung
die notwendig ist, ist der Pfad zum AS, der in der pom des Maven-Artefaktes in base/ear/pom.xml angepasst werden muss.
Die Property heißt: appserv.dir und muss auf das Glassfish-Verzeichnis zeigen (z.B. /opt/glassfishV3).

Das Projekt verwendet die Derby-DB, die mit dem GlassfishV3 zusammen ausgeliefert wird. Diese sollte zuvor gestartet werden,
und zwar im Glassfish-AS/bin Verzeichnis mit dem Befehl:

GLASSFISH_HOME/bin/asadmin start-database

Um das Projekt zu starten sollte einmalig das Projekt durchgebaut werden, und zwar im base-Projekt mit folgendem Befehl:

mvn clean install -Preal

und anschließend im ear Modul:

mvn cargo:start

Dieser Befehl startet sowohl den Application-Server und führt ebenfalls das Deployment des soeben gebauten EAR-Archives
aus. Im folgenden gehe ich noch ein wenig auf die Konfiguration ein, hauptsächlich für mich selbst zur Dokumentation.

Um das EAR-Deployment mit Cargo zu konfigurieren muß zunächst das dazu notwendige Maven-Cargo-Plugin konfiguriert werden, hierzu brauchen wir folgende Repositories, die in der Base-Pom deklariert sind.

<plugin> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven2-plugin</artifactId> <version>1.0.5-SNAPSHOT</version></plugin>

Die restliche Konfiguration erfolgt direkt in der pom.xml des EAR-Projektes.

Was wir hier benötigen ist das cargo-maven2-plugin.

<build> <finalName>hp-app</finalName> <plugins> <plugin> <groupId>org.codehaus.cargo</groupId> <artifactId>cargo-maven2-plugin</artifactId> <version>1.0.5-SNAPSHOT</version> <!-- Configuration Details in http://cargo.codehaus.org/Maven2+Plugin+Reference+Guide#Maven2PluginReferenceGuide-configurationlocatedBlockquote--> <configuration> <container> <containerId>${appserv.cargo.id}</containerId> <home>${appserv.dir}</home> <type>installed</type> </container> <configuration> <type>standalone</type> <properties> <cargo.hostname>localhost</cargo.hostname> </properties> <configfiles> <configfile> <!--file>${appserv.dir}/glassfish/domains/${glassfish.domain}/config/domain.xml</file--> <file>src/main/resources/glassfish-config/domain.xml</file> <todir>cargo-domain/config</todir> </configfile> </configfiles> <deployables> <deployable> <groupId>de.md</groupId> <artifactId>ear</artifactId> <type>ear</type> </deployable> </deployables> </configuration> </configuration> </plugin></plugins>

Betrachten wir die Konfiguration noch ein wenig genauer:

Zunächst deklarieren wir mal die Abhängigkeit auf das cargo2-plugin (hier in der Version 1.0.5-SNAPSHOT).

Das Plugin selbst hat aber wenig Nutzen, es muss konfiguriert werden.
Hierfür gibt es den Configuration-Tag innerhalb jeder Plugin-deklaration.

Was zunächst konfiguriert werden muss ist der Container selbst, dieser Konfigurationsteil konfiguriert quasi
das Cargo-Plugin und den verwendeten AS.

<container> <containerId>${appserv.cargo.id}</containerId><home>${appserv.dir}</home> <type>installed</type> </container>
Eine gute Referenz für die Konfiguration von Cargo findet sich hier.

Über das Attribut containerId wird Cargo mitgeteilt, welcher AS denn tatsächlich im Einsatz ist, dies sind feste Strings und
können hier nachgelesen werden, für den Glassfish V3 lautet der String „glassfishv3“.

Das Attribut home verweist auf das Home-Verzeichnis des Glassfish-Servers.

Wichtig ist auf das Attribut type, dieses Attribut kann die Werte „installed„, „embedded“ und „remote“ annehmen.
Was ist aber der Unterschied? Im Normalfall (und wie ich in diesem Fall) wird das Plugin zur Entwicklungszeit verwendet, und hier
hauptsächlich um ein EAR in einen lokal installierten AS zu deployen. Deswegen wird von uns auch die Variante „installed“ verwendet, was
nichts anderes für Cargo bedeutet, als das der AS lokal bereits installiert ist.

Embedded bedeutet nichts anderes, als das der Container in der gleichen JVM und sogat im gleichen Thread wie Cargo ausgeführt wird. In diesem Fall ist es wichtig, dass die Container-Jars im Classpath verfügbar sind. Der einzige Container der aktuell den Embedded-Mode unterstützt ist der Jetty-Container in der Version 4,5 oder 6.

Damit wäre der Container vollständig konfiguriert. Was jetzt noch passieren muß ist die Konfiguration für das Cargo-Plugin selbst.

Hier verwenden wir folgenden Tag:

<configuration> <type>standalone</type> <properties> <cargo.hostname>localhost</cargo.hostname> </properties> <configfiles> <configfile><!--file&gt;${appserv.dir}/glassfish/domains/${glassfish.domain}/config/domain.xml&lt;/file--><br /> <file>src/main/resources/glassfish-config/domain.xml</file><todir>cargo-domain/config</todir> </configfile> </configfiles> <deployables> <deployable> <groupId>de.md</groupId><artifactId>ear</artifactId> <type>ear</type></deployable></deployables></configuration>

Zunächst ist es wichtig, den Typ der Konfiguration zu definieren. Folgende Werte sind prinzipiell möglich:standalone, existing und runtime.

Standalone-Konfiguration bedeutet, dass Cargo den Container jedesmal von neuem komplett neu aufsetzt.

Existing-Konfiguration bedeutet, dass Cargo eine bestehende Konfiguration wiederverwendet.

Runtime-Konfiguration bedeutet, das die Konfiguration erst zur Laufzeit festgelegt wird.

Im Idealfall verwendet man eine Existing-Konfiguration, da ansonsten alle Datenbank-settings etc. bei jedem Starten des Containers jedesmal neu gesetzt werden müssen. Leider, leider, leider unterstützt GlassfishV3 keine Verwendung von Existing-Konfigurationen. Um das zum Laufen zu bringen habe ich einige Zeit investieren müssen.

Versucht man eine Existing-Konfiguration zu verwenden stößt man auf folgende Fehlermeldung:


org.codehaus.cargo.container.ContainerException: Cannot create configuration. There's no registered configuration for the parameters (container [id = [glassfish3x], type = [installed]], configuration type [existing]). Valid types for this configuration are:
 - standalone

Nicht ganz einfach, daraus schlau zu werden, richtig? Und ständig die Konfigurationen für den AS neu aufzusetzen ist definitiv keine Option. Natürlich gibt es einen kleinen Workaround:).

Wir können einfach ein bestehendes Glassfish-Configuration-File wiederverwenden. Ich habe dieses File mal direkt im EAR-Projekt unter src/main/resources/glassfish-config/domain.xml bereitgestellt.

Eingebunden werden kann das Ganze auf folgende Art und Weise.

<configfiles>
    <configfile>
          <file>src/main/resources/glassfish-config/domain.xml</file>
          <todir>cargo-domain/config</todir>
    </configfile>
</configfiles>

Das Attribut file verweist auf das Konfigurationsfile, in diesem Fall ein Domain-Configuration-File des Glassfish.
Die Domain die Defaultmäßig von Cargo neu erzeugt wird heißt „cargo-domain „, dies läßt sich auch nicht ändern, soweit ich das bisher sehe. Das Konfigurationsfile muß also zur Laufzeit in das Config-Dir der
Cargo-Domain kopiert werden.
Das passiert mit dem Tag „todir„.

Zuletzt muß Cargo noch mitgeteilt werden, was überhaupt deployed werden kann.


<deployables>
 <deployable>
 <groupId>de.md</groupId>
 <artifactId>ear</artifactId>
 <type>ear</type>
 </deployable>
 </deployables>

Das wars, die Applikation fährt jetzt hoch, wird komplett deployed, die Konfiguration des Glassfish wird zur Laufzeit geladen.

Das einzige was ich noch nicht hinbekommen hab, ist das auch automatisch die Datenbank des Glassfish hochgefahren wird. Das muss momentan immer noch manuell passieren.

Ich hoffe, der Artikel machts dem Einen oder Anderen ein wenig einfacher. Über Kommentare freue ich mich natürlich.

Enterprise Prototype Teil 1 – Beschreibung und Auschecken

Hallo zusammen,

ich hatte ja versprochen, hier im Blog über den Fortschritt meines Demoprojektes zu berichten.

Das Demoprojekt ist meine kleine Spielwiese, die ich verwende, um mir neue Technologien anzusehen. Das Ganze ist eine Enterprise-Anwendung bestehend aus u.a folgenden Technologien in nicht sortierter Reihenfolge:

  • EJB3.1
  • Spring 2.5
  • Maven2
  • Glassfish V3
  • Apache Wicket
  • JRebel
  • EasyMock
  • Scala
  • Git
  • JPA / Hibernate

Der Sinn dieser Artikelreihe soll zum Einen Dokumentation für mich selbst sein, um spezielle Konfigurationen etc. irgendwo zu dokumentieren, andererseits soll es ebenfalls einen Einstieg in die Java Enterprise Entwicklung geben und so neue Entwickler möglichst schnell an den Produktiv zu bringen. Das Projekt befindet sich aktuell im Alpha-Stadium, wird aber kontinuierlich weiterentwickelt und hier im Blog dokumentiert.

Im Folgenden soll zunächst mal demonstiert werden, wie das ganze Projekt ausgecheckt werden kann (hierfür ist das DVCS Git notwendig), das ganze ist gehostet bei GitHUB.

Auschecken kann man das Ganze mit:

git clone git@github.com:dilgerma/wicket-ejb-maven-prototype.git wicket-prototype

Zusätzlich ist ein TestUtil Projekt von mir verwendet, das hier ausgecheckt werden kann:

git clone git@github.com:dilgerma/TestUtil.git TestUtil

Dann sollte man zunächst das TestUtil-Projekt bauen:

cd TestUtil
mvn clean install

Im Folgenden wird jetzt die grundlegende Struktur des Wicket-Prototypen demonstriert. Das Ganze ist wie bereits erwähnt ein Prototyp dessen Middletier auf EJB3.1 basiert. Das Frontend basiert aus Apache Wicket. Als Bindeglied zwischen Frontend und Middletier kommt Spring 2.5 zum Einsatz. Hierfür kommt ausserdem die Bibliothek Wicket-Spring zum Einsatz, da diese die Integration enorm vereinfacht.

Die Struktur der Maven-Module ist in folgendem Bild dargestellt.

Im Folgenden werde ich auf die Besonderheiten aller POMs ein wenig genauer eingehen.

Auf der untersten Hierarchiestufe gibt es ein Base-Pom. In diesem sind alle Dependencies festgelegt, die in allen hiervon abgeleiteten POMs ebenfalls benötigt werden.


<groupId>de.md</groupId>
<artifactId>base</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>base</name>

Dieses POM ist prinzipiell eher uninteressant, nichts desto trotz will ich ein wenig näher auf einige Details eingehen:

Viele Dependencies sind durch Dependency-Management deklariert:


<dependencyManagement>
<dependencies>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>

Man muss sich hierbei klar machen, das in Maven jede Abhängigkeit an die abgeleiteten Module vererbt wird, ich hätte jetzt also auch Problemlos das Ganze nicht im Berech Dependency-Management sondern als direkte Dependency deklarieren können.

<dependencies>
<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
<version>1.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>

Nachteil hiervon wäre gewesen, dass wirklich alle Module (und tatsächlich erben alle Applikations-Maven-Module vom Base-POM) eine Abhängigkeit zur Java Persistence API hätten. Das kann und wird nicht die Lösung sein. Das andere Extremum wäre gewesen, die Dependency auf die JPA in jedem Modul explizit zu deklarieren. Das würde prinzipiell funktionieren, wäre aber ein Albtraum, sobald einige Module zusammengekommen sind. Man stelle sich nur mal vor, man müsste von JPA 1.o auf 2.0 upgraden, man müsste das POM von jedem Modul einzeln anfassen und die Version hochzählen, brrrr….

Eine elegante Lösung bietet das Maven Dependency Management.

Die Abhängigkeiten werden nicht explizit sondern implizit vererbt, d.h. ich deklariere eine Abhängigkeit wie weiter oben beschrieben mit Version etc. einmalig im Base-POM im Bereich Dependency Management, und definiere dann in jedem POM, das diese Dependency benötigt nur noch folgendes:


<dependency>
<groupId>javax.persistence</groupId>
<artifactId>persistence-api</artifactId>
</dependency>

Der Unterschied sollte klar sein, man muss hier keine Version, keinen Scope, keinen Typ mehr definieren, weil dies bereits alles im Base-POM definiert ist. Käme ich jetzt also in die Situation, dass ich die Version der JPA inkrementieren müsste, würde ich dies im Base-POM tun und automatisch würden alle abhängigen Module, die eine Abhängigkeit auf die JPA deklariert haben die neue Version anziehen. Sehr elegant, sehr schön.

Natürlich bietet sich hier auch an, die Compile-Einstellungen etc. vorzunehmen, ich habe mich für JDK1.6 entschieden, das Ganze funktioniert so:


<build>
<plugins>
<p
lugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>

Zusätzlich habe ich die Generierung der rebel.xml für die Verwendung mit JRebel hier konfiguriert, so dass für jedes Abhängige Maven-Modul die Rebel.xml automtisch mit generiert wird.


<plugin>
<groupId>org.zeroturnaround</groupId>
<artifactId>javarebel-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-rebel-xml</id>
<phase>process-resources</phase>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>

JRebel selbst werde ich irgendwann in nächster Zeit in einem eigenen Artikel vorstellen.

Wie man bereits etwas weiter oben gesehen hat sind folgende Module direkt vom Base-POM abhängig:


<modules>
<module>webtier</module>
<module>ear</module>
<module>ejb</module>
</modules>

Werfen wir einen Blick in das EJB-Pom:


<groupId>de.md</groupId>
<artifactId>ejb</artifactId>
<packaging>ejb</packaging>
<version>1.0-SNAPSHOT</version>

Man beachte das Packaging EJB.

Das einzig interessante hier ist prinzpiell die Konfiguration des Maven-EJB-Plugins:


<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<configuration>
<ejbVersion>3.0</ejbVersion>
<generateClient>true</generateClient>
<clientExcludes>
<clientExclude>**/impl/**</clientExclude>
</clientExcludes>
</configuration>
</plugin>
</plugins>
</build>

Durch die Konfiguration kann man sich ein „virtuelles“ Maven-Modul erzeugen lassen, einen EJB-Client, der die API für die EJB-Services enthält, ohne dass man hierfür explizit ein eigenes
Projekt erstellen müsste. Eine wie ich finde sehr nützliche Art und Weise, einen EJB-Client zu erstellen. Die Konfiguration gibt hierbei an, dass alle Klasse, die nicht in einem Package **/impl… vorkommen im ejb-client enthalten sein sollen. Der EJB-Client kann auf folgende Art und Weise referenziert werden:

<dependency>
<groupId>de.md</groupId>
<artifactId>ejb</artifactId>
<version>1.0-SNAPSHOT</version>
<type>ejb-client</type>
</dependency>

Also groupId, artifactId etc. direkt vom EJB-Projekt, nur der type ist ejb-client statt ejb, das wars schon.

Werfen wir einen Blick ins Webtier-POM:


<groupId>de.md</groupId>
<artifactId>webtier</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>

Am Packaging pom erkennt man direkt, dass es sich hier wiederum um ein Multimodule-Projekt handelt (also quasi ein weiteres Base-POM für das Webtier), warum wir diese weitere Indirektion brauchen werden wir gleich sehen.
Auch dieses Pom ist wiederum relativ uninteressant, das einzig interessante hierbei ist die Verwendung von Maven Profilen. Ein Maven Profil gibt mir als Entwickler quasi die Möglichkeit, jede beliebige Einstellung im POM durch eine Profilspezifische Einstellung zu überschreiben. Warum brauche ich das hier?

Um das Layout für das Frontend zu entwickeln brauche ich prinzipiell die ganzen EJB-Serviecs nicht. Der Roundtrip ist einfach zu gross (Datenbankanbindung, Application Server, Datenbank befüllen) etc..
Das Ganze geht viel einfacher, wenn man es über Mock-Implementierungen löst. Ich habe also eine Abstraktion eingeführt, die sich Service-Connector nennt. Prinzipiell ist das nichts anderes als ein weiteres Maven-Modul, das für die Produktiv-Umgebung nichts weiter als eine Spring-Context-Defintion enthält.

Die Spring-Context Definition ist quasi für das Laden der EJBs zuständig, das Frontend weiß also prinzipiell gar nicht, dass es mit EJBs arbeitet, sondern das Frontend (speziell Wicket) wird direkt durch Spring bedient. Der Trick hierbei ist, das so während der Entwicklung völlig problemlos die EJB-Implementierung durch eine dumme Mock-Implementierung ersetzt werden kann, und zwar habe ich hierfür einenn Service-Mock-Connector geschrieben (ein weiteres Maven-Modul mit Spring-Context-Definition und Mock-Implementierungen, die zwar die Business-Interfaces der EJBs implementieren aber weder Datenbank noch Applicationserver benötigen, sondern beispielsweise auch direkt in einem Tomcat deployed werden könnten). Dem Frontend ist das wie bereits erwähnt völlig egal, da die Beans direkt aus Spring kommen und ob das nun echte EJBs oder nur Mocks sind ist völlig transparent.

Wie aber kann ich nun  bestimmen, ob meine Anwendung mit Mocks oder mit echten EJBs arbeitet? Ganze einfach, in dem ich das entsprechende Connector-Modul in meine Anwendung einbinde. Und genau diesen Use-Case löst man üblicherweise mit Maven-Profilen, die Definition eines Profiles sieht man im Folgenden:


<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<modules>
<module>service-connector</module>
</modules>
</profile>

Zunächst habe ich ein Modul „Default“ definiert, das per Default aktiv ist (activeByDefault..), und ein Modul „Service-Connector“ definiert. D.h. wenn ich mein Maven-Projekt mit „mvn clean install“ baue, ist dieses Profil aktiv und deklariert die Abhängigkeit zum Modul „service-connector“. Dies ist quasi mein Produktiv-Profil, da das Modul Backend-Connector die Abhängigkeiten zu den richtigen EJBs deklariert.

Für die Arbeit mit den Mocks definiere ich jetzt ein weiteres Profil:


<profile>
<id>mock</id>
<modules>
<module>mock-service-connector</module>
</modules>
</profile>

Das Profil kann mit folgendem Befehl beim Bauen aktiviert werden „mvn clean install -Pmock“, baue ich das Projekt mit diesem Befehl wird das Profil „default“ deaktiviert und stattdessen das Profil „mock“ aktiviert, d.h. ich habe von jetzt an keine Abhängigkeit mehr zum Modul „service-connector“ sondern zum Modul „mock-service-connector“. Und durch die Definition der Module werden eben genau auch nur diese gebaut, d.h. im Fall „-Pmock“ ist das (Jar-)Modul „service-connector“ später überhaupt nicht in meiner deploybaren Anwendung vorhanden.

Die Poms zu den Connectoren sind völlig unspannend, deswegen lasse ich die hier mal aussen vor und wir werfen einen letzten Blick in das POM für die Webanwendung:


<groupId>de.md</groupId>
<artifactId>web</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>

Auch im Web-Projekt benötigen wir nun natürlich die entsprechenden Profile, denn nach der Moduldeklaration muss das Web-Projekt die entsprechenden Connectoren natürlich noch als Abhängigkeit deklarieren. Dies folgt dem selben Prinzip wie zuvor erläutert, so dass hier das entsprechende XML sprechend genug sein sollte:

<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<!– Enable EJB Deployment by default –>
<dependency>
<groupId>de.md</groupId>
<artifactId>backend-connector</artifactId>
</dependency>
</dependencies>
</profile>
<profile>
<id>mock</id>
<dependencies>
<!– Enable Mocks–>
<dependency>
<groupId>de.md</groupId>
<artifactId>mock-backend-connector</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>

Der Witz bei der Sache ist jetzt, dass man nun ohne Probleme das komplette Frontend in einem Webcontainer testen kann ohne dass man eine EJB Container braucht. Ich verwende hierfür gerne den Jetty-Webserver und das entsprechende Maven-Plugin.

So kann ich die Anwendung in einem Rutsch deployen und testen ohne grossen Roundtrip. Hierzu wird einfach in der pom für das Webprojekt folgende Konfiguration in das bereits vorhandene Mock-Profil eingetragen:

<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
<connectors>
<connector implementation=“org.mortbay.jetty.nio.SelectChannelConnector“>
<port>8080</port>
<maxIdleTime>60000</maxIdleTime>
</connector>
</connectors>
</configuration>

</plugin>
</plugins>
</build>

Wenn man jetzt die Webanwendung mit „mvn clean install -Pmock jetty:run“ baut, startet automatisch der
Jetty-Webserver und man kann direkt testen.

So, das sollte die Wichtigsten Punkte der Maven Konfiguration abgedeckt haben, ich hoffe es war ein wenig interessant, speziell für Entwickler mit noch wenig Erfahrung mit Maven. Im nächsten Teil des Artikels werde ich näher auf den Ansatz mit den Service-Connectoren und deren Verschaltung mit Spring eingehen, bis dahin freue ich mich auf Kommentare.