How to set an environment variable in application.yml - Spring Boot - spring-boot

I'm working on a spring boot application and I'm writing some tests which use MockServer.
In order to not have all the requests to the mock servers displayed in the logs, I have to set the environment variable mockserver.logLevel to OFF.
When I do it via command line, it works perfectly :
mvn clean install -Dmockserver.logLevel="OFF"
but when I try to do it in my application.yml, it doesn't work.
I've tried the following :
mockserver:
log-level: OFF
mockserver:
loglevel: OFF
mockserver:
logLevel: OFF
logging:
level:
org.mockserver: OFF
But none of these work.
I guess I don't write it correctly in the application.yml but I can't figure out the right way.

I finally found a way by adding it directly into the pom.xml as a system property variable in the concerned plugin :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${version.maven-failsafe-plugin}</version>
<configuration>
<systemPropertyVariables>
<mockserver.logLevel>OFF</mockserver.logLevel>
</systemPropertyVariables>
</configuration>
</plugin>

an another 'wiring' solution:
#Configuration
public class MockServerConfiguration {
...
public MockServerConfiguration(#Value("${mockserver.logLevel}") String mockserverLogLevel) {
if (Objects.isNull(System.getProperty("mockserver.logLevel"))) {
System.setProperty("mockserver.logLevel", mockserverLogLevel);
}
}
...
}

Related

Maven: how to invoke a plugin with execution specific config

I have written a plugin and want to treat the goal vrs (check versions) differently,
depending on execution/command line.
In my code I added
#Parameter(name = "versionsWarnOnly", defaultValue = "true")
private boolean versionsWarnOnly;
public boolean getVersionsWarnOnly() {
System.out.println("invoked get");
return this.versionsWarnOnly;
}
public void setVersionsWarnOnly(boolean versionsWarnOnly) {
System.out.println("invoked set");
this.versionsWarnOnly = versionsWarnOnly;
}
I would expect, that without specifying versionsWarnOnly in the configuration in the pom, i just get the defaultValue specified.
The problem is, that does not happen, it is always false in that case.
If i configure in the configuration
of the plugin in the pom
<versionsWarnOnly>true</versionsWarnOnly>
Then this is done (well some success) if I build the phase mvn validate.
It is even true if I invoke the goal from the command line by goal mvn latex:vrs.
But if i specify that in an execution that like,
<execution>
<id>validate_converters</id>
<phase>validate</phase>
<configuration>
<versionsWarnOnly>true</versionsWarnOnly>
</configuration>
<goals>
<goal>vrs</goal>
</goals>
</execution>
again it has no effect.
I have no idea what i do wrong
or what kind of information you need to help me.
The problem is resolved and the question could be deleted altogether.
The problem was that I put almost all of the config into a class Settings.
On the other hand, I added the new parameter outside and so it had no effect.
Thats all.
Now all works fine.

how to Use system properties to pass parameters to the runner/maven build

I want to run my test in three different preset resolution: 768x1024, 360x740, 1920x1024 using the existing framework. And I have to use system properties to pass parameters to the runner/maven build. I've tried systemPropertyVariable. It worked fine with one resolution size but I don't know how to pass all the three preset resolutions.
private static void setupBrowser(final WebDriver webDriver) {
String width=System.getProperty("width");
String heigth=System.getProperty("heigth");
final Dimension targetResolution = new Dimension(Integer.parseInt(width),Integer.parseInt(heigth));
here my systemPropertyVariables:
<configuration>
<systemPropertyVariables>
<width>768</width>
<heigth>1024</heigth>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>

Can I start a Spring Boot WAR with PropertiesLauncher?

I have a Spring Boot 1.2 app packaged as a WAR because I need to be able to deploy the app in an app server.
I also want to configure an external path which will contain jars to be added to the classpath. After reading the Launcher documentation, I configured the build to use PropertiesLauncher to this end :
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
...
<layout>ZIP</layout>
</configuration>
</plugin>
I tried to start the app with various combinations of this additional system property : -Dloader.path=lib/,lib-provided/,WEB-INF/classes,<my additional path>
But I always end up with this error :
java.lang.IllegalArgumentException: Invalid source folder C:\<path to my war>\<my war>.war
at org.springframework.boot.loader.archive.ExplodedArchive.<init> ExplodedArchive.java:78)
at org.springframework.boot.loader.archive.ExplodedArchive.<init>(ExplodedArchive.java:66)
at org.springframework.boot.loader.PropertiesLauncher.addParentClassLoaderEntries(PropertiesLauncher.java:530)
at org.springframework.boot.loader.PropertiesLauncher.getClassPathArchives(PropertiesLauncher.java:451)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:60)
at org.springframework.boot.loader.PropertiesLauncher.main(PropertiesLauncher.java:609)
I looked at the source code and it seems that PropertiesLauncher can only handle jar archives (ending with ".jar" or ".zip") and "exploded archives" (not ending with the former)
Is it possible to do achieve what I want ? Am I doing it wrong ?
If it's not possible, which alternative is there ?
If somebody end up here this might be useful:
java -cp yourSpringBootWebApp.war -Dloader.path=yourSpringBootWebApp.war!/WEB-INF/classes/,yourSpringBootWebApp.war!/WEB-INF/,externalLib.jar org.springframework.boot.loader.PropertiesLauncher
(Spring-Boot 1.5.9)
https://docs.spring.io/spring-boot/docs/1.5.x/reference/html/executable-jar.html#executable-jar-launching
In Spring Boot 1.2, PropertiesLauncher handles .jar and .zip files as "jar archives" and everything else as "exploded archives" (unzipped jars). It does not properly handles .war
Here's the alternative I found :
I eventually switched back to the regular war launcher and I managed to configure a folder which jar contents are added to the classpath using a SpringApplicationRunListener such as this (pseudo-code for concision) :
public class ClasspathExtender implements SpringApplicationRunListener {
public void contextPrepared(ConfigurableApplicationContext context) {
// read jars folder path from environment
String path = context.getEnvironment().getProperty("my.jars-folder");
// enumerate jars in the folder
File[] files = new File(path).listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) { return name.endsWith(".jar"); }
});
URL[] urls = // convert files array to urls array
// create a new classloader which contains the jars...
ClassLoader extendedClassloader = new URLClassLoader(urls, context.getClassLoader());
// and replace the context's classloader
((DefaultResourceLoader) context).setClassLoader(extendedClassloader);
}
// other methods are empty
}
This listener is instanciated by declaring it in a META-INF/spring.factories file :
org.springframework.boot.SpringApplicationRunListener=my.ClasspathExtender
This worked for me (Spring Boot 1.3.2)
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
...
<layout>WAR</layout>
</configuration>
</plugin>

