Here is the context : one application, let's name it "clientdata" is bundle into an ear to be deploy on WebSphere. We need to generate several jar for this application :
api-contract (interfaces)
ejb
ejb-client
impl
The ear contains ejb, impl and api-contract jar + the application dependencies
Let's call "checkclient" another application which need to call "clientdata" by RMI.
It will need to use api-contract and ejb-client jar.
For now the application is divided into 3 sub-modules (API, IMPL and EJB).
API module generate api-contract jar
IMPL module generate impl jar and use api-contract jar
EJB module generate ejb and ejb-client and use impl and api-contract jar
So here is my question : one member of the team thinks that we should use maven classifier plugin to generate all those jar so that we need but to maintain only one pom (one maven project).
I'm not so familiar with maven classifier plugin so i wanted to know, is this a good idea ?
Some of my readings make me think it is not, mostly because it violate a "core convention" and "Tools that have been designed to work with Maven won’t help you"
Here is the source of the citations : http://blog.sonatype.com/2010/01/how-to-create-two-jars-from-one-project-and-why-you-shouldnt/#.U7UhNCgucvQ
I would greatly appreciate your expertise on the subject.
Regards, GBE.
First the member of your team is simply wrong, cause that's the wrong way to deal with such default scenario in Maven. I assume (hope) you have created an appropriate folder structure
+-- root (pom.xml)
+-- mod-api (pom.xml)
+-- mod-ejb (pom.xml)
+-- mod-impl (pom.xml)
+-- mod-ear (pom.xml)
Based on the above folder structure you can simply define dependencies between the modules and let maven do the rest. Apart from that you can create the ejb-client automatically by maven-ejb-plugin and use this for furthere enhancements.
Now you can create an ear from it (mod-ear just add the dependencies to it) and just deploy it to WebSphere. That the way it should go. Creating a single pom to create that number of artifacts is by definition against the desing of Maven cause the convention in Maven is to have a single pom for an artifact. So you will start to fight against Maven and you will loose that combat.
Better got with the idea of Maven and make your life easier. Apart from that it's a separation of concern which means an single pom for a single part of the project which makes it clear where you can find anything in your project. Here is a simple example of a Java EE application.
Related
New to maven here...coming from the ant world
I need to create a client jar with a few files that will give my client the ability to write to my Db and make rest calls to my services.
These are mainly classes that wrap a Rest connection and db client.
Is it possible to produce this artifact as a side effect of my main maven project ?
Eg: main project produces a bundle when I run mvn package, but I'd like to produce the client jar by providing some other parameters....
What you need here is a multi-module maven project.
The structure goes like this:
-- Parent Module
----- Child 1 Module
----- Child 2 module
Here you can have all your code/files of your main app in child 1 module and put all the code/files for the client in the child 2 module.
The parent module is just an aggregator which produces an artifact of type pom. Whereas each of your child modules will produce individual jars.
You can then you the second jar in your client.
For a detailed understanding how multi-module project works, check this link.
The standard Maven way is "one project, one jar". This means that the cleanest way to achieve your goal is to set up a multi-module project where you have one module for your "normal" jar and one for your "client" jar. But there are other possibilities:
If you are talking about an ejb, you can use the maven-ejb-plugin and create a client artifact. Unfortunately, both artifacts then share the same pom (and, therefore, the same dependencies).
You can use the maven-assembly-plugin to assemble a set of files and deploy them as side artifact (same problem as in (1)).
You can use the maven-install-plugin and maven-deploy-plugin to install/deploy entirely different artifacts along with your main artifact. These artifacts need to be created before, e.g. by a custom maven plugin.
I have a Maven based J2EE project structure
Customer (root pom)
|
|------ WebTier (JSF 2/Primefaces)
|
|------ BusinessTier (EJB 3.*, interfaces, interface impl)
|
|------ PersistenceTier (JPA 2)
|
|------ CustomerEar
Now I have found that I'd need a new Java class or classes for handling basic routines
I guess its not good idea to place this Utility class under WebTier, because Utilities might be used also from BusinessTier.
Is it the "best practise" to create an independent Java Project, implement necessary classes and include this jar to the ear??
based on my experience , i recommend to have separate project folder for utility and include this as jar where ever is required
advantages are
easy maintenance, since you need to change code once .
plugin & unplug when ever you need.
you can have this as common and utilize for
other projects.
for instance
apache string util
http://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html
bean util
http://commons.apache.org/proper/commons-beanutils/
It would be hard to try and justify a "best practice" in this kind of situation as it is a very project-specific question.
There would be nothing inherently wrong with adding a "CommonLibrary" project or such-like that is a dependency of both the WebTier and BusinessTier. In fact the project I am working on now is almost exactly that structure (with a common library).
As this is a maven project, just make sure the "CommonLibrary" project dependecy scope is set to "provided" in the Business/Web/Persistence tiers, and "compile" in the ear project.
e.g. In WebTier, the dependency would be:
<dependency>
<groupID>group.name</groupID>
<artifactID>common-library</artifactID>
<scope>provided</scope>
</dependency>
EDIT: The scope would be 'provided' in the Web Tier as it would be a .war. The other tiers would be jars so the scope can be 'compile' for the persistence and business tiers.
I've stumbled across maven topic skinnyWars at http://maven.apache.org/plugins/maven-ear-plugin/examples/skinny-wars.html. As described, I can use this method to move selected dependencies from WAR module to EAR module. They will be available for all other WAR modules located in EAR.
As I have discovered the dependencies which are moved must be declared in EAR module and have to be included in META-INF\lib catalog. That does not apply for EJB modules, which are located in root catalog of EAR module.
My question is how to remove duplicated EJB modules from WARs and point the reference to those located in EAR file?
The structure right now is like this:
\-EAR
-ejb.jar
-META-INF\lib
-shared libraries
-web.war
-WEB-INF\lib
-ejb.jar
-other non-shared libraries
I've answered a similar question: How to make maven place all jars common to wars inside the same EAR to EAR root?
Unfortunately this doesn't seem to work for ejb modules. They'll get duplicated as you have already mentioned.
One thing you can additionally use is a configuration for the maven-war-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
<configuration>
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
</configuration>
</plugin>
This will completly erase everything from the WAR's lib folder but it can also have its drawbacks in cases where you have to deploy the WAR additionally itself on a separate machine without the surrounding EAR.
The problem here is that it is not the same to reference an EJB from the ear module which will be used to deploy it into the server than to reference it from a client which needs the EJB classes to interface with the server.
If you include the dependency in an ear module, it will consider you are declaring an EJB module to be deployed. It will place it in the root of the EAR and declare it in application.xml.
If you include the dependency, for example, in a war module, you will get exactly the same artifact, but it will be considered as a library and placed in WEB-INF/lib.
Now, when you are generating the skinny wars, the explicit dependency to the ejb module does not match the dependency in the WAR, as Maven does not consider them to be the same thing. This results in the JAR being kept in the WAR/s which use it.
The only solution I know is to always generate a client artifact for the ejb module, even if the client artifact will be identical to the main artifact.
Now, you only use a <type>ejb</type> dependency in the EAR. For clients, you always use a <type>ejb-client</type> one.
To remove the client from the WAR/s and locate it in the lib directory of the EAR, you have to explicitly add the dependency to the ear module.
So, you will have two dependencies to the ejb module in your ear module: one to the ejb itself and one to the client. The first one will place the EJB in the root of the EAR and declare it in application.xml. The second one will place the client in the lib directory of the EAR and update WAR/s manifest/s, if necessary.
But if client and main artifacts are identical, you get it duplicated?
The short answer is yes. The long answer is yes. It does get duplicated, but only once, and not in every WAR using it. I don't think there is a clean way to avoid this and I'm not sure it makes sense conceptually. You could, of course, use packagingExcludes and customise manifests, but it makes sense to have the JAR twice.
If your client JAR is really thinner (for example, only the interfaces) having the WAR/s reference the client JAR effectively disallows them to access to EJB implementations, which is always a good idea.
You can consider the identical JAR's as a special case of the previous one and it makes conceptual sense to keep them separate.
So, my recommendation is to always generate a client artifact for the ejb and proceed as explained. There are always things you can exclude from it, be at the very least any unneeded non-class files such as package.html or ejb-jar.xml.
I have a maven web-service project consisting of two different service classes testClass1 and testClass2 . I want to have two different WAR files for both classes of same project. Presently I am generating single WAR file for both services .
How can I generate two different WAR file for same project ?
Thanks In Advance.
General Considerations
As per doc says, what you try to achieve is a bad pratice :
Producing Multiple Unique JARs from a Single Source Directory
As many people that complain about not being able to spread out their sources into multiple source directories seem to complain about not wanting to spread anything out, producing several unique artifacts from a single directory using includes and excludes.
Why isn't this recommended?
This practice can be confusing and risky.
You may end up building two JARs that include the same classes - this indicates that the common functionality should have been abstracted into a separate dependency.
You may end up introducing a dependency between the two JARs that you didn't realise, and often a circular dependency. This indicates that the classes are in the wrong JAR, or perhaps that everything should just be a single JAR.
Solutions that fit the maven best pratices
You should consider splitting you project into two differents ones, having each one a pom, and so each one generating an artifact, here a war.
Two simples projects
You may achieve that by using either two simple projects :
service1-simple-webproject
|-- src
`-- pom.xml
service2-simple-webproject
|-- src
`-- pom.xml
This is quite simple, but you may not be able tho share easily properties / dependencies / relations between them.
Just split your own code into separates directory, and try to make it work as two independant projects.
If you think that there is some code to share between them (utilities, configuration, ...), see next section about multi module.
Multi module structure
Or you can use an appopriate multi-module hierarchy :
parent-multimodule-project
|-- service1-simple-webmodule
| |-- src/
| `-- pom.xml
|-- service2-simple-webmodule
| |-- src
| `-- pom.xml
`-- pom.xml
This will allow you to have relations between projects, share configuration at a higher level, ...
Ta ke a look to this documentation :
Maven Official doc : http://maven.apache.org/guides/mini/guide-multiple-modules.html
Sonatype fantastic doc : http://www.sonatype.com/books/mvnex-book/reference/multimodule.html
I will probably lead you to create a third project, probably named core, or util, that would produce a jar which will contains common classes to both web project.
This is really the best way !
Functionnal solutions but strongly not advised ones
I would only give you some information, because I'm even sure it could work in this case.
Maven Assembly Plugin allow you to generate different format of package (zip, jar, war, other, ...) based on xml description files.
Here documentation : http://maven.apache.org/plugins/maven-assembly-plugin/
Once again, I strongly advise you to NOT use this kind of workaround.
My question has been asked before, which I know, but I think that I am trying to do something slightly different, where existing answers are not appropriate.
Essentially, I do want to have multiple projects in Eclipse that will be built (preferably) into one final WAR file. Ideally like this:
root - pom.xml
|___ java-app
|___ web-service-v1
|___ web-service-v2
|___ web-service-v3
|___ rest-service
|___ batch-service
Imagine the Java App as the actual application, and each additional component runs as a decoupled view layer for the Java App itself. Ultimately, the Java application will be running in a tomcat instance, with the different modules providing their services. I would like all the different modules also to run in the same Spring container.
I don't know that running in Maven modules is the best way of doing this, but I would really prefer to have each component in a separate Eclipse project that ultimately get built together.
Can anyone provide any suggestions as to how I would use Maven to build this?
Just make a separate war module:
root - pom.xml (packaging: pom!!!)
|___ java-app
|___ web-service-v1
..
+--- mod-war (pom.xml)
and put the dependencies of the modules you would like to have added to the war file into the pom and that's it.
The main Maven idea is that each module must produce a single build artifact (e.g. a jar or a war file). The parent pom is usually responsible for global configuration and dependency management and also for a proper module orchestration. If your final result need to be a WAR file, then last module in the list will be the web application. The other modules could supply classes that war file depend on.
There are more complicated build structures, but above one should be sufficient for you.
This is somewhat dated, but hope this additional info helps someone.
#Mouscellaneous An example of keeping Spring configs in each module and referencing them from the web.xml can be found here in the Sonatype book. I guess this is what you are looking for.