Customised maven deployable (war with some dependencies removed) - java

I have a multi module web app building with maven. We build the war as per normal and deploy and run on developer machines and local test servers using tomcat.
Then we want to deploy the application to the cloud. To do this we create a special version of tomcat which has all the libraries preloaded and a special version of the war which only has our code. Point here is tomcat is preloaded on the cloud server, the war is uploaded each time it is changed. Currently we are having to manually remove the dependencies from the built war.
What is the best way for maven to do this? Should I build a custom packaging type or maybe run some post build plugin to remove these wars? Or something else? I think the best way to activate this custom build is via a profile. I did try and remove these dependencies by setting them to scope = provided in the new profile but the transitive dependencies still made it into the war.

If you want to exclude all dependencies, you can use the war plugin's packagingExcludes to do so:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.2</version>
<configuration>
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
...
</configuration>
</plugin>
Specify this plugin inside a profile to only perform it for production.

You can achieve using profile in maven. As you said it is not working, I can think of you configure something wrong. Try something like:
<profiles>
<profile>
<id>dev</id>
<activation>
<!-- active by default, turn off when on prod -->
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<!-- include this in dev, not in prod -->
<dependency>
<groupId>com.company</groupId>
<artifactId>xyz</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
Then in command line, mvn package -P !dev to deactivate dev profile so that not include the jars.
Make sure com.company:xzy is not included in <project><dependencies></dependencies></project>.

Related

skip certain modules during deploy in multi-module maven java project on appengine w/ appengine-maven-plugin

I have a multi-module maven java project. In the parent pom:
<modules>
<module>core</module>
<module>batch-worker</module>
<module>be</module>
<module>scheduler</module>
<module>migrations</module>
</modules>
Both the migrations and core modules aren't services I wish to deploy but just common packages used throughout all services.
When i attempt a deploy with mvn appengine:deploy, I receive goal execution failures because the core and migrations modules do not define an app.yaml as they are not deployable services.
How do I skip these and omit them from the deploy?
You can define your services in the maven plugin.
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<services>
<!-- Default service-->
<service>${project.build.directory}/${project.name}-${project.version}</service>
<!-- other service-->
<service>${project.parent.basedir}/other_module/target/other_module_finalName-${project.version}</service>
</services>
</configuration>
</plugin>
However, in the documentation the services are take into account only for start/stop command and not for deploy. I don't know if it works.
Let me know.

IntelliJ resolve dependencies of profile

I have a Java project with multiple modules. In this project, one module has a dependency to another one, which is only needed for a specific profile and hence is defined like that:
<profile>
<id>myProfile</id>
<dependencies>
<dependency>
<groupId>MyGroupId</groupId>
<!-- ... -->
</dependency>
</dependencies>
<!-- ... -->
</profile>
This works fine when building manually with maven like that:
mvn clean install -P myProfile
When using the IntelliJ build however, the dependency doesn't get resolved.
I've tried the option to delegate IDE build/run actions to maven, adding a property for maven in Build, Execution, Deployment > Build Tools > Maven > Runner (namely -P -> myProfile), and much more which is most likely not of interest.
Is it possible to configure IntelliJ to resolve the dependencies for a specific profile?
To help Intellij Idea to understand about your maven profile and maven object mode, you set as default profile in maven so that by default it will be recognized and run by any IDE. I provide below the code snippet.
<profile>
<id>firstProfile</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
..... Other code goes
</profile>
So inside profile, use this <activeByDefault>true</activeByDefault>. It may solve the problem.

Spring boot profile based WAR using maven

