I'm using google_checks.xml as a CheckStyle config in my Gradle project.
I need to be able to suppress the MemberName warning in one of my classes, and I can do so using #SuppressWarnings("checkstyle:MemberName") if and only if I add SuppressWarningsHolder and SuppressWarningsFilter to google_checks.xml
per this post.
The problem is that I update google_checks.xml regularly, and I don't want to remember to need to re-add these, so I'd like to handle these suppressions in a separate checkstyle-suppressions.xml file. This should be doable per this section of google_checks.xml:
<module name="SuppressionFilter">
<property default="checkstyle-suppressions.xml" name="file"
value="${org.checkstyle.google.suppressionfilter.config}"/>
<property name="optional" value="true"/>
</module>
However, I can't figure out how to get it to look for this file in my project's root directory instead of in the default .gradle\daemon\6.5.1\checkstyle-suppressions.xml path. How can I point it to another location?
If I set value="${config_loc}/checkstyle-suppressions.xml", it does what I want, but we're back to the problem of me not wanting to have to modify google_style.xml.
It seems like I need to set the org.checkstyle.google.suppressionfilter.config system property somehow, but I'm not sure where to do this in my Gradle config files, or what exactly to set it to.
As its a system property, you can override it in the build.gradle as per below config, say you have checkstyle-suppressions.xml in the project root folder.
NOTE: The config file is pointing to google_checks.xml from the checkstyle jar, and is not part of your project.
System.setProperty( "org.checkstyle.google.suppressionfilter.config", project.projectDir.toString()+"/checkstyle-suppressions.xml" )
checkstyle {
toolVersion = checkStyleVersion
configFile = file("/google_checks.xml")
ignoreFailures = false
showViolations = false
maxWarnings = 0
}
The Gradle plugin provides the Map<String, Object> configProperties option for this.
The properties available for use in the configuration file. These are substituted into the configuration file.
So for suppressions.xml in the .checkstyle folder,
checkstyle {
configProperties = [
"org.checkstyle.google.suppressionfilter.config":
"${projectDir}/.checkstyle/suppressions.xml",
]
}
Related
We are migrating our application from WAS 6.1 to Liberty. Our application uses third party jars that read property files byInputStream is = ClassLoader.getSystemResource("myproperty.properties").
In WAS 6.1, we set server classpath to the location of myproperty.properties. We tried the below approaches to set classpath in Liberty, but nothing works
Approach 1: Set the below in jvm.options (D:\ConfigFiles\DEV\ - path containing myproperty.properties)
-Djava.class.path=D:\\ConfigFiles\\DEV\\
Approach 2: Setting the classloader in server.xml,
<library id="config">
<folder dir="${server.config.dir}/config/" includes="*.properties" scanInterval="5s"/>
</library>
<enterpriseApplication id="applicationEAR" location="application.ear" name="application">
<classloader privateLibraryRef="config"/>
</enterpriseApplication>
Please let us know if there is any other ways to override/set classpath in Liberty profile?
Try setting this property in jvm.options (instead of -Djava.class.path=path/to/propertyDir):
-Xbootclasspath/a:path/to/propertyDir
This will append the path of the property directory (containing your resource file) to the JVM's bootstrap classpath. Because this is an append, it should also work in Java 9+ (some related options have been removed in Java 9).
I suspect that the reason -Djava.class.path=... doesn't work is that the JVM gets the classpath from the WLP server script - so the system property is essentially applied too late in the startup of the server JVM.
You might also be able to put the properties file(s) in your JVM's lib/ext directory, but I haven't tested that. The -Xbootclasspath/a:path approach works for me on Mac - I assume it will also work on Windows.
HTH, Andy
If your end goal is to load a properties file, a more straightforward way to do this would be using a bootstrap/env/system property or <jndiEntry> in server.xml to store the location of the properties file, and then load it. For example, using an environment variable:
(in server.xml file)
<server>
<featureManager>
<feature>jndi-1.0</feature>
...
</featureManager>
<jndiEntry jndiName="configDir" value="D:\\ConfigFiles\\Dev"/>
</server>
Then, you can load the resource in your application like this:
#Resource(lookup = "configDir")
String configDir;
InputStream is = new FileInputStream(configDir + "/myproperty.properties");
Or, if you will always put your config property files somewhere under ${server.config.dir}, then you can utilize the built-in SERVER_CONFIG_DIR environment variable in Liberty:
String configDir = System.getenv("SERVER_CONFIG_DIR"); // equivalent to ${server.config.dir} in server.xml
InputStream is = new FileInputStream(configDir + "/myproperty.properties");
On the topic of managing configuration, check out MicroProfile Config (e.g. <feature>microProfile-1.2</feature>) which you may find useful: Configuring microservices with Liberty
I have a spring boot application that I can package in a war that I want to deploy to different environments. To automate this deployment it'd be easier to have the configuration file externalized.
Currently everything works fine with a application.properties file in src/main/resources. Then I use ´mvn install´ to build a war deployable to tomcat.
But I would like to use a .yml file that does not need to be present on mvn install but that would be read from during deployment of the war and is in the same or a directory relative to my war.
24. externalized configuration shows where spring boot will look for files and 72.3 Change the location of external properties of an application gives more detail on how to configure this but I just do not understand how to translate this to my code.
My application class looks like this:
package be.ugent.lca;
Updated below
Do I need to add a #PropertySource to this file? How would I refer to a certain relative path?
I feel like it's probably documented in there as most spring boot documentation but I just don't understand how they mean me to do this.
EDIT
Not sure if this should be a separate issue but I think it's still related.
Upon setting the os variable the error of yaml file not found went away. Yet I still get the same error again as when I had no application .properties or .yml file.
Application now looks like this:
#Configuration
**#PropertySource("file:${application_home}/application.yml")**
#ComponentScan({"be.ugent.lca","be.ugent.sherpa.configuration"})
#EnableAutoConfiguration
#EnableSpringDataWebSupport
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
The application_home OS variable
$ echo $application_home
C:\Masterproef\clones\la15-lca-web\rest-service\target
My application.yml file(part it complains about):
sherpa:
package:
base: be.ugent.lca
Error upon java -jar *.war
All variations upon:
Caused by: java.lang.IllegalArgumentException: Could not resolve placeholder 'sherpa.package.base' in string value "${sherpa.package.base}"
at org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174)
at org.springframework.util.PropertyPlaceholderHelper.replacePlaceholders(PropertyPlaceholderHelper.java:126)
at org.springframework.core.env.AbstractPropertyResolver.doResolvePlaceholders(AbstractPropertyResolver.java:204)
at org.springframework.core.env.AbstractPropertyResolver.resolveRequiredPlaceholders(AbstractPropertyResolver.java:178)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer$2.resolveStringValue(PropertySourcesPlaceholderConfigurer.java:172)
at org.springframework.beans.factory.support.AbstractBeanFactory.resolveEmbeddedValue(AbstractBeanFactory.java:808)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1027)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545)
... 142 more
Using external properties files
The answer lies in the Spring Boot Docs, I'll try to break it down for you.
First of all, no you should not use #PropertySource when working with Yaml configuration, as mentioned here under the Yaml shortcomings :
YAML files can’t be loaded via the #PropertySource annotation. So in the case that you need to load values that way, you need to use a properties file.
So, how to load propery files? That is explained here Application Property Files
One is loaded for you: application.yml , place it in one of the directories as mentioned in the link above. This is great for your general configuration.
Now for your environment specific configuration (and stuff like passwords) you want to use external property files, how to do that is also explained in that section :
If you don’t like application.properties as the configuration file name you can switch to another by specifying a spring.config.name environment property. You can also refer to an explicit location using the spring.config.location environment property (comma-separated list of directory locations, or file paths).
So you use the spring.config.location environment property.
Imagine you have an external config file: application-external.yml in the conf/ dir under your home directory, just add it like this:
-Dspring.config.location=file:${home}/conf/application-external.yml as a startup parameter of your JVM.
If you have multiple files, just seperate them with a comma. Note that you can easily use external properties like this to overwrite properties, not just add them.
I would advice to test this by getting your application to work with just your internal application.yml file , and then overwrite a (test) property in your external properties file and log the value of it somewhere.
Bind Yaml properties to objects
When working with Yaml properties I usually load them with #ConfigurationProperties, which is great when working with for example lists or a more complex property structure. (Which is why you should use Yaml properties, for straightforward properties you are maybe better of using regular property files). Read this for more information: Type-Safe Configuration properties
Extra: loading these properties in IntelliJ, Maven and JUnit tests
Sometimes you want to load these properties in your maven builds or when performing tests. Or just for local development with your IDE
If you use IntelliJ for development you can easily add this by adding it to your Tomcat Run Configuration : "Run" -> "Edit Configurations" , select your run configuration under "Tomcat Server" , check the Server tab and add it under "VM Options".
To use external configuration files in your Maven build : configure the maven surefire plugin like this in your pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dspring.config.location=file:${home}/conf/application-external.yml</argLine>
</configuration>
</plugin>
When running JUnit tests in IntelliJ:
Run → Edit Configurations
Defaults → JUnit
add VM Options -> -ea -Dspring.config.location=file:${home}/conf/application-external.yml
Yes, you need to use #PropertySource as shown below.
The important point here is that you need to provide the application_home property (or choose any other name) as OS environment variable or System property or you can pass as a command line argument while launching Spring boot. This property tells where the configuration file (.properties or .yaml) is exactly located (example: /usr/local/my_project/ etc..)
#Configuration
#PropertySource("file:${application_home}config.properties")//or specify yaml file
#ComponentScan({"be.ugent.lca","be.ugent.sherpa.configuration"})
#EnableAutoConfiguration
#EnableSpringDataWebSupport
public class Application extends SpringBootServletInitializer{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
There is a very simple way to achieve this.
Inside your original application.properties file you can just specify the following line:
spring.config.import=file:Directory_To_The_File/Property_Name.properties
It will automatically sync all the properties from the external property file.
Now lets say that you have a situation where you need to get properties from multiple property files. In that case, you can mention the same line in the external property file which in turn will take the remaining properties from the second property file and so on.
Consider the following example.
application.properties:
spring.config.import=file:Resources/Custom1.properties
Custom1.properties:
server.port=8090
.
.
.
spring.config.import=file:Resources/Custom2.properties
One of the easiest way to use externalized property file using system environment variable is, in application.properties file you can use following syntax:
spring.datasource.url = ${OPENSHIFT_MYSQL_DB_HOST}:${OPENSHIFT_MYSQL_DB_PORT}/"nameofDB"
spring.datasource.username = ${OPENSHIFT_MYSQL_DB_USERNAME}
spring.datasource.password = ${OPENSHIFT_MYSQL_DB_PORT}
Now, declare above used environment variables,
export OPENSHIFT_MYSQL_DB_HOST="jdbc:mysql://localhost"
export OPENSHIFT_MYSQL_DB_PORT="3306"
export OPENSHIFT_MYSQL_DB_USERNAME="root"
export OPENSHIFT_MYSQL_DB_PASSWORD="123asd"
This way you can use different value for same variable in different environments.
Use below code in your boot class:
#PropertySource({"classpath:omnicell-health.properties"})
use below code in your controller:
#Autowired
private Environment env;
I have mutli-module Gradle application and I would to add properties which I've defined in gradle.properties to be available in application.properties of all my subprojects in /src/main/resources folder.
What I've alread tried is adding processResources plugin to subprojects section.
subprojects {
processResources {
expand(project.properties)
}
// ...
As an example, I've defined the following property in gradle.properties file:
appVersion='0.0.1-SNAPSHOT'
Now, I want it to be present in application.properties, so I've added a placeholder as stated here. So, my application.properties looks the following way:
app.version=${appVersion}
Later on, I would like to use it using Spring, e.g.:
#Value("${app.version}")
However, after the project is built, properties are not replaced, so I have no version value in application.properties and still ${appVersion} placeholder. Any suggestions how to do that?
I feel strongly that you should have separate folders for separate purposes. Therefore I suggest moving application.properties to src/main/filteredResources. Then:
import org.apache.tools.ant.filters.ReplaceTokens
processResources {
with copySpec {
from 'src/main/filteredResources'
filter(ReplaceTokens, tokens: project.properties)
}
}
The problem was not in the Gradle configuration, but how my Spring Boot application started. I was running main() method directly from Intellij IDEA, which didn't work for me well, probably some of the tasks were not executed properly.
So, the solution is to run ./gradlew bootRun command. This way properties are getting correctly replaced.
I want to configure log4j2 to lookup the logging path dynamically from web startup (tomcat).
From the docs (http://logging.apache.org/log4j/2.x/manual/lookups.html) there is a web: lookup with different parameter possibilities.
At first I'm trying the provided example:
<Appenders>
<File name="ApplicationLog" fileName="${web:rootDir}/app.log"/>
</Appenders>
Result: ERROR Unable to create file ${web:rootDir}/app.log java.io.IOException
I also tried the other buildin properties like servletContextName and contextPath with the same error message.
So I'm probably still missing something important. But what?
Add log4j-web JAR
Your usual log4j-core JAR file on its own is not enough.
There is an additional component called log4j-web.
For automatic replacement of the ${web:...} placeholders in your logging configuration, you need the additional log4j-web JAR file. If you don't have this log4j-web JAR file, then Log4j2 itself will still work, but it will not replace these placeholders with anything. So for example ${web:rootDir} will just end up as the literal text ${web:rootDir}.
Perhaps you are missing that dependency in your project?
Log4j-web on Maven Central
Is ${web:rootDir} a value? The placeholder is not replaced by its real value.
In the page you can red:
Information on how to use Lookups in configuration files can be found in the Property Substitution: http://logging.apache.org/log4j/2.x/manual/configuration.html#PropertySubstitution
My build begins by defining 2 properties files, importing another build XML, and then commencing with all my other targets & tasks:
build.main.xml:
<project name="${proj.name}" default="assemble" basedir=".">
<!-- BASIC CONFIGURATIONS -->
<!-- Define build properties. -->
<property file="build.main.properties"/>
<property file="build.app.properties"/>
<!-- Imports. -->
<import file="${alt.build.file}"/>
<!-- Rest of buildscript omitted for brevity... -->
</project>
build.app.properties:
proj.name=test-proj
alt.build.file=build.app.xml
It seems that build.main.xml cannot seem to see/find any properties defined inside build.app.properties; specifically:
It cannot resolve ${proj.name}, and when I add the build.main.xml file to the Eclipse Ant view, the name of the build shows up as ${proj.name}
It cannot find build.app.xml imported from build.main.xml
What's going on here? Do ant builds only get to import one properties file or something?!? Where could I start troubleshooting?
Edit: using Eclipse editor my buildscript does not have any red/highlighted syntax errors that might be causing the ant plugin to work incorrectly, etc.
Edit: I am noticing issues with properties defined inside the build.main.properties to. If I try to echo them they don't get noticed by Ant either...
The Ant project name cannot be itself a property for the reason Jochen mentioned in his comment.
Try running your script with the -v option to see more logging. I have used a technique very similar to your <import file="${alt.build.file}"/> to branch my script based on the db platform, so there should be no problem with it.
I wondered if your property files are in the same directory then your build script is.