Skip to content

Instantly share code, notes, and snippets.

@alexanderankin
Last active October 29, 2023 20:08
Show Gist options
  • Save alexanderankin/0ac7884fe84e13cc5aff014ae84c6b86 to your computer and use it in GitHub Desktop.
Save alexanderankin/0ac7884fe84e13cc5aff014ae84c6b86 to your computer and use it in GitHub Desktop.
// example-config-data-test/build.gradle
plugins {
id 'conventions' // things like lombok and maven central
id 'spring-3-conventions' // things like implemenatation platform(spring boot dependencies)
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation project(':example-config-data')
}
// example-config-data/src/main/java/org/example/config_data_source/ExampleConfigData.java
package org.example.config_data_source;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.config.*;
import org.springframework.core.env.MapPropertySource;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@Slf4j
public class ExampleConfigData {
public static final String CONFIG_PREFIX = "example-config-data:";
@Slf4j
static class Resolver implements ConfigDataLocationResolver<ExampleConfigLocation> {
@Override
public boolean isResolvable(ConfigDataLocationResolverContext context,
ConfigDataLocation location) {
return location.getValue().startsWith(CONFIG_PREFIX);
}
@Override
public List<ExampleConfigLocation> resolve(ConfigDataLocationResolverContext context,
ConfigDataLocation location)
throws
ConfigDataLocationNotFoundException,
ConfigDataResourceNotFoundException {
// return List.of(new ExampleConfigLocation().setLocation(location.getValue()));
return List.of();
}
@Override
public List<ExampleConfigLocation> resolveProfileSpecific(ConfigDataLocationResolverContext context,
ConfigDataLocation location,
Profiles profiles)
throws ConfigDataLocationNotFoundException {
if (!isResolvable(context, location))
return List.of();
// vault one does it here, not sure why
context.getBootstrapContext()
.registerIfAbsent(ExampleConfigDataConfiguration.ExampleConfigDataProperties.class,
bootstrapContext -> context.getBinder().bindOrCreate(
ExampleConfigDataConfiguration.ExampleConfigDataProperties.PREFIX,
ExampleConfigDataConfiguration.ExampleConfigDataProperties.class));
return List.of(new ExampleConfigLocation().setLocation(location));
}
}
@Slf4j
static class Loader implements ConfigDataLoader<ExampleConfigLocation> {
@SuppressWarnings("RedundantMethodOverride")
@Override
public boolean isLoadable(ConfigDataLoaderContext context,
ExampleConfigLocation resource) {
return true;
}
@Override
public ConfigData load(ConfigDataLoaderContext context,
ExampleConfigLocation resource)
throws
IOException,
ConfigDataResourceNotFoundException {
var props = context.getBootstrapContext().get(ExampleConfigDataConfiguration.ExampleConfigDataProperties.class);
if (!props.isEnabled())
return null;
System.err.println("we're here, loading: " + resource); // because spring logging isn't available yet
return new ConfigData(List.of(new MapPropertySource(resource.toPropertySourceName(), Map.of("spring.application.name", "def"))));
}
}
@Slf4j
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
static class ExampleConfigLocation extends ConfigDataResource {
ConfigDataLocation location;
String toPropertySourceName() {
return "ExampleConfigLocation_" + location;
}
}
}
// example-config-data/src/main/java/org/example/config_data_source/ExampleConfigDataConfiguration.java
package org.example.config_data_source;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@AutoConfiguration
@EnableConfigurationProperties(ExampleConfigDataConfiguration.ExampleConfigDataProperties.class)
public class ExampleConfigDataConfiguration {
@Data
@Accessors(chain = true)
@ConfigurationProperties(ExampleConfigDataProperties.PREFIX)
public static class ExampleConfigDataProperties {
public static final String PREFIX = "example.config-data";
boolean enabled = true;
}
}
// example-config-data/build.gradle
plugins {
id 'conventions'
id 'spring-3-conventions'
}
dependencies {
implementation 'org.springframework.boot:spring-boot'
implementation 'org.springframework.boot:spring-boot-autoconfigure'
}
# example-config-data/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.example.config_data_source.ExampleConfigDataConfiguration
# example-config-data/src/main/resources/META-INF/spring.factories
org.springframework.boot.context.config.ConfigDataLocationResolver=\
org.example.config_data_source.ExampleConfigData.Resolver
org.springframework.boot.context.config.ConfigDataLoader=\
org.example.config_data_source.ExampleConfigData.Loader
// example-config-data-test/src/main/java/org/example/config_data_test/TestApp.java
package org.example.config_data_test;
import lombok.Builder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.annotation.Bean;
@Slf4j
@SpringBootApplication
public class TestApp {
public static void main(String[] args) {
System.setProperty("spring.config.import", "example-config-data:/abc");
new SpringApplicationBuilder(TestApp.class)
.web(WebApplicationType.NONE)
.run(args);
}
@Bean
ApplicationRunner applicationRunner(@Value("${spring.application.name:no-name}") String value) {
return a -> log.info("value is {}", value);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment