Here is the working code for my Spring service:

public class UploadService {

    Session session;

    AsyncImageConvertService asyncImageConvertService;

    String awsBucketName;

    AmazonS3 amazonS3;

    ImageMapper imageMapper;

    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED)
    public void uploadImage(Image image, String url, Runnable fnSaveObject) {
        File file = new File(System.getProperty("java.io.tmpdir"), image.getUrl());

        PutObjectRequest request = new PutObjectRequest(awsBucketName, image.getUrl(), file);

        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
            public void afterCommit() {
                // Database has a newly inserted (and committed) image data here. asynceImageConvertService will select and update it.
                // fnSaveObject function should run in current transaction.
                asyncImageConvertService.processImage(image.getId(), file);

        imageMapper.insert(image); // image's id will be generated here.
        fnSaveObject.run();  // image's id should exists here.

It is called from the following code:

                "/user/" + user.getId() + "/" + profileImage.getUrl(),
                () -> userMapper.insertImage(user, profileImage) // generated image's id will be applied.

The Runnable functional interface will run in transaction and invoke async service method after transaction committed.

*Mapper is injected instance also, via spring-mybatis.

This code looks like it's working well, but I'm afraid it's not safe.

Is it safe to use functional interface arguments in methods of services injected via Spring?


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.