# maven und "release"-profil, Phasen-Reihenfolge



## dermoritz (5. Jul 2010)

Ich hab im Moment ein Projekt mit 2 Modulen. Eins dieser Module -- das Datenbank -Modul -- hat eine "profiliert"-persistence.xml. Auf deutsch: die URL der Datenbank wird per Profil gesetzt. Ein Profil ist per default aktiv. Desweiteren gibt es ein "Release" Profil. Im Mutterprojekt sollte das doch durch folgende Konfiguration aktive sein:

```
<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-release-plugin</artifactId>
				<version>2.0</version>
				<configuration>
					<!--
						During release:perform, enable the "release" profile
					-->
					<releaseProfiles>release</releaseProfiles>
					<goals>deploy assembly:assembly</goals>
					<tagBase>svn://.../tags</tagBase>
					<scmCommentPrefix>[sandbox] release:</scmCommentPrefix>
				</configuration>
			</plugin>
```
Profile:

```
<profiles>
		<profile>
			<id>Lokal</id>
			<activation>
				<activeByDefault>true</activeByDefault>
			</activation>
			<build>
				<finalName>${artifactId}-${version}-Testlokal</finalName>
			</build>
			<properties>
				<DB-URL>jdbc:mysql://...</DB-URL>
			</properties>
		</profile>
		<profile>
			<id>Test</id>
			<build>
				<finalName>${artifactId}-${version}-TestSlesTest</finalName>
			</build>
			<properties>
				<DB-URL>jdbc:mysql://...</DB-URL>
			</properties>
		</profile>
		<profile>
			<id>Release</id>
			<build>
				<finalName>${artifactId}-${version}</finalName>
			</build>
			<properties>
				<DB-URL>jdbc:mysql://...</DB-URL>
			</properties>
		</profile>
	</profiles>
```
Das funktioniert aber nicht.  Aus irgendeinem Grund ist beim "mvn releaserepare -DdryRund=true" immer das default-Profil aktiv. -Wieso? 

Nun hab ich noch eine ähnlich gelagerte Frage: eines der beiden Module bastelt in der Phase "package" ein Paket für Webstart-Funktion.  Im Moment enthält das Webstart packet nach dem "mvn releaserepare -DdryRund=true" eben nur ...-snapshot.jar.
Da frag ich mich ob ich dieses Plugin ähnlich wie die DB-Profile in die Mutter.pom packen soll oder ob ich eine andere Phase reinschreiben kann so dass bei einem release dieses Paket eben die release.jars enthält. Also in welcher Phase des Release entstehen die release.jars - die Phase nach dieser Phase könnte ich ja in das WebStart-Plugin eintragen?!

Insgesamt hab ich noch ein unzureiuchendes Verständnis der Phasen die Maven bei den diversen goals so durchläuft. Gibt es irgendwo eine Liste wo man alle "Phasen" sieht in ihrer korrekten Reihenfolge? Ich frage mich oft wenn ich irgendein Plugin benutze, was ich für eine Phase angeben soll. Normalerweise ist der default-Wert der meisten Plugins gut manchmal eben nicht und da würde ich gerne eine Idee bekommen was eine andere sinnvolle Phase ist.


----------



## maki (5. Jul 2010)

> Aus irgendeinem Grund ist beim "mvn releaserepare -DdryRund=true" immer das default-Profil aktiv. -Wieso?


Was soll denn dein default Profil sein?

Meinst du das hier:
[xml]		<profile>
			<id>Lokal</id>
			<activation>
				<activeByDefault>true</activeByDefault>
			</activation>
...
[/xml]
Nun, wenn du activeByDefault auf true setzt, ist es eben immer aktiv, bis es explizit de-aktiviert, zB. auf der Kommandozeile mit einem Ausrufezeichen davor.



> Insgesamt hab ich noch ein unzureiuchendes Verständnis der Phasen die Maven bei den diversen goals so durchläuft. Gibt es irgendwo eine Liste wo man alle "Phasen" sieht in ihrer korrekten Reihenfolge?


Möchtest du einen Link zur Maven2 Doku oder findest du den selber?


----------



## dermoritz (5. Jul 2010)

ich hab active bei default so verstanden: es ist aktiv wenn kein anderes gewählt wurde. Und deaktivieren funtkioniert durch simples aktivieren eins anderen Profils. Z.b. über command-zeile - das funktioniert hab ich grad probiert.

Aber ich hätte ebend gerne das ein Profil automatisch bei "release" aktiviert wird und dafür sollte eigentlich <releaseProfiles>release</releaseProfiles> (siehe oben) reichen, oder nicht?

Vielleicht hab ich auch alles etwas falsch aufgebaut, deswegen hier noch mal mein Scenario: Ein Projekt mit 2 Modulen. Ein Modul ist die DB-Schnittstelle. Die sollte sich standardmäßig immer mit der Test-DB verbinden und bei Release mit der Produktions-DB. - Ist mein Ansatz den ich oben beschrieben habe dafür geeignet oder sollte man das anders aufziehen?

