Get Request doppelt abfeuern ohne Post Redirect Get Pattern. Spring Boot Thymeleaf MVC

Avalon

Bekanntes Mitglied
Hallo, ich habe folgenden Controller der beim Aufruf des Endpunktes eine Tabelle bzw. Liste mit Daten auf einer HTML Seite darstellt.

Java:
    @GetMapping("/")
    public String showIndex(Model model) {
        model.addAttribute("tage", service.matrix());
        return "index";
    }

bei F5 oder STRG + F5 im Browser wird die Liste einfach an die Alte unten dran gehängt.
Gibt es eine Möglichkeit das ohne Post/Redirect/Get Muster zu verhindern?
Cookies werden nicht verwendet.

Spring Version 6.0.13
Spring Boot 3.1.5
Java 17
 

Marinek

Bekanntes Mitglied
Hi,

Ich verstehe nicht, woher der Fehler kommt.

Wie sieht den der Service aus? Sieht aus als würden Sachen irgendwo persistiert, die da nicht hingehören.

Gruß
 

Avalon

Bekanntes Mitglied
Hier der Service. Tupel ist schlecht gewählt. Alles läuft ohne Datenbank.

Java:
@Service
public class ArbeitstageRechnerService {
    

List<InfoTupel> liste = new ArrayList<>();

    public List<InfoTupel> matrix() {
        int jahr = 2023; // Setze das gewünschte Jahr

        for (int monat = 1; monat <= 12; monat++) {
            InfoTupel arbeitstag = new InfoTupel();
            YearMonth yearMonth = YearMonth.of(jahr, monat);
            Integer arbeitstage = berechneArbeitstageInMonat(yearMonth);
            arbeitstag.setArbeitstage(arbeitstage);
            arbeitstag.setMonat(monat);
            arbeitstag.setJahr(jahr);
            arbeitstag.setSechszigProzent(arbeitstage * 0.6);
            liste.add(arbeitstag);
        }
        return liste;
    }

    private int berechneArbeitstageInMonat(YearMonth yearMonth) {
        Integer arbeitstage = 0;
        for (int tag = 1; tag <= yearMonth.lengthOfMonth(); tag++) {
            LocalDate datum = yearMonth.atDay(tag);
            if (!istWochenende(datum)) {
                arbeitstage++;
            }
        }
        return arbeitstage;
    }

    private boolean istWochenende(LocalDate datum) {
        DayOfWeek wochentag = datum.getDayOfWeek();
        return wochentag == DayOfWeek.SATURDAY || wochentag == DayOfWeek.SUNDAY;
    }
}
 

Avalon

Bekanntes Mitglied
Bei jedem Aufruf von Matrix wird die Liste erweitert, die wird ja nie geleert

Unglaublich aber war. Es war meine erste Liste, die ich sozusagen manuell selbst erstellt und ans Model übergeben habe. Bis jetzt habe ich immer vorgefertigte Methoden wie z.B. findAll() in Verbindung mit Repositorys verwendet. Da brauch man sich um nichts zu kümmern. Also Ende vom Lied: Ich musste im Service beim Aufruf prüfen, ob die Liste leer ist oder nicht. Jetzt klappt alles. Vielen Dank fürs "Auf die Sprünge helfen". Aber eine Frage habe ich noch. Kann man das mit der Abrage ob Liste leer oder nicht leer etwas eleganter gestalten. Irgendwie sieht das im Code bescheiden aus und Code der beschissen ausssieht, ist es in der Regel auch.


Java:
@Service
public class ArbeitstageRechnerService {

    List<InfoTupel> liste = new ArrayList<>();

    public List<InfoTupel> matrix() {
        int jahr = 2023; // Setze das gewünschte Jahr
        
        Object resultat = (istListeLeer(liste)) ? "leer" : "nicht leer"; // Abfrage Liste leer
        
        if (resultat.equals("nicht leer")); // Wenn nicht leer dann leeren
        liste.clear();
        
        for (int monat = 1; monat <= 12; monat++) {
            InfoTupel arbeitstag = new InfoTupel();
            YearMonth yearMonth = YearMonth.of(jahr, monat);
            Integer arbeitstage = berechneArbeitstageInMonat(yearMonth);
            arbeitstag.setArbeitstage(arbeitstage);
            arbeitstag.setMonat(monat);
            arbeitstag.setJahr(jahr);
            arbeitstag.setSechszigProzent(arbeitstage * 0.6);
            liste.add(arbeitstag);
        }
        return liste;
    }

    private boolean istListeLeer(List<InfoTupel> list) {
        return list.isEmpty();
    }

    private int berechneArbeitstageInMonat(YearMonth yearMonth) {
        Integer arbeitstage = 0;
        for (int tag = 1; tag <= yearMonth.lengthOfMonth(); tag++) {
            LocalDate datum = yearMonth.atDay(tag);
            if (!istWochenende(datum)) {
                arbeitstage++;
            }
        }
        return arbeitstage;
    }

    private boolean istWochenende(LocalDate datum) {
        DayOfWeek wochentag = datum.getDayOfWeek();
        return wochentag == DayOfWeek.SATURDAY || wochentag == DayOfWeek.SUNDAY;
    }
}
 

thecain

Top Contributor
Wieso erstellst du die Liste nicht einfach jedes Mal neu, statt zu leeren?

Grundsätzlich würde ich sowieso davon Abraten in einem Service Instanzvariablen zu halten.
 

Oneixee5

Top Contributor
Instanzvariablen mit einem Zustand, welche nicht von Spring verwaltet werden, sind eine schlechte Idee. In Szenarien mit mehreren Nutzern oder mehreren Threads wäre das Verhalten undefiniert.
 

KonradN

Super-Moderator
Mitarbeiter
Erst einmal sehr schön, den Umgang mit den Hinweisen zu lesen. Das ist erfrischend und schön. Danke für Deine Art und Weise @Avalon.
Hab nach dem Hinweis von thecain ChatGpt schon befragt.
Ich will den nicht zu sehr vom Thema abbringen aber das das Problem gelöst scheint, erlaube ich mir, Off Topic zu werden und zu ChatGPT was zu schreiben:

ChatGPT ist eine super Hilfe - darauf greife ich auch sehr gerne zurück. Aber immer im Kopf behalten, dass ChatGPT auch direkt Dinge erfindet. Ich habe schon die lustigsten Antworten bekommen. Und bei so Dingen, die man erlernen will, würde ich dann immer dazu raten, mit den gefundenen Fachbegriffen auch weiter zu recherchieren um Quellen zu bekommen und diese zu lesen. Das vertieft das Wissen deutlich besser und verhindert, dass man falsche Dinge erlernt.

Das aber nur als reiner Hinweis am Rand und ggf. machst Du es auch nicht anders. Und selbstverständlich kann das jeder so machen, wie er möchte.
 

Neue Themen


Oben