Jcms ( 10 / 22 articles - Voir la liste )

Astuce Impossible de trouver mon nouveau skin dans JCMS

Je viens de créer un nouveau skin dans JCMS, mais malgré un redémarrage ou le vidage du work de tomcat, il n'apparaît pas dans la liste de choix du skin de mes portlets.

Par défaut, pour ajouter un nouveau skin il suffit de créer la jsp et de la déclarer dans le fichier plugin.xml. Par exemple :

<types>
    <templates type="AbstractPortletSkinable">
       <template name="newSkin" file="doNewSkin.jsp" usage="box">
             <label xml:lang="en">My new skin</label>
             <label xml:lang="fr">Mon nouveau skin</label>
       </template>
    </templates>
</type>

Il existe cependant un option méconnue dans le CMS : la possibilité d'activer des skins différents pour chaque espace de travail.

Pour cela :

  • Choisissez un espace de travail en back-offfice
  • Allez dans l'Espace d'administration fonctionnelle > Types de publication > Portlet
  • Éditez [Abstract] Portlet Skinable.
  • Cochez les skins à activer dans l'espace de travail

Par défaut dans JCMS, aucun n'est coché. Tous les nouveaux skins sont donc immédiatement disponibles.

Mais à partir du moment où l'un d'eux est coché, vous devrez repasser par cette interface à chaque création de skin pour l'activer manuellement.

Astuce Autoriser plusieurs soumissions de formulaire

Par mesure de sécurité, JCMS limite le nombre de soumissions des formulaires. Il faut attendre environ une minute entre chaque soumission.

Ce comportement peut-être éviter en ajoutant cette classe css sur la balise form du formulaire : noSingleSubmitButton.

Astuce Afficher une erreur dans JCMS

Dans JCMS (7 et +) les erreurs sont affichées dans un bloc ressemblant à ça.

Affichage d'une erreur dans JCMS

Transmettre le message

Vous devez tout d'abord transmettre votre message à JCMS.

  • Si vous êtes dans une JSP, utilisez l'une ou l'autre de ces méthodes :
// Ajoute un message d'erreur dans la request
setErrorMsg("Le téléchargement du document a échoué", request);

// Ajoute un message d'erreur dans la session
setErrorMsgSession("Le téléchargement du document a échoué", request);
  • Pour faire la même chose dans une classe Java, utilisez l'une de celles-ci :
    // Ajoute un message d'erreur dans la request
    JcmsContext.setErrorMsg("An error occured while saving your content", request);

    // Ajoute un message d'erreur dans la session
    JcmsContext.setErrorMsgSession("An error occured while saving your content", request);

Remarque :

Des méthodes équivalentes existent pour les messages d'information et d'avertissement.

Afficher le message

Une fois le message transmis, il reste à l'afficher. Il suffit pour cela d'inclure ce bout de code :

<%@ include file='/jcore/doMessageBox.jsp' %>

Cette JSP fournie par JCMS, va récupérer tous les messages d'information, d'avertissement ou d'erreur présents en session, dans les paramètres de la request et dans le contexte de la page. Chaque message trouvé est affiché.

Remarque :

Depuis la version 7.1 JCMS utilise Bootstrap. Si vous êtes en version antérieure, le message d'erreur ne ressemblera pas à celui ci-dessus.

Astuce Ordre des champs en ExtraData

Lors de l'affichage des champs en ExtraData, JCMS utilise l'ordre l'alphabétique des clés des propriétés d'ExtraData.

Si votre plugin.prop contient les propriétés suivantes :

extra.Category.jcmsplugin.monplugin.premierchamp
extra.Category.jcmsplugin.monplugin.champ2
extra.Category.jcmsplugin.monplugin.champ3
extra.Category.jcmsplugin.monplugin.dernierchamp

Les champs s'afficheront dans cet ordre en back-office :

  • champ2
  • champ3
  • dernierchamp
  • premierchamp

Astuce Rétablir le mot de passe admin par défaut

Si vous avez perdu le mot passe administrateur, ou si vous souhaitez le modifier directement dans le store, ajoutez une ligne de la forme suivante à la fin :

<member stamp="j_99999" id="j_2" op="update" author="" mdate="1091526019085" mobile="" name="Admin" password="ISMvKXpXpadDiUoOSoAfww==" />

Cette ligne remplace le mot de passe actuel par admin.

Remarques :

  • Remplacez la valeur de stamp par la même valeur que votre dernière ligne de store, en l'incrémentant.
  • Faites de même pour la date de modification (mdate).

JPlatform 10 (merci Axel pour cette MAJ)

Sur JPlatform 10, le chiffrement des mots de passe a changé. La ligne à ajouter pour le réinitialiser devient :

<member stamp="agi_7217" id="j_2" op="update" mdate="1528122795429" login="admin" name="Admin" password="$2a$10$gbCw7UaAI1kL7PXqodTY9OmzqsdFBufD063oG6ebQT/Zi2PBELX56" />

Astuce Le logger dans JCMS : log4j

Par défaut, JCMS utilise log4j pour gestionnaire de logs.

Utilisation générale de log4j

Voici comment l'utiliser dans une classe :

public class MyClass {

    /** Logger log4j */
    private static final Logger logger = Logger.getLogger(MyClass.class);

    public MyClass() {
        logger.info("Je suis dans le constructeur par défaut de ma classe.");
    }

Explications :

