How does Maven handle WAR dependencies at compile time? - rest

I'm using Maven 3 to handle a (large) project. This project defines a set of REST services, using Scala, Akka and the Spray framework. Each service is defined as an independent project, producing a WAR thanks to the "mvn package" command.
I have to "assemble" these different services into a "system", that is, a subset of these services to be deployed for a given purpose, in a single WAR. Maven WAR overlay works good as a first impression: simply create a new project, and add the services to be included as dependencies.
<dependencies>
<dependency>
<groupId>net.modelbased.sensapp.service</groupId>
<artifactId>net.modelbased.sensapp.service.metamodel.repository</artifactId>
<version>0.0.1</version>
<type>war</type>
</dependency>
</dependencies>
It works well, and the classes contained in the independent services are included in the final WAR.
jar tf target/net.modelbased.sensapp.system.envision-0.0.1-SNAPSHOT.war
[...]
WEB-INF/classes/net/modelbased/sensapp/service/metamodel/repository/ModelLister.class
[...]
But ... The Spray framework requires the implementation of a bootstrap, that is, a class that load the implemented services. This file has to be compiled, as it is a plain scala class. But it looks like maven did not includes the WAR dependencies in the compilation classpath.
I saw the WARpath plugin (http://static.appfuse.org/maven-warpath-plugin/) ... But It does not look more or less outdated. Is there a "standard" way of doing what I'd like to do (i.e., include a WAr in the compilation classpath).
Ps. One of the requirement of the project is that each service MUST be deployable as an independent artifact. A solution could be to implement the core of the service as a JAR project, and also provide a WAR project that includes a refarence to the JAR and the associated config file. But it will multiply by 2 the number of project defined, which is not optimal in a way ...

The solution you propose looks good.
You can build a jar from your classes, and then build a war using this jar as a dependency.
You probably can also do this in one single project, I can see no need for two different projects.

You can use the configuration of the maven-war-plugin which offers you a way to create a separate jar file out of the files from src/main/java.
You have to add the configuration items:
<configuration>
<archiveClasses>true</archiveClasses>
<attachClasses>true</attachClasses>
</configuration>
This will create a separate jar file with the classifier classes which can be used as a usual dependency.

Related

Skinny War file with Maven in Eclipse

I have a Maven project 'Project A' which contains dependencies. I have a requirement to abstract the dependencies from this project into another project called 'Shared Lib' so that I can make what is called a "Skinny War" file from Project A. Both these files will then be uploaded to a Weblogic server.
However, I am having a lot of difficulties being able to get Project A to pick up the dependencies in Shared Lib.
Some guidance on how I should approach this problem would be much appreciated.
Thanks!
I would split the maven project into two modules. If we call one module SharedLib and the second one Skinny War then you will have something like:
<modules>
<module>sharedLib</module>
<module>skinnyWar</module>
</modules>
In the shared lib module pom.xml you will fill all the dependencies required for the project. In the skinnyWar module your first dependency in the list will be for the sharedLib module. You might need to setup the assembly plugin for the sharedLib module to create a jar in the package phase and you are good to go ;)
Some food of though - do you really want to do this? An important part about using maven is to take care of dependencies for you and package a easy to deploy jar. If you create two different jars it would cause all other kinds of troubles like - were both deployed. Are we using an older version of the dependencies etc.

How to set Maven dependencies on a local jar file

I am starting to play around with Maven, to see whether we could use it in the future to handle our dependency management, and IDE environments.
I have looked at some YouTube vids on how to get started with Eclipse (we also use Eclipse), and where you basically start off with creating a new project of type Maven. I have done this, and imported my existing source into the src/main package type.
Now I want to start adding the dependencies. No changes to my pom file yet.
I have two directories with jar files in them, and I need to set those dependencies in the pom file.
How do I do that?
This is not how you usually use Maven. You can add a jar through a path
<dependency>
<groupId>org.javap.web</groupId>
<artifactId>testRunWrapper</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/testRunWrapper.jar</systemPath>
</dependency>
but the recommended way is to draw your jars from a Maven repository (like MavenCentral, or your Nexus/Artifactory).
So if you want to use Maven in your company, make sure you have a running Nexus or Artifactory server in your company as well. Then you can either proxy external Maven repositories (which contain most of the available open source components) or upload your own jars through the interface of your Nexus/Artifactory.

How do I setup arquillian to test a maven war project by deploying the entire war to WildFly embedded?

