Ich versuche, eine .findAll()
auf einer Repository-Schnittstelle auszuführen, die sich von CrudRepository erstreckt. Ich versuche dies innerhalb einer @Async
Methode mit einer @Autowire
Implementierung des Repositorys zu tun. Wenn ich den folgenden Code ausführe, @Async
wartet der Thread für immer auf den UpdateTasksServiceList<Task> tasks = (List<Task>)taskRepo.findAll();
Wenn ich die @Async
Anmerkung aus der Methode updateTasks() entferne, läuft das Programm wie erwartet und gibt alle.toString()-Daten aus.
Meine Fragen sind:
@Autowired TaskRepository taskRepo;
Innere einer @Async
Methode nicht verwenden?@Async
Methode verwenden?Vielen Dank im Voraus!
ScheduleComponent
@Component
public class ScheduleComponent {
@Autowired
UpdateTasksService updateTasks;
@PostConstruct
public void update(){
Future<Void> updateTasksFuture = updateTasks.updateTasks();
try {
updateTasksFuture.get();
System.out.println("Done");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
UpdateTaskService
@Service
public class UpdateTasksService {
@Autowired
TaskRepository taskRepo;
@Async
public Future<Void> updateTasks() {
System.out.println("The method starts");
List<Task> tasks = (List<Task>)taskRepo.findAll();
for(Task task: tasks){
System.out.println(task.toString());
}
return new AsyncResult<Void>(null);
}
}
TaskRepository
@Repository
public interface TaskRepository extends CrudRepository<Task, String> {
}
Lösung des Problems
Ich hatte das gleiche Problem und bemerkte, dass dieses Verhalten nicht auftritt, wenn eine Abfrage auf der JDBC-API (nicht dem JPA-Repository) basiert oder wenn die Abfrage mit @Query im SpringData-Repository definiert ist. Als Problemumgehung habe ich einen Flush für eines der Repositories in PostConstruct aufgerufen. Ich weiß immer noch nicht, warum das passiert.
Problemumgehung:
@Service
public class UpdateTasksService {
@Autowired
TaskRepository taskRepo;
@PostConstruct
public void init() {
//Workaround to a async method that waits forever when called
//from PostConstruct from another component
taskRepo.flush();
}
@Async
public Future<Void> updateTasks() {
System.out.println("The method starts");
List<Task> tasks = (List<Task>)taskRepo.findAll();
for(Task task: tasks){
System.out.println(task.toString());
}
return new AsyncResult<Void>(null);
}
}
Keine Kommentare:
Kommentar veröffentlichen