10
I just want to know whether controller class method is accessible from another java class.    

following is my controller and its method.

@Controller
public class TestResultUploadController {
    @RequestMapping(method = RequestMethod.POST,value="/uploadTestResult")  
    public @ResponseBody  
     String uploadTestResult(String testResultBarcode,int deviceLoc) {

         //some code goes here
    return something;
}

I just want to call this controller method from another java class. How can I make it work? please suggest..

tereško
  • 58,060
  • 25
  • 98
  • 150
Swapnil Walivkar
  • 295
  • 3
  • 5
  • 15
  • If you have to do that I think you've got a design problem. perhaps you should move the method to a lower level to be accessible to other controllers. – TheEwook Dec 04 '13 at 12:12
  • FYI. I can call this method by creating controllers object and directly calling that method. but in that case @Autowired fields not get initialized. I know the design is wrong but flow must be in this way, coz I m trying to call this method from thread which get initialized at the time of context initialization. – Swapnil Walivkar Dec 04 '13 at 12:15
  • @SwapnilWalivkar you can achieve this flow without having to have the wrong setup. You can just put this method in a service and make the controller and your thread each call this service instead of violating mvc principles. – Nikola Yovchev Dec 04 '13 at 12:31
  • What fo you mean you just want to call? Are you thinking of service I guess so. If you can point further I can provide concrete answer – manocha_ak Dec 04 '13 at 12:39
  • manocha_ak I have thread class which runs in a background. from thread class I am trying to call controller class method (but @autowired is giving me null). I tried creating objects by new keyword but at end in DAO layer the EntityManager is getting null. Thats why I trying to make request from controller itself. – Swapnil Walivkar Dec 04 '13 at 12:47
  • @SwapnilWalivkar even if in your thread you get the controller, it would be with empty autowired fields, unless you obtain it from the Spring context. There are many ways of obtaining a bean from the Spring context, and they are easily accessible on the internet. However, this setup would still be questionable from an architecture perspective. I suggest learning some basic Spring before diving deep into implementation. – Nikola Yovchev Dec 04 '13 at 13:46

1 Answers1

7

Short answer: yes, it is possible. In your other class/thread, you can do

// this will create a new instance of that controller where no fields are wired/injected
TestResultUploadController controller = new TestResultUploadController();
controller.uploadTestResult("someString", 1234); 

However, keep in mind that your setup is highly unusual and all your autowired fields wouldn't be wired correctly. If you obtain your controller from the context, you'd be able to have your fields wired/injected properly:

// obtain controller bean from context, should have fields wired properly
TestResultUploadController controller = ctx.getBean(TestResultUploadController.class);
controller.uploadTestResult("someString", 1234); 

or you can, in your other class, have:

@Autowired private TestResultUploadController controller;

....
public void doStuff(){
    controller.uploadTestResult("someString", 1234); 
}

Again, this is highly unusual, but highly possible. However, just cause something is possible to be done, doesn't mean you should do it. I would recommend the more common Spring/MVC approach in which you outsource the business logic to Services. Basically, to have something like this:

@Controller
public class TestResultUploadController {

    @Autowired private UploadTestResultService uploadTestResultService;

    @RequestMapping(method = RequestMethod.POST,value="/uploadTestResult")  
    public @ResponseBody String uploadTestResult(String testResultBarcode,int deviceLoc) {
        return uploadTestResultService.uploadTestResult(testResultBarcode, deviceLoc);
    }
}

And in your thread:

//somehow get the service
UploadTestResultService uploadTestResultService = //somehowGetTheService (whether from context or in some other way)
uploadTestResultService.uploadTestResult(testResultBarcode, deviceLoc);

That way, you'd be able to mock the UploadTestResultService in your tests of the controller, and you'd also be able to test the uploadTestResult method of that service on its own without it being in a controller.

EDIT: How to obtain the Spring context is outside of the scope of this question. I assume you know basic Spring and also basic java.

Nikola Yovchev
  • 9,498
  • 4
  • 46
  • 72
  • 2
    I tried all your solutions, but its not working. autowiring is giving me null instance in service layer. – Swapnil Walivkar Dec 04 '13 at 13:02
  • can u please give specification on ctx.getBean – Swapnil Walivkar Dec 04 '13 at 13:03
  • are you doing proper component scan? Are you declaring your services as beans or components? You seem to be new at Spring. It all depends on how your project is setup. Try to get autowiring to work, and if you can't do it, just create a static method somewhere and call it instead of a service: https://gist.github.com/anonymous/4d072f266ae1bb7bc457 – Nikola Yovchev Dec 04 '13 at 13:16
  • I am trying to get autowired worked. I have some doubts in mind. – Swapnil Walivkar Dec 04 '13 at 13:23
  • Explain what doubts you have. To me, you seem to not be able to quite grasp the idea of how Spring works. You somehow managed to autowire fields in your controller, why wouldn't you be able to autowire fields in your service? My suggestion would be for you to first go through a basic Spring crash course before starting to code seriously. – Nikola Yovchev Dec 04 '13 at 13:35
  • thanx baba. I m considering your suggestion and trying to implement it other way around. – Swapnil Walivkar Dec 05 '13 at 04:51
  • @SwapnilWalivkar no problem, I think it would drastically improve your speed of development if you know how to implement trivial things before you dive deep into real feature implementations. – Nikola Yovchev Dec 05 '13 at 08:38
  • @PhilipRego I assumed some basic Java and Spring knowledge, of course you'd need to obtain the context somehow, which is a totally different question: https://stackoverflow.com/questions/129207/getting-spring-application-context – Nikola Yovchev Jun 23 '19 at 20:49