No transaction aspect-managed TransactionStatus in scope] Przy asynchronicznych metodach w spring MVC

0

Chciałbym mieć współbieżny web serwis tak żeby w momencie kiedy jeden kontroller obsługuje mi jedną część web serwisu, to wtedy w drugiej karcie przeglądarki mógłbym otworzyć sobie zupełnie inną a co gorsza żeby to była tranzakcja xD . Użycie @Async raczej nie wchodzi w gre bo wtedy to i tak asynchroniczne byłyby metody warstwy serwisu ale nie całego kontrollera czyli gdybym miał w jednej karcie np. generowanie formularza(tak generowałoby się szybciej(wiem że nie zawze) bo asynchronicznie)to druga otworzona później musiałaby czekać w kolejce a nie o to mi chodzi
Więc chciałem użyć Callable ale gdy próbuję zrobić to w formie tranzakcji to wyskakuje mi błąd

There was an unexpected error (type=Internal Server Error, status=500).
No transaction aspect-managed TransactionStatus in scope
org.springframework.transaction.NoTransactionException: No transaction aspect-managed TransactionStatus in scope at org.springframework.transaction.interceptor.TransactionAspectSupport.currentTransactionStatus(TransactionAspectSupport.java:124) at org.springframework.samples.petclinic.controller.VisitController$1.call(VisitController.java:127) at org.springframework.samples.petclinic.controller.VisitController$1.call(VisitController.java:113) at org.springframework.web.context.request.async.WebAsyncManager.lambda$startCallableProcessing$4(WebAsyncManager.java:323) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at java.lang.Thread.run(Thread.java:748)

Jak mógłbym zrobić tę część żeby była w zakresie tranzakcji?

  @Transactional(isolation = Isolation.READ_COMMITTED)
    @PostMapping("/owners/{ownerId}/pets/{petId}/visits/{visitId}/edit")
    public Callable<String> processUpdateForm(@PathVariable("visitId") int visitId, @Valid Visit visit, BindingResult result){

        return new Callable<String>() {
            @Transactional(isolation = Isolation.READ_COMMITTED)
            public String call() throws Exception {
                visit.setId(visitId);
                if (result.hasErrors()) {

                    return "pets/createOrUpdateVisitForm";
                } else {

                    visitService.update(visit);

                    System.out.println("po dodaniu");
                    System.out.println(visitService.findById(visitId).getPrice());
                    System.out.println("po dodani2");
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return "redirect:/owners/{ownerId}";
                }

            }
        };
0

Niestety widac że nie wiesz jak transakcje w Springu działają. Spring używa ThreadLocali, tak więc jeśli jest stworzony nowy wątek dla nowego requestu to wszystkie transakcje muszą się wykonywać w tyższe wątku. W ogóle nie rozumiesz co robisz niestety, polecam nauczyć się co to jest programowanie aspektowe i jak działają kontenery IoC...
Zresztą ogólnie ten twój cały zamysł jest bardzo dziwny :D :D :D

1

@masterkwi - problemem jest to, że chcesz użyć debugera, który pauzuje wykonywanie jakiegokolwiek kodu aplikacji, stąd efekt "kolejkowania" przetwarzania żądań. Bo w realnej aplikacji, to żądania przecież pójdą "równolegle" (w sensie na innych wątkach).

1

@masterkwi: nic z tego co napisałeś w 1 poście nie ma sensu. Żadnego. Tomcat/jetty przecież są wielowątkowe, więc twoje osobne karty w przeglądarce są zupełnie niezależne od siebie. Zwracanie jakiegoś callable z kontrolera to pomysł tak dziwny i głupi że trudno mi się do niego odnieść. A co do transactional to zupełnie nie rozumiem co chcesz osiągnąć.

1 użytkowników online, w tym zalogowanych: 0, gości: 1