diff --git a/pom.xml b/pom.xml
index 4c71c16b1d28a349b56791027354dcab0a054f9e..62dd2f405c9a60176e153b67dc9bacabf97f4283 100644
--- a/pom.xml
+++ b/pom.xml
@@ -86,6 +86,7 @@
 		<gwt.version>2.12.1</gwt.version>
 		<gwtbootstrap3.version>0.9.4</gwtbootstrap3.version>
 		<hibernate.version>5.6.15.Final</hibernate.version>
+		<jackson.version>2.18.1</jackson.version>
 		<javax.mail.version>1.5.6</javax.mail.version>
 		<jersey.version>2.45</jersey.version>
 		<junit.version>4.13.2</junit.version>
@@ -101,10 +102,10 @@
 		<application.log.level>FINEST</application.log.level>
 		<environment>dev</environment>
 		<maven.build.timestamp.format>yyyy-MM-dd HH:mm:ss</maven.build.timestamp.format>
-		<maven.compiler.source>11</maven.compiler.source>
-		<maven.compiler.target>11</maven.compiler.target>
-		<maven.compiler.testSource>11</maven.compiler.testSource>
-		<maven.compiler.testTarget>11</maven.compiler.testTarget>
+		<maven.compiler.source>17</maven.compiler.source>
+		<maven.compiler.target>17</maven.compiler.target>
+		<maven.compiler.testSource>17</maven.compiler.testSource>
+		<maven.compiler.testTarget>17</maven.compiler.testTarget>
 		<!-- Tools -->
 		<checkstyle.config.location>file://${basedir}/config/sun_checks.xml</checkstyle.config.location>
 		<checkstyle.failsOnError>false</checkstyle.failsOnError>
@@ -307,16 +308,15 @@
 		</dependency>
 
 		<!-- fast serialization -->
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-core</artifactId>
+			<version>${jackson.version}</version>
+		</dependency>
 		<dependency>
 			<groupId>de.ruedigermoeller</groupId>
 			<artifactId>fst</artifactId>
-			<version>2.57</version>
-			<exclusions>
-				<exclusion>
-					<groupId>com.fasterxml.jackson.core</groupId>
-					<artifactId>jackson-core</artifactId>
-				</exclusion>
-			</exclusions>
+			<version>3.0.4-jdk17</version>
 		</dependency>
 
 		<!-- sido-rs -->
@@ -553,7 +553,7 @@
 						<configuration>
 							<rules>
 								<requireJavaVersion>
-									<version>11</version>
+									<version>[17,)</version>
 								</requireJavaVersion>
 							</rules>
 						</configuration>
@@ -731,7 +731,7 @@
 					<moduleName>fr.soeretempo.gwt.Tempo</moduleName>
 					<moduleShortName>tempo</moduleShortName>
 					<failOnError>true</failOnError>
-					<sourceLevel>11</sourceLevel>
+					<sourceLevel>17</sourceLevel>
 
 					<!-- Compiler configuration -->
 					<compilerArgs>
