Inject service in another service - java

I have UserService and MissionService.
Is it ok to inject MissionService in UserSerivce or vice versa?
If yes, what about unit testing?

Of course you can and it is perfectly fine. But I recommend that you use method-injection in order to allow you to set the instance at runtime without using using reflection (you can create an instance manually).
For example:
#Service
public class MissionService { }
#Service
public class UserService {
private MissionService missionService;
#Autowired
public void setMissionService(MissionService missionService) {
this.missionService = missionService;
}
}
This allows you to create both services using regular Java without Spring:
MissionService missionService = new MissioNService();
UserService userService = new UserService();
userService.setMissionService(missionService);
Caution: You have to take care of not building dependency cycles. It is not set that Spring resolves them, I think

Related

Is there any way to create a #ConditionalOnMissingBean but only after spring is fully configured?

I'm building a Spring Boot Starter for a college project on Java Reflection and Bytecode alteration.
The Reflection/Bytecode is done now, but it will scan for Spring #Controllers/#RestControllers so it can detect certain annotations to run the process.
My question here is what's the best approach? Seems to me that an annotation processor doesn't quite work nicely, and my idea is to create a #Configuration class. Now I need to ensure that all #Controller beans have been booted before I actually process them and I also need to put the result of this processing in a bean that could already exist.
So for example:
#Configuration
public class TestConfig {
#Autowired //I want to autowire but it may not exist, if the user doesn't define I need to create it
private ExternalAnnotatedRequestsModel model;
#Autowired // needed for the framework to acess spring controllers
private ConfigurableApplicationContext ctx;
#Bean // this can also be overriden since the definitions can be done via yaml
public ExternalRequestsProvider() {
return new AnnotationExternalRequestsProvider(ctx);
}
}
Now I also want that when the ExternalRequestsProvider bean is started, it runs the process method and saves the result in the object in the "model" variable.
Using #EventListener for ApplicationReadyEvent to run your process after Spring is fully configured.
#Configuration
public class ExternalRequestsConfig {
#Autowired
private ExternalAnnotatedRequestsModel model;
#Autowired
private ExternalRequestsProvider provider;
#EventListener(ApplicationReadyEvent.class)
public void onApplicationReady(ApplicationReadyEvent event) {
// do your process
}
}

How does bean self-auto-wiring work in Spring?

One of the really cool and rather mind boggling features that I have recently discovered in Spring is self auto-wiring a bean.
What I am referring to is this:
class UserServiceImpl implements UserService {
#Autowired
UserService service;
// other service methods...
}
My questions are as follows:
How is this implemented ?
How does Spring manage this ? Does it assign the same object to self auto-wire reference ? Like so:
UserServiceImpl serviceImpl = new UserServiceImpl();
serviceImpl.setService(serviceImpl); // Obviously this would be done via Reflection rather than a setter.
or
does Spring make 2 seperate objects? Like so :
UserServiceImpl obj1 = new UserServiceImpl();
UserServiceImpl obj2 = new UserServiceImpl();
obj1.setService(obj2);
And just gives us obj1 when we request it in a RestController ?
How many copies of the object are there in the Spring Application Context ?
Related to the previous question, how many actual copies of the object are there ?
Its a very convenient feature for things like transactions across methods, but I want to know what is exactly going on behind the scenes here.
It doesn't inject the UserServiceImpl if you use some annotation like #Transactional,#Cachable etc. It actually injects the proxy.
But as the base it uses the same instance.
As of 4.3, #Autowired also considers self references for injection (that is, references back to the bean that is currently injected). Note that self injection is a fallback. Regular dependencies on other components always have precedence. In that sense, self references do not participate in regular candidate selection and are therefore in particular never primary. On the contrary, they always end up as lowest precedence. In practice, you should use self references as a last resort only (for example, for calling other methods on the same instance through the bean’s transactional proxy). Consider factoring out the affected methods to a separate delegate bean in such a scenario. Alternatively, you can use #Resource, which may obtain a proxy back to the current bean by its unique name.
There is only one copy and uses reflection
Lets look at this sample
#Service
public class SampleService {
#Autowired
private SampleService service;
public SampleService getService() {
return service;
}
}
#SpringBootApplication
public class RestServiceApplication {
public static void main(String[] args) {
ConfigurableApplicationContext context
= SpringApplication.run(RestServiceApplication.class, args);
SampleService sampleService = context.getBean(SampleService.class);
//This will print true
System.out.println(sampleService == sampleService.getService());
}
}
As you can see sampleService == sampleService.getService() is true;

