Spring Boot application has about 20 ObjectMappers - spring-boot

I'm trying to configure the Jackson ObjectMapper in a Spring Boot application. I've tried various approaches as suggested here and in the documentation (e.g. using a Jackson2ObjectMapperBuilder or Jackson2ObjectMapperBuilderCustomizer #Bean). I want to register a mixin to exclude some fields in the DefaultMessageSourceResolvable class, which should be fairly straightforward.
However, by placing a breakpoint in the ObjectMapper constructor, I've seen that there are about 20 instances being created. Multiple instances of Jackson2ObjectMapperBuilder are created as well.
Creating a bean of the Jackson2ObjectMapperBuilderCustomizer type does not work either; it gets invoked, but the mixin is not registered in the instance which is eventually used for serialization.
Is it normal to have so many instances of these classes? If it is, what might be the reason that my customization efforts fail? If not, what might be wrong and how may it be fixed?

Related

Spring-Boot: share an object between components

I have a custom object which I like to share between different Spring-Boot components (e.g. WebHandler, Authenticator, Filter).
Maybe the easiest way is a static object in the main-class but thats not very elegant.
Whats the most common way to do it?
The whole point of spring as a container is to manage your objects.
Now statics do not have a well defined lifecycle ( when exactly this object gets created, who disposes it when the application gets closed, etc)
Speing answers all these questions by using thecdependency injection techniques. If you're already using spring then you should define this 'shared object' as a spring bean (by default it will have scope singleton just like static object that you've proposed but managed by spring container which is better - it will manage the lifecycle of the object by itself)
Then given the classes that must be dependent of the object are beans by themselves you can inject that bean:
class MySharedObject {}
class MyWebHandler implementsWebHandler {
private final MySharedObject mySharedObject;
public MyWebHandler(MySharedObject mySharedObject) {
this.mySharedObject = mySharedObject;
In addition to the lifecycle management this way allows easy unit testing of classes that use the shared object (like 'MyWebHandler' in this case) - now uou can create a stub/mock of the shared object and pass it into the handler - something that cannot really be easily done when using statics
So in summary if you can use spring and define it as a bean - by all means do so, the usage of statics is discouraged if you already have a dependency injection container
If you have shared object first of all it should not contain any state as differents components can change it and also it should be thread safe.
It is fine to reuse it across all components via #Autowired annotation but you need to be sure that it is threadsafe. Spring bean scope singleton is not thread safe out of box it dependes how you write the code.
You can use as static method but it dependes on logic which you have and if those component has an dependency on another objects and if they need to in spring IOC.

Spring - how to debug to find specific use of spring's auto-wiring or a request parameter?

Spring is auto-wiring in a request parameter - let's call it "bob".
I don't know where nor how it is doing this, so I cannot debug it. What spring specific code (using intellij, so I can at lest set a conditional) would be appropriate to find where the auto-wiring of the request parameter is happening, so I can work out what the system is doing?
I think I understood the question, so I will try to answer it as best as I can.
You are facing a dilemma of choosing between managing your instances, or letting Spring manage them. If you let Spring manage dependency injection, you will often face situations where you wish you had more fine control over the beans lifecycle.
By default, Spring beans are "singletons", which means that only one
instance of that object will be created, and every class that demands
a dependency injection of that object will receive the same instance.
The first step on beans lifecycle is its construction. You can setup a breakpoint to catch that moment on any method annotated with #PostConstruct. This article describes the need of running some code on bean initialization, and how it is solved by this annotation. For example:
public class AnyBean {
#PostConstruct
public void init(){
// any code or breakpoints inserted here will
// be run whenever an instance of this bean is created.
// if a singleton bean, only one instance is created and,
// only one #PostConstruct will be called.
// If a bean is a prototype bean, a new instance will be created
// for every dependency injection, and hence one #PostConstruct
// will be called for each.
}
}

Spring Context Test With Just One Bean

What's the recommended way to run a spring boot test where only the one subject under test is configured in the context.
If I annotate the test with
#RunWith(SpringRunner.class)
#SpringBootTest(properties = "spring.profiles.active=test")
#ContextConfiguration(classes = MyTestBean.class)
Then it seems to work - the test passes, the context starts quickly and seems to only contain the bean that I want. However, this seems like an incorrect use of the #ContextConfiguration(classes = MyTestBean.class) annotation. If I understand correctly the class that I reference is supposed to be a Configuration class, not a regular spring service bean or component for example.
Is that right? Or is this indeed a valid way to achieve this goal? I know there are more complex examples like org.springframework.boot.test.autoconfigure.json.JsonTest which use #TypeExcludeFilters(JsonExcludeFilter.class) to control the context - but this seems overkill for my use case. I just want a context with my one bean.
Clarification
I know that I can just construct the one bean I am testing as a POJO without a spring context test and remove the three annotations above. But in my precise use case I am actually reliant on some of the configuration applied to the context by settings in the application-test.properties file - which is why I've made this a Spring Boot test with a profile set. From my perspective this isn't a plain unit test of a single class in isolation of the spring context configuration - the test is reliant on certain configuration being applied (which is currently provided by the spring boot app properties). I can indeed just test the components as a POJO by creating a new instance outside of a spring context, I'm using constructor injection making the providing of necessary dependencies simple but the test does rely on things like the log level (the test actually makes assertions on certain logs being produced) which requires that the log level is set correctly (which is currently being done via logging.level.com.example=DEBUG in a properties file which sets up the spring context).
For starters, reading the documentation first (e.g., the JavaDoc linked below in this answer) is a recommend best practice since it already answers your question.
If I understand correctly the class that I reference is supposed to be
a Configuration class, not a regular spring service bean or
component for example.
Is that right?
No, that's not completely correct.
Classes provided to #ContextConfiguration are typically #Configuration classes, but that is not required.
Here is an excerpt from the JavaDoc for #ContextConfiguration:
Annotated Classes
The term annotated class can refer to any of the following.
A class annotated with #Configuration
A component (i.e., a class annotated with #Component, #Service, #Repository, etc.)
A JSR-330 compliant class that is annotated with javax.inject annotations
Any other class that contains #Bean-methods
Thus you can pass any "annotated class" to #ContextConfiguration.
Or is this indeed a valid way to achieve this goal?
It is in fact a valid way to achieve that goal; however, it is also a bit unusual to load an ApplicationContext that contains a single user bean.
Regards,
Sam (author of the Spring TestContext Framework)
It is definitely a reasonable and normal thing to only test a single class in a unit test.
There is no problem including just one single bean in your test context. Really, a #Configuration is (typically) just a collection of beans. You could hypothetically create a #Configuration class just with MyTestBean, but that would really be unnecessary, as you can accomplish doing the same thing listing your contextual beans with #ContextConfiguration#classes.
However, I do want to point out that for only testing a single bean in a true unit test, best practice ideally leans towards setting up the bean via the constructor and testing the class that way. This is a key reason why the Spring guys recommend using constructor vs. property injection. See the section entitled Constructor-based or setter-based DI of this article, Oliver Gierke's comment (i.e. head of Spring Data project), and google for more information. This is probably the reason you're getting a weird feeling about setting up the context for the one bean!
You can also use ApplicationContextRunner to create your context using a test configuration of your choice (even with one bean if you like, but as other people have already mentioned for one bean it's more reasonable to use the constructor the classical way without using any spring magic).
What I like this way of testing is the fact that test run very fast since you don't load all the context. This method is best used when the tested bean doesn't have any Autowired dependencies otherwise it's more convenient to use #SpringBootTest.
Below is an example that illustrates the way you can use it to achieve your goal:
class MyTest {
#Test
void test_configuration_should_contains_my_bean() {
new ApplicationContextRunner()
.withUserConfiguration(TestConfiguration.class)
.run(context -> {
assertThat(context.getBean(MyTestBean.class)).isNotNull();
});
}
#Configuraiton
public static class TestConfiguration {
#Bean
public MyTestBean myTestBean(){
new MyTestBean();
}
}
}

#Bean annotation context config cashing data

I'm following this tutorial:
http://www.zenjava.com/2011/10/24/multiple-controllers-with-shared-resources/
And my question is (regarding Spring annotation context configuration):
why #Bean annotation is cashing data between all Person instances? And how to avoid that if needed?
Sorry for trivial question but I'm new to Spring
What is actually happening, is that all beans defined in Spring are Singleton by default (not in a Design Pattern sense, but in a container managed sense, meaning that Spring will reuse the same Person instance whenever it needs a dependency of class Person.class).
If you need to have different instance of Person injected into each dependency, you need to specify #Bean(scope=DefaultScopes.PROTOTYPE)

Scenario when we may be needing #Configurable in spring?

I have question about the need of using #configurable. I have gone through the blog that explains how to use #configurable. But the question that comes to my mind is, what can be the scenario when we need to use #configurable. I can think of two scenarios where it can be useful
In a legacy project, when we are already making any bean with new operator and we want to make it spring managed.
In a new project, we want to enforce that even if developer makes the bean with new operator, still it is spring managed.
Otherwise for new beans we can always declare them in applicationContext.xml and I do not see any need to declare them #configurable.
Please let me know if above understanding is correct or if I am missing something.
UPDATE:- Basically as per my understanding configurable is generally used to inject dependency when creating the object with new operator. But why would i be creating the object with new operator when i am using spring
#Configurable annotation is meant for injecting dependencies in domain-driven applications. That means, in such applications, the domain objects interact with each other to perform a certain operation.
Take the following example:
In an invoicing application, the Invoice class provides a constructor to create it, then it has methods to validate, and finally persist it. Now, to persist the invoice, you need a DAO implementation available within the invoice. This is a dependency you would like to be injected or located. With Spring's #Configurable, whenever an invoice is created using the new operator, the appropriate DAO implementation will get injected and can be used for all persist operations.
I had a more realtime scenario where I used #Configurable annotation as described here.

Resources