Spring handling bean colliision with library - java

Here's the situation: I have a RestTemplate bean defined in my main application (Spring boot 2). This application uses a library that also defines a RestTemplate bean to handle requests. I want to keep the main application's RestTemplate definition for my code, but I don't want the library to use my bean definition, since it will create a weird behaviour.
Is there a way to do that without using #Qualifier everywhere? Perhaps something like scoping my bean to my code only?

Related

Programmatic run-time injection/auto-wiring in quarkus

I am looking for a a way to do runtime injection of a bean in Quarkus. I realize this might be a bit on an unorthodox approach for quarkus, and something on an anti-pattern, so no need to point that out, I am fully aware :)
What I am looking for is a way to construct a bean during runtime, and having any annotated properties injected from the Quarkus context.
In Spring Boot I would get the application context by having a bean initialized normally by spring boot, using the ApplicationContextAware interface to inject the application context. I would then use that as a factory by calling ApplicationContext.getAutowireCapableBeanFactory() to get the auto-wire factory and using the autowireBean method on the factory to autowire my beans during runtime. I am wondering if something similar is possible in Quarkus?
This is similar to this question.
How to programmatically inject a Java CDI managed bean into a local variable in a (static) method
javax.enterprise.inject.spi.CDI.current().getBeanManager().select(C.class).get()
To make sure that the bean class is manged use the io.quarkus.arc.Unremovable annotation.

How to understand Bean in Spring?

I am a beginner of Spring and I still can't understand clearly what Bean is. From its definition, it seems a object that is determined by some pre-set configuration files or using annotation on a class. Once the spring starts up, the bean has been created. But can Spring use DI to create some instances of which attributes are not pre-determined?(Like, a user posts a json from website to Spring. And this json contains some data that are used to new a instance. Can Spring use this json to create the instance by using DI?)
Bean is just the object created by your spring application. As you know any spring application has several interacting objects working together to give rise to the desired programmed behavior.
A Bean is basically a managed object i.e at run time the IOC container creates the bean object based on its definition supplied by the coder or as configured in the apllicationContext.xml file under beans tag, and injects it to other classes as required.
Any Spring application is basically a conglomeration of various objects interacting with each other, these objects or beans collaborate to create the application.
A Bean's lifecycle is managed by the Spring IOC container.
The JSON consumed by the Spring Application is taken care of by the HttpMessageConverter. When recieving a new request, the Spring framework will use the content-type header to determine the media type of the request.
It will then try to find the corresponding converter, available in the classpath of the application, to convert the Request body.
Thus its clear that the incoming request body object is not managed by the Spring IOC container and hence is not a Bean.
But these deserialized instances are used as Data Transfer Objects in a Spring application's various layers like, service, DAO, controller.
Spring beans are the objects that comprise your application and are managed by the Spring framework. Comparing them to the concepts of JavaBeans and POJOs provides some explanatory context, and the Spring reference documentation contains extensive documentation of Spring beans, including this summary:
A bean definition essentially is a recipe for creating one or more
objects. The container looks at the recipe for a named bean when
asked, and uses the configuration metadata encapsulated by that bean
definition to create (or acquire) an actual object.
Also included in the reference documentation are descriptions of various ways to instantiate beans via an xml-based or annotation-based configuration approach as well as the Java Config approach (which also uses annotations). This is managed by the Spring BeanFactory interface (API here; source here).
The #Bean annotation is used to indicate that a method instantiates,
configures and initializes a new object to be managed by the Spring
IoC container. For those familiar with Spring’s XML
configuration the #Bean annotation plays the same role as the
element. You can use #Bean annotated methods with any Spring
#Component, however, they are most often used with #Configuration
beans.
You refer in the question to Dependency Injection (DI), a design pattern based on the Inversion of Control principle, which is a critical part of the Spring Framework, particularly for bean instantiation. DI allows values to be passed into the object from outside. The Spring documentation describes both the constructor-based and setter-based approaches to DI provided by the Spring IoC container for instantiating objects (beans).

Can I inject properties to third-party beans?

Suppose I have classes, which were instantiated not by Spring. For example, they can be instantiated by deserializer or by JavaFX.
Can I code these classes in the same way I code Spring beans and inject properties into them later?
Actually, I would like a routine, which would scan class with reflection, find all #Autowired annotations in it and inject values from application context?
Will this happen, if I call applicationContext.getBeanFactory().registerSingleton("myName", myBean)? Note, that I would no limit myself with singletons.
If beans are not instantiated by Spring, then you cannot ask Spring to inject dependencies or advise them.
This is a common mistake I see Spring neophytes make. They call new to instantiate a bean with annotations and can't understand why their dependencies aren't injected.
Spring will handle all the beans you instantiate with the bean factory. You are on your own with all others created using new.

How to Configure Dependency Injection in a Library Project?

How to Configure Dependency Injection in a Library Project?
Let me illustrate this question with the following example.
Maven Library Project
ReservationAPI
com.example.reservation-api
This project contains a convenience class called ReservationApiClient which uses a RestTemplate (from the Spring Framework) for making HTTP calls.
Is it possible to make the RestTemplate field #Autowired in this library project instead of instantiating it myself?
Maven Executable Project
org.company.application
This project is a Spring Boot application and uses the above ReservationAPI as a dependency. This app will create a #Bean for the convenience class ReservationApiClient contained in that library and will then execute its public methods which in turn make HTTP requests.
What is a good strategy and/or best practices for the scenario described above?
You can do this if you include autowiring in your library project although that means it would always need to be used with a Spring application context to get the value unless you also have getter/setter methods to use as well. However, I don't think using RestTemplate as an autowired object makes sense since there is nothing specific about a RestTemplate and unless you name the beans there is only one bean definition for a class. All of the methods for the RestTemplate require the URI there anyhow. So in this case I would just use the bean for your ReservationApiClient in your application.
One other way to do it is if you want to include Spring dependencies in your library (which I guess you already are by using RestTemplate) you can declare your ReservationApiClient as a #Service or #Component and then use the #ComponentScan annotation in your main Spring Boot project to search that library for components to include in the bean registry.
Another option is to use a feature like Spring Boot's Autoconfigure to create factories that use third party libraries and configure them per properties in your application settings. The auto configuration documentation would be a good place to start with this. You can see the starter projects they have on GitHub and then the associated Autoconfigure classes they have associated with these.
Let me know if any of this does not make sense.

How to get ServletConfig within Spring application?

try to autowired ServletConfig into current application, not ServletContext because an API ask for it.
I know user can get ServletContext by a ServletConfig servlet but how to do the other way around or taken from spring application
Rather than autowiring, trying implementing ServletConfigAware.
Edit:
I couldn't find an example that shows using ServletConfigAware in a real project. Essentially, you'd have a class that implemented this interface to obtain the ServletConfig.
You'd create a Spring bean from the class by annotating the class with #Component or declaring a bean in XML. When Spring creates the bean, it would invoke setServletConfig(ServletConfig servletConfig).
Once you had an instance of ServletConfig in your bean, you'd do whatever you need with it.
Your question was how to obtain the ServletConfig, but I think (correct me if I'm wrong) you are looking to integrate a legacy Servlet into your Spring Web MVC application. ServletWrappingController might be a better choice. I haven't ever used it myself, but it appears to be specifically designed for that purpose.

Categories