I have a war packaging Maven project, in which I have a Java properties files called myapp.properties. In this properties file, I store some parameters, for example, database connection parameters, which will be used by the webapp.
Either in a continuous integration environment or in my development environment, I want to set some testing parameters in myapp.properties to connect to my test database for example.
At the same time, I want to leave these parameters blank in my final war package so that users can add these values by themselves during deployment to their environment. The final war package should be a build artifact generated in the continuous integration environment.
Essentially, there are two versions of myapp.properties file I want to use in different cases. My question is, what is the Maven way to solve this problem? I use Eclipse + WTP + m2eclipse in my development environment, and I hope the solution can works well together with my development tools.
You can have a look at this blog: http://blog.jayway.com/2010/01/21/one-artifact-with-multiple-configurations-in-maven/
They build different war-files and use different classifier (instead of different profiles).
I am not sure if it is the maven way, but it works for some of my projects.
i would try it with
pom.xml for your project (or parent pom)
<build>
...
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
</includes>
<filtering>true</filtering>
</resource>
...
</build>
in your properties file(s) e.g.
db.url=${db.url}
and in your settings.xml (see http://maven.apache.org/settings.html#Profiles)
<db.url>jdbc:mysql://localhost:3306/testdb</db.url>
depending on your development stage (local, build server, etc.) you can use different db.url values
this will not leave the db.url property blank, but each time you package the artifact you dont want it really to stay blank do you ?
Related
This question already has answers here:
Migrating complex project from Ant to Maven - How to handle unusual folder structures?
(2 answers)
Closed 9 years ago.
The problem is quite simple: there is an ant project that I should port to maven. As maven has a recommended/expected project directory structure, this would implicate much manual work if I restructure the directories of the java files. On the other hand, the project would also not be very happy with this solution, not mentioning others, using the packages of the current project.
Do you have any idea, how it would be possible to migrate to maven without having to change the directory structure? Thank you also in advance.
It is strongly recommended that you use Maven's standard directory structure, but you can set a custom src directory in your pom. Something like:
<build>
<sourceDirectory>path\to\actual\src</sourceDirectory>
</build>
The following might be what you're looking for: Handling unconventional source directory for a web project in maven
Edit: The following is a list of default settings that are set in the Maven Super POM and can be overriden in your project's pom.xml
<build>
<directory>target</directory>
<outputDirectory>target/classes</outputDirectory>
<finalName>${artifactId}-${version}</finalName>
<testOutputDirectory>target/test-classes</testOutputDirectory>
<sourceDirectory>src/main/java</sourceDirectory>
<scriptSourceDirectory>src/main/scripts</scriptSourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
</testResources>
</build>
I would strongly recommend you commit to the restructure. You are only adding to your problems if you do not.
However, if you really must maintain your original structure you could make use of soft folders of some sort. On Windows you can use SymLinks - I expect there are other alternatives for other OS's.
Make a new folder beside your sources folder (I called mine Maven). In that folder, build a structure that mirrors the required Maven structure but only place pom files in it. Make symlinks to the old location.
It is possible to automate this but it takes some work.
I would only recommend this solution while you are in a transition phase while some developers are still building with ant or you are transitioning your code to the new structure in your SCC system.
This question is not really about best practices or architecture, but about how to specifically configure Hudson and Maven to accomplish what I want. I'm a bit lost.
I have a Java application which uses SWT, and I need to build copies for different platforms. For now, all I need is Linux i386 and Linux amd64, but in the future, I need to add Windows x86/x64 as well, so I want to make sure I set it up "right" the first time around.
My application has all of the dependencies and other information listed in the Project pom.xml, including the different SWT jars to grab depending on OS, arch, and family.
My question is, how do I do builds for both linux i386 and linux amd64 with a minimal amount of configuration duplication? Right now I'm doing the following:
Project specifies all dependencies in pom.xml, and this project is set to build in Hudson and deploy the resulting .jar to Nexus
Builder-linux-i386 runs after Project and specifies any JNI files for i386 and uses the de.tarent maven-pkg-plugin to grab the project jar from Nexus and assemble it along with all dependencies into a single 'fat' jar file, and then into a .deb file for installation.
Builder-linux-amd64 does the same, but for amd64 files
I have been trying to specify which dependencies to use in the Builder projects by adding -P profilename to their Hudson projects, where profilename is a profile named in the Project pom. Maven doesn't seem to like this and prints that it is not activating that profile. It only uses the default profile from Project's pom.
What is the correct way to set this up? I want to have all of my dependencies specified in my Project pom, and have a Hudson project which compiles the jar for that project and deploy it to Nexus, and then independent projects which grab that jar and assemble it along with platform-specific files for release. I don't want to build the entire original project repeatedly, and I don't want to have a ton of duplicated configuration info or copy-pasted poms.
I have it working for unix-amd64 only because that's what the build machine is, so Maven targets that architecture. Also, I feel like the setup isn't as clean as it could be. Advice?
You have an syntax error. It needs to be -Pprofilename. It works for me this way.
Edit
Since the profile is read. There might be an syntax error in your profile configuration. I found a profile in one of projects, that I integrate into our CI environment. It defines some dependencies, it might help you.
<profile>
<id>junit</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>false</skip>
<testNGArtifactName>none:none</testNGArtifactName>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
Profiles should work in the way you desciped it (you could post an other question about this).
But at (least for web applications) there is an other way: Try to use classifier instead of profiles to build for different environments. -- You can have a look at this blog: http://blog.jayway.com/2010/01/21/one-artifact-with-multiple-configurations-in-maven/
The purpuse of this solution is, that you are able to build (if you want (controlled by an profile)) for all environments at once.
The builder projects do not see the profiles from the main Project because it is not actually a parent. I cannot define it as a in the builder projects because my projects are not set up that way, and I'm building using variables like ${SVN_REVISION}, which maven does not like.
I have given up and instead copy-pasted the profiles into the 'builder' projects. This isn't the prettiest but for now it works.
I tried to convert a project to a maven one... it has its .java files in other location than /src/main/java , when i run maven install, all the files (.hbm , .xml) except those .class occurs in my jar.
This is build part from pom.xml :
<build>
<resources>
<resource>
<directory>${basedir}/src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
<fork>true</fork>
<compilerVersion>1.5</compilerVersion>
<compilerArguments>
<encoding>UTF-8</encoding>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
Using the above code, .class files are missing from my jar... and no error messages are displayed on console, is it necessary to move them to /src/main/java package structure ?
Also, what could be the reason for this behavior , some missing dependencies ?
I did a change moving them to , src/main/java and i got some exceptions on console , but i am still confused if i "must" add them to this "src/main/java" structure...
Please give me an idea about this...
Thanks
You can configure the source directory to be the same as the resources like this:
<build>
<sourceDirectory>${basedir}/src</sourceDirectory>
<resources>
<resource>
<directory>${basedir}/src</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
</build>
It not strictly necessary - its configurable - but Maven comes with a standardized project layout and it is highly recommended to embrace it, like others Maven conventions (don't fight against Maven, adopt it).
I understood that you are migrating from Ant to Maven but you are IMO not on the right path, bending Maven to make it fit in your existing project structure/workflow is just not the recommended approach:
Maven strongly suggests using its conventions (over configuration) to ease things. Not doing so makes things more complicated and generate useless configuration overhead.
When deviating from the defaults, you're kinda on your own.
Not using defaults might result in bad surprises, some (poorly) implemented plugins might be using hard-coded paths (like src/main/java, target/classes, etc) and won't like changing defaults.
etc, etc, etc.
The recommended way would be to transform your existing structure into a maven compatible modular structure and to adopt the standard Maven layout.
Adopting Maven standards and conventions will just make your Maven life easier in the long run and you get a standardized structure, which Maven is much about.
I think enough people wrote similar advices so I won't insist more. But you should listen to these advices (and not insist trying to make Maven fit in your existing structure), especially since you're new to Maven. From my point of view, you're not migrating from Ant to Maven, you're trying to migrate Maven to an Ant build.
See also
How to convert from Ant to Maven in 5 minutes
Convert Ant Projects into Maven Safely in Five Phases
Have a look at the Super POM. That is the place you get the 'convention' from. You might have to change some settings in your project POM if you have a differnet project layout but it is no good advice as mentioned here before.
By far the easiest solution (if possible in your circumstances) is to move the code to /src/main/java, since that is where maven expects it. It that is not possible, you at least need to tell maven where to find the sources. From your POM I don't see anywhere where you did that.
If you want to use Maven, the path of least resistance is adhering to the Maven conventions. Surely you can have a different source path, but it is definitely more complicated (it seems that the only way is to pass the source directory as a compiler argument), and what do you gain? I believe moving your source directory is much easier.
I have a simple java maven project. One of my classes when executing needs to load an xml configuration file from the classpath. I don't want to package such xml file when producing the jar but I want to include a default xml file in a zip assembly under a conf subfolder and I also want this default xml to be available in the unit tests to test against it.
As I see it there are 2 possible places of this default xml:
src/main/resources/conf/default.xml
src/main/conf/default.xml
Both solutions demand special pom actions:
In solution 1, I get the auto copy to target folder during build which means it is available in testing but I also get it in the produced jar which i don't want.
In solution 2, I get the jar as I want it(free of the xml) but I manually have to copy the xml to the target folder to be available for testing. (I don't want to add src's subfolders in test classpath. I think it is bad practice).
Question: what is the best solution of the two?
- If the correct is 2, what is the best way to copy it to target folder?
- Is there any other solution better and more common than those two?
(I also read Where should I put application configuration files for a Maven project? but I would like to know the most "correct solution" from the "convention over configuration" point of view and this link provides some configuration type solutions but not any convention oriented. Maybe there isn't one but I ask anyway. Also the solutions provided include AntRun plugin and appAssembler plugin and I wonder if I could do it with out them.)
The question is what is the best solution of the two? If the correct is 2, what is the best way to copy it to target folder? Is there any other solution better and more common than those two?
Since you want that file to be copied to the target/classes folder, it has somehow to be considered as a resource (so either put in under src/main/resources or declare src/main/conf as resource directory). And if you don't want it in the final jar, configure the Maven JAR Plugin to exclude it:
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<excludes>
<exclude>**/conf/*</exclude>
</excludes>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
For the assembly part, assembly descriptors are pretty flexible so it should be possible to achieve what you want regardless of the choice. I'd suggest using the easiest setup though.
My solution was to use two profiles: Development (default) and Packaging
My default / section contains both src/main/resources and src/main/conf. I call this my Development profile, which is an implicit profile.
My packaging profile is an explicit profile which is defined under section. There under / I only mentioned src/main/resources. When I'm running my packaging script (we currently have this external to maven since its building an RPM out of our WAR), I'm running 'mvn install -Drpm' to activate my Packaging profile (rpm is the id for the Packaging profile.
If this wasn't clear enough, feel free to ask more questions.
You could place it in src/test/conf/default.xml. Your testclasses can find it, but it wont be packaged using the standard method.
With an additional assembly you can package it from there. That step is always necessary.
A different solution could be to create a separate maven module and place it in /src/main/resources/conf/... .Then make this jar a test dependency. You do not need to do any special plugin configuration, but I think it is overkill for a single file.
If your packaging is war, you can use the packagingExcudes configuration option of the maven-war-plugin:
<project>
...
<build>
<plugins>
...
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<!-- Exclude abc.properties found in src/main/resources/ (ends up getting packaged in WEB-INF/classes/) -->
<packagingExcludes>
WEB-INF/classes/abc.properties
</packagingExcludes>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
Use commas to separate between multiple resources you want to exclude. Also, you can use wildcards and regex in your excluded paths. For regex, it's in the %regex[YOUR_REGEX_HERE] syntax. Check the documentation for more details.
Here is an example profile in my POM:
<profiles>
<profile>
<id>QA</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<jdbc.url>jdbc:mysql://127.0.0.1:3306/SomeDB</jdbc.url>
<jdbc.username>webapp</jdbc.username>
<jdbc.password>somepassword</jdbc.password>
</properties>
</profile>
...
I then have a properties file in my resources folder like this:
jdbc.url = ${jdbc.url}
jdbc.username = ${jdbc.username}
jdbc.password = ${jdbc.password}
and finally I turn filtering on in my POM:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
...
This is actually a simplified example, but you get the idea. Basically when I run
mvn install -P QA
Maven will filter my app.properties file, replace all the placeholders with the values held in the profile, and deploy the populated properties file.
The problem with all of this is that I like to utilize the Servers mechanism in Eclipse, where I have Tomcat running within the IDE. My projects runs in this instance, and Eclipse takes care of updating, redeploying, etc. Maven is left out of the picture, however, during deployments within the IDE and this properties file never gets populated properly.
So, how can I continue running my project within the IDE, but have this properties file properly populated?
You can effectively run any Maven command (including ones with profiles) through the m2eclipse plugin. Also, m2eclipse works with WTP (which I believe is where the Servers tab comes from). I'm not certain on this part, but I've used it to deploy web apps to Tomcat within Eclipse for a Maven project.
Thanks Alex. I ended up installing Eclipse Integration for Apache Maven (Eclipse IAM), formerly Q for Eclipse
This plugin solved two problems: populating properties files during Publish to Server events in Eclipse and populating the WEB-INF/lib folder. Before, even though I was running mvn eclipse:eclipse to satisfy my Build Path in Eclipse, it was not publishing these dependencies to the embedded servers correctly. This plugin does that. Having solved these two issues, I don't see any other barriers to developing a Maven project in Eclipse using the embedded servers.