I don't fully understand what's happening behind the scenes when we inject dependencies into controllers and models.
I have the following controller:
public class TypeController : CommonController
{
private ILookUpService lookUpService;
public TypeController(ILookUpService lookUpService)
{
this.lookUpService = lookUpService;
}
}
As the application starts, the lookup service is already available. So I guess that somewhere behind scenes we have code on the lines of
TypeController controller = new TypeController(service);
or something to do with factory (which I need to read up about).
When it comes to injecting a service into a view model, it doesn't work as I need to invoke an empty constructor without passing interface to my service.
So what is happening behind the scenes? How do I inject a service into a view model? I guess I'm missing some real fundamental stuff which is stopping me from doing what I need.
I have included FactoryPattern in the tags as my gut feeling tell me it has something to do with my problem..
Thank you
You shouldn't inject anything into the view model. The view model should be a simple data container which is filled from the controller and therefore shouldn't have any dependencies.
Related
In a Spring Boot Web Application layout, I have defined a Service Interface named ApplicationUserService. An implementation called ApplicationUserServiceImpl implements all the methods present in ApplicationUserService.
Now, I have a Controller called ApplicationUserController that calls all the methods of ApplicationUserServiceImpl under different #GetMapping annotations.
As suggested by my instructor, I have defined a Dependency Injection as follows:
public class ApplicationUserController {
private final ApplicationUserService applicationUserService; //This variable will work as an object now.
public ApplicationUserController(ApplicationUserService applicationUserService) {
this.applicationUserService = applicationUserService;
}
#GetMapping
//REST OF THE CODE
}
I am new to Spring Boot and I tried understanding Dependency Injection in plain English and I understood how it works. I understood that the basic idea is to separate the dependency from the usage. But I am totally confused about how this works in my case.
My Questions:
Here ApplicationUserService is an Interface and it's implementation has various methods defined. In the code above, applicationUserService now has access to every method from ApplicationUserServiceImpl. How did that happen?
I want to know how the Object creation works here.
Could you tell me the difference between not using DI and using DI in this case?
Answers
The interface layer is used for abstraction of the code it will be really helpfull when you want to provide different implementations for it. When you create a instance you are simply creating a ApplicationUserServiceImpl and assigning it into a reference variable of ApplicationUserService this concept is called upcasting. Even though you have created the object of child class/implementation class you can only access the property or methods defined in parent class/interface class. Please refer this for more info
https://stackoverflow.com/questions/62599259/purpose-of-service-interface-class-in-spring-boot#:~:text=There%20are%20various%20reasons%20why,you%20can%20create%20test%20stubs.
in this example when a applicationusercontroller object is created. The spring engine(or ioc container) will create a object of ApplicationUserServiceImpl (since there is a single implementation of the interface ) and returns to controller object as a constructor orgument which you assign to the refrence variable also refer the concept called IOC(Invertion of control)
as explained in the previous answer the spring will take care of object creation (object lifecycle)rather than you explsitly doing it. it will make the objects loosely coupled. In this the controll of creating the instances is with spring .
The non DI way of doing this is
private ApplicationUserService applicationUserService = new ApplicationUserServiceImpl()
Hope I have answered your questions
this analogy may make you understand better consider an example, wherein you have the ability to cook. According to the IoC principle(principal which is the basis of DI), you can invert the control, so instead of you cooking food, you can just directly order from outside, wherein you receive food at your doorstep. Thus the process of food delivered to you at your doorstep is called the Inversion of Control.
You do not have to cook yourself, instead, you can order the food and let a delivery executive, deliver the food for you. In this way, you do not have to take care of the additional responsibilities and just focus on the main work.
Now, that you know the principle behind Dependency Injection, let me take you through the types of Dependency Injection
I'm using Spring-Boot and Thymeleaf as a template engine.
I have a web application which has a search input that is accessible in every view to anyone (the search triggers a form submission), the form has a th:object="${searchObject}" attribute and I'm using#RequestBody in my post controller to get the object.
Now, what i did so far was adding a model.addAttribute("searchObject", new SearchObject()) to every controller and it worked just fine but it made me think, what if there is a way to share an object between the whole app that i could declare once and use everywhere .. ?
So i did a little search and found out various solutions that refers to the available contexts in a spring application.
Iv'e tried to implement few of them but couldn't figure out how.
So, is there any simple way of sharing an object between the whole app so it can be accessed inside thymeleaf without writing the same code in every controller?
I'm thinking it should look something like this
th:object="${#sharedObjects.getObjectByName(object)}"
Thanks.
You can use a #ControllerAdvice to add a model attribute in all of your controllers:
#ControllerAdvice
public class SearchObjectModelAttributeAdvice {
#ModelAttribute("searchObject")
public SearchObject searchObject() {
return new SearchObject();
}
}
I want to call a method on another controller. The problem is that in my project, all controllers are created using Windsor castle and Windsor castle resolve the dependencies. This means that I cannot instantiate a controller by using new as then it needs its dependents. How can ask MVC to instantiate a controller and then call a method on it (which returns an object)?
I'm going to tell you two things: 1) First, I'll show you how you'll most likely be able to accomplish what you want, and 2) Then I'll recomment you achieve your goal in another way :)
1: When using auto-wiring, the way to get stuff from the container is to declare the dependency by adding it as a constructor argument - e.g. (assuming the container knows how to resolve controllers by their concrete types):
public class HomeController
{
readonly AccountController accountController;
public HomeController(AccountController accountController)
{
this.accountController = accountController;
}
}
This will most likely allow you to do what you want with AccountController from withing HomeController. However, this is not very pretty.
2: Injecting one controller into another is probably not what you (really) want. I'm guessing that you really want to move whatever logic you have in your controller's action method into a dedicated service, e.g. DoSomethingInteresting which happens to implement IDoStuff, and then let both of your controllers depend on IDoStuff. Does this make sense to you?
I have multiple SimpleFormController controllers. One controller contains a command object used to filter results in the other controllers. I seem to be missing something simple, but I can't seem to find a way to use the same instance of the command object in the other controllers.
My setup is such that this main controller, let's call it RootController extends SimpleFormController, and the rest of the controllers extend RootController. The idea was that the command object is stored in one place - RootController and the controllers that extend it reuse the same object. However, it doesn't seem to be working that way, other controllers seem to have their own copy of the command object.
Form backing objects are just normal Pojos, so you can inherit it form each other.
public class BaseCommand {
...
}
public class MoreCommand extends BaseComman {
...
}
May you just forget the "update" the commandClass in your Controller Subclasses.
Anyway: notice that SimpleFormController is deprecated in Spring 3.0. Instead the Annotation Style is preferred.
Update: One INSTANCE of an command object, can be handled by only one INSTANCE of an Controller. So you can subclass the Controller (don't miss to call super), but you can not have two instances of the controller and hope that both are invoked.
The short question:
Does Castle Windsor have something similar to Spring.Net's "Lookup Method Injection" that can be configured from XML, which provides the ability to fetch transient instances from the container without the class being aware of the IoC container?
The long question:
I'm a long time Spring/Spring.Net user and I have been experimenting with Castle Windsor, by trying to port a project over to it. Spring.Net has a concept of "Lookup Method Injection" which (from the Spring docs)...
Lookup method injection is the ability of the container to override methods on container managed objects, to return the result of looking up another named object in the container. The lookup typically involves a prototype object as in the scenario described in the preceding section. The Spring framework implements this method injection by a dynamically generating a subclass overriding the method using the classes in the System.Reflection.Emit namespace.
What this means is, If I had the following...
public class SomeTransient
{
// ... I have dependencies that need to be filled by IoC container
}
public class SomeClass
{
public virtual void Work()
{
var o = CreateTransient();
}
public virtual SomeTransient CreateTransient() { }
}
I can instruct Spring to override the CreateTransient method, and have that method return a new container created transient instance (with it's dependencies initialized) each time the method is called.
The unique part of this is, it doesn't require direct links to the Spring Framework (eg. SomeClass doesn't have to implement a specific interface).
Is there something similar in Castle Windsor to accomplish this via XML?
(I will eventually move away from XML config, but at the moment I'm just trying to get it running)
Castle has something better; Typed Factories.
You can also inject even a delegate!
http://stw.castleproject.org/Windsor.Typed-Factory-Facility-delegate-based-factories.ashx
It is better because it does not depend on dynamically generation code, and it looks much more cleaner.
It looks much more cleaner because the class doesn't depend on someone overriding that method. It is impossible to test this class without subclassing.
If you really want to do something like this, i would expect:
public abstract class SomeClass
{
public abstract SomeTransient CreateTransient();
}
but... again it doesn't feel right.
Edit 2
Unity 2 support these kind of delegate factories; you can read more here:
http://www.truewill.net/myblog/index.php/2010/05/06/unity_2_0_combining_injectionfactory_and
thanks to #eiximenis