0

In Springboot, let's say I have a configuration that reads a properties file like this.

@Configuration @PropertySource( "classpath:karmiel.properties") 

Contents of karmiel.propeties:

keystore=https:/blah/vault username-token=vault-user-value password-token=vault-password-value url=vault-connection+path 

karmiel.properties is transmitted automatically during aks pods startup and forbidden from having human intervention to modify its contents.

I would like that all names of properties read from karmiel.properties to be spontaneously prefixed with "karmiel." ,

so that it was as though the contents of the properties file were

karmiel.keystore=https:/blah/vault karmiel.username-token=vault-user-value karmiel.password-token=vault-password-value karmiel.url=vault-connection+path 

Such prefixing is necessary because more than one such file is transmitted and read, most of them with clashing property names. For example, there might be a file sderot.properties and I would need Spring to append "sderot." to the names of its properties.

The obvious solution is to update all the secrets generation processes to include the prefixes in the property names before transmitting the file.

Let's say modifying those processes is not possible and that writing intervention deployment code to transform the properties files is also discouraged.

That leaves me with one option which is to read the properties files programmatically.

However, I am hoping if I could reduce the amount of code written by depending on @PropertySource and then hoping that Spring has an automagic feature to append a prefix to the property names.

1 Answer 1

2

The @PropertySource annotation has a factory element that allows you to customize how the properties are generated.

When you implement the PropertySourceFactory interface, you have to implement the following method:

@Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { // TODO: implement } 

From the EncodedResource, you could obtain the filename so you could use it as the prefix of the properties:

String filename = resource.getResource().getFilename(); int lastPositionOfDot = filename.lastIndexOf('.'); String prefix = lastPositionOfDot > 0 ? filename.substring(0, lastPositionOfDot) : filename; 

(see alternatives at How to get the filename without the extension in Java)

In addition, you can also obtain the original properties with PropertiesLoaderUtils.loadProperties() and then loop over each property to add the prefix:

Properties sourceProperties = PropertiesLoaderUtils.loadProperties(resource); Properties resultProperties = new Properties(); Set<String> propertyNames = sourceProperties.stringPropertyNames(); propertyNames.forEach(propertyName -> resultProperties.put( prefix + "." + propertyName, sourceProperties.getProperty(propertyName)) ); 

And then finally, you have to transform the Properties into a PropertySource, but this thing requires a name. You could use the name method parameter, but this one is optional (depends on whether you set the name within @PropertySource(name = "..."). So alternatively, you could do something similar to what Spring does:

if (name != null) return new PropertiesPropertySource(name, resultProperties); String description = resource.getResource().getDescription(); if (!description.isBlank()) return new PropertiesPropertySource(description, resultProperties); String className = resource.getClass().getSimpleName(); int hashCode = System.identityHashCode(resource); String dynamicName = className + "@" + hashCode; return new PropertiesPropertySource(dynamicName, resultProperties); 

After that, you can change your @PropertySource annotation to:

@PropertySource(value = "classpath:karmiel.properties", factory = PrefixPropertySourceFactory.class) 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.