I'm participating in an open source project (ps3mediaserver) which has been moved from google code (SVN) and ANT (for build tasks) to git (GitHub) and maven. I've got my own fork (called pms-mlx), where I'd like to maintain some plugins being part of the default packaging when releasing. I'm pretty new to maven and am not too sure how the project should be structured to respect the maven way.
I'll start by describing how the environment behaved previously and will then give the thoughts about the move to maven.
Links:
Old: SVN + ANT ps3mediaserver project on google code
Old: SVN + ANT pms-mlx project on SourceForge
New: Git + Maven ps3mediaserver project on GitHub
New: Git + Maven pms-mlx project on GitHub
Old behavior:
Project structure:
+--workspace
+--plugins
+--plugin1
build.xml
+--plugin2
build.xml
+--ps3mediaserver_mlx
+--plugins
build.xml
The main project is ps3mediaserver_mlx, all plugins live in sub-folders of the workspace/plugins folder.
ps3mediaserver_mlx/build.xml contains a target BuildWithoutLibs which will build the jar of the main project and copy it to workspace/pms_no_libs.jar which will then be referenced (at this location) by the plugins.
When executing the build target of any plugin, the plugin will be build and the resulting jar copied to ps3mediaserver_mlx/plugins/[plugin_name].jar.
And finally, when packaging the application using the the build target in ps3mediaserver_mlx/build.xml, the plugins containedin workspace/ps3mediaserver_mlx/plugins will be packaged (in a exe installer for windows, dmg for OSX or tar.gz for linux).
New behavior
The project structure has been changed to this:
+-- workspace/
+-- pom.xml (global-pom)
+-- ps3mediaserver/
| +-- pom.xml (pms-pom)
| +-- src/
| ...
+-- plugins/
| +-- pom.xml (plugins-pom)
| +-- Plugin1/
| pom.xml (plugin1-pom)
| src/
| +-- Plugin2/
| pom.xml (plugin2-pom)
| src/
+-- pms-package/
+-- pom.xml (package-pom)
+-- src/main/assembly/
+-- src/main/external-resources/
Responsabilities:
global-pom The root pom containing all dependencies used by pms. This lets use the same version without redeclaring them in any plugin (is this a good idea?). Builds everything and contains a modules section to perform the same maven commands on all projects
<modules>
<module>ps3mediaserver</module>
<module>plugins</module>
<module>pms-package</module>
</modules>
pms-pom: Inherits from global-pom andbuilds the pms jar
plugins-pom: Inherits from global-pom; contains a depency for pms (which will be required for all plugins); contains a list of all modules having to be built
pluginX-pom: Inherits from plugins-pom and contains a custom configuration for a plugin
package-pom: Is responsible to package pms according to the platform it is being built on.
Does this structure represent the way maven is ment to be used?
Everything is working up to the packaging. This means the main application jar as well as all the plugins have been built and need to be packaged. The package-pom is responsible to do that.
In the original application there is only one pom.xml and the packaging is being done by using different profiles for Windows, Linux and OS X. The one I'm currently working on is for OSX and uses osxappbundle-maven-plugin, but the source code is never being packaged in the app file. That's because the packaging project doesn't inherit from the actual project anymore.
How has the built jar to be referenced in order to be packaged correctly in the app file?
I've tried referencing the jar in additionalResources and as custom class path, but never with success.
You have defined a dependency for example in the plugins/pom.xml
<dependencies>
<dependency>
<groupId>net.pms</groupId>
<artifactId>pms-mlx</artifactId>
<version>1.52.1_mlx_v0.8-SNAPSHOT</version>
</dependency>
</dependencies>
which exactly represents your parent. In other words it's wrong to define a dependency which already been defined as your parent.
It's good practice to put the modelVersion tag directly after the project tag and before the parent tag. After the parent tag put the information the current module like artifactId.
After diving into the project i noticed that you defined in your of your plugins/WebservicePlugin:
<modelVersion>4.0.0</modelVersion>
<artifactId>WebservicePlugin</artifactId>
<version>3-SNAPSHOT</version>
<packaging>jar</packaging>
<parent>
<groupId>net.pms</groupId>
<artifactId>pms-plugins</artifactId>
<version>1.52.1_mlx_v0.8-SNAPSHOT</version>
</parent>
which is against the maven way for multi-module builds. You should not define a different version in this case. It should look like this:
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>net.pms</groupId>
<artifactId>pms-plugins</artifactId>
<version>1.52.1_mlx_v0.8-SNAPSHOT</version>
</parent>
<artifactId>WebservicePlugin</artifactId>
If you have problems based on the version of the WebservicePlugin module than you should think about separating the WebservicePlugin from the rest (may be the other plugins as well).
One other things which i have noticed that you defined in many of the plugins (if not all of them) the configuration and the usage of the maven-compiler-plugin...This should be done by using a pluginManagement part in your root pom...to simplyfy maintenance of your project.
The copying of the created plugins-jars via the maven-antrun plugin into a different location whould be done different.
Repeating the license entry in every plugin is not needed cause it's inherited by the parent.
Related
I'm working on a project, which originally was set up by a different author. Each module has its own directory. Also the main pom (my-project-pom), which includes the modules, is stored in a separate sub-directory. We're using subversion:
+-- branches
+-- tags
'-- trunk
+-- my-project-pom
+-- my-project-web
+-- my-project-ear
'-- README
Now I'm trying to setup the maven release plugin with following goals:
Everything is included in the commit from maven release, also changes in the root README file
SVN tags are automatically created in the proper repository directory tags\<version>
So my questions are:
Is this possible at all, although the main pom is not in the root directory?
How should I configure the <connection> and <developerConnection> URLs in my-project-pom to achieve this? Do I have to point directly to the trunk or to trunk\my-project-pom or something different
Is there any other configuration required besides the <scm> configuration above and the definition of the plugin dependency - e.g. the tagBase setting?
In which directory do I have to execute the mvn release commands?
I'm facing the problem with setting up a development environment with Maven and OSGi dependencies in Intellij.
At the beginning, a few words about how it looks like.
Everything is built on top of the Maven build. The whole hierarchy is already set up and I don't have any problems with building the project. It consists of many small submodules:
<modules>
<module>com.modulea</module>
<module>com.moduleb</module>
<modules>
Those modules use OSGi internally so everything might be presented with the following tree:
PARENT (pom.xml)
|----- Module A (pom.xml)
|----- META-INF
|----- MANIFEST.MF
|----- Export-bundle: com.modulea
|----- Module B (pom.xml)
|----- META-INF
|----- MANIFEST.MF
|----- Require-bundle: com.modulea
|----- src
...
|----- ModuleAClass (uses classes from com.modulea bundle)
The problem is connected with importing the project into IntelliJ. I imported it as a Maven project with checkboxes selected:
Create IntelliJ IDEA modules for aggregator projects (with 'pom' packaging)
Create module groups for multi-module Maven projects
IntelliJ created project's submodules basing on maven configurations but...
dependencies of those modules are set to libraries (Maven p2.eclipse-plugin). Is there any way to force it to use project's submodules? Of course, it is possible to do it manually (Project Settings -> Dependencies -> + -> Module dependency) but there are too many dependencies and submodules to repeat it every now and then again.
Additionally, if I have dependencies configured (library dependencies), OSMORC plugin is not able to resolve OSGi dependencies/configuration. For each of classes from an external bundle I got a message:
The package 'com.modulea' is not imported in the manifest less... (Ctrl+F1)
I have a maven project which currently creates a war package on build. Now I need to bundle it as an ear project. Any pointers on how to do this. I added the m2e plugin and modified the pom.xml file, but, i am not able to get the directory structure as expected. I need the dir structure as below
project-name
- project-name.ear
- pom.xml
- project-name.war
- projec-name.jar
- META-INF/application.xml
Thanks.
It is strongly recommend that you organize your project structure in proper Maven style:
project-name/
- pom.xml (POM of project-name, multi-module POM)
+ project-name-jar
- pom.xml (main app JAR)
+ project-name-web
- pom.xml (WAR project to construct WAR by project-name-jar etc)
+ project-name-ear
- pom.xml (EAR project to construct EAR by project-name-war etc)
Normally I will have another child project call project-name-parent which use as parent POM for the whole project.
In Maven, you don't and you shouldn't have META-INF/application.xml as part of your source. It is generated dynamically base on configuration of maven-ear-plugin.
In svn repository I have a folder 'product' under which are all my Eclipse plugins and features, parallel to these there is parent POM. This setup works well when I build in Jenkins, I just check out 'product' and install pom.xml. However, I can't figure out how this setup works in Eclipse workspace? I can't check out pom.xml by itself into workspace, and if I do I need to check it out as single file under a project which brakes path to parent POM. How should I check out and build in such setup?
Also, do I need to define relativePath of parent POM in my plugins? I found that if I omit it, then I get error about path being missing.
Just to summarize, my svn repository structure is this:
repo/
trunk/
product <- maven project (folder with .project set as maven nature)
pluginA
pluginB
featureA
pom.xml
.project
I think you have two options:
Deploy your parent POM to a locally available repository, perhaps your company Nexus server, for example? This will then be available to all products and for all your colleagues.
Restructure your project to look more Maven-like, e.g.
|-- plugin1
|-- pom.xml
|-- ....
|-- plugin2...
|-- feature1...
|-- ...
pom.xml <-- parent POM
This second option may be better in the long term, otherwise your Jenkins server relies on you remembering to locally install the updated parent POM, rather than just plucking it from svn.
If you use m2eclipse (e.g. available from the Juno site), you can import any Maven project structure into Eclipse. In your case, the product folder would be imported as an Eclipse project, as well as the individual features and bundles.
<relativePath> defaults to .., so you need to specify it if the parent POM is not in the parent folder. You can set it to undefined (e.g. through an empty <relativePath/> tag) if the parent POM is not available locally. In this case, Maven will always resolve the parent POM from the local Maven repository or the configured remote (Maven) repositories.
I currently have about 16 projects that I build with maven that get deployed to the same application server that make up something like a "portal". I have built a parent pom to handle common dependencies and plugin configurations. Currently, my SVN structure looks similar to this:
portal_root
+project1
+tags
+branches
+trunk
+project2
.
.
.
+projectn
pom.xml
The individual projects are each separately deployed. That is, project1 doesn't have a dependency on project2 and each can be modified and deployed without having to modify anything else.
This presents a problem with SVN as if another developer wanted to check out the entire "portal" root (to also get the parent pom) they would also by default pull down copies of all the tags and branches! Not really ideal.
The only other thing I can think of is to use something like this:
portal_root
+tags
+branches
+trunk
+project1
+src
pom.xml
+project2
.
.
.
pom.xml
However, now all project changes will be tracked in the tags folder. This isn't a huge problem for me, but branching now seems to become a pain.
I am also currently working on hooking up Teamcity into this as well which would be a bit easier now, since I would only have to watch a single directory (e.g. tags) to catch everything that needs to be built. I am also deploying artifacts to a enterprise Nessus repository.
I'm hoping someone could give me some suggestions here as I have been unable to find any decent documentation that talks about the entire build lifecycle and best practices here.
I like the idea of being able to build and deploy all the projects with a single maven command. I also like having all the common dependencies, repository information and plugin information in one place.
You can use following layout:
+parent-project
pom.xml
+child-project-1
pom.xml
+child-project-2
pom.xml
In parent project pom add:
<modules>
<module>../child-project-1</module>
<module>../child-project-2</module>
</modules>
In children projects pom add:
<parent>
<artifactId><!-- parent artifactId --></artifactId>
<groupId><!-- parent groupdId --></groupId>
<version><!-- parent version --></version>
<relativePath>../parent-project</relativePath>
</parent>
Children Projects can optionally be dependent.
Following links may also help:
http://maven.apache.org/guides/introduction/introduction-to-the-pom.html
Maven parent pom vs modules pom
A variation to JohnS's approach would be to use svn:externals to hook appropriate trunk/tags/branches of your subprojects to the appropriate trunk/tag/branch of your parent project. In this way checking out one variant of your parent would pull out all the right version of the other projects.
This makes sense only if it's reasonable to checkout all your projects together.