How to refer a profile in maven spring boot project - maven

I am novice when it comes to maven and spring boot. I need to run a spring boot project based on the profile. By default, the scope of following dependency is test which throws error at run time if I want to use h2. As I am not allowed to change the scope, I thought of adding two profiles in pom.xml - one default to be active by default and one for the h2 dependency without scope as test.
Following is what I added to pom.xml -
<profiles>
<profile>
<id>default</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>automation</id>
<properties>
<env>automation</env>
</properties>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
Now, I tried to run my project using following command -
mvn -D "spring-boot.run.profiles=automation" -DskipTests=true spring-boot:run
But I still see the same h2 dependency scope error that I was seeing earlier.
Caused by: java.lang.IllegalStateException: Cannot load driver class: org.h2.Driver
i.e. I am unable to change the scope of dependency this way. What am I missing here?

You are defining a Maven profile, but activating a Spring profile. Use the following syntax:
mvn groupId:artifactId:goal -P profile-1,profile-2
https://maven.apache.org/guides/introduction/introduction-to-profiles.html
Update
I tested the configuration you posted, and spring-boot:run fails for me if only default profile is active with the follwoing exception:
java.lang.IllegalStateException: Cannot load driver class: org.h2.Driver
You can check your dependencies with
mvn dependency:tree
The output of above command varies according to maven profiles passed in.

Related

Spring Boot Not Resolving Properties Variable When Using spring-boot:run

This was working for me and I'm not sure what changed.. I have my spring boot profile configured to be set based on a maven profile. The basics:
application.properties:
spring.profiles.active=#environment#
pom.xml:
<profiles>
<profile>
<id>development</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<environment>development</environment>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
</profile>
<profile>
<id>production</id>
<properties>
<environment>production</environment>
</properties>
</profile>
</profiles>
When I run mvn clean package -Pdevelopment I see the line The following profiles are active: development.
Yet when I run mvn spring-boot:run -Pdevelopment I see the line The following profiles are active: #environment#.
Using the spring-boot:run command seems to not be able to resolve application property variables based on maven environment variables. Anyone know why? I tried adjusting the spring starter version without success.
According to the docs, you could tune the profiles to enable when running the application as follows:
$ mvn spring-boot:run -Dspring-boot.run.profiles=development
If not, try to comment your "spring.profiles.active" property in application.properties, that should work!
See also this thread.
Based on this tip in the docs, I added a configuration to my spring-boot-maven-plugin which broke this functionality:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<addResources>true</addResources>
</configuration>
</plugin>
Removing the addResources configuration restores the property expansion behavior.

Springboot: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean [duplicate]

