0

I'm trying to access a path variable from a request URL defined at the controller class level, from a method annotated with @PostConstruct. The idea is to use this path variable to initialize a local variable at the start of the API call before the relevant controller method is executed. This is to avoid having that piece code in every method and just let the controller set the variable at the start of the call.

The code might explain this better:

@RestController
@RequestMapping("/path/{variable}")
public class BaseController {

    protected Object object;

    @PostConstruct
    protected void setObject(@PathVariable("variable") Long variable){
        this.object= objectRepository.findById(variable).get();
    }
}

Obviously at this point I'm running into the "Lifecycle method annotation requires a no-arg method" error - so I know @PostConstruct is not the way to go, but I'm wondering if there's another way to achieve this, perhaps something like @Before for unit tests?

Thanks in advance!

Alan Hay
  • 22,665
  • 4
  • 56
  • 110
Raina
  • 99
  • 1
  • 2
  • 13
  • use @Value and google how to use it – Akshay Batra Jan 11 '19 at 07:24
  • @AkshayBatra @ Value will only accept String. If you're suggesting something like @ Value(@ PathVariable("variable")) to annotate the local variable, is there a way to convert the PathVariable type to String? – Raina Jan 11 '19 at 07:48
  • PathVariable is only available at the time of rest request – Akshay Batra Jan 11 '19 at 08:17
  • @AkshayBatra You're right, @ Value is not an option then. – Raina Jan 11 '19 at 08:46
  • You question and your comments below indicate you seriously misunderstand the life-cycle of a `@Controller`. https://stackoverflow.com/questions/16795303/must-spring-mvc-classes-be-thread-safe. `@PostConstruct` method will be invoked once on bean create and **NOT** before every request. – Alan Hay Jan 11 '19 at 15:32
  • I'm voting to close this question as off-topic because it demonstrates a fundamental lack of knowledge of the underlying technology. – Alan Hay Jan 11 '19 at 15:33
  • @AlanHay Thanks for the reference link. I do understand how PostConstruct works which is why I dismissed its use as part of my own problem statement while seeking the right way - I just wanted to explain the kind of behavior I was looking for and the initial shot I took at it. Lack of knowledge, exhaustion of search results online and time crunch is exactly what prompts people to turn to the SO community, unless I misread that it's a space for experts feeding experts. Regardless, I do appreciate your time in keeping the space clean and relevant. – Raina Jan 14 '19 at 08:35

3 Answers3

0

I am not sure why you actually would need this. Pathvariable is set externally during REST call. During startup phase you do not have this pathvariable which means that you cannot resolve anything from it.

In order to understand better what you are trying to achieve and why it is not working, I would recommend reading this short stackoverflow article: How exactly does the Spring BeanPostProcessor work?

If you have static identifiers I would rather go with ConfigurationProperties.

Can you please provide more input about what exactly you are trying to achieve with this? I personally would try to avoid global variables.

  • Slightly updated my phrasing - by initialization I'm referring to the start of the API call - not the class init. If you're familiar with how @Before works - I'm looking for a similar functionality - a method that is executed before the relevant controller method is called. The idea is to avoid having that piece of code in every method, and just let the controller set the variable at the start of the REST call. – Raina Jan 11 '19 at 08:00
  • Well @PostConstruct is called after constructing the Bean itself. – Ulrich Kowohl Jan 11 '19 at 08:12
  • Why did you need to post another answer? – NiVeR Jan 11 '19 at 08:24
0

I would not use @Value Annotation because you are spreading the entire configuration logic across the system. @ConfigurationProperties (please see here: https://www.baeldung.com/configuration-properties-in-spring-boot) would be your friend. You can as well use other object types as well as validation on top.

Regarding @Before from Unit Tests: @PostConstruct is called after constructing the bean itself, not before method call. If you would like to do something before method call, ArgumentResolver or an Aspect using Spring AOP would be your friend, I would rather go with ArgumentResolver and Manage everything under the hood. Once again, I doubt that you actually do a proper design, since @Pathvariable should be given from API user, not from configuration.

0

You can use AOP with @Aspect to run a piece of code before execution of any method from BaseController.

Please take a look to find out how to implement it. https://dzone.com/articles/aspect-oriented-programming-with-springboot

Twister
  • 161
  • 4