Das 2. Modul ist sozusagen das Frontend. Hier ist auch die main-Methode. Nun frag ich mich falls ich verschiedene Arten der Distribution realisieren möchte wo und wie das geschieht. Z.B. hätte ich gerne sowohl "assembly..jar-with-dependencies" als auch "webstart" - beides läuft. - falls man eben das entsprechende Goal auf Modul 2 ausführt.
Aber ich frag mich wie man das richtig macht. Kommen alle diese Distributionskanäle ind das Mutterprojekt? Braucht das Mutterprojekt dann Abhängigkeiten zu seinen Modulen? - Allgemein weiß ich nicht was dafür eine vernünftige Projektstruktur ist


----------



## maki (5. Jul 2010)

> es ist aktiv wenn kein anderes gewählt wurde. Und deaktivieren funtkioniert durch simples aktivieren eins anderen Profils. Z.b. über command-zeile - das funktioniert hab ich grad probiert.


Nein, das ist falsch.
Du machst was falsch, es funktioniert so wie von mir beschrieben 
Wie testest du sowas denn?
Ich hoffe nur mit [c]mvn help:active-profiles[/c]



> Aber ich hätte ebend gerne das ein Profil automatisch bei "release" aktiviert wird und dafür sollte eigentlich <releaseProfiles>release</releaseProfiles> (siehe oben) reichen, oder nicht?


Doch, das macht genau das: Ein Profil aktivieren, aber keine anderen deaktivieren.
Es sind oft viele Profile gleichzeitig aktiv 


Deine letzte Frage habe ich leider nicht so ganz verstanden...
Kannst ja immer die jar-with-dependencies und webstart bauen, auch von eigenen Modulen.


----------



## dermoritz (6. Jul 2010)

