Background Task with a Bean with Session scope

I’m trying to do this
https://docs.jmix.io/jmix/ui/background-tasks.html

I want the progress bar when ever a user is authenticating to a third party but i store these credentials in a session scoped bean.

I get a
Scope ‘session’ is not active for the current thread; IllegalStateException: No thread-bound request found.

Any idea how this can be done?

How did you define the bean and how do you access it?

The following works for me:

@Component
@Scope(value = WebApplicationContext.SCOPE_SESSION)
public class SampleSessionBean {

    private String value;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}
@UiController("TaskScreen")
@UiDescriptor("task-screen.xml")
public class TaskScreen extends Screen {

    @Autowired
    private Dialogs dialogs;

    @Autowired
    private SampleSessionBean sampleSessionBean;

    @Autowired
    private Label label;

    private static final Logger log = LoggerFactory.getLogger(SampleTask.class);

    private class SampleTask extends BackgroundTask<Integer, Void> {

        public SampleTask() {
            super(10, TimeUnit.MINUTES, TaskScreen.this);
        }

        @Override
        public Void run(TaskLifeCycle<Integer> taskLifeCycle) throws Exception {
            for (int i = 0; i < 20; i++) {
                if (taskLifeCycle.isCancelled()) {
                    break;
                }
                sampleSessionBean.setValue(String.valueOf(i));
                Thread.sleep(1000);

                taskLifeCycle.publish(i);
            }
            return null;
        }

        @Override
        public void done(Void result) {
            String value = sampleSessionBean.getValue();
            log.info("done >>> " + value);
            label.setValue(value);
        }
    }

I have the bean as
@SessionScope

changing to
@Scope(value = WebApplicationContext.SCOPE_SESSION)
breaks my application :frowning:

Perhaps it’s not a good idea to access session beans from a background thread.
Better store the data required for a background process in the background task instance itself: pass input to the constructor and return results from done() method if needed.

1 Like

great idea… this made that error go away… it super makes my code horrible now because i need to be sending these parameters all over the place… but now… the operation starts… stays there a couple of seconds and at the last second it shows the progressbar and hides it. i dont have a list of elements its only a slow web service call i need to do. Just need to notify the end user about it. so its still not really working for me.

Hi Eduardo,
I have a similar situation to what you have.

I am getting the error message below due to the fact that I use SessionData bean to pass data around in my application and there is a need to call restful service from within a background task.

Error creating bean with name ‘core_SessionData’: Scope ‘session’ is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton

Is there a cleaner solution different from what Krivopustov provided?

Right now, I need to email a pdf report from within a background task. The pdf is an output from e report with a dataset connected to an additional datastore that get its data from a restful service.

 public void emailRFQ(QuotationRequest quoteReq) throws EmailException {
        //set the tenant email smtp details
        getMailPropertiesByTenant(quoteReq.getTenant());

        String msg = String.format("Request for Quotation %s emailed",quoteReq.getRfqNo());

       

ReportOutputDocument rfqPDF = reportRunner.byReportCode(“RFQ”)
.addParam(“entity”,quoteReq)
.run();


        byte[] content = rfqPDF.getContent();
        EmailAttachment emailAtt = new EmailAttachment(content, rfqPDF.getDocumentName());

        EmailInfo emailInfo = EmailInfoBuilder.create()
                .setFrom(utilityService.getTenant(quoteReq.getTenant()).getSenderEmail())
                .setAddresses(quoteReq.getCustomer().getSalesPerson().getEmail())
                .setSubject(String.format("Request for Quotation: %s ",quoteReq.getRfqNo()))
                .setBody(msg)
                .setAttachments(emailAtt)
                .build();
        //emailer.sendEmailAsync(emailInfo);
        emailer.sendEmail(emailInfo);
    }

The solution provided above is not working for me because I don’t have the means of performing the solution above.

Please assist me here

Thanks in advance

H I did a list of callables set them up with the session variable and then sent it to the Background thread handler

private void threadDemo(String mySessionStoredValue) {
        List<Callable<Void>> callables = new ArrayList<>();
        // get current security context
        SecurityContext context = SecurityContextHolder.getContext();
        // create array of tasks
        for (String email : myEmailList){
            callables.add(() -> {
                // set security context in the thread
                SecurityContextHolder.setContext(context);
                try {
                    emailService.send("Hello",email, mySessionStoredValue);
                    return null;
                } catch (Exception e) {
                    e.printStackTrace();
                    return null;
                } finally {
                    // clear security context in the thread (just in case)
                    SecurityContextHolder.clearContext();
                }
            });
        }
        // pass the array of tasks to the BackgroundTask
        BackgroundTaskHandler<Integer> taskHandler = backgroundWorker.handle(new ThreadBackgroundTask(callables));
        // start the BackgroundTask
        taskHandler.execute();
    }
1 Like

Hi Eduardo,
Thanks very much. It works perfectly.