How to avoid Spring Boot uses my MappingJackson2HttpMessageConverter Bean? - java

I'm using Spring Boot 2. I'd like to define a singleton bean of type MappingJackson2HttpMessageConverter, which will be used only by other beans.
By default, Spring Boot picks up a user defined MappingJackson2HttpMessageConverter and replaces the default instance with the one provided by the user, as stated by official documentation (https://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-customize-the-jackson-objectmapper):
If you provide any #Beans of type MappingJackson2HttpMessageConverter, they replace the default value in the MVC configuration. Also, a convenience bean of type HttpMessageConverters is provided (and is always available if you use the default MVC configuration). It has some useful methods to access the default and user-enhanced message converters.
This is my configuration class:
#Bean
public MappingJackson2HttpMessageConverter myJacksonConverter() {
...
}
#Bean
#Scope("prototype")
public MyClient myClient(){
MyClient c = new MyClient();
c.setConverter(myJacksonConverter());
return c;
}
So, I want MappingJackson2HttpMessageConverter as a singleton bean, but I don't want that Spring Boot uses it at global application level.

I'd consider not defining your custom converter as a #Bean. Instead, you could create your custom converter and store it in a field of a #Configuration class and then reference it from there. The #Configuration class will only be created once so you're guaranteed to only get a single instance of your custom converter.

If it is used only inside the same config class, you can avoid to use #Bean annotation.
#Bean
public MyClient myClient(){
MyClient c = new MyClient();
c.setConverter(myJacksonConverter());
return c;
}
private static MappingJackson2HttpMessageConverter myJacksonConverter() {
}

See if this works .. Define a class that extends from MappingJackson2HttpMessageConverter and autowire it.
class MyCustomMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {}
#Bean
public MyCustomMappingJackson2HttpMessageConverter myJacksonConverter() {
...
}
#Bean
public MyClient myClient(){
MyClient c = new MyClient();
c.setConverter(myCustomJacksonConverter());
return c;
}```

Related

Spring : creating beans with #Bean

I have an issue with beans creations :
#Bean
Service carService() {
return new Service(new CarRepository(), "car");
}
My issue is that CarRepository class has a dependency to EntityManager em variable (with #PersistenceContext)
So if I use new operator, I'm missing this dependency (because I'm instanciating myself the bean).
Also I have many services (CarService, BikeService etc...) and many repositories too (CarRepository, BikeRepository etc...). So using annotations directly in classes seems difficult.
So any solutions ?
Simple. Pass your repository as dependency into your Bean factory function:
#Bean
Service carService(final CarRepository carRepository) {
return new Service(carRepository, "car");
}
The repository needs to exist as a bean itself. You can create the repository bean in another bean method of a configuration class, or by annotating the class and having it created during component scanning.
I think you need to annotate every repository class with #Repository
annotation. And every service class with #Service.
In Spring you should not use the new operator for Services. Use the annotation
#Service
public classSomeClass {
or
#Component
public classSomeClass {
and your class can be injected via depnendency Injection.
If you want to create a new custom bean that can be used via dependencyInjection This is what the #Configuration annotation is for.
#Configuration
public class ConfigurationClass{
#Bean
public SomeClass createSomeClass(){
return new SomeClass();
}
}

What's the difference between #Bean and #Component? [duplicate]

I understand that #Component annotation was introduced in spring 2.5 in order to get rid of xml bean definition by using classpath scanning.
#Bean was introduced in spring 3.0 and can be used with #Configuration in order to fully get rid of xml file and use java config instead.
Would it have been possible to re-use the #Component annotation instead of introducing #Bean annotation? My understanding is that the final goal is to create beans in both cases.
#Component
Preferable for component scanning and automatic wiring.
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.
The #Bean annotation returns an object that spring should register as bean in application context. The body of the method bears the logic responsible for creating the instance.
#Component and #Bean do two quite different things, and shouldn't be confused.
#Component (and #Service and #Repository) are 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 (i.e. one bean per class). Control of wiring is quite limited with this approach, since it's purely declarative.
#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.
To answer your question...
would it have been possible to re-use the #Component annotation instead of introducing #Bean annotation?
Sure, probably; but they chose not to, since the two are quite different. Spring's already confusing enough without muddying the waters further.
#Component auto detects and configures the beans using classpath scanning whereas #Bean explicitly declares a single bean, rather than letting Spring do it automatically.
#Component does not decouple the declaration of the bean from the class definition where as #Bean decouples the declaration of the bean from the class definition.
#Component is a class level annotation whereas #Bean is a method level annotation and name of the method serves as the bean name.
#Component need not to be used with the #Configuration annotation where as #Bean annotation has to be used within the class which is annotated with #Configuration.
We cannot create a bean of a class using #Component, if the class is outside spring container whereas we can create a bean of a class using #Bean even if the class is present outside the spring container.
#Component has different specializations like #Controller, #Repository and #Service whereas #Bean has no specializations.
Let's consider I want specific implementation depending on some dynamic state.
#Bean is perfect for that case.
#Bean
#Scope("prototype")
public SomeService someService() {
switch (state) {
case 1:
return new Impl1();
case 2:
return new Impl2();
case 3:
return new Impl3();
default:
return new Impl();
}
}
However there is no way to do that with #Component.
Both approaches aim to register target type in Spring container.
The difference is that #Bean is applicable to methods, whereas #Component is applicable to types.
Therefore when you use #Bean annotation you control instance creation logic in method's body (see example above). With #Component annotation you cannot.
I see a lot of answers and almost everywhere it's mentioned #Component is for autowiring where component is scanned, and #Bean is exactly declaring that bean to be used differently. Let me show how it's different.
#Bean
First it's a method level annotation.
Second you generally use it to configure beans in Java code (if you are not using xml configuration) and then call it from a class using the
ApplicationContext.getBean method. Example:
#Configuration
class MyConfiguration{
#Bean
public User getUser() {
return new User();
}
}
class User{
}
// Getting Bean
User user = applicationContext.getBean("getUser");
#Component
It is the general way to annotate a bean and not a specialized bean.
It is a class level annotation and is used to avoid all that configuration stuff through java or xml configuration.
We get something like this.
#Component
class User {
}
// to get Bean
#Autowired
User user;
That's it. It was just introduced to avoid all the configuration steps to instantiate and use that bean.
You can use #Bean to make an existing third-party class available to your Spring framework application context.
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
By using the #Bean annotation, you can wrap a third-party class (it may not have #Component and it may not use Spring), as a Spring bean. And then once it is wrapped using #Bean, it is as a singleton object and available in your Spring framework application context. You can now easily share/reuse this bean in your app using dependency injection and #Autowired.
So think of the #Bean annotation is a wrapper/adapter for third-party classes. You want to make the third-party classes available to your Spring framework application context.
By using #Bean in the code above, I'm explicitly declare a single bean because inside of the method, I'm explicitly creating the object using the new keyword. I'm also manually calling setter methods of the given class. So I can change the value of the prefix field. So this manual work is referred to as explicit creation. If I use the #Component for the same class, the bean registered in the Spring container will have default value for the prefix field.
On the other hand, when we annotate a class with #Component, no need for us to manually use the new keyword. It is handled automatically by Spring.
When you use the #Component tag, it's the same as having a POJO (Plain Old Java Object) with a vanilla bean declaration method (annotated with #Bean). For example, the following method 1 and 2 will give the same result.
Method 1
#Component
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
with a bean for 'theNumber':
#Bean
Integer theNumber(){
return new Integer(3456);
}
Method 2
//Note: no #Component tag
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
with the beans for both:
#Bean
Integer theNumber(){
return new Integer(3456);
}
#Bean
SomeClass someClass(Integer theNumber){
return new SomeClass(theNumber);
}
Method 2 allows you to keep bean declarations together, it's a bit more flexible etc. You may even want to add another non-vanilla SomeClass bean like the following:
#Bean
SomeClass strawberryClass(){
return new SomeClass(new Integer(1));
}
You have two ways to generate beans.
One is to create a class with an annotation #Component.
The other is to create a method and annotate it with #Bean. For those classes containing method with #Bean should be annotated with #Configuration
Once you run your spring project, the class with a #ComponentScan annotation would scan every class with #Component on it, and restore the instance of this class to the Ioc Container. Another thing the #ComponentScan would do is running the methods with #Bean on it and restore the return object to the Ioc Container as a bean.
So when you need to decide which kind of beans you want to create depending upon current states, you need to use #Bean. You can write the logic and return the object you want.
Another thing worth to mention is the name of the method with #Bean is the default name of bean.
Difference between Bean and Component:
#component and its specializations(#Controller, #service, #repository) allow for auto-detection
using classpath scanning. If we see component class like #Controller, #service, #repository will be scan automatically by the spring framework using the component scan.
#Bean on the other hand can only be used to explicitly declare a single bean in a configuration class.
#Bean used to explicitly declare a single bean, rather than letting spring do it automatically. Its make septate declaration of bean from the class definition.
In short #Controller, #service, #repository are for auto-detection and #Bean to create seprate bean from class
- #Controller
public class LoginController
{ --code-- }
- #Configuration
public class AppConfig {
#Bean
public SessionFactory sessionFactory()
{--code-- }
Spring supports multiple types annotations such as #Component, #Service, #Repository. All theses can be found under the org.springframework.stereotype package.
#Bean can be found under the org.springframework.context.annotation package.
When classes in our application are annotated with any of the above mentioned annotation then during project startup spring scan(using #ComponentScan) each class and inject the instance of the classes to the IOC container. Another thing the #ComponentScan would do is running the methods with #Bean on it and restore the return object to the Ioc Container as a bean.
#Component
If we mark a class with #Component or one of the other Stereotype annotations these classes will be auto-detected using classpath scanning. As long as these classes are in under our base package or Spring is aware of another package to scan, a new bean will be created for each of these classes.
package com.beanvscomponent.controller;
import org.springframework.stereotype.Controller;
#Controller
public class HomeController {
public String home(){
return "Hello, World!";
}
}
There's an implicit one-to-one mapping between the annotated class and the bean (i.e. one bean per class). Control of wiring is quite limited with this approach since it's purely declarative. It is also important to note that the stereotype annotations are class level annotations.
#Bean
#Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically like we did with #Controller. It decouples the declaration of the bean from the class definition and lets you create and configure beans exactly how you choose. With #Bean you aren't placing this annotation at the class level. If you tried to do that you would get an invalid type error. The #Bean documentation defines it as:
Indicates that a method produces a bean to be managed by the Spring container.
Typically, #Bean methods are declared within #Configuration classes.We have a user class that we needed to instantiate and then create a bean using that instance. This is where I said earlier that we have a little more control over how the bean is defined.
package com.beanvscomponent;
public class User {
private String first;
private String last;
public User(String first, String last) {
this.first = first;
this.last = last;
}
}
As i mentioned earlier #Bean methods should be declared within #Configuration classes.
package com.beanvscomponent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class ApplicationConfig {
#Bean
public User superUser() {
return new User("Partho","Bappy");
}
}
The name of the method is actually going to be the name of our bean. If we pull up the /beans endpoint in the actuator we can see the bean defined.
{
"beans": "superUser",
"aliases": [],
"scope": "singleton",
"type": "com.beanvscomponent.User",
"resource": "class path resource
[com/beanvscomponent/ApplicationConfig.class]",
"dependencies": []
}
#Component vs #Bean
I hope that cleared up some things on when to use #Component and when to use #Bean. It can be a little confusing but as you start to write more applications it will become pretty natural.
#Bean was created to avoid coupling Spring and your business rules in compile time. It means you can reuse your business rules in other frameworks like PlayFramework or JEE.
Moreover, you have total control on how create beans, where it is not enough the default Spring instantation.
I wrote a post talking about it.
https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/
1. About #Component
#Component functs similarily to #Configuration.
They both indicate that the annotated class has one or more beans need to be registered to Spring-IOC-Container.
The class annotated by #Component, we call it Component of Spring. It is a concept that contains several beans.
Component class needs to be auto-scanned by Spring for registering those beans of the component class.
2. About #Bean
#Bean is used to annotate the method of component-class(as mentioned above). It indicate the instance retured by the annotated method needs to be registered to Spring-IOC-Container.
3. Conclusion
The difference between them two is relatively obivious, they are used in different circumstances.
The general usage is:
// #Configuration is implemented by #Component
#Configuration
public ComponentClass {
#Bean
public FirstBean FirstBeanMethod() {
return new FirstBean();
}
#Bean
public SecondBean SecondBeanMethod() {
return new SecondBean();
}
}
Additional Points from above answers
Let’s say we got a module which is shared in multiple apps and it contains a few services. Not all are needed for each app.
If use #Component on those service classes and the component scan in the application,
we might end up detecting more beans than necessary
In this case, you either had to adjust the filtering of the component scan or provide the configuration that even the unused beans can run. Otherwise, the application context won’t start.
In this case, it is better to work with #Bean annotation and only instantiate those beans,
which are required individually in each app
So, essentially, use #Bean for adding third-party classes to the context. And #Component if it is just inside your single application.
#Bean can be scoped and #component cannot
such as
#Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)

why are #Configuration classes wraped by the cglib proxy with the ConfigurationClassEnhancer class

when i read and debug spring source, I find that the #configuration classes are wraped by the cglib proxy with the ConfigurationClassEnhancer class, I don`t understand the reason of the design, thanks
To handle situations like below.
#Configuration classes contains bean definitions via #Bean
annotations
Many of the beans have collaborators, so we inject those
collaborators(which are also beans) using standard java method
semantics
So, every time datasource() is called, spring does not create new
instance(since it is Singleton).
This happens because #Configuartion class is proxied and it contains
the logic to check if beans are already in ApplicationContext
#Configuration
public class MyConfig{
#Bean
public MyDao1 Dao1(){
MyDao1 d1 = new MyDao1();
d1.setDataSource(datasource());
return d1;
}
#Bean
public MyDao2 Dao2(){
MyDao1 d2 = new MyDao2();
d2.setDataSource(datasource());
return d2;
}
#Bean
public Datasource datasource(){
DataSource ds = new DataSource();
return ds;
}
}
Note: #Component classes can also define beans via #Beans, but scenario like above will definitely cause problems since bean calls don't get intercepted via proxy in that case.

Spring autowire list without merging all possible beans

I'm using 4.2.0 spring.
I create two beans:
#Bean
public String sessionAttributeName() {
return "someString";
}
#Bean
public List<String> urlsRequireAuthentication() {
return Lists.newArrayList(
"/auction/*"
);
}
When I try to autowire a list of beans like this:
#Bean
public FilterRegistrationBean someFilterRegistrationBean(List<String> urlsRequireAuthentication) {
...
}
Not only the original list will be autowired as expected ["/auction/*"] but all registered String beans will be merged to one big list like ["/auction/*", "someString"].
I used this feature back in the time and it was useful but for this particular place I really want to only include the content of the urlsRequireAuthentication list. How can I do that?
Just use the method directly instead of injecting the bean as a parameter :
#Bean
public FilterRegistrationBean someFilterRegistrationBean() {
List<String> urlsRequireAuthentication = urlsRequireAuthentication();
}
#Beans documentation :
Typically, #Bean methods are declared within #Configuration classes.
In this case, bean methods may reference other #Bean methods in the
same class by calling them directly. This ensures that references
between beans are strongly typed and navigable. Such so-called
'inter-bean references' are guaranteed to respect scoping and AOP
semantics, just like getBean() lookups would. These are the semantics
known from the original 'Spring JavaConfig' project which require
CGLIB subclassing of each such configuration class at runtime. As a
consequence, #Configuration classes and their factory methods must not
be marked as final or private in this mode. For example:
UPDATE
An other way to do it would be to use the javax #Resource annotation. It does not work with the #Qualifier annotation precisely because of this feature of #Autowired : It is possible to provide all beans of a particular type from the ApplicationContext by adding the annotation to a field or method that expects an array of that type) :
#Configuration
public class ConfigurationClass {
#Resource(name="urlsRequireAuthentication")
private List<String> urlsRequireAuthentication;
#Bean
public FilterRegistrationBean someFilterRegistrationBean() {
urlsRequireAuthentication.size();
}
}
sessionAttributeName and urlsRequireAuthentication should be configuration properties and not beans. Create application.properties in the resources dir and add the following line authentication-urls = /auction/*, /url2/*. Now you can access your properties using the #Value annotation.
#Configuration
#PropertySource("classpath:application.properties")
public class AppConfig {
#Bean
public FilterRegistrationBean someFilterRegistrationBean(#Value("${authentication-urls}") String[] authenticationUrls) {
...
}
}
If you are using spring boot you should check out the docs for externalized configuration.
Use Qualifier annotation:
#Bean
public FilterRegistrationBean someFilterRegistrationBean(#Qualifier("urlsRequireAuthentication") List<String> urlsRequireAuthentication) {
...
}

Some doubts about Java Configuration of the Spring Application Context (dependency injection)

I am studying for Spring Core certification.
I know that in Spring I can configure the dependency injection using 3 way:
Java Configuration
Classes annotations
XML Configuration
I have some doubt related to how to use the first kind of dependency injection configuration.
For example I have something like this:
1) A class named TransferServiceImpl:
public class TransferServiceImpl implements TransferService {
public TransferServiceImpl(AccountRepository ar) {
this.accountRepository = ar;
}
...
...
...
}
This class contain the TransferServiceImpl() constructor that take an AccountRepository object as input paramether, so AccountRepository is a dependency that have to be injected into TransferServiceImpl().
2) This is the implementation of the previous AccountRepository class:
public class JdbcAccountRepository implements AccountRepository {
public JdbcAccountRepository(DataSource ds) {
this.dataSource = ds;
}
...
...
...
}
So the constructor of this class thake a DataSource object that have to be injected into the JdbcAccountRepository class.
Then I have a configurations class that contains the dependency injection configuration:
#Configuration
public class ApplicationConfig{
#Bean public TransferService transferService(){
return new TransferServiceImpl(accountRepository());
}
#Bean public AccountRepository accountRepository(){
return JdbcAccountRepository(dataSoruce());
}
#Bean public DataSource dataSource(){
DataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.postgresql.Driver");
...................................
...................................
...................................
}
}
So it seems to me that it work in the following way:
I have my 2 implemented beans named TransferServiceImpl and JdbcAccountRepository and the configuration class named ApplicationConfig.
Into the configuration class I say that when someone ask to the factory to create a TransferService object it automatically build its implementation TransferServiceImpl creating and injecting automatically a JdbcAccountRepository into the TransferServiceImpl constructor.
In the same way when a JdbcAccountRepository is created it is injected a DataSource object into its constructor.
Is it right?
If it is right I have the following doubts:
1) Into the ApplicationConfig class I also declare the DataSource bean but I don't implement this class. Is it a class provided by Spring and I have only to set its properties values?
2) When are created the bean definied into the ApplicationConfig class? At the application startup? I think that, in the previous example, if I annotate a constructor using #Bean it is created as singleton at the application startup. Is it right or am I missing something?
Tnx
1) Into the ApplicationConfig class I also declare the DataSource bean
but I don't implement this class. Is it a class provided by Spring and
I have only to set its properties values?
Yes. There are a number of DataSource implementations provided by Spring. For example: DriverManagerDataSource, SingleConnectionDataSource, and more.
2) When are created the bean definied into the ApplicationConfig
class? At the application startup? I think that, in the previous
example, if I annotate a constructor using #Bean it is created as
singleton at the application startup. Is it right or am I missing
something?
By default beans are created when Spring container is instantiated (usually at startup if the app is wired as such). You can change this behavior, however, by using the #Lazy annotation where the bean will only be created when explicitly requested.
#Bean #Lazy public TransferService transferService(){
return new TransferServiceImpl(accountRepository());
}

Categories