"Du machst was falsch, es funktioniert so wie von mir beschrieben" - Ich kann nur sagen, wenn ich mit -P release ein Maven goal ausführe funktioniert es wie es soll. Meine Frage ist auch weniger wie ich überhaupt ein Profil aktiviere - dass kann ich so das es funktioniert. Sondern wie ich es schlauer weise in meiner Situation (Test-DB, Produktions-DB) aktiviere.
Ich hab bemerkt, dass ein prinzipielles aktivieren bei release eigentlich bescheuert ist, denn dann laufen die UnitTests auch auf der Produktions-DB :-|. (nichts desto trotz würde mich interessieren wieso "<releaseProfiles>release</releaseProfiles>
" nicht funktioniert aber -P release)
Also wie richtet man so ein Profil am besten ein?

Meine letzte Frage bezieht sich auf die prinzipielle Modulstruktur. Falls ich extra Module einrichte, welche eigentlich keinen Code sondern nur Abhängigkeiten und ein bestimmtes Goal bereitstellen hätte, würde ich mich Fragen wofür man dann noch eine Parent.pom bzw. überhaup multi-Module-Builds braucht. Also ich Frage mich wie vernünftigerweise ein 2 Modulprojekt aussieht was als executable jar und als webstart ausgeliefert werden soll.


----------



## kama (6. Jul 2010)

Hallo,



dermoritz hat gesagt.:


> ich hab active bei default so verstanden: es ist aktiv wenn kein anderes gewählt wurde. Und deaktivieren funtkioniert durch simples aktivieren eins anderen Profils. Z.b. über command-zeile - das funktioniert hab ich grad probiert.


Du kannst Profiles nur aktivieren aber gleichzeitig ein anderes ausschalten geht nicht...



dermoritz hat gesagt.:


> Aber ich hätte ebend gerne das ein Profil automatisch bei "release" aktiviert wird und dafür sollte eigentlich <releaseProfiles>release</releaseProfiles> (siehe oben) reichen, oder nicht?


Damit das funktioniert muss Dein Profile aber auch den entsprechenden Namen (id) haben.

Das bedeutet zum einen, dass Du das folgende in der POM hast:

```
<plugin>
    <artifactId>maven-release-plugin</artifactId>
    <version>2.0</version>
    <configuration>
      <!--
        During release:perform, enable the "release" profile
       -->
      <releaseProfiles>release</releaseProfiles>
    </configuration>
  </plugin>
```
und zweitens selbstverständlich auch ein Profil hast, dass einen entsprechende Id hat:

```
<profiles>
        <profile>
            <id>release</id>
            ....
        </profile>
    </profiles>
```

Gruß
Karl Heinz Marbaise


----------



## dermoritz (6. Jul 2010)

Danke kama aber  nun hast du exakt den Code kopiert den ich oben hingeschrieben habe (bis auf die Groß-Kleinschreibung des ID-Namens - das ist aber in meinem Code korrigiert). Und eben genau das funktioniert nicht. Und zum Thema aktive nicht aktive - mir geht es natürlich um "effektiv aktiv"(relativ zu den Eigenschaften) das heißt wenn 2 profile die selbe Eigenschaft setzen, hat die Eigenschaft später genau einen Wert - den des "effektiv aktiven" Profils.
Und wenn 2 Profile eine Eigenschaft setzen und eines davon "default" ist, wird meiner Meinung nach (per Tests bestätigt mit -P...) das default Profil "effektiv inaktiv" sobald ich das andere setze. - Können wir uns auf diesen Sprachgebrauch einigen oder ist es immer noch falsch verstanden?

Aber wie erwähnt ist das gar nicht mehr das Hauptproblem. Sondern vielmehr, dass mir das aktive Release-Profil eigentlich so nix nützt, da es eine DB-URL setzt. Und auch bei einem Release will ich natürlich nicht, das der Unit-Test auf der Produktions-DB läuft. Ich müsste das Profil irgendwie erst zu einer sehr späten Phase des Release aktivieren. Und als mir das aufgefallen ist, habe ich angefangen grundsätzlich an meiner Projektstruktur zu zweifeln -siehe oben. Denn irgendwie muss ich nicht nur die 2 DB-URL's unter einen Hut bringen sondern auch 2 Auslieferungsvarianten: Webstart und Assembly (jar with dependencies) und was und wie das ganze im Releas-Repository landen soll ist mir noch schleierhaft. Im Moment landet das was - aber eben nur die 2 jar der 2 Module. Schön wäre natürlich auch das Webstartpaket und die jar-with-dependencies. Also wie schon beschrieben ich habe alle Bausteine und kann im Moment alles machen was ich will, aber alles sehr unschön mit manuellen eingriffen bzw durch explizites ausführen bestimmter goals auf bestimmten Modulen. Geht das irgendwie alles zusammen in einem (release)-Rutsch?


----------



## maki (6. Jul 2010)

> Und zum Thema aktive nicht aktive - mir geht es natürlich um "effektiv aktiv"(relativ zu den Eigenschaften) das heißt wenn 2 profile die selbe Eigenschaft setzen, hat die Eigenschaft später genau einen Wert - den des "effektiv aktiven" Profils.
> Und wenn 2 Profile eine Eigenschaft setzen und eines davon "default" ist, wird meiner Meinung nach (per Tests bestätigt mit -P...) das default Profil "effektiv inaktiv" sobald ich das andere setze. - Können wir uns auf diesen Sprachgebrauch einigen oder ist es immer noch falsch verstanden?


Es gibt kein "effektives aktives Profil".
Anstatt neue Begriffe für dein falsches Verstäbndnis zu erfinden solltest du dir genau ansehen was da wirklich passiert:
Das letzte aktive Profil belegt die Eigenschaft mit einem Wert, wenn dieser vorher gesetzt war, wird dieser überschrieben.
Das ist keine gute Idee, die Reihenfolge der aktiven Profile lässt sich nicht steuern und würde die Sache unnötig kompliziert machen.
Deine "Tests" sind ehrlich gesagt reiner Blödsinn, warum die nicht den richtigen Weg (mvn help:active-profiles) nimmst wird wohl dein Geheimnis bleiben.

Zum Thema mehrere Module:
Es ist nicht unüblich komplexes & langsames packaging auszulagern, vor allem wenn die eigentlichen Module in mehreren Packagings verwendet wird. 
Konfigurationen verwaltet man mit Profilen, da solltest du dir die Grundlagen unbedingt mal ansehen.
Du kannst ja die Variablen mit Standardwerten (zB. für lokale Entwicklung) vorbelegen, Profile (Test, Prod, etc.) überschreiben diese dann.


----------



## dermoritz (6. Jul 2010)

Um das mal abzukürzen hab ich nochmal die Doku gelesen zu <activeByDefault>:"This profile will automatically be active for all builds unless another profile in the same pom is activated using one of the previously described methods."
Also ich verstehe das so, dass das default Profil nur so lange aktive ist bis nicht irgendein anderes Profil in der selben pom aktiviert wird und nicht mehr oder weniger hab ich im ersten Post gesagt.
Meine Frage war warum das Setting "<releaseProfiles>release</releaseProfiles>
" nicht funktionierte. Nun zu mvn help:active-profiles - das hate ebend genau das geliefert was ich vermutet habe: mein default-Profil. Der Befehl nützt nichts wenn man wissen will welche Profile zu welchen Phasen aktive sind. Aslo ob während des Release prepare/perform irgendwann ein anderes Profil aktiv wird oder war - oder kann man sich die aktivierung von Profilen anzeigen lassen - während mvn ausgeführt wird?
Aber insgesamt wollte ich das Thema abschließen und zumTema Module überschwenken - genau dein Idee Maki gefällt mir. Also für bestimmte "Targets" separate Module einzusetzen (hab ich das richtig verstanden?). 
Wie sehe das praktisch aus? Diese Moduele hätten dann keinen Code sondern nur dependencies und build-Plugins mit entsprechender Konfiguration?


----------



## maki (6. Jul 2010)

> Um das mal abzukürzen hab ich nochmal die Doku gelesen zu <activeByDefault>:"This profile will automatically be active for all builds unless another profile in the same pom is activated using one of the previously described methods."
> Also ich verstehe das so, dass das default Profil nur so lange aktive ist bis nicht irgendein anderes Profil in der selben pom aktiviert wird und nicht mehr oder weniger hab ich im ersten Post gesagt.


Steht zwar so da, stimmt aber leider nicht 
Erst seit Maven 2.1 kann man Profile auch wieder abschalten.
Man kann mit dem -X Parameter ziemlich viel Debug ausgaben bekommen, aber einen anderen Weg kenne ich nicht zum die aktiven Profile anzuzeigen.



> Wie sehe das praktisch aus? Diese Moduele hätten dann keinen Code sondern nur dependencies und build-Plugins mit entsprechender Konfiguration?


Ja, die Module kümmern sich nur um bestimmte Aspekte wie packaging, man kann auch pro Packaging ein Modul machen.
Es lässt sich zB. auch über Profile steuern, welche Module Teil der (Parent-)Pom sind. Beim Entwicklen müsstest du so nicht nach jedem mvn install warten, bis das War und das Webstart gepackt sind und die Integrationstests durchgeführt wurden.


----------



## dermoritz (6. Jul 2010)

ok dann mal Danke. In der Zwischezeit hab ich mir auch schon 2 Module für die 2 Targets gemacht beide hab ich mit "package" verknotet. Bis auf die Tatsache, dass das Webstart Plugin was ich benutze auf Dependencies pfeift und alle jars verpackt(http://www.java-forum.org/deployment/101238-maven-webstart-programm.html) und ich das offizielle nicht zum laufen kriege hab ich jetzt fast alles so wie ich es will.

Nun fehlt leider nur noch die Sache mit dem Profil: wie realisiere ich verschiedene DB_Urls bzw "Umgebungen", so dass man bei bestimmten Phasen oder Goals verschiedene URLs hat. Wie gesagt hätte ich gerne nur in (bestimmten) Release-Artefakten die Prduktions-db-url. Ansonsten soll immer eine Test-db-url gelten. Ich sah da eben die einzige Möglichkeit das mit Profilen mit "default" zu realisieren. Dank euch weiß ich nun das das Müll ist, aber leider noch nicht wie ich es richtig mache.


----------



## maki (6. Jul 2010)

> Nun fehlt leider nur noch die Sache mit dem Profil: wie realisiere ich verschiedene DB_Urls bzw "Umgebungen", so dass man bei bestimmten Phasen oder Goals verschiedene URLs hat.


Würde sagen: Variablen ja nach Phasen und Goals kannst du vergessen, wird nicht funktionieren. Du kannst das über Profile steuern, aber eben nicht für Phasen und Goals.

Wie ich das (manchmal) mache:
Lokale Entwicklung hat lokale Db-Urls etc., dann ein Profil für den Testserver und eines für den Prod Server. Diese Profile überschreiben die Standard Properties mit anderen DB URLs etc.
Ich baue dann für jede Umgebung einzeln mit entsprechendem Profil, ausser für die lokale Entwicklung, da gibt es kein Profil, nur Standardwerte.


----------



## dermoritz (6. Jul 2010)

ok dass heißt alles würde immer mit lokalem Profil kompilieren einschließlich Release, es sei denn du setzt explizit ein Profil? Und wie laufen die UNIT-Tests bei aktiviertem Produktionsprofil? die düfen ja nicht auf der Produktions-DB laufen?! Ich hatte gehofft man kann vernünftig bestimmte Profile zu bestimmten Phasen anschalten.


----------



## maki (6. Jul 2010)

Wie gesagt, würde kein Profil für lokale Entwicklung anbieten, da sollten default-werte reichen, sonst bekommst du das Problem "Welches Profil wurde zuletzt aktiviert?"...

Vielleicht verwechselst du was mit den Phasen, wozu sollte man für die Phasen unterschiedliche Profile haben?
Egal..

Echte Unittests im Prod-Profil sind ja kein Problem, da diese nix externes ändern 
Integrationstests schaltet man im Prod-Profil ab.


----------



## dermoritz (6. Jul 2010)

Es kommt eben drauf an wie Realitätsnah man Unit-Tests machen will. In meinem Fall geht es um eine JPA/Eclipselink/MySQL basierende DB-Schnittstelle. Deren Unit-Tests sollten auf einer MySQL -DB laufen. Inzwischen hab ich auch die Standardwerte (loakele DB) als simple Properties gesetzt.

Aber wie krieg ich nun einen Release hin dessen UnitTests natürlich auch auf der loakelen oder TestDB laufen aber dessen Artefakte (genaugenommen in einem Artefakt die persistence.xml) die Werte für die Produktionsumgebung aufweisen?


----------



## maki (6. Jul 2010)

> Es kommt eben drauf an wie Realitätsnah man Unit-Tests machen will. In meinem Fall geht es um eine JPA/Eclipselink/MySQL basierende DB-Schnittstelle.


Unittests != Integrationstests

Deine Tests überschreiten Systemgrenzen, da wird die DB mitgetestet -> Integrationstests
Diese Unterscheidung wird sehr wichtig wenn das Projekt mal größer oder komplex wird.



> Aber wie krieg ich nun einen Release hin dessen UnitTests natürlich auch auf der loakelen oder TestDB laufen aber dessen Artefakte (genaugenommen in einem Artefakt die persistence.xml) die Werte für die Produktionsumgebung aufweisen?


IMHO eben gar nicht, für jede Umgebung (per Profil) ein Build.
Integrationstests sollten abgeschaltet sein im Prod Profil.


----------



## dermoritz (6. Jul 2010)

Je nach dem von welcher Seite man es betrachtet oder welche genaue Definition man zu Rate zieht habe ich Unit-Tests (Tests von kleinsten sinvoll ausführbaren Einheiten - ohne DB sind diese Einheiten eben nicht mehr sinnvoll ausführbar) oder eben Integrationstests da ich ja (auch) die DB-Schnittstelle teste. Da dieses Modul nichts anderes mach als die DB-Schnittstelle zu implementieren, sollten meiner Meinung nach diese Tests immer ausgeführt werden sobal etwas am Code geändert wird - analog zu "echten Unittests"
Praktisch schlägst du aber vor, bei Release diese Tests prinzipiell abzuschalten, oder? Maven - Building For Different Environments with Maven 2 machen das indem das sure-fire-plugin abgeschalten wird für bestimmte Profile. Machst du das abschalten der Tests ähnlich?
Warum es im dortigen Beispiel auch für das Test-Profil abgeschaltet wird ist mir schleierhaft. 
So richtig wohl ist mir aber nicht dabei. Ich fand es eigentlich sehr angenehm, das quasi alle goals auch Test ausführen. Insbesondere beim Release find ich einen letzten Unit-Test ein gutes Fangnetz.


----------



## maki (6. Jul 2010)

Tests die Java Code und die DB testen sind keine isolierten Unittests sondern Integrationstests, solche Tests sind langsam & fragil, da sie eben Systemgrenzen überschreiten, sie bringen auch meist massive Abhängigkeiten mit(installiertes & konfiguriertes RDBMS), wenn man zum testen ein RDBMS wie HSQLDB, H2 oder Derby nutzt ist das nicht mehr so schlimm.

Für den Release gibt es die sog. "preparationGoals" die man umkonfigurieren kann, also anstatt "clean, install" wird es dann u.U. nur noch "clean", die Konfig. des Surefire Plugins wird ignoriert beim Release  

Klar wäre es toll immer alle Tests laufen zu lassen, aber wenn deine Tests die DB umschiessen ist es nicht lustig wenn die URL zur Prod DB als konfig angegeben wird.

Nebenbei, es gibt 2 einigermassen aktuelle Maven Bücher umsonst, bringen mehr als die u.U. sehr alten Webseiten (dein letzter link zB.), sind aber auch nicht immer 100% akurat bzw. aktuell.


----------



## dermoritz (7. Jul 2010)

Ich will mal kurz zusammenfassen welche Alternativen es gäbe so weit ich es verstanden habe: Tests mit DB's sollte man entweder mit "in Memory"-DBs machen oder sie als Integrationstest behandeln und damit eventuell in ein gesondertes Modul auslagern. In ersterem Fall müsste man die Tests nur so umstricken, dass sie einen anderen "Persistence Provider" benutzen, also eine 2. persistence.xml hinterlegen. Wie man genau mit einem seperaten Testmodul umgeht kann ich mir noch nicht so richtig vorstellen. - Was wäre da das Elternmodul? Wann wie würden Tests automatisch erfolgen falls sich im zugrundeliegenden Code etwas geändert hat?

Wenn man sich einige Bücher anschaut die Maven und Entwicklung mit DB's behandeln wird sehr oft der Weg mit in Memory-DB's gegangen. Ich glaube ich werde meine Tests umstricken - was meinst? An den Release Goals rumzubasteln halte ich für nicht die beste Wahl - zumal das install doch wichtig ist damit die jeweiligen abhängigkeiten in der neuesten Version (SVN-Revision) im Release landen, oder?

Meinst du mit den Maven Büchern "beter builds with maven" und "maven the complete reference"? - auf die ganzen Sonatypebücher wurde ich hier im Forum hingewiesen (könnte nicht ausschließen, dass du es warst Maki ;-)) - Letzteres behandelt Profile sehr ausführlich - deshlb hab ich das Kapitel da auch noch nicht gelesen ;-).