Spring Boot: Thymeleaf not resolving fragments after packaging

im using fragments like this:
#RequestMapping(value="/fragment/nodeListWithStatus", method= RequestMethod.GET)
public String nodeListWithStatus(Model model) {
// status der nodes
model.addAttribute("nodeList", nodeService.getNodeListWithOnlineStatus());
return "/fragments :: nodeList";
}
The templates are in /src/main/resources/templates. This works fine when starting the application from IntelliJ.
As soon as i create an .jar and start it, above code no longer works. Error:
[2014-10-21 20:37:09.191] log4j - 7941 ERROR [http-nio-666-exec-2] --- TemplateEngine: [THYMELEAF][http-nio-666-exec-2] Exception processing template "/fragments": Error resolving template "/fragments", template might not exist or might not be accessible by any of the configured Template Resolvers
When i open the .jar with winrar, i see /templates/fragments.html - so it seems to be there.
My pom.xml has this part for building the jar (Maven clean, install) :
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>de.filth.Application</mainClass>
<layout>JAR</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Can anyone tell me what im doing wrong here?
Thanks!
You don't need the leading / on the view name, i.e. you should return fragments :: nodeList rather than /fragments :: nodeList. Having made this change Thymeleaf should be able to find the template when run from your IDE or from a jar file.
If you're interested, here's what's happening under the hood:
The view name is used to search for a resource on the classpath. fragments :: nodeList means that the resource name is /templates/fragments.html and /fragments :: nodeList means that the resource name is /templates//fragments.html (note the double slash). When you're running in your IDE the resource is available straight off the filesystem and the double slash doesn't cause a problem. When you're running from a jar file the resource is nested within that jar and the double slash prevents it from being found. I don't fully understand why there's this difference in behaviour and it is rather unfortunate. I've opened an issue so that we (the Spring Boot team) can see if there's anything we can do to make the behaviour consistent.
It's an old topic, but I stumbled upon it while having problem with similar symptoms and different root cause. Wanted to share solution which helped me in case it could help somebody else...
Apparently name of the messages.properties file is case sensitive, but not everywhere. I had mine called "Messages.properties" (with capital M) and it worked just fine from inside IDE (IntelliJ), but once I tried to run app from jar, all messages were replaced with ??parameter.name??. Replacing M with lowercase m resolved the problem.

How to pass input from command line to junit maven test program

I wrote a junit test to add two numbers. I need to pass this numbers from command line. I am running this junit test from maven tool as
mvn -Dtest=AddNumbers
My test program looks like this
int num1 = 1;
int num2 = 2;
#Test
public void addNos() {
System.out.println((num1 + num2));
}
How to pass these numbers from command line?
Passing the numbers as system properties like suggested by #artbristol is a good idea, but I found that it is not always guaranteed that these properties will be propagated to the test.
To be sure to pass the system properties to the test use the maven surefire plugin argLine parameter, like
mvn -Dtest=AddNumbers -DargLine="-Dnum1=1 -Dnum2=2"
To pass input from command line to junit maven test program you follow these steps. For example if you need to pass parameter fileName into unit test executed by Maven, then follow the steps:
In the JUnit code - parameter will be passed via System properties:
#BeforeClass
public static void setUpBeforeClass() throws Exception {
String fileName = System.getProperty("fileName");
log.info("Reading config file : " + fileName);
}
In pom.xml - specify param name in surefire plugin configuration, and use {fileName} notation to force maven to get actual value from System properties
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<!-- since 2.5 -->
<systemPropertyVariables>
<fileName>${fileName}</fileName>
</systemPropertyVariables>
<!-- deprecated -->
<systemProperties>
<property>
<name>fileName</name>
<value>${fileName}</value>
</property>
</systemProperties>
</configuration>
</plugin>
In the command line pass fileName parameter to JVM system properties:
mvn clean test -DfileName=my_file_name.txt
You can pass them on the command line like this
mvn -Dtest=AddNumbers -Dnum1=100
then access them in your test with
int num1=Integer.valueOf(System.getProperty("num1"));

Resources