Reputation: 63
I am developing an multi-tenant REST spring boot application. I am able to dynamically switch between different data-sources based on a header value in every request. But my problem is on the application.properties file. The different tenants have different values for the same properties in their properties files.
How can I separate the properties files per tenant and also dynamically determine which properties files to use based on a value in the request header
Upvotes: 6
Views: 1377
Reputation: 12999
You can't switch profiles at runtime. Your options are limited to either creating a new ApplicationContext
which comes with its own drawbacks or you can load the tenant property files at startup and implement a tenant-specific getProperty
method to call when needed.
This ought-to handle the latter case:
@Component
public class TenantProperties {
private Map<String, ConfigurableEnvironment> customEnvs;
@Inject
public TenantProperties(@Autowired ConfigurableEnvironment defaultEnv,
@Value("${my.tenant.names}") List<String> tenantNames) {
this.customEnvs = tenantNames
.stream()
.collect(Collectors.toMap(
Function.identity(),
tenantId -> {
ConfigurableEnvironment customEnv = new StandardEnvironment();
customEnv.merge(defaultEnv);
Resource resource = new ClassPathResource(tenantId + ".properties");
try {
Properties props = PropertiesLoaderUtils.loadProperties(resource);
customEnv.getPropertySources()
.addLast(new PropertiesPropertySource(tenantId, props));
return customEnv;
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}));
}
public String getProperty(String tenantId, String propertyName) {
ConfigurableEnvironment ce = this.customEnvs.get(tenantId);
if (ce == null) {
throw new IllegalArgumentException("Invalid tenant");
}
return ce.getProperty(propertyName);
}
}
You need to add a my.tenant.names
property to your main application properties that contains a comma separated list of tenant names (name1, name2
, etc.). tenant-specific properties are loaded from name1.properties
, ... from the classpath. You get the idea.
Upvotes: 3
Reputation: 29
Spring profiles would work in your case.
If tenants are static in the sense predictive tenants and its properties only before starting the service then I would suggest tovgo for static profile specific files.
If some of properties can be changed whilst service is serving for other tenants, then it would be good to go for config server so that without restart you can change those.
If tenants are dynamic, you can go for db based on your data points, if tenants count may increase substantially.
Upvotes: 0