1

I've a webservice similar to the following:

@RequestMapping(value = "/getMovies", method = RequestMethod.POST, produces = "application/json")
public @ResponseBody ResponseVO getMoviesList(@RequestBody RequestVO vo) { .... }

The RequestVO class is :

public class RequestVO {
private String[] genreList;

    public void updateRequest() {
        if (genreList != null) {
            // remove the duplicates from the list
            // or something else
        }
    }

    public String[] getGenreList() {
        return genreList;
    }

    public void setGenreList(String[] genreList) {
        this.genreList = genreList;
    }

}

Now I want the method updateRequest to be called automatically after the request json is processed as RequestVO. One thing I currently think of is @PostConstruct, but seems to be of no use in this case.

My question is does Spring provide any such annotation or mechanism ? Or @PostConstruct will do the trick ?

NB : I don't need workarounds as I've plenty of them. So please refrain yourself from posting them. Again above codes are mere samples (please ignore minor mistakes).

blackSmith
  • 3,054
  • 1
  • 20
  • 37

2 Answers2

0

Couple of thins to consider:

  • Don't use verbs in Rest Service method names (like getMovies) because you specify action using HTTP verbs like GET, POST and so on.
  • POST should be used to create a resource on the server not to retrieve them (what is implied by the method name: 'getMovies')

What do you want to achieve is RequestVO.updateRequest() invoked before passing RequestVO instance to getReportData(), is it right? If so, could you elaborate, why can't you invoke this method on the beginning of the getReportData()?

If you want to achieve this kind of functionality despite the fact it's sensible or not, try:

  • create new aspect which will be invoked before getReportData() and invoke updateRequest()
  • use @JsonFactory (provided you use Jackson to map JSON to Java objects) like:

    public class RequestVO {
    private String[] genreList;
    
    public void updateRequest() {
        if (genreList != null) {
            ...
        }
    }
    
    public String[] getGenreList() {
        return genreList;
    }
    
    public void setGenreList(String[] genreList) {
        this.genreList = genreList;
    }
    
    @JsonFactory
    public static RequestVO createExample(@JsonProperty("genreList") final String[] genreList) {
        RequestVO request = new RequestVO(genreList);
        request.updateRequest();
        return request;
    }
    

    }

Alinoe
  • 73
  • 1
  • 10
  • U probably didn't go through my NB section. Anyway thanks the for convention tips. FYI `getMovies` consumes a Json, thus it's a POST. I'm using `Jackson` so I can try ur solution, can you elaborate it a bit. Will `createExample` be called on every service call before it enters the method body ? – blackSmith Oct 20 '14 at 08:02
  • hey I'm not able to import `@JsonFactory` annotation. Any pointers ? – blackSmith Oct 20 '14 at 08:27
  • It should be `@JsonCreator` instead. One another question have you tried GET method and send genre list as a request parameter (/movie?id=1,2,3) and then instead of `@RequestBody` you can use `@RequestParam` Set genres – Alinoe Oct 20 '14 at 10:04
  • It's not a simple Movie listing App, that was just a sample. I have no choice but to post a complex Json. – blackSmith Oct 20 '14 at 12:35
0

As you are saying, @PostConstruct is only call after a bean creation and is of no use here. But you have 2 simple ways of calling a method after the end of another method.

  • explicit : just wrap your real method in another one, and do all pre- or post-processing there

    @RequestMapping(value = "/getMovies", method = RequestMethod.POST, produces = "application/json")
    public @ResponseBody ResponseVO getMoviesList(@RequestBody RequestVO vo) {
        // pre_processing
        ResponseVO resul = doGetMoviesList(vo);
        // post_processing
        return resul;
    }
    public ResponseVO doGetMoviesList(RequestVO vo) { ... }
    

Is is simple to write, even if not very nice.

  • use Spring AOP. You can define an after returning advice that will be called after the advised method returns normally. The advice can be shared across multiple classes if you need it and write your pointcut accordingly. It is really powerfull, but has one caveat : Spring implementation uses proxies and by default JDK proxies. That means that any advised method should be member of an interface and called through that interface. So it would be much simpler and cleaner to advise a service than a controller. IMHO, if you really need to do AOP on a controller, you should use full AspectJ including class weaving ... In short, it is very nice, very powerfull, but a little harder to implement.
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252
  • Actually, that's the workAround I was talking about (ur explicit solution) ! The second one seems to be interesting but kinda beyond my scope and understanding as well. Thanks anyway. – blackSmith Oct 20 '14 at 07:51