Maven: Combine web projects - maven-2

I have following Maven projects set up:
PM-Core
PM-Web (with a dependency to PM-Core)
Now, this project is used for several clients but for each client there are some small differences: mostly differences in configuration files but some clients also require additional java files (which may not be installed for the other clients).
I've been considering several alternatives on how to support this with maven but am still looking for the perfect solution.
The best solution I can think of is to create a separate maven project for each client (e.g. PM-CLIENT1, ...) which contains only the client specific configuration files and additional java files or jsp's, ... . Next step would be to consider the PM-Web project and the client project as one web project, meaning: have them combined (packaged) into 1 war file with files from the client project having precedence over files from the PM-Web project.
More concrete: running mvn package on PM-Client1 would take everything from PM-Web, add/replace the files from PM-Client1 and then package this into a single war.
So the question is: how to achieve this with maven?

Yes, this can be done using Overlays. The sample on the webpage is exactly what you are talking about.
For the project structure, you could have something like this:
.
|-- PM-Core
|-- PM-WebCommon (of type war, depends on core)
|-- PM-Client1 (of type war, depends on webcommon)
`-- PM-Client2 (of type war, depends on webcommon)
And use overlay in PM-Client1 and PM-Client2 to "merge" them with PM-WebCommon and package wars for each client.
UPDATE I won't cover all the details but I think that declaring the war dependency with a scope of type runtime is required when using overlay, this is how overlay do work (actually, the whole overlay thing is a kind of hack). Now, to solve your eclipse issue, one solution would be to create a JAR containing the classes of the PM-WebCommon project. To do so, use the attachClasses optional parameter and set it to true. This will tell maven to create a PM-WebCommon-<version>-classes.jar that you'll then be able to declare as dependency in PM-Client1 (with a provided scope). For the details, have a look at MWAR-73 and MWAR-131. This is also discussed in the FAQ of the war plugin. Note that this is not a recommended practice, the right way would be to move the classes to a separate module (and this is the other solution I wanted to mention).
UPDATE (201001018): I've tried the attachClasses parameter and it works with version 2.1-beta-1 of the plugin.

You could use profiles see http://maven.apache.org/guides/mini/guide-building-for-different-environments.html and use classifiers to distinguish between the artifacts from the different builds for the same version.
In this setup, you could create additional optional modules for each of your clients specific customisations under the parent project i.e.
+ PM
++ PM-Core
++ PM-Web
++ PM-Client1
++ PM-Client2
Or you could look at using use the maven assembly plugin

Compare also the answers for question different WAR files, shared resources .

Related

JBoss 7 : fluff or a real good application server?

I am asking this especially, because JBoss AS 7+ has completely changed 360 degrees, enforcing the application developer to think completely in terms of JBoss Modules. That prevents earlier classpath-hell issues etc and encourages clean modular thinking etc. Also it claims a quick startup time etc.
All that is fine BUT my major concerns are thus, please confirm if you feel the same :
JBoss insists to put the jboss-deployment-structure.xml file inside WEB-INF. This would make the WAR file not portable at all since now it contains app server specific configuration files inside it. I am worried about inter-operability.
I am still nervous about the enormous amount of XML configuration needed - Create a module directory structure for each dependency you would like to add, create a module.xml for that dependency, create a jboss-deployment-structure.xml entries for non-modules or Manifest entries for libs inside WEB-INF/lib. etc etc.
That would require enough developer time and effort being spent towards being an configuration expert or hire an expert or buy the support - a significant cost in the long run for any team and company.
There is nothing about jboss-deployment-structure.xml that makes it non-portable. Other application servers will simply ignore the file if they don't use it.
You do not need to create a module if you want to use a dependency in your application. You would only do that if you want to use a common dependency among several deployments. For example a JDBC driver library.
There is no need to create a jboss-deployment-structure.xml or add manifest entries for libraries in WEB-INF/lib. The only time you would need a jboss-deployment-structure.xml is if you want to exclude server dependencies, like log4j, or add dependencies outside the scope of your deployment that are not automatically added. There are probably some other use cases, but those are the most common.

Maven2: Possible to deploy depends on artifact classifier?

In fact I have 2 different problems, but I think they are kind of related:
I have an artifact, with an assembly descriptor set which will build an extra JAR (with extra classifier). By default, Maven2/3 will deploy the assembly generated together with the main artifact to remove Maven repository. Is there any way that I can deploy only the main artifact but not the assembly?
I have an artifact, in which I have jar plugin generate another artifact with different classifier (more specific, an EJB artifact, and I generate an client JAR). I want to deploy only the client JAR to Maven repo coz I think the main EJB artifact is not really going to be shared by other project. Is it possible to do so?
Thanks a lot
editied to provide more info:
The reason for avoiding deploy the EJB, is because the EJB main artifact is not going to be depended by other project except the containing project. The containing project will build a EAR (which contains the EJB), and normally we only need that build locally (by mvn package). However, the EJB client is something that we will deploy to our repo to let other project share when they need to communicate with our application.
Honestly it doesn't harm to deploy the EJB too, but I just want to see if I can save unnecessary waste of disk space on our repository.
Similarly, for deploying assembly, it is because the project is something we want to deploy to let other project to depends on. However, when building that project, we also have a separate assembly created on the same time (for example, an all-in-one executable jar) which we only need that built locally, and it is not something that other projects will depends on.
Turn off the 'attach' option to the assembly plugin. Then it won't be officially an artifact and it won't deploy; it will just lurk in the target directory, sulking that you don't love it as much as it's elder sibling and plot revenge.
Based on your first question i would like to know why do you create the supplemental assembly which is usually deployed as well as the main artifact. If you wan't to prevent you can put the creation of the assembly into a profile but this means you will not generate the supplemental artifact in your usual build only by activating the profile.

Setting up a standard directory layout using Maven

I'm new to Maven and have skimmed over the documentation as I am following the Hibernate tutorial at http://docs.jboss.org/hibernate/stable/core/reference/en/html_single/#tutorial-firstapp-mvn.
I have installed Maven and successfully setup a web-app but this does not contain all of the standard directories mentioned in the tutorial. Am I going mad?
When building my Maven project I am using the maven-archetype-webapp. This gives me the arh-webapp\src\main\resources and arh-webapp\src\main\webapp directories but I'm missing quite a few directories mentioned on the link http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html.
Surely I don't have to manually add these? If not then the Hibernate documentation does not mention what archetype to use in order to achieve the directory structure used in their tutorial. Please can someone enlighten me.
What archetype do I need to use in order to have the above directory plus the src/main/java directory? If there is no such archetype then can easily append these using Maven? and how?
Surely you'll have to manually add these.
Just create those directories that according to the Maven convention are missing. Remember, a Maven Archetype is just a starting point to save you time configuring your workspace. After encountering many problems in some Archetypes myself I've been accustomed to just use a basic-web-app-archetype and then customize it myself, as a beginner with Maven you'll be better off doing that, and will learn a lot.
Regards.
Not all the directories mentioned are required for your standard web application. In fact, the reason behind the presence of the src/main/java, src/main/resources and the src/main/webapp directories is due to the archetype that you've used.
IMHO, the book titled "Better Builds with Maven" will serve you better; the Sonatype books on Maven might also help. The complete Maven documentation is also available as a PDF file, for future reference.
But just in case, you need some clarity on the terms used, here's some:
Archetype: A pattern for projects. Simple web applications (with no dependencies on other frameworks/libraries) have their own archetypes, so do applications using Spring, Hibernate, Seam, etc. Some archetypes will result in creation of different directories, as they are coded that way. You might be able to change the directory structures in most cases, although I cannot vouch for every archetype. For instance, it is quite possible to place your sources in 'src' instead of 'src/main/java', although this requires additional configuration in the POM.
Lifecycles, Phases and Goals: A Maven build lifecycle is a series of phases, with each phase executing a set of goals. Maven can be commanded to execute a build phase, which results in execution of all phases until and including the specified phase.
Maven plugins: Maven plugins contain one or more goals. Goals need not be bound to phases, but usually you would bind them to particular phases. Plugins are the basis for everything operational in Maven; you're using plugins even though you are just compiling the application (the Maven compiler plugin is a core plugin that is present in the Maven distribution).
I hope the above helps, but I would suggest that the reference books be followed.

What are some Maven project naming conventions for web application module?

When creating a project with the webapp archetype in Maven, they subtly advise not putting any Java source in the webapp project by not including the "src/main/java" folder.
What do you name your Maven projects?
project-webapp for the project that contains the JSP, CSS, Images, etc.
project for the project that contains domain specific entities
? for the project that contains the web application files like Servlets, Listeners, etc.
My first inclination would be to use "webapp" for the project containing the web application files (Servlets/Listeners), however the archetype uses "webapp" to convey the JSP/CSS/Images project and would cause confusion to other developers.
When creating a project with the webapp archetype in Maven, they subtly advise not putting any Java source in the webapp project by not including the "src/main/java" folder.
That's not really true. When you create a project with the maven-archetype-quickstart, you don't get a src/main/resources directory. Would that mean you should not put resources in this project? No.
What do you name your Maven projects?
There is no general rules, nor conventions. Use something that makes sense for your organization and your team. But as I said above, your initial assumption is not true and putting Java code inside a maven war module is a common practice (except for code you want to share between modules).
Not sure if this below link directly answers your question, but it makes sense to refer it
Refer their JIRA task here Document the naming convention for archetypes
As per this, the naming convention can be as below
The Artifact id of the archetype should be of the format -archetype-
Ex: + maven-archetype-quickstart : Which indicates the archetype is from maven and the project is a quick start
Same way you scala-archetype-simple : Which indicates it is from scala and is a simple scala project
Best of luck

Is it possible to build a zip-distribution that would contain a jar-with-dependencies?

I would like to produce a binary zip distribution of my project that would contain an uber jar and a set of scripts. Right now, I am using two descritors, first one for the uber jar, and the second for the zip that contains the uberjar + extra scripts and documentation. The problem is that both of these get deployed to maven repo, while I don't actually need the uberjar, only the distro. Is there any way to either:
create the distro using one descriptor or
avoid the uberjar being deployed?
Edit: I found this question regarding part 2, but perhaps there is an easier way to do it...
In my opinion, the easiest way is to create the uberjar in one module (set the skip optional parameter in the maven-deploy-plugin configuration to bypass it during deploy) and to create the zip distribution in another module (using a dependency on the previously created assembly as described in Assembling Assemblies via Assembly Dependencies). And that's very close to what you already have which is good news.