How to remove a dependency in Gradle depending on the Spring Boot runtime environment? - gradle

Not sure if this is a Gradle question or a Spring Boot one, but here goes...
I am using Spring security and LDAP in a spring boot application.
I have the following dependencies in my build.gradle:
compile 'org.springframework.security:spring-security-ldap:3.2.4.RELEASE'
compile 'org.apache.directory.server:apacheds-server-jndi:1.5.5'
The second of these supplies an embedded LDAP server that is only needed during development.
I have established a SB #Profile and configure/load an LDIF file into the embedded server within a class that has the #Profile('development') annotation.
The question is: how to remove the second dependency when not in dev mode?
I establish the spring.profiles.active property within my config/application.yml file, thusly:
spring:
profiles:
active: development
Can I reference spring.profiles.active so that I can somehow exclude the unneeded dependency?

For posterity, what I ended up doing...
At the top of my build.grade file:
def readActiveProfile() {
final config = new org.yaml.snakeyaml.Yaml().loadAll(new File('config/application.yml').newReader())
final defaultPart = config?.take(1)
defaultPart?.spring?.profiles?.active
}
final activeProfile = readActiveProfile() ?: ['development']
This reads the config file that I am keeping my externalised settings in (one of which is the setting defining the active profile).
And then, in the dependencies section:
compile 'org.springframework.security:spring-security-ldap:3.2.4.RELEASE'
if( ! ('production' in activeProfile))
compile 'org.apache.directory.server:apacheds-server-jndi:1.5.5'
This works well enough for my purposes, but doesn't feel quite right; I was assuming that there would be a more idiomatic "Gradle way" of doing this.

Related

In which class in the source code of spring-boot or spring is the application.yml or application.properties file processed?