I have a spring-boot application that needs to:
Be deployable as a war in a servlet container
Be runnable via `mvn spring-boot:run``
I'd also like to be able to run this application in my IDE (Eclipse or IntelliJ IDEA Community) by right clicking on the main and running it.
Here are the interesting parts of my pom.xml (Note that I do not inherit from spring-boot-starter-parent pom):
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<failOnMissingWebXml>false</failOnMissingWebXml>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Here's my SpringBootServletInitializer:
#Configuration
#EnableAutoConfiguration
#ComponentScan("com.company.theproject")
public class Application extends SpringBootServletInitializer
{
private static final Logger logger = LoggerFactory.getLogger(Application.class);
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
{
return application.sources(Application.class);
}
public static void main(String[] args)
{
SpringApplication.run(Application.class, args);
}
}
When running the main inside an IDE I get the following error:
org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.java:183) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.java:156) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.java:130) ~[spring-boot-1.2.3.RELEASE.jar:1.2.3.RELEASE]
... 12 common frames omitted
Seems like mvn spring-boot:run does some more magic that does not happen when running the main directly.
Removing the provided scope from the spring-boot-starter-tomcat dependency fixes this issue but causes trouble when the war is run inside a servlet container.
Right now the only "fix" I've found is to run mvn spring-boot:run within IntelliJ IDEA instead of running the main directly. While this is an acceptable workaround, I'd still like to know why this doesn't work and if it can be fixed.
A workaround that is strongly inspired from https://youtrack.jetbrains.com/issue/IDEA-140041 is to start your main class with the test classpath (which includes the embedded servlet.)
Steps (IntelliJ 16):
Run -> Edit Configurations -> Add new configuration -> Pick Application type.
Set Main class to <your.main.class>
Set Use classpath of module to <*>_test (the test module!)
Ok and Run it!
I believe this could be related to https://youtrack.jetbrains.com/issue/IDEA-107048
IntelliJ IDEA is not injecting the provided dependencies into the CLASSPATH and as Andy stated this is why spring is unable to create the embedded servlet container.
They have a feature request since 2005 about this: https://youtrack.jetbrains.com/issue/IDEABKL-99
Workarounds mentioned in the comments includes having a fake module with the necessary libs and using it as classpath, using the -Xbootclasspath JVM argument or using custom maven profiles for running (compiled) vs building (provided).
I had the same problem using IntelliJ 2018.
Initially, Make sure that you have added the maven library for the spring project in your IntelliJ.
My solution is:
Go to Run -> Edit Configurations.
Select Application && choose your current project.
Check Include dependencies with "Provided" scope.
OK -> RUN
I was able to make this work by changing the scope of the spring-boot-starter-tomcat dependency to "compile" under Project structure->Dependencies tab. This doesn't effect pom.xml but allows this dependencies to be available to spring boot run configuration
Click here for image on where to change this setting in idea
mvn spring-boot:run includes provided dependencies when it's creating the classpath. It sounds like IntelliJ IDEA does not. Without Tomcat on the classpath, Spring Boot's unable to create an embedded servlet container which causes the exception you're seeing. Arguably this is a bug in IntelliJ as, if there's no container to provide the dependency, then it really needs to be on the classpath.
You may be able to fix the problem by overriding the default classpath that IntelliJ uses when running the main method to include the spring-boot-starter-tomcat dependency.
I find this page, and use the maven profile to manage the profiles.
<profiles>
<profile>
<id>PROD</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
<profile>
<id>DEV</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>TEST</scope>
</dependency>
</dependencies>
</profile>
</profiles>
and config the main class beforeLanuce,set the command
mvn clean compile -Pdev
I was able to work around this problem in Intellij IDEA 2017.2 by adding the provided libaray (spring-boot-starter-tomcat) to the project configuration.
Select File -> Project Structure. Select Libraries and add a new project library (type = From Maven...). Search for spring-boot-starter-tomcat using the dialog, select the correct version and add it by clicking on OK. The library is added to the list of external libraries.
The disadvantage is that if the Spring Boot version is changed then you will have to remember to delete this library and add the new version.
Using the profile and instructions below, you can add a profile to maven that allows development in IntelliJ without changing things for other environments.
<!-- Leave original dependency as-is -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
<profiles>
<!-- Enable this profile to run in IntelliJ. IntelliJ excludes provided dependencies from compile by default. -->
<profile>
<id>intellij</id>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>compile</scope>
</dependency>
</dependencies>
</profile>
</profiles>
Click the Maven Projects button on the right side of IntelliJ, and under Profiles, select intellij.
Follow these steps:
On the top right side of intellij window, click the drop down and select edit configuration and a new window will open.
In this window, on top left side, click "+" button and select sprint boot.
Then add you main class, and other details as shown in screenshot.
Now Run the application.

Unable to include cassandra dependency in spring-mvc

I am facing issues while trying to include cassandra dependency in my project's pom.xml.
Some problems were encountered while processing the POMs: [ERROR]
Failed to determine Java version for profile doclint-java8-disable #
com.datastax.cassandra:cassandra-driver-parent:2.1.6,
/root/.m2/repository/com/datastax/cassandra/cassandra-driver-parent/2.1.6/cassandra-driver-parent-2.1.6.pom,
line 92, column 14
I have tried googling but no success there.
Up till cassandra-driver-core-2.1.2, build gets completed without any error. But when I try building with version 2.1.6 though the build completes successfully the cassandra-driver-parent pom breaks as highlighted above, thus preventing me from importing the required classes.
This is my pom entry:
<!-- Cassandra Dependency -->
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-parent</artifactId>
<version>2.1.6</version>
<type>pom</type>
</dependency>
<dependency>
<groupId>com.datastax.cassandra</groupId>
<artifactId>cassandra-driver-core</artifactId>
<version>2.1.6</version>
</dependency>
The offending profile is declared as this in com.datastax.cassandra:cassandra-driver-parent:2.1.6 :
<profiles>
<profile>
<id>doclint-java8-disable</id>
<activation>
<jdk>[1.8,)</jdk> <!-- This is line 92 -->
</activation>
<properties>
<javadoc.opts>-Xdoclint:none</javadoc.opts>
</properties>
</profile>
</profiles>
It seems that your Maven installation is unable to determine which Java version you are running. The syntax is correct and should work (even if it wasn't, you wouldn't be able to do much about it).
You could try disabling the automatic profile activation through the command line:
-P !doclint-java8-disable

How to use one maven dependency for JUnit tests and another dependency for the build?

I am facing a situation, where I thought that Maven offers me the correct tools.
Either I am wrong or Maven ;o)
Seriously.
We are writing software to work with a 3rd party lib, let's call it prod.jar. This lib needs an environment that can connect to the prod.jar servers.
Obviously, our Jenkins is not and cannot be set up in this way. Thus, when running the tests with the prod.jar, everything will fail, as no connection can be set up.
My idea was to write a simulator that behaves like the real prod.jar and can be used for unit tests, called simulator.jar. Both, the prod.jar and the simulator.jar hold the same packages with the same class names. They only do differ in functionality. I have done this, to enable development and to cover as much on JUnit side on Jenkins. Of course, we also do test against the prod.jar, but not with Jenkins.
So what I did is to create two eclipse projects:
prod-code: with a pom.xml that has prod.jar as a dependency
simulator-code: with a pom.xml that has the simulator.jar as a dependency
So depending on which project you add as a dependency to the main project, either the simulator or the prod code are used. That works fine.
But then we get the error that the build contains the wrong jar.
How can I set up maven, if possible, so that I can use always the same pom, but maybe with different mvn parameters, to use the simulator during the test process and to use the prod code during the build process.
I tried with maven profiles, but when using the build jar, it will complain.
<profiles>
<profile>
<id>simulator</id>
<dependencies>
<dependency>
<groupId>main-project</groupId>
<artifactId>simulator</artifactId>
</dependency>
</dependencies>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>jenkins</id>
<dependency>
<groupId>main-project</groupId>
<artifactId>simulator</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>main-project/groupId>
<artifactId>prod</artifactId>
</dependency>
</dependencies>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
<profile>
<id>realSystem</id>
<dependencies>
<dependency>
<groupId>main-project</groupId>
<artifactId>prod</artifactId>
</dependency>
</dependencies>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
Any help appreciated.
Many thanks in advance.

Using "provided" classpath in tomcat7-maven-plugin goals

I have some dependencies in my webapp that I've marked as provided because I expect them to be provided by an appserver (maybe a production environment provides these dependencies at the specified versions). How do I simulate that when I'm running tests or in development on my localhost using for example the tomcat7-maven-plugin goals like run?
I can't see any way to do it without manually copying jars around. I can see how to use the test classpath - is there something wrong with what I'm trying to do?
OK, I've found a way of getting this to work - it's reasonable but there's a duplication of dependency information and a magic profile... I feel that the tomcat7-maven-plugin should provide a means of making provided dependencies available in the container when running.
Add a profile that is activated when the tomcat plugin runs, and add the dependencies that have provided scope with compile scope to that profile, eg.
... in project pom ...
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>my-provided-artifact</artifactId>
<version>1.2.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
...
<profiles>
<profile>
<!-- profile activated as cli param when tomcat7 plugin runs -->
<id>tomcat</id>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>my-provided-artifact</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
</profile>
</profiles>
I use, for example, this:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<path>/myApp</path>
</configuration>
<dependencies>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
</dependencies>
</plugin>
and then also include the dependency again later with provided.

Resources