Can you stop Spring Cloud rebinding/reloading POJOs annotated with #ConfigurationProperties? - java

If you annotate a POJO with #ConfigurationProperties, it allows you to easily load properties from a (yml) properties file and make them available at runtime.
However, when Spring Cloud is on the classpath, the behaviour changes somewhat: the POJO is now re-bound whenever an EnvironmentChangeEvent is fired. That's great, unless you have manipulated the properties at app startup somewhat - those changes can now get overridden at any point.
Is there a way to stop that from happening (e.g. by adding another annotation to that class to say "never" rebind)?
In particular, I have a #SpringBootTest-annotated test class where a library I use is dynamically generating a port number. I'm accessing that number in my #Before method, and want to "inject" it into the POJO, so the app under test picks it up and connects to that port (i.e. the equivalent to -Dmy.port=0000 at JVM launch). What would be a better way to achieve that (if switching off the rebinding and just assigning the value to the right field doesn't work or is the wrong approach)?
I have tried setting it via System.setProperty(), unsurprisingly with little success, or to add it via adding a new PropertySource to the ApplicationContext, and by using the TestPropertySourceUtil.addInlinePropertiesToEnvironment() - all to no avail...

Related

Spring boot - Loading configuration property file in to java.util.properties

I need to load a configuration property fully into java.util.Properties file in my spring boot project and then need to pass this wherever needed. With Spring boot I can load the full file and can get the access of the values though keys. But how I can load the whole configuration file into Properties object or pass the spring loaded property (not a single value rather all the values) wherever required?
My current code:
Properties myProps= new Properties();
myProps.load(resourceAsStream);
If you're looking for specific ways of loading them using Spring-boot I'd suggest looking into:
Binding properties to an object by using the #Configuration, #ConfigurationProperties and #PropertySource annotations if you want to enforce and implicitly manage type-safety at all times
The Environment interface you can #AutoWire to your classes, if you don't need to enforce type-safety at all times (you can still do it, but you're not forced to). #PropertySource can be used in this case as well to load properties outside the default default-loaded application.properties, although they'll be loaded only when the application context refreshes (e.g. they won't be available while the application is booting up)
The PropertiesLoaderUtils class, as suggested in the comments, if you want to selectively load a configuration file at runtime for example
I usually recommend the first. The result is the same as using an #AutoWired Environment, with the advantages of implicit type-safety and improved readability. You can then get the properties and write them inside your java.util.properties if you need them to be there.
However, there is more than one way to do that, both using Spring-Boot or not. Loading properties like that is also perfectly fine, although arguably not the best practice since you're using Spring-boot.

Spring #Configuration class contains #Bean methods but how can I get execute init() first?

I'm on a Spring project and have skill level 1 with Spring.
2 days I have been reading and trying to get Jasypt encryption working with some existing code but the value that is passed is the ENC(....) value that needs to be transformed.
The one project that I'm to look at is a self ran project using a main() whereas the one I am on is a service that is called and does not run as the other.
I was last looking over this example Spring EnableEncryptableProperties with Jasypt but I noticed after awhile that it is pulling it's properties with the method call:
environment.getRequiredProperty("spring.datasource.username")
The method is pulling from the System variables which I don't see how the propertied get into it. None of the properties that are in my property file are present in the System property level.
What am I missing here as to how to get the system properties updated with what is in the application.properties file?
The other project is updating the System properties and then calls SpringApplication.run(Application.class, args), which is not applicable to this other project as it is not the same type of application.
Would love some guidance. Please no smart remarks as to take a class. I'm doing what I can outside of work but being at step 4 and the project is at step 321 it's going to be awhile before I get there.
If you want to execute some code before actual Spring been creation, you can use implement your custom BeanFactoryPostprocessor. Here is an example with EnvironmentPostProcessor, which can be useful for your situation with encrypted properties:
example
You can implement postProcessEnvironment in a next way:
Get all props from an environment
Check if a property value has 'ENC()'
Decrypt and set its value back
I believe that EncrytablePropertySource from jasypt-starter works in that way.
P. S. It's better to use the default approach with #EncrytablePropertySource if it is possible than reinventing a wheel with custom EnvironmentPostProcessor.

