package dev.lions.config; import dev.lions.exceptions.ConfigurationException; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Observes; import jakarta.faces.annotation.FacesConfig; import jakarta.faces.application.ViewHandler; import jakarta.faces.component.UIViewRoot; import jakarta.faces.context.FacesContext; import jakarta.faces.event.PostConstructApplicationEvent; import jakarta.faces.event.PreDestroyApplicationEvent; import jakarta.faces.event.SystemEvent; import jakarta.inject.Inject; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import org.eclipse.microprofile.config.inject.ConfigProperty; import java.util.Map; /** * Configuration Jakarta Server Faces (JSF) de l'application. * Cette classe gère l'ensemble des paramètres et comportements spécifiques à JSF, * assurant une expérience utilisateur cohérente et performante. * * @author Lions Dev Team * @version 2.1 */ @Slf4j @ApplicationScoped @FacesConfig public class JSFConfiguration { @Inject @ConfigProperty(name = "jakarta.faces.PROJECT_STAGE", defaultValue = "Development") String projectStage; @Inject @ConfigProperty(name = "jakarta.faces.FACELETS_REFRESH_PERIOD", defaultValue = "2") Integer faceletsRefreshPeriod; @Inject @ConfigProperty(name = "jakarta.faces.STATE_SAVING_METHOD", defaultValue = "server") String stateSavingMethod; @Inject @ConfigProperty(name = "primefaces.THEME", defaultValue = "saga") private String primefacesTheme; @Inject @ConfigProperty(name = "jakarta.faces.VALIDATE_EMPTY_FIELDS", defaultValue = "true") private Boolean validateEmptyFields; @Inject @ConfigProperty(name = "jakarta.faces.FACELETS_SKIP_COMMENTS", defaultValue = "true") private Boolean skipComments; /** * Initialise la configuration JSF au démarrage de l'application. * * @param event Événement de construction de l'application. */ public void initialize(@Observes @NotNull PostConstructApplicationEvent event) { try { log.info("Initialisation de la configuration JSF"); configureFacesContext(); configureViewHandler(); configurePrimeFaces(); applyPerformanceOptimizations(); log.info("Configuration JSF initialisée avec succès - Mode: {}", projectStage); } catch (Exception e) { String message = "Erreur lors de l'initialisation de la configuration JSF"; log.error(message, e); throw new ConfigurationException(message, e); } } /** * Nettoie les ressources JSF avant l'arrêt de l'application. * * @param event Événement de destruction de l'application. */ public void cleanup(@Observes @NotNull PreDestroyApplicationEvent event) { log.info("Nettoyage des ressources JSF"); } /** * Configure le contexte Faces avec les paramètres spécifiques. */ private void configureFacesContext() { log.debug("Configuration du contexte Faces"); setFacesParameter("jakarta.faces.PROJECT_STAGE", projectStage); setFacesParameter("jakarta.faces.STATE_SAVING_METHOD", stateSavingMethod); setFacesParameter("jakarta.faces.FACELETS_REFRESH_PERIOD", faceletsRefreshPeriod.toString()); setFacesParameter("jakarta.faces.VALIDATE_EMPTY_FIELDS", validateEmptyFields.toString()); setFacesParameter("jakarta.faces.FACELETS_SKIP_COMMENTS", skipComments.toString()); } /** * Configure les paramètres spécifiques au gestionnaire de vue. */ private void configureViewHandler() { log.debug("Configuration du gestionnaire de vues JSF"); FacesContext facesContext = FacesContext.getCurrentInstance(); if (facesContext == null) { log.warn("Impossible de configurer le gestionnaire de vue : FacesContext est null."); return; } ViewHandler viewHandler = facesContext.getApplication().getViewHandler(); UIViewRoot root = facesContext.getViewRoot(); if (root == null) { root = viewHandler.createView(facesContext, "/index.xhtml"); facesContext.setViewRoot(root); } root.getAttributes().put("encoding", "UTF-8"); root.getAttributes().put("contentType", "text/html"); root.getAttributes().put("characterEncoding", "UTF-8"); log.debug("Gestionnaire de vues configuré avec succès."); } /** * Configure les paramètres spécifiques à PrimeFaces. */ private void configurePrimeFaces() { log.debug("Configuration de PrimeFaces"); setFacesParameter("primefaces.THEME", primefacesTheme); setFacesParameter("primefaces.FONT_AWESOME", "true"); setFacesParameter("primefaces.CLIENT_SIDE_VALIDATION", "true"); setFacesParameter("primefaces.UPLOADER", "auto"); configurePrimeFacesCache(); } /** * Configure le cache PrimeFaces selon l'environnement. */ private void configurePrimeFacesCache() { String cacheProvider = isDevelopmentMode() ? "memory" : "ehcache"; setFacesParameter("primefaces.CACHE_PROVIDER", cacheProvider); } /** * Applique les optimisations de performance. */ private void applyPerformanceOptimizations() { if (!isDevelopmentMode()) { setFacesParameter("jakarta.faces.FACELETS_REFRESH_PERIOD", "-1"); setFacesParameter("jakarta.faces.COMPRESS_VIEWSTATE", "true"); setFacesParameter("jakarta.faces.PARTIAL_STATE_SAVING", "true"); } } /** * Définit un paramètre dans le contexte Faces. */ private void setFacesParameter(String name, String value) { FacesContext.getCurrentInstance() .getExternalContext() .getApplicationMap() .put(name, value); log.debug("Paramètre défini : {} = {}", name, value); } /** * Vérifie si l'application est en mode développement. * * @return true si en mode développement, false sinon. */ public boolean isDevelopmentMode() { return "Development".equals(projectStage); } }