Search code examples
javaspringspring-bootprogress

Spring Boot Progress report


I would like to be able to report a certain method's progress in Spring Boot. I used a seperate class which I store the current status in and return as the current view: It looks like this:

public class SearchTableReloadState {

    //STATIC STORAGE

    public static long TABLE_ROW_COUNT = 0;
    public static long CURRENT_OFFSET = 0;
    public static long CURRENT_LIMIT = 0;
    public static long DEFAULT_LIMIT = 20000;

    public static void reset() {
        TABLE_ROW_COUNT = 0;
        CURRENT_OFFSET = 0;
        CURRENT_LIMIT = DEFAULT_LIMIT;
    }

    public static void setDefaultLimit(long defaultLimit) {
        DEFAULT_LIMIT = defaultLimit;
    }

    // VIEWMODEL
    public long tableRowCount = 0;
    public long currentOffset = 0;
    public long currentLimit = 0;

    public static SearchTableReloadState getState() {
        SearchTableReloadState reloadState = new SearchTableReloadState();
        reloadState.tableRowCount = TABLE_ROW_COUNT;
        reloadState.currentOffset = CURRENT_OFFSET;
        reloadState.currentLimit = CURRENT_LIMIT;
        return reloadState;
    }
}

And the methods:

@RequestMapping(value = {"/manage/searchtable/reload/state"}, method = RequestMethod.GET)
public @ResponseBody SearchTableReloadState searchTableReloadState() {
    return SearchTableReloadState.getState();
} 

@ResponseStatus(HttpStatus.OK)
    @RequestMapping(value = {"/manage/searchtable/reload"}, method = RequestMethod.GET)
    public void searchTableReload() throws ResourceAlreadyExistsException, ParameterMissingIdException {
     SearchTableReloadState.reset();
     SearchTableReloadState.TABLE_ROW_COUNT = productDataReferenceDao.countJobReferences();
     productDataReferenceDao.truncateSearchTable();
     while (SearchTableReloadState.CURRENT_OFFSET < SearchTableReloadState.TABLE_ROW_COUNT) {
          ... long running task
          ....
          SearchTableReloadState.CURRENT_OFFSET += SearchTableReloadState.CURRENT_LIMIT;
        }
}

The method with the /state would report the current state, so I could call these with Ajax on a site. Problem is, If I start the long running one, the state report request won't complete until the long running did not complete. I thought Spring uses separate threads for each request. Do I need to implement threading in Spring?

If I use the @Async annotation for the long running process, it works like I expected, but I still don't understand, why could two separate HTTP requests for a different method block each other!


Solution

  • If I use the @Async annotation on the method that is supposed to take a long time, the HTTP Request calling it will get a response immediately and it will run in the background and I can call the state method as I expected. Even though it is working, I still don't know why it won't work without the asynchronous execution.

    If you want to use the @Async annotation, you have to put the @EnableAsync annotation on the class you used the @SpringBootApplication and/or @EnableAutoConfiguration.

    I hope someone can provide a better answer later.