2
\$\begingroup\$

I am logging entries into a website form using Spring4 and Java 8 (originally Java 7). I was using the slf4j logging framework firstly to write to file as a PoC and then directly to db as a mistaken final implementation. Mistaken as it shouldn't talk to the db directly. So I now have a very simple REST API server running with a couple of POST end points. So far so good. The basic code is working with no problems.

As this is non core functionality (logging NOT auditing) I thought I should make this call asynchronous so that if there are any issues this peripheral functionality won't degrade core functionality so I thought I should make the call asynchronously.

I have a created a Service class which is injected into the controller classes and has methods like this:

public void postLog (EntryItemLog logItem){
    String uri = REST_API_ENDPOINT;

    try {
        RestTemplate restTemplate = new RestTemplate();

        ResponseEntity<EntryItemLog> response = restTemplate.postForEntity(uri, logItem, EntryItemLog class);   

        LOGGER.debug("Returned logging POST with status  " + response.getStatusCode());

    }catch (Exception ex) {
        LOGGER.debug("Error Calling " + uri + ": " + ex.getMessage());
    }
}

and I am calling the function in this way:

 @RequestMapping(value = Controller.RESOURCE_NAME, method = RequestMethod.GET)
 public ModelAndView controlMethod(HttpServletRequest request, HttpServletResponse response,
            @ModelAttribute(REQUEST_MODEL_NAME) RequestBean requestBean, Model model) {
//some logging & set up

new Thread(() -> {
               dbRESTClientService.postLog(searchRequestBean.getTerm(), "searchProject", "WEB", (request.getHeader("X-FORWARDED-FOR") == null) ? request.getRemoteAddr() : request.getHeader("X-FORWARDED-FOR"));
            }).start();

//perform main functionality

I imagine this is very basic and unsophisticated for many people on this site, but is it broadly acceptable? Can anyone offer me any advice on doing it in a better way?

I guess I have 3 queries myself but any other (broadly constructive) criticism would gratefully accepted as the is a fairly new area to me:

  1. Starting a new thread seems like quite an overhead for this task but I don't see an alternative (other than using a 3rd party tool like Jersey which will presumably do the same thing anyway?)

  2. Should I be doing something more sophisticated than creating a local RestTemplate each time?

  3. Is it generally the right approach anyway (it feels over simplistic)?

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

1) Starting a new thread seems like quite an overhead for this task but I don't see an alternative (other than using a 3rd party tool like jersey which will presumably do the same thing anyway ?)

I would use there some message processing tool. Send somewhere and than process what should be processed. But it's much more complicated. I would use ExecutorService which is provided by java-8. I think it's old school to create Thread manually for this case.

2) Should I be doing something more sophisticated than creating a local RestTemplate each time ?

You can use @Configuration FactoryBean where you can create one spring @Bean for RestTemplate and inject this instance into your class where is postLog method located.

@Configuration
public class BeansFactory {
 @Bean public RestTemplate restTemplate(){
       return new RestTemplate();
 }
}

and inject in spring @Component

@Autowire private RestTemplate restTemplate;

3) Is it generally the right approach anyway (it feels over simplistic)

From my perspective doing async work for REST with Threads is little bit tricky. And open to few potential problems like - too many Threads, by default all threads with the same priority etc.

I think that for some async tasks the best way is to have publisher-subscriber approach. You are doing something, then you want to run something in the background to avoid waiting for response and return response without already finised async call.

To avoid doing another call you can push somewhere this event and process event somewhere else which is not depended on the current application.

Check also https://spring.io/guides/gs/messaging-reactor/

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.