diff --git a/src/main/java/fr/soeretempo/gwt/client/AppActivityMapper.java b/src/main/java/fr/soeretempo/gwt/client/AppActivityMapper.java
index cb207738b43cb6351eb793a473368d36b617597d..0e2a253dd32d97adb83c7ad4f702e982797a67d3 100644
--- a/src/main/java/fr/soeretempo/gwt/client/AppActivityMapper.java
+++ b/src/main/java/fr/soeretempo/gwt/client/AppActivityMapper.java
@@ -79,12 +79,12 @@ public class AppActivityMapper implements ActivityMapper {
             return new PreviewActivity(clientFactory);
         } else if (place instanceof AccountFormPlace) {
             return new AccountFormActivity(clientFactory);
-        } else if (place instanceof DataSrDescPlace) {
-            return new DataSrDescActivity((DataSrDescPlace) place, clientFactory);
+        } else if (place instanceof DataSrDescPlace dataSrDescPlace) {
+            return new DataSrDescActivity(dataSrDescPlace, clientFactory);
         } else if (place instanceof QueriesPlace) {
             return new QueriesActivity(clientFactory);
-        } else if (place instanceof AccessDataPlace) {
-            return new AccessDataActivity((AccessDataPlace) place, clientFactory);
+        } else if (place instanceof AccessDataPlace accessDataPlace) {
+            return new AccessDataActivity(accessDataPlace, clientFactory);
         } else if (place instanceof AccessesPlace) {
             return new AccessesActivity(clientFactory);
         } else if (place instanceof DataSourcesAdminPlace) {
@@ -93,8 +93,8 @@ public class AppActivityMapper implements ActivityMapper {
             return new MailPageActivity(clientFactory);
         } else if (place instanceof ProfilePlace) {
             return new ProfileActivity(clientFactory);
-        } else if (place instanceof NewsEditorPlace) {
-            return new NewsEditorActivity((NewsEditorPlace) place, clientFactory);
+        } else if (place instanceof NewsEditorPlace newsEditorPlace) {
+            return new NewsEditorActivity(newsEditorPlace, clientFactory);
         } else if (place instanceof NewsManagerPlace) {
             return new NewsManagerActivity(clientFactory);
         } else if (place instanceof NewsPlace) {
diff --git a/src/main/java/fr/soeretempo/gwt/client/dataSrDesc/DataSrDescViewImpl.java b/src/main/java/fr/soeretempo/gwt/client/dataSrDesc/DataSrDescViewImpl.java
index 047871f2a6dd71ec25c9a4b8743a6bd5698de76f..3ff80c9c736eb24a20feb889bd43d01ebc8953a7 100644
--- a/src/main/java/fr/soeretempo/gwt/client/dataSrDesc/DataSrDescViewImpl.java
+++ b/src/main/java/fr/soeretempo/gwt/client/dataSrDesc/DataSrDescViewImpl.java
@@ -639,32 +639,38 @@ public class DataSrDescViewImpl extends Composite implements DataSrDescView {
             final int nb = aData.getNbOfTaxonsByRank().get(rankValue);
             final RankDTO rank = RankDTO.valueOf(rankValue);
             switch (rank) {
-            case SUBSPECIES:
+            case SUBSPECIES -> {
                 final String[] sbsp = {"" + nb, clientCst.tabsubspecies()};
                 provider.add(sbsp);
                 continue;
-            case VARIETY:
+                }
+            case VARIETY -> {
                 final String[] var = {"" + nb, clientCst.tabvarieties()};
                 provider.add(var);
                 continue;
-            case SPECIES:
+                }
+            case SPECIES -> {
                 final String[] spc = {"" + nb, clientCst.tabspecies()};
                 provider.add(spc);
                 continue;
-            case GENUS:
+                }
+            case GENUS -> {
                 final String[] gen = {"" + nb, clientCst.tabgenera()};
                 provider.add(gen);
                 continue;
-            case KINGDOM:
+                }
+            case KINGDOM -> {
                 final String[] kin = {"" + nb, clientCst.tabkingdoms()};
                 provider.add(kin);
                 continue;
-            case CLONE:
+                }
+            case CLONE -> {
                 final String[] clo = {"" + nb, clientCst.tabclones()};
                 provider.add(clo);
                 continue;
-            default:
-                break;
+                }
+            default -> {
+                }
             }
         }
         final Panel panel = new Panel();
diff --git a/src/main/java/fr/soeretempo/gwt/client/news/newsmanager/NewsManagerViewImpl.java b/src/main/java/fr/soeretempo/gwt/client/news/newsmanager/NewsManagerViewImpl.java
index 362cc6980c2dd239fcbd8dd73920e69038cbf75e..2d1cc8437750ae51fefa22e23b145436ff03edcf 100644
--- a/src/main/java/fr/soeretempo/gwt/client/news/newsmanager/NewsManagerViewImpl.java
+++ b/src/main/java/fr/soeretempo/gwt/client/news/newsmanager/NewsManagerViewImpl.java
@@ -155,19 +155,13 @@ public class NewsManagerViewImpl extends Composite implements NewsManagerView {
 
                 final NewsStatus state = NewsStatus.valueOf(object);
                 SafeHtml addIcon;
-                switch (state) {
-                case DRAFT:
-                    addIcon = TEMPLATES.addIcon(
+                addIcon = switch (state) {
+                    case DRAFT -> TEMPLATES.addIcon(
                             CONSTANTS.newsColStatusDraft(),
                             IconType.CLOSE.getCssName());
-                    break;
-
-                default:
-                    addIcon = TEMPLATES.addIcon(CONSTANTS.newsColStatusPublished(),
+                    default -> TEMPLATES.addIcon(CONSTANTS.newsColStatusPublished(),
                             IconType.CHECK.getCssName());
-                    break;
-
-                }
+                };
                 return sb.append(addIcon).toSafeHtml();
             }
         };
diff --git a/src/main/java/fr/soeretempo/gwt/client/profile/ProfileViewImpl.java b/src/main/java/fr/soeretempo/gwt/client/profile/ProfileViewImpl.java
index ec919b64da114cda3e9208b86a1e2619e342e573..974d3340b5bd1498753e96d09b0ec9e9c3d1972c 100644
--- a/src/main/java/fr/soeretempo/gwt/client/profile/ProfileViewImpl.java
+++ b/src/main/java/fr/soeretempo/gwt/client/profile/ProfileViewImpl.java
@@ -329,7 +329,7 @@ public final class ProfileViewImpl extends Composite implements ProfileView {
 
         // Mail :
         final Delegate<OidcAccountDTO> openPanel = this::makeMailModificationModal;
-        final TextActionCell<OidcAccountDTO> cell = new TextActionCell<OidcAccountDTO>(ButtonType.DEFAULT,
+        final TextActionCell<OidcAccountDTO> cell = new TextActionCell<>(ButtonType.DEFAULT,
                 IconType.WRENCH, TEMPOCSTS.changeMail(), openPanel);
         final Column<OidcAccountDTO, OidcAccountDTO> mailCol =
                 new Column<OidcAccountDTO, OidcAccountDTO>(cell) {
@@ -343,7 +343,7 @@ public final class ProfileViewImpl extends Composite implements ProfileView {
 
         // Commands:
         final Delegate<OidcAccountDTO> deleteDelegate = this::makeDeleteOidcAccountModal;
-        final ActionCell<OidcAccountDTO> deleteCell = new ActionCell<OidcAccountDTO>(ButtonType.DEFAULT,
+        final ActionCell<OidcAccountDTO> deleteCell = new ActionCell<>(ButtonType.DEFAULT,
                 IconType.TRASH, TEMPOCSTS.deleteOidcAccount(), deleteDelegate);
         final Column<OidcAccountDTO, OidcAccountDTO> actionCol =
                 new Column<OidcAccountDTO, OidcAccountDTO>(deleteCell) {
@@ -420,7 +420,7 @@ public final class ProfileViewImpl extends Composite implements ProfileView {
 
         // Request details
         final Delegate<AccessDTO> openPanel = this::makeAccessHistoryModal;
-        final ActionCell<AccessDTO> cell = new ActionCell<AccessDTO>(ButtonType.INFO,
+        final ActionCell<AccessDTO> cell = new ActionCell<>(ButtonType.INFO,
                 IconType.EYE, TEMPOCSTS.accessRequestDetails(), openPanel);
         final Column<AccessDTO, AccessDTO> actionCol =
                 new Column<AccessDTO, AccessDTO>(cell) {
diff --git a/src/main/java/fr/soeretempo/gwt/client/queries/QueriesViewImpl.java b/src/main/java/fr/soeretempo/gwt/client/queries/QueriesViewImpl.java
index 67ed84661eda39417a2ab7c2a958ed7f224db176..b799b137caf16389be36c7996ae257682502ddfb 100644
--- a/src/main/java/fr/soeretempo/gwt/client/queries/QueriesViewImpl.java
+++ b/src/main/java/fr/soeretempo/gwt/client/queries/QueriesViewImpl.java
@@ -156,7 +156,7 @@ public class QueriesViewImpl extends Composite implements QueriesView {
      */
     private void initMockDataQueries(
             final ListDataProvider<QueryDTO> dataProvider) {
-        for (int i = 0; i < dataProvider.getList().size(); i++) {
+        for (QueryDTO list : dataProvider.getList()) {
             dataProvider.getList().add(new QueryDTO());
         }
         dataProvider.flush();
@@ -287,12 +287,13 @@ public class QueriesViewImpl extends Composite implements QueriesView {
         final TextColumn<QueryDTO> col8 = new TextColumn<QueryDTO>() {
             @Override
             public String getValue(final QueryDTO object) {
-                if (String.valueOf(object.getFormat()).equals("CSV")) {
-                    return csts.csv();
-                } else if (String.valueOf(object.getFormat()).equals("CSV&PMP")) {
-                    return csts.csvPmp();
-                } else {
-                    return csts.notSaved();
+                switch (String.valueOf(object.getFormat())) {
+                    case "CSV":
+                        return csts.csv();
+                    case "CSV&PMP":
+                        return csts.csvPmp();
+                    default:
+                        return csts.notSaved();
                 }
             }
         };
diff --git a/src/main/java/fr/soeretempo/gwt/client/search/PanelSitesSearchView.java b/src/main/java/fr/soeretempo/gwt/client/search/PanelSitesSearchView.java
index 294ee6f438c7b9e70d93064b157c31716964a94e..a05f324e3728df1c961800f929a0f999f0a4d324 100644
--- a/src/main/java/fr/soeretempo/gwt/client/search/PanelSitesSearchView.java
+++ b/src/main/java/fr/soeretempo/gwt/client/search/PanelSitesSearchView.java
@@ -402,33 +402,32 @@ public class PanelSitesSearchView extends PartialSearchViewHasData<SiteDTO> {
         MultiSelectionModel<T> selectionModel;
         Function<LocationDTO, String> generateDisplay;
         switch (locationLevel) {
-        case SITE_CONSTANT:
+        case SITE_CONSTANT -> {
             selectionModel = (MultiSelectionModel<T>) siteSelection;
             generateDisplay = item -> item.getName() + " (" + item.getParent().getName() + ")";
-            break;
+            }
 
-        case COMMUNE_CONSTANT:
+        case COMMUNE_CONSTANT -> {
             generateDisplay = item -> item.getName() + " (" + item.getParent().getName() + ")";
             selectionModel = (MultiSelectionModel<T>) communeSelection;
-            break;
+            }
 
-        case DEPARTMENT_CONSTANT:
+        case DEPARTMENT_CONSTANT -> {
             selectionModel = (MultiSelectionModel<T>) departmentSelection;
             generateDisplay = LocationDTO::getName;
-            break;
+            }
 
-        case REGION_CONSTANT:
+        case REGION_CONSTANT -> {
             selectionModel = (MultiSelectionModel<T>) regionSelection;
             generateDisplay = LocationDTO::getName;
-            break;
+            }
 
-        case COUNTRY_CONSTANT:
+        case COUNTRY_CONSTANT -> {
             selectionModel = (MultiSelectionModel<T>) countrySelection;
             generateDisplay = LocationDTO::getName;
-            break;
+            }
 
-        default:
-            throw new IllegalArgumentException("Should never occur !");
+        default -> throw new IllegalArgumentException("Should never occur !");
         }
 
         if (locationList.size() < 2000) {
@@ -500,28 +499,18 @@ public class PanelSitesSearchView extends PartialSearchViewHasData<SiteDTO> {
             toSearch = null;
         }
         switch (level) {
-        case COUNTRY_CONSTANT:
-            generateBrowsingList(getCountries(toSearch), level);
-            break;
+        case COUNTRY_CONSTANT -> generateBrowsingList(getCountries(toSearch), level);
 
-        case REGION_CONSTANT:
-            generateBrowsingList(getRegions(toSearch), level);
-            break;
+        case REGION_CONSTANT -> generateBrowsingList(getRegions(toSearch), level);
 
-        case DEPARTMENT_CONSTANT:
-            generateBrowsingList(getDepartments(toSearch), level);
-            break;
+        case DEPARTMENT_CONSTANT -> generateBrowsingList(getDepartments(toSearch), level);
 
-        case COMMUNE_CONSTANT:
-            generateBrowsingList(getCommunes(toSearch), level);
-            break;
+        case COMMUNE_CONSTANT -> generateBrowsingList(getCommunes(toSearch), level);
 
-        case SITE_CONSTANT:
-            generateBrowsingList(getSites(toSearch), level);
-            break;
+        case SITE_CONSTANT -> generateBrowsingList(getSites(toSearch), level);
 
-        default:
-            break;
+        default -> {
+            }
         }
     }
 
diff --git a/src/main/java/fr/soeretempo/gwt/client/search/StagesSearchView.java b/src/main/java/fr/soeretempo/gwt/client/search/StagesSearchView.java
index 84865bb5ffc69953b164bf09ad5834b9f2a6ea38..3c5ca052ced18774682dc1d799ccd8fb279bce82 100644
--- a/src/main/java/fr/soeretempo/gwt/client/search/StagesSearchView.java
+++ b/src/main/java/fr/soeretempo/gwt/client/search/StagesSearchView.java
@@ -755,38 +755,26 @@ public class StagesSearchView extends PartialSearchViewHasData<StageDTO> {
         if (toSearch.length() > 2) {
             switch (level) {
 
-            case MAIN_EVENT:
-                mainEventSearch(toSearch);
-                break;
+            case MAIN_EVENT -> mainEventSearch(toSearch);
 
-            case SCALE:
-                scaleSearch(toSearch);
-                break;
+            case SCALE -> scaleSearch(toSearch);
 
-            case STAGE:
-                stageSearch(toSearch);
-                break;
+            case STAGE -> stageSearch(toSearch);
 
-            default:
-                break;
+            default -> {
+                }
             }
         } else if (toSearch.isEmpty()) {
             switch (level) {
 
-            case MAIN_EVENT:
-                mainEventSearch(null);
-                break;
+            case MAIN_EVENT -> mainEventSearch(null);
 
-            case SCALE:
-                scaleSearch(null);
-                break;
+            case SCALE -> scaleSearch(null);
 
-            case STAGE:
-                stageSearch(null);
-                break;
+            case STAGE -> stageSearch(null);
 
-            default:
-                break;
+            default -> {
+                }
             }
         }
     }
diff --git a/src/main/java/fr/soeretempo/gwt/client/search/TaxonsSearchView.java b/src/main/java/fr/soeretempo/gwt/client/search/TaxonsSearchView.java
index ca3c74b0a5692f6ae1e8aefc8322be6f714446d8..68f30963917d7472679556aad8af0ed2dbd0efc0 100644
--- a/src/main/java/fr/soeretempo/gwt/client/search/TaxonsSearchView.java
+++ b/src/main/java/fr/soeretempo/gwt/client/search/TaxonsSearchView.java
@@ -672,39 +672,38 @@ public class TaxonsSearchView extends PartialSearchViewHasData<TaxonDTO> {
             final Element li = Document.get().createLIElement();
             MultiSelectionModel<TaxonDTO> selectionModel;
             switch (level) {
-            case CLONE:
+            case CLONE -> {
                 selectionModel = cloneSelection;
                 li.setInnerText(item.getName());
-                break;
+                }
 
-            case VARIETY:
+            case VARIETY -> {
                 selectionModel = varietySelection;
                 li.setInnerText(item.getName());
-                break;
+                }
 
-            case SUBSPECIES:
+            case SUBSPECIES -> {
                 selectionModel = subspeciesSelection;
                 li.setInnerText(item.getParent().getParent().getName()
                         + " " + item.getParent().getName() + " " + item.getName());
-                break;
+                }
 
-            case SPECIES:
+            case SPECIES -> {
                 selectionModel = speciesSelection;
                 li.setInnerText(item.getParent().getName() + " " + item.getName());
-                break;
+                }
 
-            case GENUS:
+            case GENUS -> {
                 selectionModel = genusSelection;
                 li.setInnerText(item.getName());
-                break;
+                }
 
-            case KINGDOM:
+            case KINGDOM -> {
                 selectionModel = kingdomSelection;
                 li.setInnerText(item.getName());
-                break;
+                }
 
-            default:
-                throw new IllegalArgumentException("Should never occur !");
+            default -> throw new IllegalArgumentException("Should never occur !");
             }
             li.setAttribute(VALUE_ATTRIBUTE, item.getId().toString());
             if (selectionModel.isSelected(item) || selected.contains(item.getId())) {
@@ -836,32 +835,20 @@ public class TaxonsSearchView extends PartialSearchViewHasData<TaxonDTO> {
         if (process) {
             switch (level) {
 
-            case KINGDOM:
-                generateBrowserList(getKingdoms(toSearch), KINGDOM);
-                break;
+            case KINGDOM -> generateBrowserList(getKingdoms(toSearch), KINGDOM);
 
-            case GENUS:
-                generateBrowserList(getGenera(toSearch), GENUS);
-                break;
+            case GENUS -> generateBrowserList(getGenera(toSearch), GENUS);
 
-            case SPECIES:
-                generateBrowserList(getSpecies(toSearch), SPECIES);
-                break;
+            case SPECIES -> generateBrowserList(getSpecies(toSearch), SPECIES);
 
-            case SUBSPECIES:
-                generateBrowserList(getSubspecies(toSearch), SUBSPECIES);
-                break;
+            case SUBSPECIES -> generateBrowserList(getSubspecies(toSearch), SUBSPECIES);
 
-            case CLONE:
-                generateBrowserList(getClones(toSearch), CLONE);
-                break;
+            case CLONE -> generateBrowserList(getClones(toSearch), CLONE);
 
-            case VARIETY:
-                generateBrowserList(getVarieties(toSearch), VARIETY);
-                break;
+            case VARIETY -> generateBrowserList(getVarieties(toSearch), VARIETY);
 
-            default:
-                break;
+            default -> {
+                }
             }
         }
     }
diff --git a/src/main/java/fr/soeretempo/gwt/client/search/YearsSearchView.java b/src/main/java/fr/soeretempo/gwt/client/search/YearsSearchView.java
index 953cfd0e77a366aadea46aff88760eee1036a545..0cb80fcab1e083de1f51c07ee860455c7e75a3ec 100644
--- a/src/main/java/fr/soeretempo/gwt/client/search/YearsSearchView.java
+++ b/src/main/java/fr/soeretempo/gwt/client/search/YearsSearchView.java
@@ -241,7 +241,7 @@ public class YearsSearchView extends PartialSearchView<YearDTO> {
             LOGGER.atFinest().log("selectionModel.clear()");
             return;
         }
-        final PeriodDTO newPeriod = new PeriodDTO(new YearDTO(min.intValue()), new YearDTO(max.intValue()));
+        final PeriodDTO newPeriod = new PeriodDTO(new YearDTO(min), new YearDTO(max));
         refreshView();
         TempoInitData.getInstance().getYearSelectionModel().setSelected(newPeriod, true);
     }
diff --git a/src/main/java/fr/soeretempo/gwt/client/ui/ImageAnchor.java b/src/main/java/fr/soeretempo/gwt/client/ui/ImageAnchor.java
index 83e6277fc4448f2c53a694a1fba260bac21fe622..0544a476e8471efebaeb1cf1822e51c65f53044b 100644
--- a/src/main/java/fr/soeretempo/gwt/client/ui/ImageAnchor.java
+++ b/src/main/java/fr/soeretempo/gwt/client/ui/ImageAnchor.java
@@ -156,18 +156,15 @@ public final class ImageAnchor extends Anchor implements HasType<ImageType> {
 
         // We defer to make sure the elements are available to manipulate their
         // position
-        Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
-            @Override
-            public void execute() {
-                separator.removeFromParent();
-                caret.removeFromParent();
-
-                if (toggle == Toggle.DROPDOWN) {
-                    addStyleName(Styles.DROPDOWN_TOGGLE);
-
-                    add(separator, (Element) getElement());
-                    add(caret, (Element) getElement());
-                }
+        Scheduler.get().scheduleDeferred(() -> {
+            separator.removeFromParent();
+            caret.removeFromParent();
+
+            if (toggle == Toggle.DROPDOWN) {
+                addStyleName(Styles.DROPDOWN_TOGGLE);
+
+                add(separator, (Element) getElement());
+                add(caret, (Element) getElement());
             }
         });
     }
diff --git a/src/main/java/fr/soeretempo/gwt/client/ui/TextActionCell.java b/src/main/java/fr/soeretempo/gwt/client/ui/TextActionCell.java
index 54921c6fe2da978157f173da53d69190446185d3..b9f99d902a6e1e2cf57049df89f3c2dbbc3cc694 100644
--- a/src/main/java/fr/soeretempo/gwt/client/ui/TextActionCell.java
+++ b/src/main/java/fr/soeretempo/gwt/client/ui/TextActionCell.java
@@ -130,15 +130,15 @@ public class TextActionCell<C> extends com.google.gwt.cell.client.ActionCell<C>
     @Override
     public final void render(final Context context, final C value,
             final SafeHtmlBuilder sb) {
-        if (value instanceof OidcAccountDTO) {
-            final String content = ((OidcAccountDTO) value).getEmail();
+        if (value instanceof OidcAccountDTO oidcAccountDTO) {
+            final String content = oidcAccountDTO.getEmail();
             if (content == null) {
                 sb.append(button(buttonType, buttonIcon, buttonMessage, TEMPOCSTS.noMail()));
             } else {
                 sb.append(button(buttonType, buttonIcon, buttonMessage, content));
             }
-        } else if (value instanceof String) {
-            sb.append(button(buttonType, buttonIcon, buttonMessage, (String) value));
+        } else if (value instanceof String string) {
+            sb.append(button(buttonType, buttonIcon, buttonMessage, string));
         } else {
             sb.append(button(buttonType, buttonIcon, buttonMessage, "unknown object"));
         }
diff --git a/src/main/java/fr/soeretempo/gwt/client/ui/UiUtils.java b/src/main/java/fr/soeretempo/gwt/client/ui/UiUtils.java
index d41120a6e2148ceebfeed363ba1841e148e98466..6335fbffcfd44eaddb1f42e2c70f80c3d08b449c 100644
--- a/src/main/java/fr/soeretempo/gwt/client/ui/UiUtils.java
+++ b/src/main/java/fr/soeretempo/gwt/client/ui/UiUtils.java
@@ -390,24 +390,21 @@ public final class UiUtils {
         modal.setClosable(true);
         final ModalBody modalBody = new ModalBody();
         final HTML html = new HTML();
-        if (caught instanceof RPCException) {
-            final RPCException exception = (RPCException) caught;
+        if (caught instanceof RPCException exception) {
             html.setHTML(exception.getMessage());
         } else if (caught.getLocalizedMessage().equals(" 0")) {
             html.setHTML(CONSTANTS.connectionErrorPleaseRefresh());
-        } else if (caught instanceof StatusCodeException) {
-            final StatusCodeException sce = (StatusCodeException) caught;
+        } else if (caught instanceof StatusCodeException sce) {
             switch (sce.getStatusCode()) {
-            case HTTP_500:
+            case HTTP_500 -> {
                 modal.setTitle(CONSTANTS.serverErrorTitle());
                 html.setHTML(CONSTANTS.internalServerErrorText());
-                break;
-            case HTTP_503:
+                }
+            case HTTP_503 -> {
                 modal.setTitle(CONSTANTS.serviceUnavailableTitle());
                 html.setHTML(CONSTANTS.serviceUnavailableText());
-                break;
-            default:
-                html.setHTML(CONSTANTS.serverError() + "<br/>...<br/>"
+                }
+            default -> html.setHTML(CONSTANTS.serverError() + "<br/>...<br/>"
                         + caught.getClass().getCanonicalName() + "<br/>"
                         + sce.getStatusCode() + "<br/>" + sce.getStatusText()
                         + "<br/>" + caught.getLocalizedMessage());
diff --git a/src/main/java/fr/soeretempo/gwt/server/DataTransfers.java b/src/main/java/fr/soeretempo/gwt/server/DataTransfers.java
index 291f478c0cbb28ae43c3a3d839ecaacf6cb8421a..155043bc96f6de81eb29f35dc9b74382b5ce8453 100644
--- a/src/main/java/fr/soeretempo/gwt/server/DataTransfers.java
+++ b/src/main/java/fr/soeretempo/gwt/server/DataTransfers.java
@@ -524,118 +524,118 @@ public final class DataTransfers {
         }
         if (clazz == AccessDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Access) {
-                    dtos.add((T) dto((Access) entity));
+                if (entity instanceof Access access) {
+                    dtos.add((T) dto(access));
                 }
             }
         } else if (clazz == AccountDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Account) {
-                    dtos.add((T) dto((Account) entity));
+                if (entity instanceof Account account) {
+                    dtos.add((T) dto(account));
                 }
             }
         } else if (clazz == DataSourceDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof DataSource) {
-                    dtos.add((T) dto((DataSource) entity));
+                if (entity instanceof DataSource dataSource) {
+                    dtos.add((T) dto(dataSource));
                 }
             }
         } else if (clazz == SiteDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Site) {
-                    dtos.add((T) dto((Site) entity));
+                if (entity instanceof Site site) {
+                    dtos.add((T) dto(site));
                 }
             }
         } else if (clazz == StageDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Stage) {
-                    dtos.add((T) dto((Stage) entity));
+                if (entity instanceof Stage stage) {
+                    dtos.add((T) dto(stage));
                 }
             }
         } else if (clazz == TaxonDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Taxon) {
-                    dtos.add((T) dto((Taxon) entity));
+                if (entity instanceof Taxon taxon) {
+                    dtos.add((T) dto(taxon));
                 }
             }
         } else if (clazz == YearDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Year) {
-                    dtos.add((T) dto((Year) entity));
-                } else if (entity instanceof Integer) {
-                    dtos.add((T) new YearDTO((Integer) entity));
+                if (entity instanceof Year year) {
+                    dtos.add((T) dto(year));
+                } else if (entity instanceof Integer integer) {
+                    dtos.add((T) new YearDTO(integer));
                 }
             }
         } else if (clazz == CountryDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Country) {
-                    dtos.add((T) dto((Country) entity));
+                if (entity instanceof Country country) {
+                    dtos.add((T) dto(country));
                 }
             }
         } else if (clazz == RegionDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Region) {
-                    dtos.add((T) dto((Region) entity));
+                if (entity instanceof Region region) {
+                    dtos.add((T) dto(region));
                 }
             }
         } else if (clazz == DepartmentDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Department) {
-                    dtos.add((T) dto((Department) entity));
+                if (entity instanceof Department department) {
+                    dtos.add((T) dto(department));
                 }
             }
         } else if (clazz == CommuneDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Commune) {
-                    dtos.add((T) dto((Commune) entity));
+                if (entity instanceof Commune commune) {
+                    dtos.add((T) dto(commune));
                 }
             }
         } else if (clazz == QueryDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Query) {
-                    dtos.add((T) dto((Query) entity));
+                if (entity instanceof Query query) {
+                    dtos.add((T) dto(query));
                 }
             }
         } else if (clazz == ScaleDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Scale) {
-                    dtos.add((T) dto((Scale) entity));
+                if (entity instanceof Scale scale) {
+                    dtos.add((T) dto(scale));
                 }
             }
         } else if (clazz == StatisticsDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof Statistics) {
-                    dtos.add((T) dto((Statistics) entity));
+                if (entity instanceof Statistics statistics) {
+                    dtos.add((T) dto(statistics));
                 }
             }
         } else if (clazz == LicenseDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof License) {
-                    dtos.add((T) dto((License) entity));
+                if (entity instanceof License license) {
+                    dtos.add((T) dto(license));
                 }
             }
         } else if (clazz == TempoScaleDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof TempoScale) {
-                    dtos.add((T) dto((TempoScale) entity));
+                if (entity instanceof TempoScale tempoScale) {
+                    dtos.add((T) dto(tempoScale));
                 }
             }
         } else if (clazz == OidcIdpDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof OidcIdp) {
-                    dtos.add((T) dto((OidcIdp) entity));
+                if (entity instanceof OidcIdp oidcIdp) {
+                    dtos.add((T) dto(oidcIdp));
                 }
             }
         } else if (clazz == OidcAccountDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof OidcAccount) {
-                    dtos.add((T) dto((OidcAccount) entity));
+                if (entity instanceof OidcAccount oidcAccount) {
+                    dtos.add((T) dto(oidcAccount));
                 }
             }
         } else if (clazz == NewsDTO.class) {
             for (final Object entity : entities) {
-                if (entity instanceof News) {
-                    dtos.add((T) dto((News) entity));
+                if (entity instanceof News news) {
+                    dtos.add((T) dto(news));
                 }
             }
         } else {
@@ -703,38 +703,38 @@ public final class DataTransfers {
         final Set<T> entities = new HashSet<>();
         if (clazz == Site.class) {
             for (final Object dto : dtos) {
-                if (dto instanceof SiteDTO) {
-                    entities.add((T) entity((SiteDTO) dto));
+                if (dto instanceof SiteDTO siteDTO) {
+                    entities.add((T) entity(siteDTO));
                 }
             }
         } else if (clazz == Stage.class) {
             for (final Object dto : dtos) {
-                if (dto instanceof StageDTO) {
-                    entities.add((T) entity((StageDTO) dto));
+                if (dto instanceof StageDTO stageDTO) {
+                    entities.add((T) entity(stageDTO));
                 }
             }
         } else if (clazz == Taxon.class) {
             for (final Object dto : dtos) {
-                if (dto instanceof TaxonDTO) {
-                    entities.add((T) entity((TaxonDTO) dto));
+                if (dto instanceof TaxonDTO taxonDTO) {
+                    entities.add((T) entity(taxonDTO));
                 }
             }
         } else if (clazz == Integer.class) {
             for (final Object dto : dtos) {
-                if (dto instanceof YearDTO) {
-                    entities.add((T) ((YearDTO) dto).getId());
+                if (dto instanceof YearDTO yearDTO) {
+                    entities.add((T) yearDTO.getId());
                 }
             }
         } else if (clazz == License.class) {
             for (final Object dto : dtos) {
-                if (dto instanceof LicenseDTO) {
-                    entities.add((T) entity((LicenseDTO) dto));
+                if (dto instanceof LicenseDTO licenseDTO) {
+                    entities.add((T) entity(licenseDTO));
                 }
             }
         } else if (clazz == News.class) {
             for (final Object dto : dtos) {
-                if (dto instanceof NewsDTO) {
-                    entities.add((T) entity((NewsDTO) dto));
+                if (dto instanceof NewsDTO newsDTO) {
+                    entities.add((T) entity(newsDTO));
                 }
             }
         } else {
diff --git a/src/main/java/fr/soeretempo/gwt/server/dao/EntityManagerHandler.java b/src/main/java/fr/soeretempo/gwt/server/dao/EntityManagerHandler.java
index f3198ee4f7c38706c2b7aba6a5d543ce865edac9..93dcb44547ceaf8c6fedbbb2751b44071b2c013a 100644
--- a/src/main/java/fr/soeretempo/gwt/server/dao/EntityManagerHandler.java
+++ b/src/main/java/fr/soeretempo/gwt/server/dao/EntityManagerHandler.java
@@ -92,8 +92,8 @@ public final class EntityManagerHandler implements InvocationHandler {
         final Object result = null;
         try {
             t.begin();
-            if (fn instanceof ScopedEntityManager.Transaction) {
-                ((ScopedEntityManager.Transaction) fn).execute();
+            if (fn instanceof ScopedEntityManager.Transaction transaction) {
+                transaction.execute();
             } else if (fn instanceof ScopedEntityManager.TransactionFunction) {
                 ((ScopedEntityManager.TransactionFunction<?>) fn).execute();
             }
diff --git a/src/main/java/fr/soeretempo/gwt/server/datasources/WebServiceClient.java b/src/main/java/fr/soeretempo/gwt/server/datasources/WebServiceClient.java
index 9b70e05312b6bf2165e3f91cef76f28926b02ccf..ebc0cf3be8a3318bf8d3b579a46936fbe79a0338 100644
--- a/src/main/java/fr/soeretempo/gwt/server/datasources/WebServiceClient.java
+++ b/src/main/java/fr/soeretempo/gwt/server/datasources/WebServiceClient.java
@@ -175,42 +175,45 @@ public abstract class WebServiceClient {
             final WebTarget target) {
         LOGGER.trace("Response status : " + response.getStatus());
         switch (response.getStatus()) {
-        case HTTP_200:
-            setStatus(Status.OK);
-            break;
-        case HTTP_400:
+        case HTTP_200 -> setStatus(Status.OK);
+        case HTTP_400 -> {
             setStatus(Status.BAD_REQUEST);
             LOGGER.error("Bad request: " + target.getUri());
             return false;
-        case HTTP_403:
+            }
+        case HTTP_403 -> {
             setStatus(Status.BAD_REQUEST);
             LOGGER.error("Forbidden: " + target.getUri());
             return false;
-        case HTTP_404:
+            }
+        case HTTP_404 -> {
             setStatus(Status.NOT_FOUND);
             LOGGER.trace("Not found: " + target.getUri());
             return false;
-        case HTTP_414:
+            }
+        case HTTP_414 -> {
             setStatus(Status.BAD_REQUEST);
             LOGGER.error("URI too long: " + target.getUri());
             return false;
-        case HTTP_415:
+            }
+        case HTTP_415 -> {
             setStatus(Status.BAD_REQUEST);
             LOGGER.error("Unsupported Media Type: " + target.getUri());
             return false;
-        case HTTP_500:
+            }
+        case HTTP_500 -> {
             setStatus(Status.REMOTE_ERROR);
             LOGGER.error("Internal Remote Server Error: " + target.getUri());
             LOGGER.error(response.readEntity(String.class).trim());
             return false;
-        case HTTP_503:
+            }
+        case HTTP_503 -> {
             setStatus(Status.REMOTE_ERROR);
             LOGGER.error("Service Unavailable: " + target.getUri());
             return false;
-        default:
-            LOGGER.error(
+            }
+        default -> LOGGER.error(
                     "Response status not handled: " + response.getStatus());
-            break;
         }
         return true;
     }
@@ -237,8 +240,8 @@ public abstract class WebServiceClient {
             for (final String key : args.keySet()) {
                 final Object value = args.get(key);
                 if (value != null) {
-                    if (value instanceof Collection<?>) {
-                        final Collection<?> col = (Collection<?>) value;
+                    if (value instanceof Collection<?> collection) {
+                        final Collection<?> col = collection;
                         for (final Object val : col) {
                             newTarget = newTarget.queryParam(key, val);
                         }
diff --git a/src/main/java/fr/soeretempo/gwt/server/datasources/crea/CreaHandler.java b/src/main/java/fr/soeretempo/gwt/server/datasources/crea/CreaHandler.java
index 0c5104abfe4810c9d77f6ca7663f96f78835f22c..3f9be2ad4c2cfb36680477d19dab4afd7bf04379 100644
--- a/src/main/java/fr/soeretempo/gwt/server/datasources/crea/CreaHandler.java
+++ b/src/main/java/fr/soeretempo/gwt/server/datasources/crea/CreaHandler.java
@@ -221,7 +221,7 @@ public final class CreaHandler implements Handler {
         if (data != null) {
             return data;
         }
-        data = new ArrayList<WsObservation>();
+        data = new ArrayList<>();
         Integer page = 0;
 
         while (true) {
@@ -309,11 +309,17 @@ public final class CreaHandler implements Handler {
                 cachedData.add(observation);
             }
         }
-        LOGGER.info("Post fetch data counts: "
-                + "\nstages: " + cachedStages.size()
-                + "\nsites: " + cachedSites.size()
-                + "\ntaxa: " + cachedTaxons.size()
-                + "\ndata: " + cachedData.size());
+        LOGGER.info("""
+                    Post fetch data counts:
+                    sites: {}
+                    stages: {}
+                    taxons: {}
+                    data: {}
+                    """,
+                    cachedSites.size(),
+                    cachedTaxons.size(),
+                    cachedStages.size(),
+                    cachedData.size());
         return data;
     }
 
diff --git a/src/main/java/fr/soeretempo/gwt/server/datasources/tela2/TelaHandler.java b/src/main/java/fr/soeretempo/gwt/server/datasources/tela2/TelaHandler.java
index 52445737dcc0a5a4209a70bdf5aad719a72ffe0d..282cf81646a3bf7f150e59b31a8347ac87121bfa 100644
--- a/src/main/java/fr/soeretempo/gwt/server/datasources/tela2/TelaHandler.java
+++ b/src/main/java/fr/soeretempo/gwt/server/datasources/tela2/TelaHandler.java
@@ -129,19 +129,11 @@ public final class TelaHandler implements Handler {
         final String[] parts2 = parts[0].split(" ");
         final Taxon genus = new Taxon(kingdom, parts2[0], Rank.GENUS);
         final Taxon species = new Taxon(genus, parts2[1], Rank.SPECIES);
-        final Taxon found;
-        switch (parts.length) {
-        case 1:
-            found = species;
-            break;
-        case 2:
-            final Taxon variety = new Taxon(species, parts[1], Rank.VARIETY);
-            found = variety;
-            break;
-        default:
-            throw new RuntimeException("Parsing error for " + name);
-        }
-        return found;
+        return switch (parts.length) {
+        case 1 -> species;
+        case 2 -> new Taxon(species, parts[1], Rank.VARIETY);
+        default -> throw new RuntimeException("Parsing error for " + name);
+        };
     }
 
     private static Site toSite(final WsStation wsStation) {
@@ -362,9 +354,9 @@ public final class TelaHandler implements Handler {
             // data
             final StringJoiner sj = new StringJoiner(SEP);
             sj.add(wsStation.getEnvironment())
-                    .add(String.valueOf(wsStation.getIsPrivate()))
+            .add(String.valueOf(wsStation.getIsPrivate()))
             .add(obs.getId().toString())
-                    .add(obs.getUser().getId())
+            .add(obs.getUser().getId())
             .add("individu");
             final Data d = new Data();
             d.setAdditionalDataText(sj.toString());
diff --git a/src/main/java/fr/soeretempo/gwt/server/download/RecordZipper.java b/src/main/java/fr/soeretempo/gwt/server/download/RecordZipper.java
index ae4cb2296971af982745d21edf29bb85fae08aab..776b6a076c9944f3a5df359cb535304f50142c0b 100644
--- a/src/main/java/fr/soeretempo/gwt/server/download/RecordZipper.java
+++ b/src/main/java/fr/soeretempo/gwt/server/download/RecordZipper.java
@@ -882,53 +882,40 @@ public final class RecordZipper {
                 break;
             }
             boolean first = true;
+
             for (final Column col : columns) {
                 if (!first) {
                     osw.write(";");
                 }
                 switch (col) {
-                case DATASOURCE:
-                    osw.write(dataSource);
-                    break;
-                case ADDITIONALDATA:
+                case DATASOURCE -> osw.write(dataSource);
+                case ADDITIONALDATA -> {
                     if (!commonData) {
                         osw.write(cache.getAdditionalData().getText());
                     }
-                    break;
-                case DATE:
-                    osw.write(sdf.format(cache.getDate()));
-                    break;
-                case DOY:
-                    osw.write(Integer.toString(cache.getDate().getDayOfYear()));
-                    break;
-                case SITEID:
-                    osw.write(cache.getSite().getId().toString());
-                    break;
-                case SITEALTITUDE:
+                }
+                case DATE -> osw.write(sdf.format(cache.getDate()));
+                case DOY -> osw.write(Integer.toString(cache.getDate().getDayOfYear()));
+                case SITEID -> osw.write(cache.getSite().getId().toString());
+                case SITEALTITUDE -> {
                     if (cache.getSite().getAltitude() != null) {
                         osw.write(cache.getSite().getAltitude().toString());
                     }
-                    break;
-                case SITELATITUDE:
+                }
+                case SITELATITUDE -> {
                     if (cache.getSite().getLatitude() != null) {
                         osw.write(cache.getSite().getLatitude().toString());
                     }
-                    break;
-                case SITELONGITUDE:
+                }
+                case SITELONGITUDE -> {
                     if (cache.getSite().getLongitude() != null) {
                         osw.write(cache.getSite().getLongitude().toString());
                     }
-                    break;
-                case SITENAME:
-                    osw.write("\"" + cache.getSite().getName() + "\"");
-                    break;
-                case DATASCALE:
-                    osw.write(cache.getStage().getScale().getName());
-                    break;
-                case STAGECODE:
-                    osw.write(cache.getStage().getCode());
-                    break;
-                case STAGEDESCRIPTION:
+                }
+                case SITENAME -> osw.write("\"" + cache.getSite().getName() + "\"");
+                case DATASCALE -> osw.write(cache.getStage().getScale().getName());
+                case STAGECODE -> osw.write(cache.getStage().getCode());
+                case STAGEDESCRIPTION -> {
                     if (cache.getStage().getDescription().contains(";")
                             || cache.getStage().getDescription().contains("\n")
                             || cache.getStage().getDescription().contains(",")) {
@@ -936,72 +923,49 @@ public final class RecordZipper {
                     } else {
                         osw.write(cache.getStage().getDescription());
                     }
-                    break;
-                case MAINEVENT:
-                    osw.write(cache.getStage().getTemposcale().getMaineventAsString(isFrench));
-                    break;
-                case MAINEVENTDESCRIPTION:
-                    osw.write(cache.getStage().getTemposcale().getDescription(isFrench));
-                    break;
-                case TAXONBINOMIAL:
-                    osw.write(cache.getTaxon().getFullname());
-                    break;
-                case TAXONID:
-                    osw.write(cache.getTaxon().getId().toString());
-                    break;
-                case KINGDOM:
-                    osw.write(kingdom);
-                    break;
-                case SPECIES:
-                    osw.write(species);
-                    break;
-                case SUBSPECIES:
-                    osw.write(subspecies);
-                    break;
-                case GENUS:
-                    osw.write(genus);
-                    break;
-                case VARIETY:
-                    osw.write(variety);
-                    break;
-                case CLONE:
-                    osw.write(clone);
-                    break;
-                case YEAR:
-                    osw.write(Integer.toString(cache.getDate().getYear()));
-                    break;
-                case INITIALSLICENSEVERSION:
+                }
+                case MAINEVENT -> osw.write(cache.getStage().getTemposcale().getMaineventAsString(isFrench));
+                case MAINEVENTDESCRIPTION -> osw.write(cache.getStage().getTemposcale().getDescription(isFrench));
+                case TAXONBINOMIAL -> osw.write(cache.getTaxon().getFullname());
+                case TAXONID -> osw.write(cache.getTaxon().getId().toString());
+                case KINGDOM -> osw.write(kingdom);
+                case SPECIES -> osw.write(species);
+                case SUBSPECIES -> osw.write(subspecies);
+                case GENUS -> osw.write(genus);
+                case VARIETY -> osw.write(variety);
+                case CLONE -> osw.write(clone);
+                case YEAR -> osw.write(Integer.toString(cache.getDate().getYear()));
+                case INITIALSLICENSEVERSION -> {
                     if (cache.getLicense() != null && cache.getLicense().getShortening() != null) {
                         osw.write(cache.getLicense().getShortening());
                     }
-                    break;
-                case LICENSENAME:
+                }
+                case LICENSENAME -> {
                     if (cache.getLicense() != null && cache.getLicense().getName() != null) {
                         osw.write(cache.getLicense().getName());
                     }
-                    break;
-                case LICENSEURL:
+                }
+                case LICENSEURL -> {
                     if (cache.getLicense() != null && cache.getLicense().getUrl() != null) {
                         osw.write(cache.getLicense().getUrl());
                     }
-                    break;
-                case CONTACTNAME:
+                }
+                case CONTACTNAME -> {
                     if (cache.getContact() != null && cache.getContact().getName() != null) {
                         osw.write(cache.getContact().getName());
                     }
-                    break;
-                case CONTACTEMAIL:
+                }
+                case CONTACTEMAIL -> {
                     if (cache.getContact() != null && cache.getContact().getEmail() != null) {
                         osw.write(cache.getContact().getEmail());
                     }
-                    break;
-                case CONTACTORGANISATION:
+                }
+                case CONTACTORGANISATION -> {
                     if (cache.getContact() != null && cache.getContact().getOrganisation() != null) {
                         osw.write(cache.getContact().getOrganisation());
                     }
-                    break;
-                default:
-                    throw new IllegalArgumentException("Column not handled to write CSV: " + col);
+                }
+                default -> throw new IllegalArgumentException("Column not handled to write CSV: " + col);
                 }
                 first = false;
             }
@@ -1318,40 +1282,26 @@ public final class RecordZipper {
         String taxonLine;
         final String separator = ";";
         final String emptyCell = "NA";
-        switch (taxon.getRank()) {
-        case CLONE:
-            taxonLine = taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator
-            + taxon.getName(Rank.SPECIES) + separator + taxon.getName(Rank.VARIETY) + separator
-            + taxon.getName() + separator + emptyCell;
-            break;
-        case GENUS:
-            taxonLine = taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator + emptyCell
-            + separator + emptyCell + separator + emptyCell + separator + emptyCell;
-            break;
-        case KINGDOM:
-            taxonLine = taxon.getName(Rank.KINGDOM) + separator + emptyCell + separator + emptyCell + separator
-            + emptyCell + separator + emptyCell + separator + emptyCell;
-            break;
-        case SPECIES:
-            taxonLine = taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator
-            + taxon.getName(Rank.SPECIES) + separator + emptyCell + separator + emptyCell + separator
-            + emptyCell;
-            break;
-        case SUBSPECIES:
-            taxonLine = taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator
-            + taxon.getName(Rank.SPECIES) + separator + taxon.getName(Rank.VARIETY) + separator
-            + taxon.getName(Rank.CLONE) + separator + taxon.getName();
-            break;
-        case VARIETY:
-            taxonLine = taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator
-            + taxon.getName(Rank.SPECIES) + separator + taxon.getName(Rank.VARIETY) + separator + emptyCell
-            + separator + emptyCell;
-            break;
-        default:
-            taxonLine = emptyCell + separator + emptyCell + separator + emptyCell + separator + emptyCell + separator
-            + emptyCell + separator + emptyCell;
-            break;
-        }
+        taxonLine = switch (taxon.getRank()) {
+        case CLONE -> taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator
+        + taxon.getName(Rank.SPECIES) + separator + taxon.getName(Rank.VARIETY) + separator
+        + taxon.getName() + separator + emptyCell;
+        case GENUS -> taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator + emptyCell
+        + separator + emptyCell + separator + emptyCell + separator + emptyCell;
+        case KINGDOM -> taxon.getName(Rank.KINGDOM) + separator + emptyCell + separator + emptyCell + separator
+        + emptyCell + separator + emptyCell + separator + emptyCell;
+        case SPECIES -> taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator
+        + taxon.getName(Rank.SPECIES) + separator + emptyCell + separator + emptyCell + separator
+        + emptyCell;
+        case SUBSPECIES -> taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator
+        + taxon.getName(Rank.SPECIES) + separator + taxon.getName(Rank.VARIETY) + separator
+        + taxon.getName(Rank.CLONE) + separator + taxon.getName();
+        case VARIETY -> taxon.getName(Rank.KINGDOM) + separator + taxon.getName(Rank.GENUS) + separator
+        + taxon.getName(Rank.SPECIES) + separator + taxon.getName(Rank.VARIETY) + separator + emptyCell
+        + separator + emptyCell;
+        default -> emptyCell + separator + emptyCell + separator + emptyCell + separator + emptyCell + separator
+        + emptyCell + separator + emptyCell;
+        };
         osw.write(String.format("%s;%s", taxon.getId(), taxonLine) + newLine);
     }
 
diff --git a/src/main/java/fr/soeretempo/gwt/server/model/Taxon.java b/src/main/java/fr/soeretempo/gwt/server/model/Taxon.java
index 82f6e64f0d5dd8f38b59f90edd9a267cc84db630..5b7fc89ea1f242e21bc3701e643cb49c0e93cf26 100644
--- a/src/main/java/fr/soeretempo/gwt/server/model/Taxon.java
+++ b/src/main/java/fr/soeretempo/gwt/server/model/Taxon.java
@@ -54,9 +54,9 @@ import lombok.Setter;
 @javax.persistence.Cacheable
 @EqualsAndHashCode(of = "id")
 @Table(name = "taxon", uniqueConstraints = {
-                        @UniqueConstraint(columnNames = { "rank", "parent",
-                        "name" }, name = "uk_taxon_rank_parent_name"),
-                        @UniqueConstraint(columnNames = "fullname", name = "UK_fullname") })
+        @UniqueConstraint(columnNames = { "rank", "parent",
+        "name" }, name = "uk_taxon_rank_parent_name"),
+        @UniqueConstraint(columnNames = "fullname", name = "UK_fullname") })
 public class Taxon implements Serializable, Comparable<Taxon> {
 
     /**
@@ -245,20 +245,11 @@ public class Taxon implements Serializable, Comparable<Taxon> {
             return;
         }
         fullname = getParent().getFullname();
-        switch (getRank()) {
-        case GENUS:
-        case KINGDOM:
-        case SPECIES:
-        case SUBSPECIES:
-            fullname += " ";
-            break;
-        case CLONE:
-        case VARIETY:
-            fullname += " - ";
-            break;
-        default:
-            throw new UnsupportedOperationException("not implemented!");
-        }
+        fullname += switch (getRank()) {
+        case GENUS, KINGDOM, SPECIES, SUBSPECIES -> " ";
+        case CLONE, VARIETY -> " - ";
+        default -> throw new UnsupportedOperationException("not implemented!");
+        };
         fullname += getName();
     }
 
diff --git a/src/main/java/fr/soeretempo/gwt/server/openid/OpenIdCallbackServlet.java b/src/main/java/fr/soeretempo/gwt/server/openid/OpenIdCallbackServlet.java
index 80cdb1b079ecc69c5d493d33c450d433d79ca877..6566311a019c7afafc29fee20b7aa6a70f332af5 100644
--- a/src/main/java/fr/soeretempo/gwt/server/openid/OpenIdCallbackServlet.java
+++ b/src/main/java/fr/soeretempo/gwt/server/openid/OpenIdCallbackServlet.java
@@ -254,8 +254,8 @@ public class OpenIdCallbackServlet extends HttpServlet {
         LOGGER.traceEntry(getFullURL(request));
         final AuthenticationResponse authResp =
                 AuthenticationResponseParser.parse(new URI(getFullURL(request)));
-        if (authResp instanceof AuthenticationErrorResponse) {
-            final ErrorObject error = ((AuthenticationErrorResponse) authResp)
+        if (authResp instanceof AuthenticationErrorResponse authenticationErrorResponse) {
+            final ErrorObject error = authenticationErrorResponse
                     .getErrorObject();
             LOGGER.error(error);
             throw new IOException(error.toString());
@@ -277,8 +277,8 @@ public class OpenIdCallbackServlet extends HttpServlet {
         final HTTPResponse tokenHTTPResp = tokenReq.toHTTPRequest().send();
         // Parse and check response
         final TokenResponse tokenResponse = OIDCTokenResponseParser.parse(tokenHTTPResp);
-        if (tokenResponse instanceof TokenErrorResponse) {
-            final ErrorObject error = ((TokenErrorResponse) tokenResponse).getErrorObject();
+        if (tokenResponse instanceof TokenErrorResponse tokenErrorResponse) {
+            final ErrorObject error = tokenErrorResponse.getErrorObject();
             LOGGER.error("Response is {}", tokenHTTPResp.getContent());
             LOGGER.error("error: {}", error);
             throw new IOException(error.toString());
@@ -306,8 +306,8 @@ public class OpenIdCallbackServlet extends HttpServlet {
                 tokens.getBearerAccessToken());
         final HTTPResponse userInfoHTTPResp = userInfoReq.toHTTPRequest().send();
         final UserInfoResponse userInfoResponse = UserInfoResponse.parse(userInfoHTTPResp);
-        if (userInfoResponse instanceof UserInfoErrorResponse) {
-            final ErrorObject error = ((UserInfoErrorResponse) userInfoResponse).getErrorObject();
+        if (userInfoResponse instanceof UserInfoErrorResponse userInfoErrorResponse) {
+            final ErrorObject error = userInfoErrorResponse.getErrorObject();
             LOGGER.error(error);
             throw new IOException(error.toString());
         }
diff --git a/src/main/java/fr/soeretempo/gwt/server/resources/mail/Mail.java b/src/main/java/fr/soeretempo/gwt/server/resources/mail/Mail.java
index 4142708d3fbd4353853d9c52a01cb9b4311b0f6f..41724975214426e60c1b168e299a0ed6f1ad9d7c 100644
--- a/src/main/java/fr/soeretempo/gwt/server/resources/mail/Mail.java
+++ b/src/main/java/fr/soeretempo/gwt/server/resources/mail/Mail.java
@@ -49,7 +49,7 @@ public final class Mail {
     /**
      * Attachments.
      */
-    private List<String> mailAttachements = new ArrayList<String>();
+    private List<String> mailAttachements = new ArrayList<>();
 
     /**
      * Character set definition.
diff --git a/src/main/java/fr/soeretempo/gwt/server/resources/mail/MailService.java b/src/main/java/fr/soeretempo/gwt/server/resources/mail/MailService.java
index 08cc1a943a267c54dd4f2fdbbfb740a4c39958c8..8c35608a44feee66325b6bcd35c91257298c337b 100644
--- a/src/main/java/fr/soeretempo/gwt/server/resources/mail/MailService.java
+++ b/src/main/java/fr/soeretempo/gwt/server/resources/mail/MailService.java
@@ -464,12 +464,10 @@ public class MailService {
             LOGGER.catching(mex);
             Exception ex = mex;
             do {
-                if (ex instanceof AddressException) {
-                    final AddressException ae = (AddressException) ex;
+                if (ex instanceof AddressException ae) {
                     throw new SendMailException("send : Invalid Address : "
                             + ae.getRef() + " : " + ex.getMessage());
-                } else if (ex instanceof SendFailedException) {
-                    final SendFailedException sfex = (SendFailedException) ex;
+                } else if (ex instanceof SendFailedException sfex) {
                     final Address[] invalid = sfex.getInvalidAddresses();
                     final StringBuilder messageException = new StringBuilder();
                     if (invalid != null) {
@@ -503,8 +501,8 @@ public class MailService {
                                         + messageException.toString());
                     }
                 }
-                if (ex instanceof MessagingException) {
-                    ex = ((MessagingException) ex).getNextException();
+                if (ex instanceof MessagingException messagingException) {
+                    ex = messagingException.getNextException();
                 } else if (ex instanceof java.net.SocketException) {
                     LOGGER.error(ex);
                     throw new SendMailException(ex, "Send failed!");
diff --git a/src/main/java/fr/soeretempo/gwt/server/rpc/AdminServiceImpl.java b/src/main/java/fr/soeretempo/gwt/server/rpc/AdminServiceImpl.java
index e41503ad0faeaa59e5f3825e64c726e76cac9e3f..9154609486c8adc38d8b35e56c6078f788c341da 100755
--- a/src/main/java/fr/soeretempo/gwt/server/rpc/AdminServiceImpl.java
+++ b/src/main/java/fr/soeretempo/gwt/server/rpc/AdminServiceImpl.java
@@ -96,12 +96,15 @@ implements AdminService {
     @Override
     public final String sendMultipleMails(final String target, final String title, final String body) {
         List<String> targets;
-        if (target.equals("allusers")) {
-            targets = oidcAccountDao.findAllMails();
-        } else if (target.equals("validators")) {
-            targets = oidcAccountDao.findAllValidatorMails();
-        } else {
-            return "failure, bad target";
+        switch (target) {
+            case "allusers":
+                targets = oidcAccountDao.findAllMails();
+                break;
+            case "validators":
+                targets = oidcAccountDao.findAllValidatorMails();
+                break;
+            default:
+                return "failure, bad target";
         }
         LOGGER.trace(targets.toString());
         if (targets.isEmpty()) {
diff --git a/src/main/java/fr/soeretempo/gwt/server/rpc/ApplicationServiceImpl.java b/src/main/java/fr/soeretempo/gwt/server/rpc/ApplicationServiceImpl.java
index bbe91faba471667fc34a59465fb2febe09cafbaa..b219051149fe00cb33089b48148617a333b99138 100644
--- a/src/main/java/fr/soeretempo/gwt/server/rpc/ApplicationServiceImpl.java
+++ b/src/main/java/fr/soeretempo/gwt/server/rpc/ApplicationServiceImpl.java
@@ -595,12 +595,19 @@ implements ApplicationService {
                 commune = communeDao.findOrCreateCommuneTree(address);
                 updated++;
             } else {
-                LOGGER.warn("Some levels were returned empty:\n"
-                        + "Country: " + address.getCountry()
-                        + "\nRegion: " + address.getState()
-                        + "\nDepartment: " + address.getDepartment()
-                        + "\nCommune: " + address.getCommune()
-                        + "\n(Site: " + st.getName() + ")");
+                LOGGER.warn("""
+                            Some levels were returned empty:
+                            Country: {}
+                            Region: {}
+                            Department: {}
+                            Commune: {}
+                            (Site: {})
+                            """,
+                            address.getCountry(),
+                            address.getState(),
+                            address.getDepartment(),
+                            address.getCommune(),
+                            st.getName());
                 commune = unknownCommune;
             }
             st.setCommune(commune);
diff --git a/src/main/java/fr/soeretempo/gwt/server/rpc/RequestServiceImpl.java b/src/main/java/fr/soeretempo/gwt/server/rpc/RequestServiceImpl.java
index 6c91bab16acc5c666a2db145ee78dc18549d03cb..539560658b91c3879aa1efc0f893a96afc7414ee 100644
--- a/src/main/java/fr/soeretempo/gwt/server/rpc/RequestServiceImpl.java
+++ b/src/main/java/fr/soeretempo/gwt/server/rpc/RequestServiceImpl.java
@@ -243,120 +243,122 @@ implements RequestService {
     public final Integer createZip(final CriteriaDTO critDTO, final boolean pmp, final boolean logged,
             final String localeName) throws IOException, SessionExpiredException {
         LOGGER.traceEntry();
-        final Timer timer = SavaUtils.histogramStartTimer(SavaServlet.Metrics.CREATE_ZIP);
-        final Account account = getAccountEntity();
-        if (logged && account == null) {
-            LOGGER.warn("User session was expired !");
-            throw new SessionExpiredException();
-        }
-        // Set up Data sources
-        final List<DataSource> dataSources = new ArrayList<>();
-        boolean noDataSourceSelected = false;
-        // If no datasource was selected in filters
-        if (critDTO.getDataSources().isEmpty()) {
-            noDataSourceSelected = true;
-            dataSources.addAll(dataSourceDao.getAll());
-            LOGGER.trace("No datasource selected in criteria. Loading every datasource from DB");
-        } else {
-            critDTO.getDataSourceIds().forEach(datasourceId -> dataSources.add(dataSourceDao.findById(datasourceId)));
-            LOGGER.trace("Criteria selected datasources ids : {}, result : {}", critDTO.getDataSourceIds().toString(),
-                    dataSources.toString());
-        }
-        final List<DataSource> unauthorized = getUnauthorizedDatasources(dataSources, account);
-        final List<DataSource> unauthorizedWithData = new ArrayList<>();
-        critDTO.setDataSources(DataTransfers.dtoSet(DataSourceDTO.class, dataSources));
-        final List<DataSource> nocache = new LinkedList<>();
-        final Map<DataSource, List<Cache>> computed = new HashMap<>();
-        final List<DataSource> finalDataSources = new LinkedList<>();
-        final List<Cache> caches = new ArrayList<>();
-        for (final DataSource dt : dataSources) {
-            final List<Cache> cachesds = cacheDao.downloadDataFromCriteria(critDTO, dt);
-            // Getting the cache of unauthorized too to warn user
-            if (unauthorized.contains(dt)) {
-                if (!cachesds.isEmpty()) {
-                    unauthorizedWithData.add(dt);
-                }
+        final List<Cache> caches;
+        final Query query;
+        try (Timer timer = SavaUtils.histogramStartTimer(SavaServlet.Metrics.CREATE_ZIP)) {
+            final Account account = getAccountEntity();
+            if (logged && account == null) {
+                LOGGER.warn("User session was expired !");
+                throw new SessionExpiredException();
+            }
+            // Set up Data sources
+            final List<DataSource> dataSources = new ArrayList<>();
+            boolean noDataSourceSelected = false;
+            // If no datasource was selected in filters
+            if (critDTO.getDataSources().isEmpty()) {
+                noDataSourceSelected = true;
+                dataSources.addAll(dataSourceDao.getAll());
+                LOGGER.trace("No datasource selected in criteria. Loading every datasource from DB");
             } else {
-                if (!noDataSourceSelected && cachesds.isEmpty()) {
-                    // Datasource was selected but has no data
-                    nocache.add(dt);
-                } else if (noDataSourceSelected && cachesds.isEmpty()) {
-                    // No datasource selected and has no data
-                    continue;
+                critDTO.getDataSourceIds()
+                .forEach(datasourceId -> dataSources.add(dataSourceDao.findById(datasourceId)));
+                LOGGER.trace("Criteria selected datasources ids : {}, result : {}",
+                        critDTO.getDataSourceIds(), dataSources);
+            }
+            final List<DataSource> unauthorized = getUnauthorizedDatasources(dataSources, account);
+            final List<DataSource> unauthorizedWithData = new ArrayList<>();
+            critDTO.setDataSources(DataTransfers.dtoSet(DataSourceDTO.class, dataSources));
+            final List<DataSource> nocache = new LinkedList<>();
+            final Map<DataSource, List<Cache>> computed = new HashMap<>();
+            final List<DataSource> finalDataSources = new LinkedList<>();
+            caches = new ArrayList<>();
+            for (final DataSource dt : dataSources) {
+                final List<Cache> cachesds = cacheDao.downloadDataFromCriteria(critDTO, dt);
+                // Getting the cache of unauthorized too to warn user
+                if (unauthorized.contains(dt)) {
+                    if (!cachesds.isEmpty()) {
+                        unauthorizedWithData.add(dt);
+                    }
                 } else {
-                    finalDataSources.add(dt);
-                    computed.put(dt, cachesds);
-                    caches.addAll(cachesds);
+                    if (!noDataSourceSelected && cachesds.isEmpty()) {
+                        // Datasource was selected but has no data
+                        nocache.add(dt);
+                    } else if (noDataSourceSelected && cachesds.isEmpty()) {
+                        // No datasource selected and has no data
+                        continue;
+                    } else {
+                        finalDataSources.add(dt);
+                        computed.put(dt, cachesds);
+                        caches.addAll(cachesds);
+                    }
                 }
             }
-        }
-        LOGGER.trace("Start query creation");
-        final Query query = createQuery(critDTO, caches.size(), pmp);
-        LOGGER.trace("Query id: {}", query.getId());
-        final String depotZip = config.get(Key.ZIP_DIR);
-
-        try (FileOutputStream sos = new FileOutputStream(
-                depotZip + query.getId() + ".zip");
-                ZipOutputStream zipOS = new ZipOutputStream(sos)) {
-            LOGGER.trace("Timestamp: {}", System.currentTimeMillis());
-            zipOS.setComment("Timestamp: " + System.currentTimeMillis());
-            // I18n.
-            // TODO récupérer la locale de l'url ou de LocaleInfo
-            final Locale locale = LocaleUtils.getLocale(localeName);
-            i18n = I18nResource.get(
-                    "fr.soeretempo.gwt.server.resources.i18n.TempoConstants",
-                    locale);
-            // Detect OS to allow buggy Excel to work.
-            final String userAgent = request.getHeader("user-agent");
-            String csvCharset = "UTF-8";
-            String newLine = "\n";
-            if (browserManager.isWindows(userAgent)) {
-                csvCharset = "Windows-1252";
-                newLine = "\r\n";
-            }
-            zip.setCsvCharset(csvCharset);
-            zip.setNewLine(newLine);
-            zip.setI18n(i18n);
-            zip.setLocale(locale);
-            zip.setCachesData(caches, query, finalDataSources);
-            final Map<String, String> lastSynchroDates = new HashMap<>();
-            for (final DataSource ds : finalDataSources) {
-                final Synchronization lastSync = synchronizationDao.findLast(ds);
-                if (lastSync == null || lastSync.getEndtime() == null) {
-                    // should never happen, but fixes bug in case of null sync found
-                    continue;
+            LOGGER.trace("Start query creation");
+            query = createQuery(critDTO, caches.size(), pmp);
+            LOGGER.trace("Query id: {}", query.getId());
+            final String depotZip = config.get(Key.ZIP_DIR);
+            try (FileOutputStream sos = new FileOutputStream(
+                    depotZip + query.getId() + ".zip");
+                    ZipOutputStream zipOS = new ZipOutputStream(sos)) {
+                LOGGER.trace("Timestamp: {}", System.currentTimeMillis());
+                zipOS.setComment("Timestamp: " + System.currentTimeMillis());
+                // I18n.
+                // TODO récupérer la locale de l'url ou de LocaleInfo
+                final Locale locale = LocaleUtils.getLocale(localeName);
+                i18n = I18nResource.get(
+                        "fr.soeretempo.gwt.server.resources.i18n.TempoConstants",
+                        locale);
+                // Detect OS to allow buggy Excel to work.
+                final String userAgent = request.getHeader("user-agent");
+                String csvCharset = "UTF-8";
+                String newLine = "\n";
+                if (browserManager.isWindows(userAgent)) {
+                    csvCharset = "Windows-1252";
+                    newLine = "\r\n";
                 }
-                final LocalDateTime sync = lastSync.getEndtime();
-                lastSynchroDates.put(ds.getName(), sync.format(DateTimeFormatter.ISO_LOCAL_DATE)
-                        + " " + sync.getHour() + ":" + sync.getMinute());
-            }
-            zip.writeDescription(zipOS, critDTO, unauthorizedWithData, nocache,
-                    noDataSourceSelected, logged, pmp, lastSynchroDates);
-            zip.writeCsvFiles(zipOS);
-            zip.addCitationFile(zipOS, getCitationText());
-            if (pmp) {
-                zip.writePmp(zipOS);
-            }
-            for (final Map.Entry<DataSource, List<Cache>> entry : computed.entrySet()) {
-                LOGGER.trace("Zipping ... {} ", entry.getKey().getName());
-                if (entry.getValue().isEmpty()) {
-                    continue;
+                zip.setCsvCharset(csvCharset);
+                zip.setNewLine(newLine);
+                zip.setI18n(i18n);
+                zip.setLocale(locale);
+                zip.setCachesData(caches, query, finalDataSources);
+                final Map<String, String> lastSynchroDates = new HashMap<>();
+                for (final DataSource ds : finalDataSources) {
+                    final Synchronization lastSync = synchronizationDao.findLast(ds);
+                    if (lastSync == null || lastSync.getEndtime() == null) {
+                        // should never happen, but fixes bug in case of null sync found
+                        continue;
+                    }
+                    final LocalDateTime sync = lastSync.getEndtime();
+                    lastSynchroDates.put(ds.getName(), sync.format(DateTimeFormatter.ISO_LOCAL_DATE)
+                            + " " + sync.getHour() + ":" + sync.getMinute());
+                }
+                zip.writeDescription(zipOS, critDTO, unauthorizedWithData, nocache,
+                        noDataSourceSelected, logged, pmp, lastSynchroDates);
+                zip.writeCsvFiles(zipOS);
+                zip.addCitationFile(zipOS, getCitationText());
+                if (pmp) {
+                    zip.writePmp(zipOS);
                 }
-                // create files pheno
-                try {
-                    zip.createPhenoFiles(entry.getValue(), entry.getKey(), zipOS);
-                    LOGGER.trace("Insertion finished.");
-                } catch (final IOException e) {
-                    LOGGER.catching(e);
+                for (final Map.Entry<DataSource, List<Cache>> entry : computed.entrySet()) {
+                    LOGGER.trace("Zipping ... {} ", entry.getKey().getName());
+                    if (entry.getValue().isEmpty()) {
+                        continue;
+                    }
+                    // create files pheno
+                    try {
+                        zip.createPhenoFiles(entry.getValue(), entry.getKey(), zipOS);
+                        LOGGER.trace("Insertion finished.");
+                    } catch (final IOException e) {
+                        LOGGER.catching(e);
+                    }
                 }
+                zip.writeCommonDataFile(zipOS, computed);
+                sos.flush();
+                LOGGER.traceExit();
+            } catch (final Exception e) {
+                LOGGER.catching(e);
             }
-            zip.writeCommonDataFile(zipOS, computed);
-            sos.flush();
-            LOGGER.traceExit();
-        } catch (final Exception e) {
-            LOGGER.catching(e);
         }
-        timer.close();
         SavaUtils.incrementCounter(SavaServlet.Metrics.DOWNLOADED, "interface", (double) caches.size());
         return query.getId();
     }
diff --git a/src/main/java/fr/soeretempo/gwt/server/rs/DataService.java b/src/main/java/fr/soeretempo/gwt/server/rs/DataService.java
index ba961c95bfc65ab3e932c75cee49bdbaa0276e06..b5143945f966285c0d1e4819822651f40f2f9be5 100644
--- a/src/main/java/fr/soeretempo/gwt/server/rs/DataService.java
+++ b/src/main/java/fr/soeretempo/gwt/server/rs/DataService.java
@@ -358,7 +358,7 @@ public class DataService {
 
     private Map<String, List<Integer>> fillMap(final List<Integer> taxon, final List<Integer> site,
             final List<Integer> stage) {
-        final Map<String, List<Integer>> parameterMap = new HashMap<String, List<Integer>>();
+        final Map<String, List<Integer>> parameterMap = new HashMap<>();
         if (!taxon.isEmpty()) {
             parameterMap.put("taxon", taxon);
         }
@@ -643,7 +643,7 @@ public class DataService {
         response.setStatus(status);
 
         try {
-            final List<WsTaxon> taxonList = new LinkedList<WsTaxon>();
+            final List<WsTaxon> taxonList = new LinkedList<>();
             for (final Integer taxonId : id) {
                 if (taxonDao.findById(taxonId) == null) {
                     status.setMessage("Taxon with the id [" + taxonId + "] does not exists.");
diff --git a/src/main/java/fr/soeretempo/gwt/server/scheduled/BackgroundJobManager.java b/src/main/java/fr/soeretempo/gwt/server/scheduled/BackgroundJobManager.java
index b1044b2beb0c9e227703bf2912cc84e18eb59e23..fed0231e93b78abf756967ad9d138748f1874188 100644
--- a/src/main/java/fr/soeretempo/gwt/server/scheduled/BackgroundJobManager.java
+++ b/src/main/java/fr/soeretempo/gwt/server/scheduled/BackgroundJobManager.java
@@ -216,7 +216,7 @@ public class BackgroundJobManager implements ServletContextListener {
      * @throws IOException
      */
     private Map<String, String> createPropertiesMap() throws IOException {
-        final Map<String, String> persistenceProperties = new HashMap<String, String>();
+        final Map<String, String> persistenceProperties = new HashMap<>();
         persistenceProperties.put(PERSISTENCE_PASSWORD, config.get(Key.JDBC_PASSWORD));
         return persistenceProperties;
     }
diff --git a/src/main/java/fr/soeretempo/gwt/server/synchrocache/SynchronizationData.java b/src/main/java/fr/soeretempo/gwt/server/synchrocache/SynchronizationData.java
index 47b340112ed8df40e2f9e282ae590a4823ad1b91..c7e8549dd0cf79f650c4f91589e7ea3ffd16a9a3 100644
--- a/src/main/java/fr/soeretempo/gwt/server/synchrocache/SynchronizationData.java
+++ b/src/main/java/fr/soeretempo/gwt/server/synchrocache/SynchronizationData.java
@@ -539,9 +539,9 @@ public class SynchronizationData implements Runnable {
         }
         final long synchCacheId = synchCache.getId();
         cacheDao.afterCreate();
-        if (cacheIterator instanceof AutoCloseable) {
+        if (cacheIterator instanceof AutoCloseable autoCloseable) {
             try {
-                ((AutoCloseable) cacheIterator).close();
+                autoCloseable.close();
             } catch (final Exception e) {
                 LOGGER.error("Can't close cacheIterator", e);
             }
@@ -621,10 +621,10 @@ public class SynchronizationData implements Runnable {
             final Class<?> clazz = Class.forName(className);
             final Constructor<?> constructor = clazz.getConstructor();
             handler = (Handler) constructor.newInstance();
-            if (handler instanceof CreaHandler) {
+            if (handler instanceof CreaHandler creaHandler) {
                 final TaxrefHandler taxrefHandler = new TaxrefHandler();
                 taxrefHandler.setTaxrefTaxonDao(taxrefTaxonDao);
-                ((CreaHandler) handler).setTaxrefHandler(taxrefHandler);
+                creaHandler.setTaxrefHandler(taxrefHandler);
             }
         } catch (final ClassNotFoundException e) {
             LOGGER.warn("Hey dev, class handler {} wasn't found ! maybe you misspelled it: {}", dataSource,
diff --git a/src/main/java/fr/soeretempo/gwt/server/utils/FileUtils.java b/src/main/java/fr/soeretempo/gwt/server/utils/FileUtils.java
index f1c760023381a1d1b71ad3c2d4918e3e1a44c1c2..7d24d39dd5cb1a186a68146a016d7ab595fa54f9 100644
--- a/src/main/java/fr/soeretempo/gwt/server/utils/FileUtils.java
+++ b/src/main/java/fr/soeretempo/gwt/server/utils/FileUtils.java
@@ -89,10 +89,11 @@ public final class FileUtils {
         if (is == null) {
             throw new IllegalArgumentException(filename + " not found!");
         }
-        final BufferedReader buffer = new BufferedReader(new InputStreamReader(is));
-        final String temp = buffer.lines().collect(
-                Collectors.joining(System.getProperty("line.separator")));
-        buffer.close();
+        final String temp;
+        try (BufferedReader buffer = new BufferedReader(new InputStreamReader(is))) {
+            temp = buffer.lines().collect(
+                    Collectors.joining(System.getProperty("line.separator")));
+        }
         return temp;
     }
 
diff --git a/src/site/markdown/index.md b/src/site/markdown/index.md
index d0a5b017be817f106e0b3a558b6fa427a164d1ec..96773acc10d8e06e6a5fa73c1a0ce282838681c8 100644
--- a/src/site/markdown/index.md
+++ b/src/site/markdown/index.md
@@ -71,6 +71,22 @@ Ce fichier de Tomcat est modifié pour contenir différents identifiants que l'o
 
 La valeur de la clef pour Epiphyt est obtenue à https://dgal-vegetal.opendatasoft.com/account/api-keys/.
 
+## Configuration de Tomcat
+
+Les arguments de la VM pour Tomcat doivent contenir :
+
+```
+--add-opens=java.base/java.io=ALL-UNNAMED
+--add-opens=java.base/java.lang=ALL-UNNAMED
+--add-opens=java.base/java.math=ALL-UNNAMED
+--add-opens=java.base/java.net=ALL-UNNAMED
+--add-opens=java.base/java.text=ALL-UNNAMED
+--add-opens=java.base/java.util=ALL-UNNAMED
+--add-opens=java.base/java.util.concurrent=ALL-UNNAMED
+--add-opens=java.sql/java.sql=ALL-UNNAMED
+--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED
+```
+
 ## Inscrire data.pheno.fr dans les services d'authentification
 
 TEMPO gère désormais plusieurs fournisseurs d'identité.
@@ -191,7 +207,7 @@ Définir dans la base de données de TEMPO les données de la base dans la table
 	Ex :
 ```
 	Base publique : “1” | “tobeerased” | “Phenoclim Agroclim INRAE” | TRUE | “https://www6.paca.inrae.fr/agroclim/“ | “fr.soeretempo.gwt.server.dataSources.sido.SidoHandler” | “img/logo-phenoclim.png” | “DESCRIPTION : Haec igitur Epicuri non probo, inquam.” | "tobeerased"
-	Base soumise à autorisation :  “1” | “tobeerased” | “Phenoclim Agroclim PRO” | FALSE | “https://www6.paca.inrae.fr/agroclim/“ | “fr.soeretempo.gwt.server.dataSources.sido.SidoHandler” | “img/logo-phenoclim.png” | “DESCRIPTION : Haec igitur Epicuri non probo, inquam.” | "tobeerased" 
+	Base soumise à autorisation :  “1” | “tobeerased” | “Phenoclim Agroclim PRO” | FALSE | “https://www6.paca.inrae.fr/agroclim/“ | “fr.soeretempo.gwt.server.dataSources.sido.SidoHandler” | “img/logo-phenoclim.png” | “DESCRIPTION : Haec igitur Epicuri non probo, inquam.” | "tobeerased"
 ```
 
 
@@ -221,7 +237,7 @@ WHERE S.relkind = 'S'
     AND T.relname = PGT.tablename
 ORDER BY S.relname;
 ```
-facilite la tâche. Sa fonction est de créer une requête qui remettra chaque séquence à la valeur où elle est supposée être actuellement. 
+facilite la tâche. Sa fonction est de créer une requête qui remettra chaque séquence à la valeur où elle est supposée être actuellement.
 Pour s'en servir en ligne de commande, sauvegarder le code précédent dans un fichier, `resetsequences.sql` par exemple. Puis :
 ```
 psql -Atq -f resetsequences.sql -o temp
diff --git a/src/test/java/fr/soeretempo/gwt/server/download/RecordZipperTest.java b/src/test/java/fr/soeretempo/gwt/server/download/RecordZipperTest.java
index 8c71081de510e4bd9cb3926a071fbfe16a8c8bf0..7e054453c9a4cb423dbd9b67922e7c069288b736 100644
--- a/src/test/java/fr/soeretempo/gwt/server/download/RecordZipperTest.java
+++ b/src/test/java/fr/soeretempo/gwt/server/download/RecordZipperTest.java
@@ -391,29 +391,28 @@ public final class RecordZipperTest {
 
         final File file = File.createTempFile("zip", null);
         assertTrue(file.exists());
-        /**
+        try ( /**
          * ZIP.
-         */
-        final FileOutputStream sos = new FileOutputStream(file);
-        final ZipOutputStream zipOS = new ZipOutputStream(sos);
-        final RecordZipper zip = new RecordZipper();
-
-        zipOS.setComment("Timestamp: " + System.currentTimeMillis());
-
-        zip.setCsvCharset(csvCharset);
-        zip.setNewLine(newLine);
-        zip.setI18n(i18n);
-        zip.setLocale(Locale.FRENCH);
-        zip.setCachesData(caches, query,
-                setDataSource.stream().collect(Collectors.toList()));
-        // zip.writeDescription(zipOS, setDataSource);
-        zip.writePmp(zipOS);
-        zip.createPhenoFiles(caches1, source1, zipOS);
-        zip.createPhenoFiles(caches2, source2, zipOS);
-
-        zipOS.close();
-        sos.flush();
-        sos.close();
+         */ FileOutputStream sos = new FileOutputStream(file)) {
+            final ZipOutputStream zipOS = new ZipOutputStream(sos);
+            final RecordZipper zip = new RecordZipper();
+
+            zipOS.setComment("Timestamp: " + System.currentTimeMillis());
+
+            zip.setCsvCharset(csvCharset);
+            zip.setNewLine(newLine);
+            zip.setI18n(i18n);
+            zip.setLocale(Locale.FRENCH);
+            zip.setCachesData(caches, query,
+                    setDataSource.stream().collect(Collectors.toList()));
+            // zip.writeDescription(zipOS, setDataSource);
+            zip.writePmp(zipOS);
+            zip.createPhenoFiles(caches1, source1, zipOS);
+            zip.createPhenoFiles(caches2, source2, zipOS);
+
+            zipOS.close();
+            sos.flush();
+        }
 
         assertTrue(file.exists());
         assertTrue(file.length() > 0);
diff --git a/src/test/java/fr/soeretempo/gwt/shared/StringUtilsTest.java b/src/test/java/fr/soeretempo/gwt/shared/StringUtilsTest.java
index c01b375912db17ecfb7fc2065f6cdbe5ac4e78d0..61b5466d9b80c027e5967af721077c2cb1316c3c 100644
--- a/src/test/java/fr/soeretempo/gwt/shared/StringUtilsTest.java
+++ b/src/test/java/fr/soeretempo/gwt/shared/StringUtilsTest.java
@@ -214,7 +214,7 @@ public final class StringUtilsTest {
                                 "Beaujeu-Saint-Vallier-Pierrejux-et-Quitteur",
                                 "ÀÄÂÉÈÊËÏÎÑÔÖÜÛàäâéèêëïîñôöüû",
                                 "Mingəçevir", "èê ëï ÊË", ""};
-        final List<String> result = new LinkedList<String>();
+        final List<String> result = new LinkedList<>();
         for (final String name : test) {
             result.add(StringUtils.normalizeAccented(name));
         }
diff --git a/src/test/java/fr/soeretempo/gwt/shared/dto/QueryDTOTest.java b/src/test/java/fr/soeretempo/gwt/shared/dto/QueryDTOTest.java
index 051f613c692e45b5a8f9c67fffea2a75cc372fa5..63f8f9c192eb1e39ad3b54179c6f578600e533d6 100644
--- a/src/test/java/fr/soeretempo/gwt/shared/dto/QueryDTOTest.java
+++ b/src/test/java/fr/soeretempo/gwt/shared/dto/QueryDTOTest.java
@@ -36,13 +36,13 @@ public class QueryDTOTest {
     @Test()
     public void getPeriodList() {
         Integer[] years = {1,2,3,4,5,6,7,8,9,10,11,15,16,17,18,19,21,22,23,24,25,27};
-        List<YearDTO> testyears = new LinkedList<YearDTO>();
+        List<YearDTO> testyears = new LinkedList<>();
         for (Integer i : years) {
             testyears.add(new YearDTO(i));
         }
         test.setYears(years);
         test.setlistYears(testyears);
-        List<PeriodDTO> expected = new LinkedList<PeriodDTO>();
+        List<PeriodDTO> expected = new LinkedList<>();
         expected.add(new PeriodDTO(new YearDTO(1), new YearDTO(11)));
         expected.add(new PeriodDTO(new YearDTO(15), new YearDTO(19)));
         expected.add(new PeriodDTO(new YearDTO(21), new YearDTO(25)));