SeamFramework.orgCommunity Documentation

Chapitre 23. Mise en cache

23.1. Utilisation de JBossCache dans Seam
23.2. La mise en cache de fragment de page

Dans presque toutes les applications d'entreprise, la base de données est le premier goulet d'étranglement et le moins scalable tierce-partie de l'environement d'exécution. Les gens venant des environements PHP/Ruby vont essayer de vous dire que les architectures surnommées "ne partage rien" se dimensionnent bien. Et bien c'est peut être littérallement vrai, je ne sait pas combien d'application intéréssantes multi-utilisateurs peuvent être implémentées avec aucun partage de ressources entre les différentes noeuds du cluster. Que pensent vraiment ces personnes loufoques d'une architecture "ne rien partager sauf la base de données". Bien sur, le partage de la base de données est un problème principal quand on dimensionne une application multi utilisateur donc réclammer que cette architecture soit hautement dimensionnable est absurde et dites vous que c'est pas mal de ce type d'application sur les quelles ces gens passent la plus part du temps à travailler dessus.

Le moins que nous puissions rendre faisable et de partager la base de données le moins souvent est d'une grande valeur.

Cela demande un cache. Et bien , pas juste un seul cache. Une application Seam bien désignée va fonctionner avec une stratégie de cache multi couche riche qui va impacter chaque couche de l'application:

Pour plus d'informations à propos du cache de second niveau, vous allez avoir besoin de vous référer à la document de votre solution ORM, car c'est un sujet extrèmement complexe. Dans cette section, nous allons parler de l'utilisation du chache directemnet via le composant cacheProvider , ou comme le cache de fragment de page, via le controle <s:cache>.

Le composant livré cacheProvider gère une instance de:

Vous pouvez de manière sure mettre tout objet Java immuable dans le cache, et il sera stocké dans le cache et répliqué au travers du cluster (en supposant que la réplication est disponible et activée). Si vous voulez conserver les objets mutables dans le cache, vous allez avoir besoin de lire la documentation nécéssaire à l'outil de cache pour comprendre commen lui notifier du changement dans la mise en cache auprès de l'outil du cache.

Pour utiliser cacheProvider, vous aller devoir inclure les fichiers jars de l'implémentation de ce cache dans votre projet:

Pour un déploiement EAR de Seam, nous vous recommandaons que les fichiers jars de la mise en cache et la configuration soient directement mis dans l'EAR.

Vous allez avoir aussi besoinde fournir un fichier de configuration pour JBossCache. Placez treecache.xml avec une configuration de la mise en cache approprié dans le classpath (par exemple le fichier jar ejb ou WEB-INF/classes). JBossCache a de nombreuses horreurs et des réglages de configurations confus, donc nous n'allons pas en parler ici. Merci de vous référer à la document de JBossCache pour plus d'information.

Vous trouverez un exemple de treecache.xml dans examples/blog/resources/treecache.xml.

EHCache sera exécuté dans sa configuration par défaut sans fichier de configuration

Pour modifier le fichier de configuration en cours d'utilisation, configurez votre cache dans components.xml:


<components xmlns="http://jboss.com/products/seam/components"
            xmlns:cache="http://jboss.com/products/seam/cache">
   <cache:jboss-cache-provider configuration="META-INF/cache/treecache.xml" />
</components
>

Maintenant, vous pouvez injecter votre cache dans tout composant de Seam:

@Name("chatroomUsers")

@Scope(ScopeType.STATELESS)
public class ChatroomUsers
{
    @In CacheProvider cacheProvider;
    @Unwrap
    public Set<String
> getUsers() throws CacheException   {
        Set<String
> userList = (Set<String
>) cacheProvider.get("chatroom", "userList");
        if (userList==null) {
            userList = new HashSet<String
>();
            cacheProvider.put("chatroom", "userList", userList);
        }
        return userList;
    }
}

Si vous voulez avoir de multplies configurations de mises en cache dans votre application, utilisez components.xml pour configurer vos différents fournisseur de mise en cache:


<components xmlns="http://jboss.com/products/seam/components"
            xmlns:cache="http://jboss.com/products/seam/cache">
   <cache:jboss-cache-provider name="myCache" configuration="myown/cache.xml"/>
   <cache:jboss-cache-provider name="myOtherCache" configuration="myother/cache.xml"/>
</components
>

L'utlisation la plus intéressante de JBossCache est le tag <s:cache> , la solution de Seam pour le problème de mettre en cache les fragments de pages.<s:cache> utilise pojoCache en interne, donc nous avez besoin de suivre les étapes listées ci dessous avant de pouvoir l'utiliser. (Mettez les jars dans le EAR, barboter dans les horribles options de configurations , etc.)

<s:cache> est utilisé pour mettre en cache quelques contenues rendues rarement. par exemple, la page bienvenue de votre blog qui affiche les entrées récentes du blog:


<s:cache key="recentEntries-#{blog.id}" region="welcomePageFragments">
   <h:dataTable value="#{blog.recentEntries}" var="blogEntry">
      <h:column>
         <h3
>#{blogEntry.title}</h3>
         <div>
            <s:formattedText value="#{blogEntry.body}"/>
         </div>
      </h:column>
   </h:dataTable>
</s:cache
>

La key permet d'avoir de multiples versions en cache de chaque fragment de page. Dans ce cas, il n'y a qu'une version mise en cache par blog. La region détermine le cache ou le noeud local pour toutes les versions qui seront à stocker. Les noeuds différents peuvent avoir des politiques d'expirations différentes. (C'est du boulot que vous configuriez tout en utilisant les horribles options de configurations susmentionnées.)

Bien sur, le gros problème avec <s:cache> est qu'il est trop stupide pour connaitre quand les données sousjacentes changent (par exemple, quand les billets d'un bloggeur ont une nouvelle entrée). Donc vous avez besoin de virer les fragment en cache manuellement:

public void post() {

    ...
    entityManager.persist(blogEntry);
    cacheProvider.remove("welcomePageFragments", "recentEntries-" + blog.getId() );
}

Autre alternative, si ce n'est pas critique que les modifications ne soient pas immédiatement visitble pour l'utilisateur, vous pouvez définir une periode d'expiration courte dans le noeud de JbossCache.