----------



## maki (7. Jul 2010)

> Wie man genau mit einem seperaten Testmodul umgeht kann ich mir noch nicht so richtig vorstellen. - Was wäre da das Elternmodul?


Nö, nicht in die Parent Pom, sondern wirklich eigene Module 

Ein Integrationstest gehört zu den "black box" tests, d.h. du testest keine Interna Direkt (wie zB. mit Mocks), sondern du testest nur von "aussen" das ganze Modul, u.U. mit anderen Modulen/Systemen (wie der DB zB.).
Deswegen hast du keinen Nachteil ein eigenes (oder mehrere) Integrationstest Modul zu verwenden, sondern nur mehr Klarheit und dadurch Vorteile. Abgesehen davon bekommt man schnell Probleme (Henne-Ei) wenn man versucht das ganze Modul im Modul selber zu testen 



> Wenn man sich einige Bücher anschaut die Maven und Entwicklung mit DB's behandeln wird sehr oft der Weg mit in Memory-DB's gegangen. Ich glaube ich werde meine Tests umstricken - was meinst?


Die Beispiele sind meist sehr einfach gehalten, komplex wird es in der Realität.
Umstricken? Siehe unten..



> An den Release Goals rumzubasteln halte ich für nicht die beste Wahl - zumal das install doch wichtig ist damit die jeweiligen abhängigkeiten in der neuesten Version (SVN-Revision) im Release landen, oder?


