Qualifier in Spring JavaConfig - spring

I'm trying to write one JavaConfig file, which will contain all dependencies to have the ability to choose injected class.
For example one function of JavaConfig
#Bean
#Qualifier("bigWheel") // Has no impact (I have several types of wheel)
public Car getCar(Wheel wheel){
return new Car(wheel);
}
Also when I mark Car class with #Component I got "No default constructor" exception. What I'm doing wrong?

You have to realize that when Spring is creating your spring context and instantiating the beans it needs default constructors i.e. constructors without any parameters. Quite simply it wouldn't know what Wheel to supply.
I also think you're likely to be unhappy using the pseudo-reserved get/set methods as an object name. Regardless of your Qualifier annotation you are creating an object getCar of class Car.
It kinda looks like you are trying to make getCar a factory method? I'm not going to write a big description in case that's not what you're doing. But if so your pattern needs some work.
EDIT: From your comment below I really don't think you want a bean instantiated at context creation time. It sounds like you just want a regular Spring Aware bean that can use Cars and Wheels. Something like This.
#Component
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
class Wheel {
... wheel stuff
}
#Component
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
class Car {
... car stuff
}
#Component
class Dealership extends ApplicationContextAware {
#Autowired
ApplicationContext applicationContext;
... bunch of dealership code
Wheel wheel = (Wheel) applicationContext.getBean("Wheel");
Car car = (Car) applicationContext.getBean("Car");
car.setWheel(wheel);
... profit
It just doesn't sound like you are looking for a global singleton called wheel that is injected into the global singleton car, during context initialization.
That is why I added the SCOPE_PROTOTYPE annotations above. Normally Spring will instantiate an object and keep injeting that object when you call for it. This works well most of the time. But if your object starts storing state or if you're multithreaded of course, that doesn't work.
But Spring can't figure that out. So if you want a unique object instantiated for each getBean call, you have to add the #Scope annotation.
Hope this helps

Related

Is it still loose coupling if we use #qualifier

we use interface for autowiring service into controller
this is for loose coupling , coz the interface can hold object of any of its implementations. so no need to write the implementation name and create tight coupling.
however when we have more than one implementations for an interface, we write the #qualifier .
my question is if we have to write qualifier to tell which implementation needs to be injected, then should we still call it loose coupling??
class ServiceInterface {
interfaceMethod();
}
implementation 1:
#component("service1")
class ServiceImpl1 implements ServiceInterface {
interfacemethod(){
}
}
implementation 2:
#component("service2")
class ServiceImpl2 implements ServiceInterface {
interfaceMethod(){
}
now only instead of directly creating Object of ServiceImpl1() using new
ServiceImpl1 obj = new ServiceImpl1();
we write in
class Controller {
#autowired
#qualifier("service1")
ServiceInterface se;
sc.interfaceMethod();
}
Partially yes, because the component that uses the injected qualified bean still didn't create it or handle its lifecycle.
But indeed using #Qualifier creates some sort of coupling. If you want to avoid this, consider making one of your ServiceInterface beans the primary implementation for the interface annotating its class with #Primary as follows:
#Component
#Primary
class ServiceImpl1 implements ServiceInterface {
interfacemethod(){
}
}
With this, every time you need a ServiceInterface implementation but you don't actually specify which one you want (using #Qualifier) the primary one is injected by Spring.
Even though you are using the #Qualifier annotation you are still using inversion of control to let the framework manage your dependencies.
Furthermore, lets say you wouldn't autowire this implementation but use 'new' to create your object.
When the implementation changes you would need to update all the places where this is created. However, with dependency injection you wouldn't need to do so. Therefore you still have the advantages of dependency injection with regards to loose coupling.
If you would like to have your implementation less coupled with your target class then you could do a few things
Use #Primary for a bean to determine the default implementation.
Autowire your implementations into a List<ServiceInterface>
Use Spring's ObjectFactory to determine which bean to use at runtime
Use Profiles to determine which bean to autowire

Factory design pattern and Spring

I am wondering what is the current best practice as to the use of factory pattern within the context of Spring framework in using dependency injection. My wonder arises about whether the factory pattern is still relevant nowadays in light of the use of Spring dependency injection. I did some searching and see some past discussion (Dependency Injection vs Factory Pattern) but seem there is different view.
I see in some real life project in using a Map to hold all the beans and rely on autowiring to create those beans. When the bean is needed, it get it via the map using the key.
public abstract class Service {
//some methods
}
#Component
public class serviceA extends Service {
//implementation
}
#Component
public class serviceB extends Service {
//implementation
}
Map<String, Service> services;
But I see there is some difference among the two approaches.
Using the above method, all beans are created on application start up and the creation of object is handled by the framework. It also implies there is only one bean for each type.
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
The answer to this question can be really deep and broad, I'll try to provide some points that hopefully will help.
First off, spring stores its beans (singletons) in the ApplicationContext. Essentially this is the map you're talking about. In a nutshell, it allows getting the bean by name, type, etc.
ApplicationContext, while being a really important concept, is not the whole Spring, in fact Spring framework allows much more flexibility:
You say, using a map implies that all the beans will be created at the beginning of the application and there is one instance of the bean.
Spring has a concept of Lazy beans, basically supporting a concept of beans being actually created only when they're required for the first time, so Spring supports the "delayed" beans initialization
Spring also allows more than one instance of a bean per type. So this map is more "advanced". For example you can create more than one implementation of the interface and use declare both as beans. As long as you provide enough information about what bean should be injected to the class that might use them (for example with a help of qualifiers suppored in spring), you're good to go. In addition, there are features in spring IoC container that allow injecting all registered implementations of an interface into a list:
interface Foo {}
#Component
class FooImpl1 implements Foo {}
#Component
class FooImpl2 implements Foo {}
class Client {
#Autowired
List<Foo> allFoos;
}
Now you say:
While for factory pattern, the factory class creates the object on request. And it can create a new object for each request.
Actually Spring can create objects per request. Not all beans have to be singletons, in general spring has a concept of scopes for this purposes.
For example, scope prototype means that Spring will create a bean upon each usage. In particular one interesting usage that spring supports in variety of ways is Injecting prototype bean into singleton. Some solutions use exactly like a factory (read about annotation #Lookup others rely on auto-generated proxy in runtime (like javax.inject.Provider). Prototype scope beans are not held in the application context, so here again spring goes beyond a simple map abstraction.
Last feature that you haven't mentioned is that sometimes even for singletons the initialization can be a little bit more complicated then calling a constructor with Parameters. Spring can address that by using Java Configurations:
#Configuration
public class MyConfig {
public SomeComplicatedObject foo(#Value("...") config, Bar bar) {
SomeComplicatedObject obj = new SomeComplicatedObject() // lets pretend this object is from some thirdparty, it only has no-op constructor, and you can't place spring annotations on it (basically you can't change it):
obj.setConfig(config);
obj.setBar(bar);
return obj;
}
}
The method foo here initializes the object SomeComplicatedObject and returns it. This can be used instead of factories to integrate "legacy" code (well, java configurations go way beyond this, but its out of scope for this question).
So bottom line, you Spring as an IoC container can provide many different ways to deal with object creation, in particular it can do everything that factory design pattern offers.
Now, I would like to also refer to your last sentense:
I think a deeper question may be, when Spring framework is used in a project, should it be strived to not create any object inside a class, which means the factory pattern ( or any creational design patterns?) should not be used, as Spring is supposed to be the central handler of the objects dependency ?
Indeed you don't have to use Factory Pattern when using Spring, since (as I hopefully have convinced you) provides everything that factory can do and more.
Also I agree that spring is supposed to be the central handler of the objects dependency (unless there are also parts of the application which are written in a different manner so you have to support both :) )
I don't think we should avoid using "new" altogether, not everything should/can be a bean, but I do see (from my subjective experience, so this is arguable) that you use it much less leaving the creation of most of the objects to Spring.
Should we avoid a usage of any creation design pattern? I don't think so, sometimes you can opt for implementing "builder" design pattern for example, its also a creational pattern but spring doesn't provide a similar abstraction.
I think if your project uses Spring framework you should use it. Although it depends on your project design e.g. You may use creational patterns along side with Spring IoC. e.g when you have abstraction layers not framework dependant (agnostic code)
interface ServiceFactory {
Service create(String type);
}
#Component
class SpringServiceFactory implements ServiceFactory {
#Autowired private ApplicationContext context;
Service create(String type) {
return context.getBean(type)
}
}
I use Factory pattern as well when I refactor legacy not unit testable code which also uses Spring Framework in order to implement unit tests.
// legacy service impossible to mock
class LegacyApiClient implements Closeable {...}
#Component
class LegacyApiClientFactory {
LegacyApiClient create(String endpoint) {
return new LegacyApiClient(endpoint);
}
}
#Component
class OtherService {
private final String endpoint
private final LegacyApiClientFactory factory;
OtherService(#Value("${post.endpoint}") String endpoint,
LegacyApiClientFactory factory) {...}
void doCall {
try (LegacyApiClient client = factory.create(endpoint)) {
client.postSomething();
}
}
}
....
// a random unit test
LegacyApiClient client = mock(LegacyApiClient.class)
LegacyApiClientFactory factory = mock(LegacyApiClientFactory.class)
OtherService service = new OtherService("http://scxsc", factory);
when(factory.create(any())).thenReturn(client)
service.doCall()
....

How to use #Autowired correctly in spring boot standalone app

I've learned a lot recently about Spring and one thing i think i might be misunderstanding is the #Autowired annotation, especially when using it in constructors. You see, the app i'm developing is a service so basically EVERYTHING is initialized within a constructor. The only actual user-driven events that happen are buttons that restart certain modules of the service. This is my main method :
ConfigurableApplicationContext ctx = new SpringApplicationBuilder(MDHIS_Service.class)
.headless(false).web(false).run(args);
java.awt.EventQueue.invokeLater(() ->
{
MDHIS_Service frame = ctx.getBean(MDHIS_Service.class);
frame.setSize(1024, 768);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
This is the constructor of my main class, where basically everything happens. I have omitted the calls to the methods initializing each module to shorten it :
#Autowired
public MDHIS_Service(GlobalParamService globalParamService, LogEntryService logentryService, InterfaceService interfaceService,
ConnectionService connectionService, OutboundMessageService outboundMessageService, OutboundMessageHistoryService outboundMessageHistoryService,
InboundMessageService inboundMessageService, FacilityService facilityService, ModuleStatusService moduleStatusService,
SequenceService sequenceService)
{
this.globalParamService = globalParamService;
this.logEntryService = logentryService;
this.interfaceService = interfaceService;
this.connectionService = connectionService;
this.outboundMessageService = outboundMessageService;
this.outboundMessageHistoryService = outboundMessageHistoryService;
this.inboundMessageService = inboundMessageService;
this.facilityService = facilityService;
this.moduleStatusService = moduleStatusService;
this.sequenceService = sequenceService;
}
My main class has a private final global variable for each service. Each module is a separate thread and i'm finding myself having to pass those variables to the constructor of each module which in term stores them into it own private final variables. The way i'm doing things right now #Autowired is pretty much useless since i'm having to pass the instance around. Is there a way to better use #Autowired? This service is used as the backend for a large web app and i find myself making much better use of the annotation in there. I did a lot of research on this topic and i did try the #PostContruct annotation but all i ever got was null services.
Any help would be appreciated.
Thanks!
I figured out my problem, and it was a pretty dumb one. First off, i had not annotated my main class with #Component so Spring never bothered to inject the dependencies in it. Secondly, I did not realize that a method annotated with #PostContruct would run by itself after the constructor runs WITHOUT NEEDING TO EXPLICITELY BE CALLED!
I moved all my initialization code to an init method annotated with #PostConstruct and annotated my main class with #Component, everything is working now!
You typicall don't have to use a constructor + #Autorwired, you can directly use autowired on fields and spring would fill the dependencies for you:
#Component
public class MDHIS_Service {
#Autowired
private GlobalParamService globalParamService;
}
What is important to understand is that for spring to work, you must let it create the objects for you, and not calling the constructors explicitely. It would then fill the dependencies as needed. This is done by declaring the service as a component (for example with the #Component annotation) and never create the service yourself but getting them from dependency injection.
The first object you start with has to have been created by spring and returned by the application context.
What you gain in exchange is that you don't have to forwared everything explicitely. A sub-sub-sub service quite distant from the root of the application can depend on anything it has visibility without you having to forward the reference all the way.
I would advise to take a look a the spring reference documentation, it quite detailled and complete:
https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#spring-core
Edit: I'll try to clarify a bit with an example... What do the init code of the various service actually does ?
Maybe it set the dependencies. Then just autowire them:
#Component
MySubService {
#Autowired MySubSubService mySubSubService;
}
Maybe it does some more thing than setting fields so you can add on top an init method that do it and this init method can eventually call the other services.
#Component
MySubService {
#Autowired MySubSubService mySubSubService;
#PostConstruct
public void init() {
//Init code that may use mySubSubService.
}
}
You don't have to declare a constructor and forward dependencies yourself, sprint does it for you.
The only case where you'd have problem is if finally you need some parameters that are not dependency to the init method. But even in that case you could do it from you main code. That's actually what you did with the main service calling the various setters rather than messing with the constructor to set theses values.

Autowired Domain/Entity classes retains Old values

I have a mapper class for an incoming Event message.
Once the event message comes to the application, the mapper class sets the values in the entity object and saves it in the Database.
I have Autowired the entity object in my mapper class.
Whenever a new event comes in, the autowired entity object is still having the Old/previous values.
Is autowiring of Domain/Entity object possible in this case or I should go with 'New' keyword instead of Autowiring as Spring bean.
I see some posts about using #Configurable. I am not sure which is the best coding practice in this case?
#Service
public class LegacyEventMapper {
#Autowired
private LegacyEvent legacyEvent;
#Autowired
private LegacyEntity legacyEntity;
public void mapLegacyNotificationDetails(LegacyScheduleEvent body) throws Exception {
//Setting the values into the Entity object
Thanks
I have no idea why you actually want to #Autowire an #Entity and make it spring aware. This is wrong. You can do it, but it makes absolutely no sense.
What you actually want to do is create a new LegacyEntity (via the new LegacyEntity) and save that instance to DB.
What you have read via #Configurable is the other way around - you inject a spring bean/service into an Entity.
I think We can #Autowire an #Entity class. But then we need to mention in Entity class that it is of Request scope
#Entity
#Scope(scopeName=WebApplicationContext.SCOPE_REQUEST, proxyMode=ScopedProxyMode.TARGET_CLASS)
public class LegacyEntity {
I am not sure if using the new keyword is the better approach instead of autowiring an Entity class?

spring annotation manage pojo

I use spring annotation to manage java bean, use #service in service layer, and #autowired when inject service, but now I have a question, how to manage POJO by spring?
for example, I need to return a user for ajax call, so I need to always write like:
User user = new User()......
return user;
So, how I can use like
#autowired User user;
And the User POJO will be:
#component
#scope("prototype")
public class User{}
so each time the user entity will be a new one, and I needn't to new it everytime,
But I failed to write like this, so can spring manage POJO to be a prototype?
Update====================================
Thanks for answering
You have three options that i can think of straigh away. What you want is to be able to create prototypes from within a singleton. So you can either use..
1) AOP Scoped Proxy.
So change your User class annotation to ...
#Scope(value = "prototype", proxyMode = ScopedProxyMode.TARGET_CLASS)
(this required cglib on your classpath)
or
2) lookup-method
this is a bit more involved and makes things a bit harder to test
or
3) make your class implement ApplicationContextAware and then you can just call getBean on the context when you want a new prototype.
A bit of googling will sort you out anyway but I recommend the first option
Try following code:
#Component
#Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class User
{
......
}
Hope it helps.

Resources