1
votes

everyone. I have a service class in my spring boot application. Where I should call one method sync and one async.

@Service
public class CreationRequestServiceImpl implements CreationRequestService {

    @Autowired
    private MessageSender messageSender;

    @Override
    public void sendMessage() {

        sendMessageToManager(createParamMap(/*some param*/));

        //send message to customr async
        new Thread(
            () -> sendMessageToCustomer(createParamMap(/*some param*/))
        ).start();
    }

    private void sendMessageToManager(Map<String, String> param) {
        MessageTemplate messageTemplate;
        //some code
        messageSender.send(messageTemplate)
    }

    private void sendMessageToCustomer(Map<String, String> param) {
        MessageTemplate messageTemplate;
        //some code
        messageSender.send(messageTemplate)
    }

    private Map<String, String> createParamMap(/*some param*/) {
        Map<String, String> param;
        //some code
        return param;
    }
}

I use new Thread(...).start() to invoke method async. But I think it is not a good idea.

I did the following changes:

I define Executor bean in Configuration, add @EnableAsync

    @Bean(name = "taskExecutor")
    public Executor getAsyncExecutor() {
        //some code
    }

create a new service for async invocation

@Service
public class AsyncMessageSenderImpl implements AsyncMessageSender {

    @Async("taskExecutor")
    @Override
    public void run(Runnable runnable) {
        runnable.run();
    }
}

Refactor my CreationRequestServiceImpl class

@Service
public class CreationRequestServiceImpl implements CreationRequestService {

    @Autowired
    private MessageSender messageSender;

    @Autowired
    private AsyncMessageSender asyncMessageSender;

    @Override
    public void sendMessage() {

        sendMessageToManager(createParamMap(/*some param*/));

        //send message to customr async
        asyncMessageSender.run(
            () -> sendMessageToCustomer(createParamMap(/*some param*/))
        );
    }

    private void sendMessageToManager(Map<String, String> param) {
        MessageTemplate messageTemplate;
        //some code
        messageSender.send(messageTemplate)
    }

    private void sendMessageToCustomer(Map<String, String> param) {
        MessageTemplate messageTemplate;
        //some code
        messageSender.send(messageTemplate)
    }

    private Map<String, String> createParamMap(/*some param*/) {
        Map<String, String> param;
        //some code
        return param;
    }
}

But this is not working async.

QUESTION:

  1. How can I replace Thread(...).start() to start my method async. OR
  2. How can I make the second example to work?
1
Have you enabled async with @EnableAsync annotation? If not this should at least help you to run the method async. - cool

1 Answers

3
votes

Why not use CompletableFuture, which is more elegant and gives you lots of powerful option in terms of exception handling and functional way of writing code. Here is how I would do -

@Override
public void sendMessage() {

    sendMessageToManager(createParamMap(/*some param*/ ));
    CompletableFuture.runAsync(() -> sendMessageToCustomer(createParamMap(/*some param*/ )));
}