Die preparationGoals sind nur die Vorbereitung vor dem eigentlichen Build & Install/Release, mit Release Plugin wird dieser nämlich mehrmals ausgeführt, musst dir da keine Sorgen machen dass die falschen Versionen in den Repos liegen 

Die beste Lösung ist imho wirklich keine Integrationstests für den Release.
Sieh es mal so: Deine Prod DB wäre zB. Oracle oder MS-SQL Server, deine Integrationstests sollten irgendwann wirklich auf diesem DBs arbeiten (am besten von einem CI Server aus), für den "normalen" Entwickler nimmst du eine IN-Memory DB, aber irgendwann muss ja auch auf der richtigen DB getestest werden.



> Meinst du mit den Maven Büchern "beter builds with maven" und "maven the complete reference"? - auf die ganzen Sonatypebücher wurde ich hier im Forum hingewiesen (könnte nicht ausschließen, dass du es warst Maki ) - Letzteres behandelt Profile sehr ausführlich - deshlb hab ich das Kapitel da auch noch nicht gelesen .


Ja die beiden meinte ich, hab shcon mehrmals darauf verlinkt, gut dass du mir das diesmal erspart hast 
in "Better Builds with Maven hatte ich selber schon Fehler entdeckt.. kommt vor.


----------



## dermoritz (7. Jul 2010)