I 'd like to do macro (not micro!) black box testing of my war on an embedded WildFly instance.
My maven project looks like this
<project>
...
<packaging>war</packaging>
<!-- Lots of classes in src/main/webapp and files in src/main/webapp -->
<dependencies>
<!-- Lots of compile/runtime dependencies that change very frequently -->
<!-- Lots of test dependencies that change very frequently -->
</dependencies>
</project>
My arquillian tests need to fulfill the following requirements:
Deploy the entire war to the app server in the tests. This includes all production classes, all runtime dependencies and all src/main/webapp files. From a maintenance perspective it's impossible to do micro deployments because class dependencies and jar dependencies change very frequently. So we cannot enumerate anything in the ShrinkWrap deployment.
Don't hardcode anything in the test or arquillian.xml that is already known by the maven pom.xml. This includes version strings, dependency lists, package or class lists, app server installation directories, etc.
Don't use more than 1 maven module. My tests to test my war belong in the test folder of the same maven module that produces the war.
Users that checkout my code need to be able so simply run the tests:
Tests needs to run from IntelliJ after simply opening the pom.xml with IntelliJ.
Use WildFly embedded container, so nothing needs to be installed first, no process needs to be run first and definitely no JBOSS_HOME environment variable needs to be set first.
I am only interested in black box testing, so all my tests can run as client.
In theory, this is all possible with Arquillian's Maven resolver, embedded containers, #RunAsClient, maven failsafe plugin, some arquillian.xml magic and a lot of maven magic. But in practice, I cannot get that stuff to work together, nor do I find any documentation that covers this scenario decently, so I am hoping someone can clearly show how they can work together.
Definitely sounds like a case for ShrinkWrap Resolver Maven Importer (not to be confused with the Maven Resolver). Here are some tests showing its usage.
I have a standalone sample for just a case of Gradle Importer ( I know you're using maven ), but the test construction is similiar here.
I don't have currenly a whole example publically available with both #RunAsClient and Maven Importer but I have a project using them together with Graphene and this combination do work :). Generally the test should look like:
#RunWith(Arquillian.class)
public class SomeControllerIT {
#Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create(MavenImporter.class).loadPomFromFile("pom.xml").importBuildOutput()
.as(WebArchive.class);
}
#Test
#RunAsClient
public void shouldDoSth() throws Exception {
...
}
}
Why to use Maven Importer instead of the war deployment? War is created after tests execution, this means that if the war exists during test execution, then it comes from previous build and is outdated.

How to import/embed one Spring-Maven JAR Application into Another Spring-Maven WAR Application

I want to create the persistence-tier (the Model of MVC) in a different application generating a JAR that will be imported in to the WAR (With the View and Controller of MVC)...
In both aplications (the JAR and the WAR) I want to use Spring (to manage persistence and transactions and dependency injection) and Maven (to manage de dependencies of both projects)...
I think that every Spring-Maven Application would have their own applicationContext.xml (or the WAR Application could inject dependency in the JAR Application too with only one configuration file for both projects?) and I know that each one will have their own pom.xml...
But how must proceed to integrate them? I wish that the JAR Application will be declared as dependency in the WAR Application and that Maven download the Jar automatically from the SVN respository... but I guess that this another question...
Create a simple Maven project (this will be the parent, parent-module) and in pom.xml define the common dependencies for the war-module and jar-module.
Create a new maven module, war-module, and define it as a war and a child of the parent-module. You will have here the web.xml and one applicationContext.xml.
Create a new maven module, jar-module, and define it as a jar and a child of the parent-module. You will have here another applicationContext.xml.
In the pom.xml file from war-module import jar-module as a dependency.
In the applicationContext.xml from war-module import applicationContext.xml from jar-module like here
Hope it helps.

Work with Maven, EJBs and Eclipse

I would like to build a Maven EJB project that generate EJB client to expose interfaces.
It works fine when I use this in my POM :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<ejbVersion>3.1</ejbVersion>
<generateClient>true</generateClient>
</configuration>
</plugin>
Two JARs are built in target but in Eclipse I have only one project for both implementations and interfaces.
I would like to create two separate projects in Eclipse, one for interfaces, one for implementations (the Eclipse traditional way when we create EJB project without Maven). How can I do this please?
Well, I succeeded by building with M2E in Eclipse 2 Maven Projects based on maven-archetype-quickstart archetype, one for ejb implementation (ejb-impl) and one for ejb client (ejb-client).
In ejb-impl, I choose packaging to ejb and in my ejb-client I choose jar packaging.
I use maven-ejb-plugin plugin to generate ejb from ejb-impl and I do NOT use generateClient option (default value is already set to false).
I use maven-ear-plugin to generate ear from ejb-impl, ejb-client and some war module (jsf). I use jarModule to include ejb-client so it's packaged under lib directory into ear file so no need to modify manifest or anything else, ejb-client cand be reached easily for others modules.
So, with Maven I can now use or distribute only interfaces methods of EJBs not implementations and there is no redundant code.