San*_*a J 7 java spring spring-boot
In my application, on the creation of a task, I need to make an API call to Google to create a google calendar event.
I decided to make that API call on a separate thread so that our client doesn't have to wait longer for the response.
@Override
@Transactional( rollbackFor = DataException.class )
public TaskResponseBean createTask( TaskCreationBean taskCreationBean, UserAccessDetails accessDetails )
        throws DataException
{
    String googleEventId = "";
    try
    {
        TaskServiceUtil.validateInputBeforeCreatingTask(taskCreationBean, accessDetails);
        MatterModel matterModel = matterService.giveMatterIfExistElseThrowException(taskCreationBean.getMatterId(),
                owner);
        //A task is unique for a user for a matter
        taskCommons.throwExceptionIfTaskNameAlreadyExistForTheMatter(taskCreationBean.getTaskName().trim(), owner,
                matterModel);
        TaskModel savedTask = taskModelRepository.save(savableTask);
        if( !NullEmptyUtils.isNull(savableTask.getDueDate()) )
        {
            final CreateEventBean createEventBean = getCreateEventBean(getEventParticipants(savedTask), savedTask);
            calendarTrigerer.triggerEventCreation(createEventBean, savedTask.getId(), null,
                    GoogleCalendarTrigerer.EVENT_TYPE_CREATE);
        }
        // Keep track of the list of assignees of a task
        if( taskCreationBean.getHaveAssignee() || taskCreationBean.getIsSelfAssigned() )
        {
            saveTaskAssignedHistory(savedTask, owner, savedTask.getAssignedTo(), false);
        }
    }
    catch( DataException e )
    {
        LOGGER.error(GeneralConstants.ERROR, e);
        if( !NullEmptyUtils.isNullOrEmpty(googleEventId) )
        {
            LOGGER.info("Deleting google event id {}", googleEventId);
            googleCalendarService.deleteGoogleCalendarEvent(googleEventId);
        }
        throw e;
    }
    catch( Exception e )
    {
        LOGGER.error(GeneralConstants.ERROR, e);
        if( !NullEmptyUtils.isNullOrEmpty(googleEventId) )
        {
            LOGGER.info("Deleting google event id {}", googleEventId);
            googleCalendarService.deleteGoogleCalendarEvent(googleEventId);
        }
        throw new DataException(GeneralConstants.EXCEPTION, GeneralConstants.SOMETHING_WENT_WRONG,
                HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
@Async
void triggerEventCreation( CreateEventBean createEventBean, Long taskId, String eventId, String eventType )
        throws DataException
{
    try
    {
        TaskModel taskModel = null;
        if( !NullEmptyUtils.isNullOrEmpty(taskId) )
        {
            int retryCount = 0;
            Optional<TaskModel> taskModelOptional = taskModelRepository.findByIdAndIsActiveTrue(taskId);
            while( !taskModelOptional.isPresent() )
            {
                System.out.println("NOT PRESENT***********************************************");
                taskModelOptional = taskModelRepository.findByIdAndIsActiveTrue(taskId);
                if( retryCount++ > 50 )
                {
                    throw new DataException(GeneralConstants.EXCEPTION, "Transaction is unable to commit",
                            HttpStatus.INTERNAL_SERVER_ERROR);
                }
            }
            taskModel = taskModelOptional.get();
        }
        switch ( eventType )
        {
            case EVENT_TYPE_CREATE :
                eventId = googleCalendarService.addGoogleCalendarEvent(createEventBean);
                System.out.println("ADDED EVENT***********************************************" + eventId);
                System.out.println("PRESENT***********************************************");
                taskModel.setGoogleEventId(eventId);
                taskModelRepository.save(taskModel);
                break;
            case EVENT_TYPE_DELETE :
                NullEmptyUtils.throwExceptionIfInputIsNullOrEmpty(eventId);
                googleCalendarService.deleteGoogleCalendarEvent(eventId);
                taskModel.setGoogleEventId(null);
                taskModel.setIsActive(false);
                taskModelRepository.save(taskModel);
                break;
            case EVENT_TYPE_UPDATE :
                NullEmptyUtils.throwExceptionIfInputIsNullOrEmpty(eventId);
                NullEmptyUtils.throwExceptionIfInputIsNullOrEmpty(createEventBean);
                taskModel.setGoogleEventId(
                        googleCalendarService.updateGoogleCalendarEvent(eventId, createEventBean));
                taskModelRepository.save(taskModel);
                break;
            default :
                throw new DataException(GeneralConstants.EXCEPTION, "Invalid eventType", HttpStatus.BAD_REQUEST);
        }
    }
    catch( DataException e )
    {
        log.error(GeneralConstants.ERROR, e);
        throw e;
    }
    catch( Exception e )
    {
        log.error(GeneralConstants.ERROR, e);
        throw new DataException(GeneralConstants.EXCEPTION,
                "Something went wrong while trigering create event action", HttpStatus.INTERNAL_SERVER_ERROR);
    }
}
How I solved (make sure it works) while creating an event In the separate thread, I will iterate and wait till the task gets created and then update it with the event id and save it.
But, a new problem arises, when updating the task, I already have its details in the database. In the update method, I will set updated values to TaskModel and do taskModelRepo.save() and in a separate thread I am calling google calendar update API and after successful API call, I have to update the corresponding TaskModel and save it.
The issue here is, sometimes when I fetch task by id after google API call is successful, I will get the TaskModel with non-updated values as the previous transaction is not committed yet.
So How to ensure the new thread runs only after the transaction of the method from which it is called is committed?
小智 0
你可以使用Google Guava Event Bus来解决这个问题。它是一种发布-订阅模型,其中生产者负责发出事件,然后将这些事件传递到事件总线并发送到订阅该事件的所有侦听器。
侦听器订阅事件,并在从生产者发布该事件时触发它,您可以根据您使用的事件总线的类型同步或异步运行侦听器方法。
这是链接: https: //github.com/google/guava/wiki/EventBusExplained
| 归档时间: | 
 | 
| 查看次数: | 133 次 | 
| 最近记录: |