In which class in the source code of spring-boot or spring is the application.yml file or application.properties processed?
For spring boot (version 2.x) the application properties are loaded from the environment into the context via a PropertySourceLoader.
In for example the spring-boot-2.6.3.jar we can find the following file:
META-INF/spring.factories
# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader
Where PropertiesPropertySourceLoader loads .properties and .xml files, and YamlPropertySourceLoader loads .yml and .yaml.
These are loaded with the SpringFactoriesLoader, which we can see in action in org.springframework.boot.context.config.ConfigFileApplicationListener (deprecated) or org.springframework.boot.context.config.StandardConfigDataLocationResolver (via ConfigDataEnvironmentPostProcessor -> ConfigDataEnvironment -> ConfigDataLocationResolvers) :
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(PropertySourceLoader.class,
getClass().getClassLoader());
You can read in the ConfigFileApplicationListener JavaDoc that the properties are indeed loaded with this class:
EnvironmentPostProcessor that configures the context environment by loading properties from well known file locations. By default properties will be loaded from 'application.properties' and/or 'application.yml' files in the following locations:
file:./config/
file:./config/*/
file:./
classpath:config/
classpath:
...
If you're interested in context loading from the environment in spring(boot), I suggest you setup your project with maven, download the sources jars, and have a look around in the mentioned factories file. You will find more relevant code in the org.springframework.boot.env and org.springframework.boot.context (config and properties) packages.
You can find your application.yml or application.properties at the src/main/resources. You can have as many as possible configurations for your spring boot application for every case. Lets assume that you have 3 local-profiles like demo, production and server, so you made 3 configuration and assumingyou set for active profile the demo at the application.yml . I hope you get the idea. Its the first thing that actually is running before the springboot is up.
Please look the officials docs !

How to configure netflix dgs?

This is a really simple question, but hard to find the answer.
I'm using kotlin DSL and gradle (so build.gradle.kts and settings.gradle.kts).
I'm using netflix-dgs and spring boot like so:
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("com.netflix.graphql.dgs:graphql-dgs-spring-boot-starter")
And of course a few others (e.g. extended scalars).
I've figured out how to edit my generateJava task:
tasks.withType<com.netflix.graphql.dgs.codegen.gradle.GenerateJavaTask> {
schemaPaths = mutableListOf("$projectDir/src/main/resources/schema")
packageName = "envoy.roomba.netflix.dgs.generated"
}
How do I edit the rest of the configuration mentioned here? https://netflix.github.io/dgs/configuration/.
I tried a gradle.properties file, I've looked briefly at extending #DgsAutoConfiguration, but without any luck.
you can configure properties in the applciation.yml file or application.properties whatever is relevant in your case. Since you are using spring boot, DGS will pick up properties from your application properties file.

Different YAML configuration file for junit test using an Externalized configuration in Spring Boot

I am following a tutorial on using external configuration files for Spring Boot. I got everything to work exactly as intended but I'm having issues overriding the default YAML config for my tests.
Could someone please point me in the right direction or advice if using '#PropertySource' is the best way to load config files into the project (There is a bunch of properties and I would like to keep the application.yaml as clean as possible)
Project Structure:
src: - main/resources/foo.yml <-- always loads this one
- test/resources/foo.yml <-- never loads
What I tried:
#PropertySource(value = "classpath:foo.yml")
Doesn't load test/resoruces/foo.yml to the classpath
ActiveProfiles()
How I usually change config properties but in this case, it's not a profile so it doesn't work.
Details:
Spring boot: 2.2.7.RELEASE
Try this:
#TestPropertySource(properties = { "spring.config.location=classpath:foo.yml" })

Primitive Axon App run as Fat JAR Doesn't Autoconfigure Axon Beans

PROBLEM:
RESEARCH: At https://gitlab.com/ZonZonZon/simple-axon.git I've made up a simple Axon-app to show that JAR-artifact built with Gradle-plugin com.github.johnrengelman.shadow doesn't autoconfigure Axon beans when (when run as JAR). Though it runs fine under Intellij.
From project root in terminal:
run gradle clean build shadowJar;
java -jar build/simpleaxon.jar;
Stacktrace is enclosed here. I expect that Axon Autocongiguration provides beans like CommandBus, Snapshotter and other by default.
QUESTION: How to autoconfigure default axon beans in a fat jar?
So, this took my some investigation to get a hunch what is going wrong, but I know what the problem is.
Quick notice, it's not an Axon specific thing, rather the plugin you are using.
I ran your sample project and indeed ended up with the same result; no Axon beans were being wired, ever. That led me to investigate the process of creating fat JAR's step by step. First Maven, then Spring Boot with Maven, then Gradle with Spring Boot and finally with the Shadow plugin you are referring too.
This endeavour landed me on this issue, which states as much as "projects which require the use of META-INF files need to add this to the shadow plugin, and this should be documented".
The portion referenced through this is the following:
import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer
// Left out all other specifics from your 'build.gradle' file
shadowJar {
// Required for Spring
mergeServiceFiles()
append 'META-INF/spring.handlers'
append 'META-INF/spring.schemas'
append 'META-INF/spring.tooling'
transform(PropertiesFileTransformer) {
paths = ['META-INF/spring.factories' ]
mergeStrategy = "append"
}
setArchiveFileName("simpleaxon.jar")
getDestinationDirectory().set(new File(projectDir, "./build"))
}
After adding that piece of logic to your build.gradle file, I could run your sample project as expected.
I've hit a similar issue when using Axon in a multimodule Gradle project. The app would not work when packaged and worked fine in IDE. The exact error I was getting was
org.axonframework.messaging.annotation.UnsupportedHandlerException: Unable to resolve parameter 0 in handler
The reason for this was because ParameterResolverFactories were not loaded due to the META-INF/services resources not being resolved correctly in the shadow jar plugin as #Steven hinted.
I've managed to fix it with simply (using Kotlin DSL in Gradle):
tasks.shadowJar {
mergeServiceFiles()
}
#Steven 's solution was the only one working for me, after searching for a long time for other solutions.
The Gradle Kotlin Version looks like this https://github.com/spring-projects/spring-boot/issues/1828#issuecomment-607352468:
import com.github.jengelman.gradle.plugins.shadow.transformers.PropertiesFileTransformer
plugins {
id("com.github.johnrengelman.shadow") version "7.1.2"
}
...
tasks.shadowJar {
// Required for Spring.
// The shadowJar plugin should merge the services correctly, but it doesn't!
mergeServiceFiles()
append("META-INF/spring.handlers")
append("META-INF/spring.schemas")
append("META-INF/spring.tooling")
transform(
PropertiesFileTransformer().apply {
paths = mutableListOf("META-INF/spring.factories")
mergeStrategy = "append"
})
}

Environment Configuration Spring Boot

Created a Spring Boot application that will need to migrate from "Local Dev" to "Test", "QA" and "Prod" environments.
Application currently uses a "application.properties" for database connectivity and Kafka configuration.
I am wanting to deploy to "Test" and realized that the properties will not work for that enviornment. After reading the ref docs, it looks like I can simply copy the application.properties file and add a new one application-test.properties, so on, and then run the standalone jar with a -Dspring.profiles.active=test and that seems to work.
But by the time I am done, that means I h ave 4 different appliction-XXXXX.properties files in the jar which may or may not be bad. I know the ultimate configuration would be to use Spring Config server, but right now we are not there with regards to this.
Can anyone validate that using multiple properties files is viable and will work for a bit, or if I am looking at th is all wrong. I do not want to have configuration on the servers in each environment, as I am thinking these mini-services should be self-contained.
Any input would be appreciated.
in a word, your configuration file should be outside your source code.
#PropertySource(value = {"classpath:system.properties"})
public class EnvironmentConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer properties() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Let's say it's named "system.properties", which will be uploaded to server at deployment stage under your application classpath.

Resources