Spring Batch: Starten eines Jobs mit einem Spring MVC contorller MIT NEUEM GEWINDE

Ich habe einen Spring-Batch-Job, den ich von einem Spring MVC-Controller aus starte. Der Controller erhält eine hochgeladene Datei vom Benutzer und der Job soll die Datei verarbeiten:

@RequestMapping(value = "/upload") public ModelAndView uploadInventory(UploadFile uploadFile, BindingResult bindingResult) { // code for saving the uploaded file to disk goes here... // now I want to launch the job of reading the file line by line and saving it to the database, // but I want to launch this job in a new thread, not in the HTTP request thread, // since I so not want the user to wait until the job ends. jobLauncher.run( jobRegistry.getJob(JOB_NAME), new JobParametersBuilder().addString("targetDirectory", folderPath).addString("targetFile", fileName).toJobParameters() ); return mav; } 

Ich habe die folgende XML-Konfiguration ausprobiert:

            

… aber es scheint, als ob das Multithreading nur innerhalb der Jobgrenzen selbst stattfindet. Dh, der Controller-Thread wartet, bis der Job beendet ist, und die Jobausführung wird von mehreren Threads abgewickelt (was gut ist, aber nicht die Hauptsache, die ich wollte). Die Hauptsache, die ich wollte, ist, dass der Job in einem separaten Thread (oder Threads) gestartet wird, während der Controller-Thread seine Ausführung fortsetzt, ohne auf das Ende der Job-Threads zu warten.

Gibt es eine Möglichkeit, dies mit Spring-Batch zu erreichen?

Die offizielle Dokumentation beschreibt Ihr genaues Problem und eine Lösung in 4.5.2. Jobs aus einem Webcontainer ausführen :

[…] Der Controller startet einen Job mit einem JobLauncher , der für den asynchronen Start konfiguriert wurde und der sofort eine JobExecution . Der Job wird wahrscheinlich noch ausgeführt, aber dieses nicht blockierende Verhalten ermöglicht es dem Controller, sofort zurückzukehren , was bei der Verarbeitung eines HttpRequest erforderlich ist.

Spring Batch http://sofde.miximages.com/java/launch-from-request.png

Sie waren also ziemlich nah TaskExecutor , den JobLauncher zu verwenden, er muss jedoch stattdessen an den JobLauncher werden:

     

Haftungsausschluss: Ich habe Spring Batch nie verwendet …

Die jobLauncher.run() Methode kann in einem neuen Thread wie jobLauncher.run() aufgerufen werden:

 @RequestMapping(value = "/upload") public ModelAndView uploadInventory(UploadFile uploadFile, BindingResult bindingResult) { [...] final SomeObject jobLauncher = [...] Thread thread = new Thread(){ @Override public void run(){ jobLauncher.run([...]); } }; thread.start(); return mav; } 

Die thread.start() Zeile erzeugt einen neuen Thread und führt anschließend den darunter liegenden Code aus.

Beachten Sie, dass, wenn jobLauncher eine lokale Variable ist, diese als final deklariert werden muss, damit sie in der anonymen Thread class verwendet werden kann.

Wenn Sie Ihrem Client keine Verarbeitungserrors anzeigen müssen, können Sie den Spring-Batch-Job in einem separaten Thread starten.