How to fix the Autowired in an External jar import

I'm having a well working library and I would like to utilize the library in one of my sample Spring boot console application.
I built the library using the command mvn clean install and the newly generated .jar file I imported in my sample Spring boot console application.
I created a bean in my new sample application and tried to create an object of UserManagementService, which is in the external .jar and the said jar internally has two properties
External Jar's - Service file
public class UserManagementService {
#Autowired
UserService userService;
#Autowired
ManagementService managementService;
public String getUserFirstName(String userName) {
return userService.getUserFirstName(userName);
}
.. Rest of the implementation
}
These two autowired is not working and it has the value null moreover it throws an exception org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class...
My Sample Application:
public class ApplicationBean {
private UserManagementService userService = new UserManagementService();
public void run() {
if(userService == null) {
System.out.println("Oops");
}
String userFirstName = userService.getUserFirstName("Emma");
... Rest of the implementation
}
}
Kindly assist me how to fix this.
You need to declare your user management service as a bean in order to be able to inject it.
First Approach
Annotate the UserManagementService class with #Service if you have control over the library, UserService and ManagementService needs to be annotated with #Service too so they can be injected into UserManagementService. You may need to use #ComponentScan(basePackages = { "libray.package" }) in your spring app (over main class) to make it scan your library and load the services.
Second Approach
You make your library framework independent and make UserManagementService a simple POJO where you pass UserService and ManagementService as constructor arguments, then declare those beans in your spring app
public class ApplicationBean {
#Bean
public UserService userServiceProvider(){
return new UserService();
}
#Bean
public ManagementService managementServiceProvider(){
return new ManagementService();
}
#Bean
public UserManagementService userManagementServiceProvider(UserService userService, ManagementService managementService){
return new UserManagementService(userService, managementService);
}
}
These beans declaration go to application main class or to a class annotated with #Configuration

DI & Autowiring vs instantiation in Spring [duplicate]

I've started to use Spring recently. And I'm making spring mvc project. So my question is if it's preferred to make interfaces and autowire it with particular implementation by spring or just use class instances in case when I have only one implementation of that interface?
For example:
#Controller
public class MyController {
#Autowired
MyService myService;
#RequestMap("/")
public String mainPage() {
...
}
}
or
#Controller
public class MyController {
#RequestMap("/")
public String mainPage() {
MyService myService = new MyServiceImpl();
...
}
}
if there is only one implementation of MyService interface?
In most cases you should go with injection because:
It eases unit testing (you can inject mock or different implementation)
Spring can inject some dependencies into MyServiceImpl as well because it manages this object
You are not coupling your controller with particular implementation
Even if your service does not have an interface, because of the second reason you should consider injection.
The only case when you might want to skip Spring is when the class does not have any dependencies and is stateless. But most likely such a class is a utility that does not need any an instance at all because it has only static members.
It will depend on whether MyService is a bean that holds a state or not. If MyService does not hold state, then you don't need to create new instances and you can let Spring to inject it having the advantages above described

Autowiring vs instantiating in Spring

I've started to use Spring recently. And I'm making spring mvc project. So my question is if it's preferred to make interfaces and autowire it with particular implementation by spring or just use class instances in case when I have only one implementation of that interface?
For example:
#Controller
public class MyController {
#Autowired
MyService myService;
#RequestMap("/")
public String mainPage() {
...
}
}
or
#Controller
public class MyController {
#RequestMap("/")
public String mainPage() {
MyService myService = new MyServiceImpl();
...
}
}
if there is only one implementation of MyService interface?
In most cases you should go with injection because:
It eases unit testing (you can inject mock or different implementation)
Spring can inject some dependencies into MyServiceImpl as well because it manages this object
You are not coupling your controller with particular implementation
Even if your service does not have an interface, because of the second reason you should consider injection.
The only case when you might want to skip Spring is when the class does not have any dependencies and is stateless. But most likely such a class is a utility that does not need any an instance at all because it has only static members.
It will depend on whether MyService is a bean that holds a state or not. If MyService does not hold state, then you don't need to create new instances and you can let Spring to inject it having the advantages above described

Categories