Can SpEL be passed an enviroment variable directly or is a properties file in some form always required?

We build micro services and I am working on a generic way of generating documentation for them. This has created a situation where I need to set a variable which is static across all our services yet has two possible values depending on the environment the service is deployed in. Hence I would like to inject a value based directly on an environment variable rather than through my Application.yml file, and it's various profiles, as I would usually do. Is there any way to do this?
Here is an example of what I imagine this would look like (with a syntax similar to what it would have looked like if it was a regular property in Application.yml):
#Value("#{enviromentProperties['environment'].equals['production'] ? jupiter : mars}")
private String APIGatewayHostname;
Just to be clear we have situations where we deploy several profiles behind the same proxy. Hence we want the hostname reference to be the proxy host so people don't attempt to call the service directly as this is not possible. We only have one proxy per environment regardless which profiles we are running at any given time hence my desire to use an environment variable rather than a property. Also this proxy is not really a part of the design of the services themselves so it seems counter intuitive to store it in multiple profiles in the Application.yml file.
NB: If there are other better ways to accomplish this feel free to let me know :)

Get list of Spring property placeholder and their resolved values

I would like to make all property placeholder and their resolved values of a running Spring (Boot) application available for process monitoring. In the first step this could be just by writing them to the logs or by creating a 'resolved.properties' file similar to the application.pid file.
All properties where property placeholder are used (implicit/explicit) should be considered.
Motivation: It is usually hard during operation to know the values of resolved properties. System properties or command line arguments are "visible" but e.g. hidden default values in the code (like #Value("${timeout:30000}")) are hard to find out. I would like to be able to answer the question "How does the configuration of the running application looks like?" in a generic way that I can use in all of my spring applications.
I know about the Spring Boot Actuator /configprops endpoint, but this only includes #ConfigurationProperties. I would like to get a list of all properties where placeholder are used.
The requirement does not seem to be new (see here or here) but I wonder if there is an appropriate (bootiful) way nowadays.
There is (currently) no way to obtain all the properties in the Environment abstraction. This is intentional as can be read here. This is also why it isn't possible to obtain all the values used for resolution.
The values and resolutions are logged at runtime telling which key was resolved from where at runtime. But that logging is quite verbose and logged each time a StringValueResolver is used.
You might get a partial result by providing your own customized PropertySourcesPlaceholderConfigurer which maintains a collection of resolved key/value pairs. But not every resolution uses the PropertySourcesPlaceholderConfigurer some directly use a StringValueResolver implementation bypassing the PropertySourcesPlaceholderConfigurer.
It doesn't cover all your needs (ie: properties from all files, default values, application arguments, etc.).
I'll still keep the answer for other readers/future reference.
Spring Boot's Actuator /env endpoint
You may use the /env endpoint. It lists a bunch of stuff but it also includes the content of application.properties (near the end):
applicationConfig: [classpath:/application.properties]={myproperty=blah, server.port=8080}

Spring integration and changing data routes

I'm reading through Spring Integration documentation and I still can't get into one thing: does Spring resolve all dependencies and make that automagic IoC dependency injection at compile time or at runtime?
I believed that it is runtime job to wire available components together in a data route from gateway to some data endpoint (e.g. DB). But since most of examples are made using DSL syntax in java, it seems that it's a compile time job.
So, glueing together beans in a data highway can be made only at compile time?
Summing up my comments here :
1) Spring IOC container manages beans from its creation till destruction. What this means is the beans are ready in sort of a bucket, which is a ready to use application. Thus, it is necessary to create the contents of the bucket at compile time, rather then runtime. This does not include hot-swapping of beans.. I hope this is what you were looking for.
2) You can create as many routes as you want, those all beans will be put in the container.... And as far as I understand, you cannot just change your source code and synchronize it with already running one, you have to atleast do a graceful restart. There is a bottom line to this, Spring must see if all beans are properly autowired, no circular dependencies, and there is no expectation of source code during run time. Sure you can get your beans via RMI, but that doesn't count as you have declared it already. So yes, compile time it is
The java DSL syntax is simply a different way of defining a flow definition (a series a bean definitions). The beans are still created and wired together during application initialization (runtime).

Categories

Resources