So nun bin ich gerade beim umbiegen der UnitTests auf eine DerbyDB. In Beispielen hab ich gesehen, dass man dass über verschiedene persistence.xml Dateien realisiert (eine in src/test/resources und eine in src/main/resources). Das scheint auch zu funktionieren solange man keine "<resources>" in der pom angibt (ich glaub dann wird nur dort gesucht?).
Die Frage wäre falls ich Resource-Filterung benötige wie kann ich die resourcen so angeben, das der Test nur seine Test Resourcen sieht und das Programm die normalen Resourcen?
Das Filtern nach Test DB und Release DB hätte ich immernoch gerne. So dass immer gegen die Test-DB kompiliert wird. Es sei denn ich setze explizit ein Release/Prod-Profil (kann man sowas automatisch setzen bei release?). Die Tests würden dann immer auf Derby laufen, da die Tests nur ihre persistence.xml kennen.


----------



## maki (7. Jul 2010)

Hier wird das ganze komplex ...und vorsicht mit Besipielen aus dem Netz, viele sind nur klein & einfach, und in der Praxis nicht einsetzbar 

Man kann zB. auch die Tests als Jar ins Repo schreiben lassen, andere Projekte (zB. Integrationstests) können die aiese Testklassen dann wiederverweden, mit anderer Konfig zB. 
Maven - Guide to using attached tests

Oder eben Profile nutzen, oder eine Mischung aus beidem, oder die Resourcen nochmals abändern bzw überlagern (Resource mit gleichem Namen aber anderen Inhalt im IT Modul unter src/test/resources)..


----------



## dermoritz (7. Jul 2010)

