How does the spring framework map properties to a Java Object? - java

I am trying to do something very similar to what spring #ConfigurationProperties does to map properties to a Java POJO, but at runtime. I am hoping to be able to reuse the spring framework code that does this for spring properties.
I looked through a bunch of spring's code but I am having trouble isolating the code that does this specific functionality. I can write my own algorithm to do this, but it feels like a waste since I know this is existing functionality in the spring framework and I have spring dependencies in my project already.

After some more digging, I found the following class: ConfigurationPropertiesBinder, which binds properties from various PropertySources to a Bindable object. I was able to extract enough information from this bean to create my own version to do the conversion I was looking for.

Related

Where is utilizing Spring Beans instead of Classic Java Objects

I recently joined a company where I'm working extensively with Spring Boot microservices. I see how useful spring is for writing MVC code as well as managing cloud-deployed services with Spring Cloud. Something that has eluded me so far though is why we sometimes do and sometimes don't use Spring Beans. I don't see how labeling a class with Component makes it more useful to use than simply instantiating an object the classic way where we have more control over it. When we hand control over the object to Spring, it seems like it makes passing constructor parameters more difficult and only saves us from having to write a small bit of boiler plate code ie. new MyObject(). Even more confusing is why we sometimes would want to add a #Bean method into a configuration class just so we can have a little more control over how the object is created.
It seems like we have a lot more flexibility and control over our objects if we just employ "classic" java design patterns instead of relying on Spring to manage beans for us. Can someone explain what I'm missing?
Even more confusing is why we sometimes would want to add a #Bean
method into a configuration class just so we can have a little more
control over how the object is created
#Component/#service/#Repository and #Bean are quite different things, don't get confused about these 2.
#Component is used to auto-detect and auto-configure beans using classpath scanning. There's an implicit one-to-one mapping between the annotated class and the bean.
So #Component is used for component scanning and automatic wiring
#Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically as above. It decouples the declaration of the bean from the class definition and lets you create and configure beans exactly how you choose.
When should you use #Bean?
Sometimes automatic configuration is not an option. When? Let's imagine that you want to wire components from 3rd-party libraries (you don't have the source code so you can't annotate its classes with #Component), so automatic configuration is not possible.

How #ConfigurationProperties works internally in spring

I have used Spring #ConfigurationProperties to map values from properties file to java object. It works flawlessly and I am trying to find the logic behind that,
I tried Java reflection packages to create proxy but it allows only interfaces. For classes I need to use third party library which I would like avoid at this point.
I explored the source in IDE as well as in Github but not able to get the
actual code.
Can anyone direct me in the right way to find the logic behind the #ConfigurationProperties and how it works?

Javax Validation - Values from Properties

I have a Spring Boot project (currently using 2.2.6), with web starter.
In some classes I use validation annotations like
#Size(max = 1, min = 2)
or
#Pattern(regexp = "[0-9]+")
on fields, from javax.validation.constraints
It works as expected, but the values for the annotations are hard coded. I would like to set them dynamically, for example reading from a properties file, because in some situations the values might be different.
Is that possible, how to do it?
These annotations are implemented under the hood by Hibernate Validator project.
The default messages coming from annotation values appear due to the Default Interpolator (the concept of Hibernate validator).
So the solution, I believe should consist of two steps:
Create a custom Message Interpolator in terms of spring Validator project. Take a loot here for details, they have an example of message interpolator that reads from some file system resource. At this point this has nothing to do with spring / spring boot yet.
Integrate the message interpolator that you've created during Step 1 with spring boot application.
For that your code should include something like this:
Validation.byDefaultProvider().configure().messageInterpolator(
new MyCustomMessageInterpolator(
Validation.byDefaultProvider().configure().getDefaultMessageInterpolator())
);
I've found a tutorial about such an integration here
This tutorial seems to not telling where exactly you should put this code, so I think you should try some listener that will listen to "ApplicationStarted" event or something
I think in Spring boot values in annotations have to be hardcoded and can not be set as placeholders for property values. I am not completely sure about it and maybe wrong but I think this is the case. A while ago, I dealt with a similar issue for scheduled job runner, and I ended up running my own custom code that allows parsing time intervals and other custom needed properties from properties files. I included that feature into my own Open source library so it could be re-used. Here you can read about this particular feature (JavaDoc). In general, if you are interested you can read about the library here and get it from Git (Including sources and JavaDoc) or Maven Central. Just JavaDoc could be seen here
Perhaps this is also possible solution, but requires to define custom annotations, so the build-in annotations from javax.validatation.constraints can't be used:
Spring Bean Validation with configurable constraint values

How can I check all qualifying beans for Spring-boot or related frameworks

I want to know how to discover all qualifying beans that should be implemented when using some component together Spring.
For example, when using JPA and Spring Boot we need beans as like as sessionFactory and dataSource (Any more? I don't know, see It?).
Is there any official place where I can check the pre requisite list of beans?
I've made many searches through the official schemas and I couldn't find a pattern for bean dependencies.
After some time I've come into some steps that helped me and maybe help others. I'm answering this also because there are a lot of material related to Beans in XML files and in a Maven project, but if you try to create a XML free project, things become more rare when using Spring.
Notice: in deep Spring doesn't cares if the bean is an annotation or inside a XML. I preferred these configurations as a personal choice.
Some project details:
Gradle (project configurations are in application.properties file)
Java 8
Bean class(es) for src and for test. Note: You can use extends among them.
In case of doubt, https://start.spring.io/ an awesome way to create from nothing a spring project with your dependencies. Gradle format dependencies usually can be found at maven repository nearby the maven format.
Resolution:
Create a unit test (e.g JUnit) to just test your layer. For example mine was persistence layer.
Be careful to add each framework(that is going to be loaded by Spring) at once. Dealing with many unconfigured frameworks at same time would lead to caos since may be hard to figure out from where the Bean class should come from.
When the test fails look at his bottom of your console. Some exception will be thrown saying that a Bean with some name is missing. This are the guys you need.
Create a method typed with #Bean inside a class typed with #Configuration. This method must returns variable/object type complained in the exception message. Additional annotations maybe be required, for example, #EnableTransactionManagement for JPA beans.
Bonus:
Spring is deeply connected to IoC (dependency injection) and containers. Take a look at this contents because when you see that you realizes why to use Beans.

how do java annotations work with spring, are they scanned at runtime or at startup?

Just trying to understand how Java annotations work under the covers.
Seeing as spring relies on annotations and scanning the object graph for DI and AOP (reflection), curious how things actually work.
With spring, are all lookup mappings etc. done at startup, so at runtime spring looks at its own inner mappings for DI/AOP/etc. instead of scanning the entire object graph?
Performance wise, if what I am guessing above is correct, it is basically performing a hash lookup?
Spring scans classes in the specified package when <context:component-scan> is present in the config.
Otherwise, Spring only looks at the annotations of classes explicitly declared in the config.
It is not true that Spring "relies" on annotations. Configuring your classes via annotations is just one option, using XML or other configuration files is another.

Categories