  • Déclarez un nouvel attribut de classe statique qui utilise la méthode getLogger() de log4j.
  • Passez votre classe en argument de cette méthode.
  • Utilisez le logger en appelant ses méthodes debug(), info(), warn(), error() ou fatal(), avec le message en argument, plus éventuellement une exception.

Configuration de log4j

Log4j est configuré via le fichier log4j.xml. Dans JCMS, ce fichier se trouve dans WEB-INF/data/.

Si dans un nouveau projet JCMS vous créez un package pour y mettre vos classes Java, il est probable que les logs ne fonctionnent pas. En effet, log4j n'a pas connaissance de ce nouveau package.

Pour l'en informer, éditez le fichier log4j.xml et ajoutez :

<!-- Logger de classes personnalisées --> 
<logger name="mon.package" additivity="false">
    <level value="DEBUG" />
    <appender-ref ref="JCMS" />
    <appender-ref ref="CONSOLE" />
    <appender-ref ref="LOGFILE" />
    <appender-ref ref="PLUGIN" />
</logger>

Explications :

  • L'attribut name définit pour quels packages utiliser log4j. (Les sous-packages seront automatiquement logués.)
  • L'attribut value de l'élément <level> permet de déterminer quel niveau de log appliquer. En développement on utilise souvent DEBUG ou INFO alors qu'en production on se contentera de INFO ou WARN. Concrètement, avec le niveau WARN, les méthodes logger.debug() et logger.info() n'auront aucun effet (suivant cet ordre : debug < info < warn < error < fatal).
  • Les <appender> sont les sorties à utiliser : fichier de log, console, ...
  • Vous pouvez déclarer autant de logger que vous le souhaitez dans le fichier log4j.xml.

Astuce Utiliser un logger dans les classes de test

Dans vos classes de test, vous pouvez utiliser le gestionnaire de log slf4j Il s'agit d'une façade qui peut utiliser plusieurs loggers au choix, comme log4j par exemple.

Voici comment utiliser ce gestionnaire :

public class MyClassTest extends JcmsTestCase {

    /** Logger **/
    private static Logger logger;

    /**
     * Initialise un contexte pour une suite de tests, avec des méthodes d'initialisation et de finalisation.
     * 
     * @return une configuration de suite de tests
     */
    public static TestSetup suite() {

        return new TestSetup(new TestSuite(MyClassTest.class)) {

            @BeforeClass
            @Override
            protected void setUp() throws Exception {

                logger = LoggerFactory.getLogger(MyClassTest.class);
                logger.debug("Début des tests unitaires pour la classe " + MyClass.class.getSimpleName() + ".");
            }
            @AfterClass
            @Override
            protected void tearDown() throws Exception {
                logger.debug("Fin des tests unitaires.");
            }
        };
    }

Explications :

  • Déclarez le logger dans votre classe de test.
  • Créez la méthode statique suite(), pour pouvoir initialiser des éléments au début des tests.
  • Utilisez la méthode LoggerFactory.getLogger(), pour initialiser le logger.
  • Utilisez le logger comme avec log4j (ex : logger.info(), logger.debug(), ...).

Remarque :

Pour pouvoir utiliser slf4j avec log4j, vous devez inclure ces deux jars dans votre projet : slf4j-api-1.5.8.jar et slf4j-log4j12-1.5.8.jar.

Astuce Récupérer la version antérieure d'une Data, dans un DataController

Si vous avez besoin de comparer l'ancienne et la nouvelle version d'une Data, dans un DataController (par exemple dans afterWrite()), vous aurez besoin d'utiliser le contexte en paramètre de la méthode.

Pour obtenir cette version, utilisez quelque chose comme :

final Article oldArticle = (Article) context.get("Data.previous");

Astuce Les variables disponibles dans le contexte, pour les DataController

Lorsque vous créez un DataController et que vous surchargez les méthodes beforeWrite(), checkWrite() et afterWrite(), le dernier paramètre de la méthode (la Map), contient tout le contexte disponible.

Dans cette variable il y a notamment :

  • request : L'objet HttpServletRequest de tomcat.
  • response : L'objet HttpServletResponse de tomcat.
  • formHandler : Le FormHandler utilisé lors de l'édition du contenu.

Et dans le cas d'une modification de donnée, il y a également :

  • Data.previous : La dernière version de la Data avant modification.

Astuce Vider toutes les tables de la base de données Derby

Si vous utilisez Derby dans vos tests unitaires, vous aurez sans doute besoin de réinitialiser votre base entre chaque test.

Pour supprimer le contenu de toutes les tables d'un coup, vous pouvez utiliser cette fonction :

/**
 * Vide toutes les tables de la base de données, dont le nom commence par "G_" ou "J_".
 * 
 * @throws SQLException
 */
public static void derbyClearAllTables() throws SQLException {

    ResultSet tables;
    Statement stat;

    final String schema = "jdbc:derby:jcmsdbunit";

    // Récupération de la liste des tables de la base de données
    final Connection connection = DriverManager.getConnection(schema);
    tables = connection.getMetaData().getTables(null, null, null, null);

    final Set<String> tableNameSet = new HashSet<String>();

    // Parcours des tables de la base de données
    while (tables.next()) {

        final String tableName = tables.getString("TABLE_NAME");

        if (tableName.startsWith("G_") || tableName.startsWith("J_")) {

            tableNameSet.add(tableName);
        }
    }

    // Parcours des tables à vider
    for (final String tableName : tableNameSet) {

        // Nettoyage de la table
        stat = connection.createStatement();
        stat.executeUpdate("DELETE FROM " + tableName);
        connection.commit();
    }

    if (!tables.isClosed()) {
        tables.close();
    }
}

Remarque :

Les tables ne commençant ni par G_ ni par J_ sont probablement des tables utiles au fonctionnement interne de Derby. Elles ne sont pas à vider.