I need to create WAR file based on specific environment properties file.
So I have created 2 properties files,
application.DEV.properties
application.PROD.properties
Now when I run the project using eclipse embedded tomcat, I pass on the -Dspring.profiles.active=DEV as VM argument. Then when I hit my endpoint, I can see the DEV related messages returned. Same is the case when I pass PROD as parameter.
Now, what I want to do is I want to create a WAR file with maven command and pass the parameter in such a way that my specific properties file gets loaded. So I have referred google as well as stackoverflow and found various options like below,
mvn clean install -Drun.profiles=DEV
mvn clean install -Drun.jvmArguments="-Dspring.profiles.active=DEV"
mvn clean install -Dspring.profiles.active="DEV"
mvn clean install -Dspring.profiles.active=DEV
I tried all above. When I hit the command, the WAR gets generated. but it doesn't get deployed on tomcat, because it cant read the properties file and gives error. It seems like the profile specific properties file does not get loaded in the WAR.
I want to know what is the alternative to -Dspring.profiles.active=DEV when I want to generate a WAR file using maven?
How to generate WAR to correctly include proper profile specific properties file?
I am using spring boot 1.5.14.RELEASE.
As commented on this answer by Mickael, you can get help from the maven documentation on how to use profiles : https://maven.apache.org/guides/introduction/introduction-to-profiles.html
The usual way to choose a profile with maven is
mvn -Pprod package
Where prod is the name of your profile. If you want to build with the dev profile, it would be
mvn -Pdev package
Such profiles are defined in your file pom.xml under project>profiles>profile. And at that place, you can specify packaging options.
Here is such a profile:
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<!-- log configuration -->
<logback.loglevel>DEBUG</logback.loglevel>
<!-- default Spring profiles -->
<spring.profiles.active>dev${profile.no-liquibase}</spring.profiles.active>
</properties>
</profile>
You have to pass spring.profiles.active to the runtime, not to the "build runtime". The only spring profiles, which are desirable at build time, would be for testing purposes.
In case of "war on Tomcat", you can set spring.profiles.active:
(Globally) Create a file in <tomcat_home>/bin/ named setnev.sh (respectively .bat, when you are on a Windows machine) with:
export JAVA_OPTS="-Dspring.profiles.active=PROFILE_OF_THIS_TOMCAT"
respectively:
set JAVA_OPTS="-Dspring.profiles.active=PROFILE_OF_THIS_TOMCAT"
(Globally) Add a line to <tomcat_home>/conf/catalina.properties:
spring.profiles.active=PROFILE_OF_THIS_TOMCAT
(At Container level) Add a file named context.xml at $CATALINA_BASE/conf/[enginename]/[hostname]/ (, you could also put it into /<webapp_root>/META-INF/, but then you'd have to distinguish at build time) with the following content:
<Context>
<Environment name="spring.profiles.active" value="PROFILE_OF_THIS_TOMCAT" />
</Context>

Maven Tomcat7 run a dependency war

I have a question regarding maven and its tomcat7 plugin :)
I have the following maven projects:
plugin1: plain java project packaged as jar
plugin2: plain java project packaged as jar
webapp: standalone webapp project packaged as jar
those three project are properly build in maven and the outcome works fine:
I can use the jars from plugin1/plugin2
I can deploy the webapp war file to a web container
I can run tomcat7:run to start the webapp
Now, I need to provide different packaging of the webapp containing specific plugin setup.
i.e. I want to generate a war file with webapp + plugin1 and another one with webapp + pugin2
To achieve this, I have created 2 additionnal maven projects that declare dependancies on the webapp project + the appropriate plugin projects and are packaged as wars.
The generated war files have the expected content, and can be deployed to a tomcat, but when I try to use the maven tomcat plugin (tomcat7:run again), it simply doesnt start anything.
Though this is not blocking for me (my main point was to generate the war files), I have the feeling that I missed something.
the pom.xml for those aggregate projects looks like this (note that there is absolutly no code in those projects, these were just created for packaging with specific dependancies convenience).
<groupId>my.project</groupId>
<artifactId>live1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>MyWebapp</name>
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>my.project</groupId>
<artifactId>plugin1</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>my.project</groupId>
<artifactId>webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>MyWebapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<url>http://localhost:8080/manager</url>
<server>localhost</server>
<path>/${project.build.finalName}</path>
</configuration>
</plugin>
</plugins>
</build>
Thanks !
note: long time lurker, first time asker here, if some information is missing tell me :)
Depending on the structure of your project it may not be suficient to just add a dependency of type war. You may need also to configure <overlays> as described here maven-war-plugin.
It looks like your final war does not provide the full web configuration that you expect. With overlays you can configure how the resources from the dependency will be packed into your final web app.
There must be some difference in the way that your external tomcat starts the app compared to the tomcat7 plugin. May be you can try -X option :
mvn -X tomcat7:run
This should log out some details, of what the embedded tomcat is configuring..

Maven Dependency error in Eclipse

I have a war artefact and I need use some of their classes from a jar.
I can't move the classes to another project, then I deploy the classes and resources included in my webapp as an "attached" artifact using the following configuration:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
This will result in two artifacts being deployed: mywebapp-1.0-SNAPSHOT.war and mywebapp-1.0-SNAPSHOT-classes.jar.
To use those classes I Referencing the artifact as follows:
<dependency>
<groupId>mygroup</groupId>
<artifactId>mywebapp</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
</dependency>
When I compiled from Jenkins everything works correctly, but when I run the tests locally from Eclipse can not find the reference classes. (java.lang.NoClassDefFoundError)
I think it might be a bug in the maven eclipse plugin, someone has any idea that can be happening?
Workaround is described on http://wiki.eclipse.org/M2E-WTP_FAQ:
A workaround exists though, we need to change the dependency whether the project is built in Eclipse or not. In your dependent project, you can configure the following :
<dependencies>
...
<dependency>
<groupId>com.company</groupId>
<artifactId>mywebapp</artifactId>
<version>1.0.0-SNAPSHOT</version>
<classifier>${webClassifier}</classifier>
</dependency>
...
</dependencies>
...
<properties>
...
<webClassifier>classes</webClassifier>
</properties>
...
<profiles>
<profile>
<id>m2e</id>
<activation>
<property>
<name>m2e.version</name>
</property>
</activation>
<properties>
<webClassifier></webClassifier>
</properties>
</profile>
</profiles>
The m2e profile is automatically activated when the project is built with m2e, ignored in other circumstances. In that case only, the dependent project will use an empty classifier to reference the web project, which will be added to the classpath as expected.
My simple answer is the following link to the bug tracking system of Eclipse:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=365419
See the answers inside.
Yes it's a problem with Eclipse itself..
The solution within Eclipse just add the project manually within your workspace to the appropriate project where you need the classes out of your war project.

Categories

Resources