das die Beispiele aus dem Netz nicht gelten, hab ich spätestend da bemerkt als mir bewusst wurde, dass JPA-Anwendungen ohne J2EE eher ungebräuchlich sind. Das zieht dann ein eigenes Managment der DB Resourcen nach sich (siehe http://www.java-forum.org/data-tier/101781-umgehen-ressource-entitymanager-e-m-factory.html) und damit fängt Kacke an zu dampfen. Denn die Klassen die ich Teste benutzen diese DB-Resource über ein Singleton (Quasi mein JPA Container). 
Und wenn ich diese Klassen während der Tests aufrufe greifen diese Klassen effektiv auf die main/resourcen zu und nicht auf die Test/resourcen, oder?
Damit schlug das überlagern auch fehl in irgendeinem Test hatte ich einen error nach dem der Test nur mit einem mvn clean reproduzierbar war. Aus irgendeinem Grund ist nach dem ersten Durchlauf nur noch die resource aus main/resources berücksichtigt worden. (Mir stehen nun auch die Haare zu Berge )
Kann ich irgendwie die Resourcen so angeben/filtern in einer pom, dass bestimmter Resourcen aus dem Test unsichtbar sind? Oder kann ich irgendwie sicher gehen, das diese Überlagerung funktioniert?
Ich würde gerne sicher gehen, dass niemand aus versehen einen Test schreibt, der auf die main/resource zugreift, denn damit würde bei einem release und gestzter Prod-DB der Test darauf ablaufen.


----------



## maki (7. Jul 2010)

> das die Beispiele aus dem Netz nicht gelten, hab ich spätestend da bemerkt als mir bewusst wurde, dass JPA-Anwendungen ohne J2EE eher ungebräuchlich sind. Das zieht dann ein eigenes Managment der DB Resourcen nach sich (siehe wie umgehen mit Ressource EntityManager und E-M-Factory) und damit fängt Kacke an zu dampfen. Denn die Klassen die ich Teste benutzen diese DB-Resource über ein Singleton (Quasi mein JPA Container).


Spring bietet sich dafür an 



> Und wenn ich diese Klassen während der Tests aufrufe greifen diese Klassen effektiv auf die main/resourcen zu und nicht auf die Test/resourcen, oder?
> Damit schlug das überlagern auch fehl in irgendeinem Test hatte ich einen error nach dem der Test nur mit einem mvn clean reproduzierbar war. Aus irgendeinem Grund ist nach dem ersten Durchlauf nur noch die resource aus main/resources berücksichtigt worden. (Mir stehen nun auch die Haare zu Berge )
> Kann ich irgendwie die Resourcen so angeben/filtern in einer pom, dass bestimmter Resourcen aus dem Test unsichtbar sind? Oder kann ich irgendwie sicher gehen, das diese Überlagerung funktioniert?
> Ich würde gerne sicher gehen, dass niemand aus versehen einen Test schreibt, der auf die main/resource zugreift, denn damit würde bei einem release und gestzter Prod-DB der Test darauf ablaufen.


Nö, eigentlich nciht, während Unittests laufen, sollten die Testressourcen(src/test/resources) die normalen Ressourcen (src/main/resources) überlagern, Vorrausgesetzt du verwendest ein aktuelles Maven2 (2.2.1).
Kannst ja mal testen (bei mir gehts immer), in dem du jeweils eine Property Datei gleichen Namens aber unterschiedlichen Inhalts unter den Testressourcen und normalen Ressourcen hast.


----------



## dermoritz (7. Jul 2010)

Also dass das Überlagern nicht funktioniert erklär ich mir so: der Test grift auf Resource xy zurück. Im Test wird eine Klasse instanziiert/getestet die selbst auch auf die Resource xy zurückgreift. Wenn alles korrekt läuft sollte der test xy in test/resources benutzen und die Klasse main/resources oder?
Das es in meinem Fall so übel schief geht leigt glaube an der Art der Resource. Der Persistence Kontext wird ja nur über den Namen der PersistenceUnit aufgerufen. Nun kann ich mir irgendwie nicht vorstellen, dass Persistence.createEntityManagerFactory("pu") weiß welche der 2 vorhandenen PU's die richtige ist?!

In den Beispielen dazu aus Büchern werden eben nur die Entitätsklassen selbst getestet. Den Peristenzkontext stellt in diesen Beispielen dann einmal die main() zur Verfügung oder eben der Unittest.Da ich Klassen teste die selbst den Persitenzkontext bereitstellen bzw. ein Singleton (quasi mein jpa container) nehmen ist es etwas haariger.

Lange Rede kurzer Sinn, ich schreibe mal wie ichs nun gemacht habe:
Ich hab nun eine zweite PersitenceUnit (Derby in Memory) damit nun alle Klassen (die den Singleton benutzen) in diesem Kontext laufen musste ich ein setEMF(emf) in das singleton einbauen (unschön ich weiß). Ein Test muss also zunächst einen eigenen P.Kontext bauen und diesen dann in das Singleton "injizieren". Dann funktioniert es :-|.
Die einzige Alternative die ich sehe ist tatsächlich alle DB-Tests komplett auszulagern und eben als Integrationstest zu betrachten. Oder gibt es noch andere Alternativen?

Nun zurück zum ursprünglichen Problem: Das Unit-Test-Profil brauch ich ja nun nicht mehr. Aber ich hätte gerne noch eine Unterscheidung zwischen Prod-DB und Test-DB (für spätere Testphasen). Nun frag ich mich prinzipiell wo und wann und wie sollte ich diese Weiche stellen? Z.B. sollte es überhaupt einen Releas geben der nicht auf der Prod-DB läuft? Oder sollte man für beide Fälle seperate Releases vorsehen? Oder sollte man diese Weiche völlig aus Maven raushalten? Also am Ende irgendeine Settingsdatei dazupacken?


----------



## maki (7. Jul 2010)

> Also dass das Überlagern nicht funktioniert erklär ich mir so: der Test grift auf Resource xy zurück. Im Test wird eine Klasse instanziiert/getestet die selbst auch auf die Resource xy zurückgreift. Wenn alles korrekt läuft sollte der test xy in test/resources benutzen und die Klasse main/resources oder?
> Das es in meinem Fall so übel schief geht leigt glaube an der Art der Resource. Der Persistence Kontext wird ja nur über den Namen der PersistenceUnit aufgerufen. Nun kann ich mir irgendwie nicht vorstellen, dass Persistence.createEntityManagerFactory("pu") weiß welche der 2 vorhandenen PU's die richtige ist?!


Würde sagen da gibt es ein anderes Problem...
Eine Datei mit Namen "dummy.txt" unter Testressourcen sollte die Datei "dummy.txt" unter den normalen Sourcen überlagen, d.h. letztere Datei ist nicht zugreifbar.
Mache das ständig mit meinem Ressourcen (log4j konfig usw.).



> Nun zurück zum ursprünglichen Problem: Das Unit-Test-Profil brauch ich ja nun nicht mehr. Aber ich hätte gerne noch eine Unterscheidung zwischen Prod-DB und Test-DB (für spätere Testphasen). Nun frag ich mich prinzipiell wo und wann und wie sollte ich diese Weiche stellen? Z.B. sollte es überhaupt einen Releas geben der nicht auf der Prod-DB läuft? Oder sollte man für beide Fälle seperate Releases vorsehen? Oder sollte man diese Weiche völlig aus Maven raushalten? Also am Ende irgendeine Settingsdatei dazupacken?


IMHO sollte diese Entscheidung von Maven gemacht werden.
Im Test Profil werden eben die Test DB Konfig verwendet, im Prod Profil die Prod DB Konfig, ohne Profil die Standardeinstellungen (lokal).


----------



## dermoritz (12. Jul 2010)

"Eine Datei mit Namen "dummy.txt" unter Testressourcen sollte die Datei "dummy.txt" unter den normalen Sourcen überlagen, d.h. letztere Datei ist nicht zugreifbar.
Mache das ständig mit meinem Ressourcen (log4j konfig usw.)."

Zugreifbar ist die letzte schon aber Maven sorgt dafür, dass bei Anfrage dieser Resource die aus den Testresourcen die sichtbare ist.

Die Frage ist eben ob man das auf eine Persistence.xml übertragen kann. Auf diese Resource wird ja nicht wie auf andere zugegriffen. Irgendwie sucht der Persistenceprovider nach einer persistence.xml in einem meta-inf-ordner. Und wenn eine Klasse die Datei per Namen aufruft kann ich mir schon vorstellen, dass die Testklassen die imer Testordner zuerst entdecken und die anderen Klassen zuerst die aus dem main -Ordner.
Wie gesagt ich versuche nur sehr eigenartiges Verhalten zu erklären, mit verschieden benannten Persitenceunits geht es (dateinamen sind identisch). Und damit kann ich ganz gut leben?!

Zur Profilproblematik:
ähnlich wie du hab ich es mir nun auch gedacht. Praktisch würde ich im DB-Modul also feste Properties setzen (lokale DB) und im Parent-Modul die Profile einbauen - oder? Oder sollten die Profile auch in das DB-Modul? Irgendwie bin ich mir unsicher wie ich verschiedene Varianten unterscheiden kann. Ich müsste ja das DB-Modul in verschiedenen Varianten "installieren" damit andere Module diese Varianten auch "sehen". Kindmodule die abhängig sind von einem anderen Kindmodul werden doch immer gegen das was lokal im repository ist kompiliert oder? falls ich also die DB-Schnittstelle nur neu kompiliere mit einem anderen Profil sehen das die anderen Module nicht, oder?

Edit: ich habgrad bemerkt dass die idee die Profile im Parent zu haben Kacke ist. Trotz gesetztem Profil wurden die festen Properties verwendet und nicht die aus dem Profil. Der "final name" wurde richtig gesetzt aber die Properties wurden nicht überschrieben - wieso?
Ich hab mal die Gegenprobe gemacht, falls ich keine Properties explizit setze werden die aus dem Profil (im parent pom) genommen. Ich dachte das ein aktiviertes Profil sämtliches Einstellungen überschreibt?! Mach ich was falsch?
die Properties setze ich so:

```
...
<version>0.2-SNAPSHOT</version><
	<properties>
		<DB-URL>jdbc:mysql://...</DB-URL>
		<DB-USER>...</DB-USER>
		<DB-PW>...</DB-PW>
	</properties>
	<build>
...
```
das Profil sieht so aus:

```
<profiles>
		<profile>
			<id>Lokal</id>
			<build>
				<finalName>${artifactId}-${version}-Testlokal</finalName>
			</build>
			<properties>
				<DB-URL>jdbc:mysql://...</DB-URL>
				<DB-USER>...</DB-USER>
				<DB-PW>...</DB-PW>
			</properties>
		</profile>
...
</profiles>
```
Wie gesagt der final name wird immer gesetzt bei aktiviertem Profil. Die Properties werden aber nur gesetzt wenn sie lokal nicht gesetzt wurden.


----------



## dermoritz (19. Jul 2010)

mich würde wirklich interessieren wieso ich per parent.pom-Profil keine Properties der einzelnen Module überschreiben kann. Bzw. wie man sowas bewerkstelligt.
Ein "install" oder "package" auf dem Modul soll etwas halbwegs lauffähiges erzeugen, deshalb brauche ich standard Properties. Andererseits würde ich gerne Daten für Produktionsumgebungen (url, login und passwort) aus dem Modul raushalten.


----------



## maki (19. Jul 2010)

dermoritz hat gesagt.:


> mich würde wirklich interessieren wieso ich per parent.pom-Profil keine Properties der einzelnen Module überschreiben kann. Bzw. wie man sowas bewerkstelligt.
> Ein "install" oder "package" auf dem Modul soll etwas halbwegs lauffähiges erzeugen, deshalb brauche ich standard Properties. Andererseits würde ich gerne Daten für Produktionsumgebungen (url, login und passwort) aus dem Modul raushalten.


Sollte gehen, mach ich auch, Profile in der Parent POM, die die Standardpoperties (d.h. ohne Profil gesetzt) überschreiben.


----------



## dermoritz (20. Jul 2010)

aber wie ich oben geschrieben habe (dort stehen die properties und die profile) werden alle Properties die in der Modul-Pom gesetzt sind nicht überschrieben, aber alle anderen. Im Moment funktionieren nur 2 Alternativen: entweder alle Modul-Properties in die Modul-Pom, dann aber auch die Profile die exakt diese überschreiben.
Oder Ich packe alles in die parent.pom, also die Properties selbst und die Module. Jetzt frag ich mich woran das liegen kann?!


----------

