call a method on a controller from another controller in mvc - model-view-controller

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?

Related

How does Dependency Injection work in this case?

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

Accessing Spring Controller Name from View

With Spring, how can i retrieve the following Controller attributes in the view?
Controller name
Controller's #RequestMapping URI
Action method name
Action method's #RequestMapping URI
One approach which i have tried is by creating a subclass of HandlerInterceptorAdapter and overriding postHandle. I register my subclass as an mvc:interceptor for a list of given paths - which is clunky to maintain but was the only way to avoid my interceptor being called for ResourceHandler requests (which i don't want). In my postHandle i can easily add the 2 name attributes, but not the URIs...
Parsing from the HttpRequest object requires constraints on all Controller RequestMappings. I.e. i must always map /Controller/Action or equiv scheme. Quite limiting.
Creating an ApplicationContext and querying that with the requestURI is too long-winded.
I am thinking about dropping the HandlerInterceptorAdapter and instead defining a BaseController for all my controllers to extend.
I wanted to ask before i do this, is there a better approach?
You haven't stated why you need to do this (it sometimes helps to include your motivation, as others can suggest alternative approaches).
But I'm guessing that the Spring 3.1 features loosely termed "end point documentation" may do what you are asking... See RequestMappingHandlerMapping in the Spring documentation which doesn't provide a lot of detail, so this example project is the best place to see it in action:
Spring MVC 3.1 Demo App
example controller
example JSP page

Can a controller use the same instance of command from a controller it extends?

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.

Ninject MVC 3 - Injecting dependencies into models and controllers

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.

MVC3: proper place to add a dependency on a logger class?

I have an MVC3 app with a simple Log service. All my services are invoked using Microsoft's Unity Dependency Injection container.
For most methods, I ignore exceptions; they're caught in a top-level error handler, which categorizes them and decides whether or not to log them, generates the HTTP response I desire and calls an action method on the error controller to return my custiom error page.
Sometimes, tho, I don't want to do that; I want to handle the exception where it happens, e.g. in my controller. In that case, I want to log the error before substituting an appropriate default value and continuing with the controller's logic.
I did that in one place: in my controller, I added:
var logService = DependencyResolver.Current.GetService<ILogService>();
try { /* something indeterminate */ }
catch ( Exception ex ) {
logService.LogException(category, ex);
/* do something else instead */
}
Now I want to do it a second time in that controller (as it happens, later in the same method). As soon as I do this again, I see it's time to refactor, as I'm repeating myself.
What's the best way to make my logger available to my controllers? My controllers all inherit from a custom ControllerBase; my first thought is to add it to the ControllerBase's constructor. BUT:
currently I don't have a constructor in the ControllerBase,
I'm a bit worried that referencing the DI container in the
controller breaks the isolation of the controller, negating the
value of DI to begin with, and
I don't think I can pass the
logger in to the ControllerBase's constructor, because (as I
understand it, pls correct me if 'm wrong) controllers can only have
parameterless constructors, so there's no way to pass anything to
them.
Where's the proper place to make the service available to all my controllers?
Place it in your constructor. You can even place it in a BaseController.
Ideally, you will use Dependency Injection and have it come in on your controller. Controllers can have parameters if your IoC container supports it.
private readonly ILogService logService;
public MyController(ILogService logService)
{
this.logService = logService;
}
I wouldn't add it to the base controller for the sole reason that it sounds as if you only use it sporadically. I would add it as Daniel White suggests in the constructor of the controller. If it's looking as though you use it in most controllers, then I'd consider moving it to the base.

Resources