Bienvenue
Jalios Community
Tout ce que vous souhaitez savoir sur l'écosystème Jalios
Cette page présente les principales nouveautés de JPlatform 10 concernant les développements back-ends.
Certaines fonctions de JPlatform (portées par coeur ou par les modules) proposent à l'utilisateur des options qui peuvent être persistées.
Par exemple, la nouvelle Topbar de JPlatform 10 propose le menu "Applications" dans lequel l'utilisateur peut choisir ses applications préférées et l'ordre dans lequel elles apparaissent dans le menu.
Jusqu'à présent les développeurs devaient gérer eux même un mode de stockage spécifique pour ces préférences utilisateur (ExtraDBData ou type dédié).
JPlatform 10 fournit désormais une API homogène et performante pour le stockage des préférences utilisateurs.
L'article JPlatform 10 - API des préférences utilisateurs (MemberPreference) présente en détail cette nouvelle API.
Avec JPlatform 10 un type de publication stockés en base de données peut désormais avoir des champs multilingues. Il dispose ainsi de la plupart des capacités multilingues des publications du store. Le multilinguisme peut s'appliquer sur des champs mono-valués ou multi-valués. Les publication en base ont maintenant un champ "Langue principale". Enfin, elles disposent aussi des copies de traduction.
Il y a néanmoins quelques limites :
En standard, les types suivants disposent de champs multilingues :
C'est aussi le cas de certains types livrés par des modules
Techniquement, les textes dans les langues additionnelles d'un champ multilingue sont sérialisés en JSON et stockés dans un champ dédié. Ce champ reprend le nom du champ texte associé avec le suffixe MLE (pour MultiLingual Encoding). Par exemple, au champ title
est associé le champ titleMLE
contenant une Map JSON contenant le titre dans les langues additionnelles.
Les contenus stockées dans la base de données disposent désormais de la fonction "copie de travail".
3 champs sont utilisées pour les copies de travail
Ces 3 champs sont ajoutés aux HBM des DB Content ainsi qu'aux HBM de leur révision.
Les contenus en base disposent dans JPlatform 10 des URLs intuitives (friendly URL) comme pour les contenus stockés dans JStore.
Dans le cas des publications du Store, les QueryFilter s'appliquent sur l'ensemble des résultats. Ce mode de fonctionnement n'est pas adapté aux contenus en base puisqu'il intervient après que la requête ait eu lieu et n'appliquerait donc qu'aux seuls les résultats de la tranche paginée.
A l'instar des RightPolicyFilter, il convient donc d'appliquer le filtrage durant l'itération de recherche (scroll). Ce mode de fonctionnement ayant un coût sur la recherche, il ne doit être enclenché que si des QueryFilter sont susceptibles d'intervenir sur cette recherche.
Pour le savoir, le QueryFilter doit l'indiquer au travers de la méthode callFilterDBResult() de la classe =QueryFilter
. Cette méthode est appellée au début de la recherche en base afin de déterminer si au moins un QueryFilter souhaite participer à la recherche. Ceci imposera une recherche avec scrolling (comme dans le cas des RightPolicyFilter).
En complément, et pour des cas simple, la méthode = callFilterDBResult(Class clazz, Map<String,Object> context)= est fournie lorsque le contrôle se base simplement sur le type de publication.
Enfin, la méthode filterDBResult
est appelée pour chaque résultats remontée de la recherché afin de déterminer si il doit être gardé ou non.
En synthèse, voici donc les méthodes qui ont été ajouté à la classe QueryFilter
:
public abstract class QueryFilter { ... boolean callFilterDBResult (PublicationCriteria); boolean callFilterDBResult(Class clazz, Map<String,Object> context); boolean filterDBResult(Publication pub, Map<String,Objet> context) }
Dans le cadre de la prise en charge de volumétrie de données importantes, l'une des pistes consiste à répartir ces données dans différentes table de JcmsDB. En effet, moins une table contient de données plus les performances sont bonnes.
Traditionnellement, cette répartition en table peut être prise en charge directement par la base de données avec la technique du table partionning. Cependant, JPlatform 10 utilise l'ORM Hibernate pour le stockage des données en base, ce qui rend cette pratique compliquée à mettre en oeuvre.
L'alternative consiste donc à faire la répartition depuis JPlatform. On constate généralement que ce sont les documents qui représentent une grand part de la volumétrie à prendre en charge. Parmi eux, les média (images, video, audio) représentent une part importante. Pouvoir répartir ces média dans une table dédié est donc souhaitable.
Pour répondre à cet objectif, JPlatform 10 introduit la sélection automatique du type de document lors des dépôts ainsi que le type Media dédié au stockage des médias (images, video, audio).
En plus des bénéfices sur les performances, la sélection automatique du type de document aiderai encore d'avantage les utilisateurs qui sont amenés à déposer des documents en ne ce souciant plus du type à utiliser.
La sélection automatique peut s'appliquer à d'autres type que les documents.
La sélection automatique du type de document prend 3 paramètre :
loggedMember
L'algorithme de sélection du type de document est la suivant :
image/jpeg
)loggedMember
peut publier ce type dans dans l'espace cible alors on retient ce typeimage
)loggedMember
peut publier ce type dans dans l'espace cible alors on retient ce typeloggedMember
peut publier le type de document par défaut dans dans l'espace cible alors on retient ce typeloggedMember
peut publier le type DBFileDocument par défaut dans dans l'espace cible alors on retient ce typeloggedMember
peut publier le type FileDocument par défaut dans dans l'espace cible alors on retient ce typeloggedMember
peut publier dans l'espace cibleLes modes de dépôts concernés par la sélection automatique du type de documents sont :
file
)Le mapping d'un type de fichier avec un type de document de JPlatform se fait par une déclaration de propriété. Ces propriétés commencent par le préfix file-document.upload.class
et sont de la forme :
file-document.upload.class.<top-level/subtype>: <classe du type de document>=
<top-level/subtype>
représente le MIME type. Il peut s'agir d'un MIME type complet (eg. image/jpeg
, video/mp4
, application/pdf
, ...) ou uniquement du top-level (eg. image
, video
, application
, ...)
Exemples :
file-document.upload.class.image: generated.Media file-document.upload.class.video: generated.Media file-document.upload.class.audio: generated.Media file-document.upload.class.application/pdf: generated.MyCustomDocumentType
Lorsque l'utilisateur dispose de plusieurs type de documents pour son dépôt et qu'il n'existe pas de mapping pour le contentType du fichier déposé, on se rabat sur le type de document par défaut à utiliser.
La définition du type de document à utiliser par défaut sur la plateforme se fait avec la propriété file-document.upload.class.default
Exemple :
file-document.upload.class.default: com.jalios.jcms.DBFileDocument
Le type Media dérive de DBFileDocument. Il dispose des champs supplémentaire suivans :
mediaWidth
mediaHeight
mediaDuration
Il est à noter que, bien que destiné au stockage des médias, rien n'empêche un contributeur d'utiliser le type Media pour d'autres types de documents.
L'interface de dépôt avancé ("Plus d'options") a été légèrement revue :
L'API FileDocument proposent de nouvelles méthodes statiques :
getUploadClass(String contentType)
renvoie la classe de dépôt à utiliser pour le contentType
donné ou null
.getDefaultUploadClass()
renvoie la classe de dépôt à utiliser par défautgetFirstDocumentClassAuthorized(Member, Workspace)
renvoie la première classe de FileDocument
que le membre donné peut utiliser dans le workspace
donné. Revient à appeler la méthode suivante avec un contentType
=null=getFirstDocumentClassAuthorized(Member, Workspace, String contentType)
renvoie la première classe de FileDocument
que le membre donné peut utiliser dans le workspace
donné, en commençant par la classe mappée dans les propriétés pour le contentType
donné. (Ex: si le contentType
est "image"
ou "image/png"
, on essaye en premier le type generated.Media
).De plus en plus de modules participent à la gestion des processus de l'organisation (JLearn, JProcess, Gestion des congés, Recrutement, ...)
Pour cela, ces modules ont besoins de connaitre la structure de l'organisation et la relation hiérarchique entre les membres (qui est responsable de qui). Il est notamment important de pouvoir déterminer les membres qui composent l'équipe d'un responsable.
Jusqu'à présent ces informations étaient portées par le module Organigramme (FlowChart). En conséquence plusieurs modules était donc dépendant de ce module pour pouvoir fonctionner.
JPlatform 10 lève cette contrainte en ré-introduisant dans le coeur une API de gestion de la structure de l'organisation.
L'article JPlatform 10 - API de gestion de l'organisation et des responsables de département présente en détail cette nouvelle API.
Dans un cluster JSync, seules les données du store (et éventuellement les fichiers associés) sont recopiés sur les différents réplicas du cluster. JcmsDB étant commune aux différents réplica, les données sont accessibles par tous les réplicas.
JPlatform 10 introduit une nouvelle API, les ReplicaMessage, qui permet aux réplicas de communiquer en dehors des échanges JSync. Le protocole utilisé garanti la distribution des messages dans l'ordre d'émission, même si un réplica n'est pas joignable lors de l'envoi.
JPlatform 10 utilise cette API pour propager les changements sur la structure des Workflows entre les réplicas.
Cette API pourrait aussi être utilisée plus tard pour propager les changement sur certaines propriétés de paramétrage.
L'article JPlatform 10 - L'API des ReplicaMessage présente cette API en détail.
JPlatform 10 permet de partager un contenu entre plusieurs espaces. Le guide JPlatform 10 - Partage de contenu entre espaces illustre cette nouvelle fonctionnalité.
Le partage de contenu entre espace est matérialisé par le nouveaux champ attachWorkspaceSet
sur la classe Publication. Pour les contenus stockés en base, un deuxième champ, hasAttachWorkspaceSet
, est stocké pour dénormaliser cette information et accélérer les requêtes.
class Publication { Set<Workspace> attachWorkspaceSet; boolean public boolean hasAttachWorkspaceSet() {...} }
Ces évolutions sur le modèle sont transparentes pour les données existantes
Il y a plusieurs modalité d'affichage d'un contenu :
L'affichage d'un contenu dépend donc de 2 paramètres : l'endroit d'où le contenu est accédé et qui y accède.
Soit trois espaces E1
, E2
et E3
Soit C
un contenu public de E1
qui est partagé dans E2
et E3
.
Soit M1
un membre appartenant à E1
, E2
et E3
Soit M2
un membre appartenant à E2
mais pas à E1
et E3
Soit M3
un membre appartenant à E3
mais pas à E1
et E2
Soit M2-3
un membre appartenant à E2
et E3
mais pas à E1
Cette matrice indique dans quel espace doit être affiché C
en fonction de qui fait l'accès et du lien avec lequel il est accédé :
Lien dans E1 |
Lien dans E2 |
Lien dans E3 |
Lien dans un autre espace | Lien externe | |
---|---|---|---|---|---|
M1 |
E1 |
E2 |
E3 |
E1 |
E1 |
M2 |
- | E2 |
- | E2 |
E2 |
M3 |
- | - | E3 |
E3 |
E3 |
M2-3 |
- | E2 |
E3 |
E2 ou E3 |
E2 ou E3 |
Soit C
un contenu appartenant à l'espace E1
Le contenu C
peut être partagé vers l'espace E2
par le membre M
si la condition suivante est vrai : M
est admin central OU (M
a accès à C
ET M
est contributeur dans E2
)
Dès qu'un partage a lieu, une alerte est envoyée à l'auteur de C
et à l'ensemble des admin de l'espace de C
indiquant qui a déclenché le partage (M
) et dans quel espace (E2
)
Un membre M
peut arrêter le partage du contenu C
dans l'espace E2
si la condition suivante est vraie : M
est admin central OU M
est l'auteur de C
OU M
est admin de E1
OU M
est admin de E2
OU M
est contributeur dans E2
La propriété publication.attach-ws.enabled
permet de désactiver complètement cette nouvelle fonctionnalité.
Il n'est alors plus possible de rattacher/détacher des publications à des espaces. Si des publications avaient préalablement été attachées, elles n'apparaitront plus dans les espaces de rattachement.
Classe Publication
Méthode | Description |
---|---|
canBeAttachedBy(Member) |
Retourne true si ce membre peut rattacher cette publication à un autre espace. |
canBeAttachedTo(Workspace, Member) |
Retourne true si ce membre peut rattacher cette publication à cet espace. |
canBeDetachFrom(Workspace, Member) |
Retourne true si ce membre peut détacher cette publication de cet espace. |
getAttachedWorkspaceSet() |
Retourne l'ensemble des espaces auxquels est rattaché cette publication. |
attachTo(Workspace, Set<Category>, Member mbr) |
Effectue le rattache de la publication dans l'espace donné avec les catégories données et pour le membre donné |
detachFrom(Workspace) |
Effectue le détacment de la publication de l'espace donné. |
Classe Channel
Méthode | Description |
---|---|
isWSAttachmentEnabled() |
Retourne true si le rattachement est autorisé. |
Classe PublicationCriteria
Méthode | Description |
---|---|
setSearchInAttachWS(boolean) |
Permet d'indiquer si la recherche doit porter dans les espaces de rattachement. |
Les API REST de JPlatform peuvent maintenant exporter leurs données au format JSON.
Pour utiliser cette fonctionnalité, il faut envoyer la requête REST avec un header Accept:application/json
.
Ex.
curl --header "Accept:application/json" https://<jplatform>/rest/WhoAmI
Exemple de retour :
{ "class": "com.jalios.jcms.Member", "id": "jn1_92854", "cdate": "2010-04-30T07:10:01Z", ... "login": "xxxxx", "name": "xxxxx", "firstName": "xxxx", "organization": "Jalios", "department": "R & D", "jobTitle": "Ingénieur R&D", "email": "xxxxxxxxxx@jalios.com", "mobile": "XX XX XX XX XX", ... "declaredGroups": [ { "class": "com.jalios.jcms.Group", "id": "jn1_339640", "name": "xxxxxx" }, { "class": "com.jalios.jcms.Group", "id": "jn1_103636", "name": "XXXXX" } ], "ldapSync": true, "lastLdapSynchro": "2017-10-09T20:00:00Z", "language": "en" }
La fonctionnalité des relateds (décrite dans la documentation Services Web RESTful avec JCMS Open API) est aussi applicable dans ce cas.
Par défaut la librairie d'export json exporte tout le contenu d'un objet et aussi le contenu des champs de l'objet. On peut donc avoir une quantité importante d'information voir une boucle infinie (exemple d'un membre appartenant à un groupe qu'il a créé). Un autre paramètre a donc été ajouté pour éviter ce problème, c'est la notion de profondeur (paramètre depth). L'export se fait en respectant la notion de profondeur n (par défaut 1) et affiche un résumé des éléments de profondeur n+1. Si cette donnée est une data, on affiche la class, l'id et le titre.
Note : Cela ne change pas le format de soumission des données (toujours au format form data)
Dans JPlatform 10 on peut donc utiliser tous les DataSelector
comme des prédicats Java 8.
L'interface DataSelector
dérive maintenant de Predicate<Data>
. La méthode héritée test()
a été implémentée avec une default method qui appelle la méthode isSelected()
Exemple : Récupération de l'ensemble des publications dont l'auteur est mbr
et dont la date de publication est comprise entre startDate
et endDate
.
Set<Data> set = channel.getDataSet(Publication.class) .stream() .filter( Data.getAuthorSelector(mbr) .and(Publication.getPdateSelector(startDate, endDate)) ) .collect(Collectors.toSet());
Afin de garantir un affichage court dans le menu des alertes de la topbar, les alertes dispose d'un attribut summary
. Cet attribut est optionnel et sera dans la plupart des cas vide.
Pour les alertes ayant une description avec beaucoup de texte il est recommandé de produire un résumé de quelques lignes.
Les résumé doivent être en HTML.
Il est possible de demander à afficher le résumé de la publication lorsqu'une alerte est envoyée via certaines propriétés.
Par exemple pour afficher l'abstract de la publication mentionnée lorsqu'une alerte de nouvelle mention est envoyée, il faut ajouter :
alert.channel.web.content.abstract.mention.notification: true // Pour les alertes web alert.channel.mail.content.abstract.mention.notification: true // Pour les alertes web
Ces deux propriétés correspondent à la déclaration d'alerte alert.name.mention.notification
Il est possible de forcer la non prise en compte dans l'activité d'une écriture à partir d'un formHandler
en positionnant l'attribut skipActivity
sur le formHandler
. Ceci est notamment mis en oeuvre lors des dépôts depuis le MediaBrowser.
L'entrée de contexte DataController.CTXT_IS_SILENT_WRITE
permet d'indiquer qu'il s'agit d'une écriture silencieuse. Elle est alors ignorée des PublicationFollower
et l'activité ESN.
Cette classe permet de récupérer les méta données d'un site distant en inspectant le code source (Les balises meta "og" sont privilégiées si disponibles).
Vous pouvez l'utiliser via le code suivant :
L'objet WebPageMetaData contient :
Javadoc :
Le générateur de type produit désormais des classes Java supportant l'évolution de schéma avec des type primitif sur les publications stockées en base.
Ainsi, si on ajoute un champ entier ou booléen sur un type de publication stocké en base, les anciennes valeurs seront automatiquement rechargées (et réenregistrés) avec la valeur par défaut du champ.
Il n'est donc plus nécessaire de passer des requêtes SQL pour les montées de version lorsqu'un champ primitif a été ajoutée à une type stocké en base.
Une rationalisation des JAR utilisés par la plateforme et ses modules a été effectuée (normalisation des versions de librairies, résolution des conflits entre modules, ...).
Une procédure automatique de recherche de vulnérabilité sur les JAR embarqués par JPlatform (et ses modules) a été mise en oeuvre et de nombreux jars ont été mis à jour avec les versions plus récentes non vulnérables.
Pour permettre des mises à jour plus fréquentes des librairies Java externes (jar
) et garantir une parfaite cohérence de ces librairies entre le coeur et tous les modules, Maven a été mis en oeuvre dans le système de build de JPlatform 10 (actuellement uniquement pour la gestion des dépendances entre le coeur et les modules).
Pour cela, un pom parent commun au coeur et à tous les modules a été créé, c'est lui qui assure la cohérence de version de toutes les librairies.
Une version publique de ce fichier pom.xml
est mis à disposition des intégrateurs et clients afin qu'ils puissent proposer des modules garantissant leur bonne intégration dans JPlatform (et ses modules) : JPlatform 10.0.0 - pom.xml
La librairie Lucene a été mise à jour vers la version 6.4.2.
Des configurations simplifiées et nouveaux hook pour développements spécifiques sont disponibles.
Les moteurs de recherche lucene des Publications, des Membres, ou des Catégories, peuvent désormais être personnalisés par simple configuration.
Configuration XML
L'initialisation de chaque moteur de recherche se fait à partir du premier fichier XML valide identifié, en privilégiant dans l'ordre :
WEB-INF/data/lucene-{Publication|Member|Category}.xml
: WEB-INF/jalios/lucene/lucene-{Publication|Member|Category}.xml
WEB-INF/jalios/lucene/lucene.xml
Le format de ce fichier XML est proche de celui du fichier schema.xml
de Apache SOLR, sans toutefois proposer les mêmes fonctionnalités.
Il permet de spécifier les classes lucene à utiliser et leur configuration :
Analyzer
pour les traitements d'analyse lors de l'indexation et de la recherche, comprenant :
CharFilter
Tokenizer
Filter
Similary
à utiliser pour le comportement de calcul de score lucenePour cela, le fichier utilise le format suivant :
<?xml version="1.0" encoding="UTF-8" ?> <lucene> <analyzer> <charFilter name="..." ... attribute1="value1" attribute2="value2"/> <tokenizer name="..." /> <filter name="..." /> </analyzer> <similarity class="..."/> </lucene>
Les CharFilter
, Tokenizer
et Filter
sont chargés grâce à la classe CustomAnalyzer
name
CharFilter
: htmlstrip, mapping, persian, patternreplaceTokenizer
: keyword, letter, lowercase, whitespace, edgengram, ngram, pathhierarchy, pattern, classic, standard, uax29urlemail, wikipediaTokenFilters
: apostrophe, decimaldigit, lowercase, stop, type, uppercase, englishminimalstem, englishpossessive, porterstem, frenchlightstem, frenchminimalstem, asciifolding, capitalization, codepointcount, daterecognizer, fingerprint, hyphenatedwords, keepword, keywordmarker, keywordrepeat, length, limittokencount, limittokenoffset, limittokenposition, removeduplicates, stemmeroverride, trim, truncate, worddelimiter, edgengram, ngram, patternreplace, patterncapturegroup, reversestring, shingle, snowballporter, classic, standard, synonym, elision, suggeststopFactory
permettant de les créer, avec l'attribut class
,WEB-INF/
de la webappLa Similarity
à utiliser peut être renseignée en spécifiant le FQDN de la classe dans l'attribut class
.
Consultez les fichiers WEB-INF/jalios/lucene/lucene.xml
et WEB-INF/jalios/lucene/lucene-Member.xml
fournis en standard pour 2 exemples de configuration.
Notez également l'existence de la classe LoggingFilterFactory pouvant être utilisée pour diagnostiquer le processus d'analyse en activant les logs de niveau TRACE
sur la classe com.jalios.jcms.search.analysis.LoggingFilter
(dans la configuration log4j).
Exemple :
<?xml version="1.0" encoding="UTF-8" ?> <lucene> <analyzer> <tokenizer name="classic" maxTokenLength="255"/> <filter class="com.jalios.jcms.search.analysis.LoggingFilterFactory" prefix="in" /> <filter name="lowercase" /> <filter class="com.jalios.jcms.search.analysis.LoggingFilterFactory" prefix=" after lowercase" /> <filter name="classic" /> <filter class="com.jalios.jcms.search.analysis.LoggingFilterFactory" prefix=" after classic" /> </analyzer> <similarity class="org.apache.lucene.search.similarities.BM25Similarity"/> </lucene>
Propriétés de configuration
Des nouvelles propriétés permettent de configurer le nombre maximum de résultat récupérés par lucene à chaque requete :
query.lucene.mbr.max-results: 2000 query.lucene.cat.max-results: 100 query.lucene.pub.max-results: 100 query.lucene.archive.max-results: 100
Recherche
Une nouvelle méthode LuceneSearchEnginePolicyFilter#parseQuery(String, ParseOptions, Analyzer, Query)
permet d'intervenir lors de chaque recherche utilisateur pour construire l'objet lucene Query
.
Ce hook remplace custom.LuceneSearchEnginePolicy.parse(String, ParseOptions, Analyzer)
et les méthodes associées.
En l'absence de développement spécifique, le traitement est assuré par la classe com.jalios.jcms.search.queryparser.DefaultQueryParser.parse(String, ParseOptions, Analyzer)
Migration
Les développements précédement effectués dans LuceneSearchEnginePolicy
doivent être adaptés
custom.LuceneSearchEnginePolicy.CustomAnalyzer
pour personnaliser les Tokenizer
et TokenFilter
se font désormais par configuration XML comme évoqué ci-dessusISOLatin1AccentFilter
a été remplacée par l'utilisation du MappingCharFilter avec le fichier texte WEB-INF/jalios/lucene/mapping-FoldToASCII.txt
fourni en standardApostropheFilter
a été remplacé par l'utilisation du ElisionFilter avec le fichier WEB-INF/jalios/lucene/french-articles.txt
fourni en standardDashFilter
et UnderscoreFilter
ont été remplacé par le développement d'un Tokenizer
spécifique à Jcms : le JcmsTokenizer.ContextualStopFilterFactory
permet d'appliquer des StopFilter
en utilisant la langue courante d'analyse (que ça soit pour l'indexation ou la recherche).LuceneSearchEnginePolicy.parse
) doivent être migrés vers une LuceneSearchEnginePolicyFilter.parseQueryJusqu'à JCMS 9 les différents états d'un module étaient :
Avec JPlatform 10 les états d'un module sont :
Idem chargé mais le module n'est pas désactivé
L'activation ou la désactivation de module est matérialisée par une propriété de la forme :
plugin.<PLUGIN_NAME>.enabled: true/false
Exemple :
plugin.JReadingPlugin.enabled: false plugin.JTaskPlugin.enabled: true
Si la propriété est absente pour un module, le module est considéré comme activé.
Les composants représente l'ensemble des points de débranchement que peut fournir un module :
Par extension on inclus aussi dans les composants
Ces composants sont branchés au démarrage de JPlatform pour tous les modules actifs.
Lorsqu'un module est activé à chaud, la méthode ChannelListener.initAfterStoreLoad() est appelé pour chacun de ses ChannelListeners.
Note : les resources Open API ne seront activées/désactivées à chaud qu'à partir de JPlatform 10 SP1 ou avec l'application du patch https://issues.jalios.com/browse/JCMS-6227
Les propriétés d'un module ne sont chargés que si le module est actif à l'exception des propriétés de langues qui sont chargé même si le module est inactif.
A l'activation et à la désactivation d'un module on appelle donc, comme lors du démarrage, la méthode Channel.reloadProperties(
) qui rejoue l'ensemble des propriétés
Jusqu'à JCMS 9, les types livrés par un module n'était pas différentié des types du coeur ou de l'application.
A partir de JPlatform 10, pour chaque type on peut connaitre le module qui l'a livré. L'information est accessible par la méthode TypeEntry.getPlugin()
.
Tous les types sont chargés ; même ceux des modules inactifs ou arrêtés. Cependant, seuls les types du coeur, de la webapp ou des modules actifs sont affichés dans les différentes interfaces.
Jusqu'à JCMS 9, les workflows livrés par un module n'était pas différentié de ceux du coeur ou de l'application.
A partir de JPlatform 10, pour chaque workflow on peut connaitre le module qui l'a livré. L'information est accessible par la méthode Workflow.getPlugin()
.
Tous les workflows sont chargés ; même ceux des modules inactifs ou arrêtés. Cependant, seuls les workflows du coeur, de la webapp ou des modules actifs sont affichés dans les différentes interfaces.
Les shortcuts sont des contenus qui sont créé au démarrage de JCMS par analyse des propriétés de modules.
La génération des shortcuts se basant sur les propriétés, si un module est inactifs, ses propriétés n'étant pas chargés, les éventuels shortcuts ne seront pas générés.
Lorsqu'on active un module à chaud, le ShortcutManager
est appelé pour générés les éventuels shortcut associés.
Lorsqu'un module est désactivé, le ShortcutManager
est appelé pour supprimer les éventuels shortcut associés.
Lors de l'activation ou la désactivation d'un module les données en cache peuvent devenir invalide. Aussi, à chaque activation/désactivation de module on supprime l'ensemble des entrées du CacheManager.
A partir de JPlatform 10 SP1, la gestion des dépendances est enrichi pour permettre d'avoir des dépendance sur des modules actifs (par défaut) ou désactivé. Pour chaque dépendance il est possible de préciser avec l'attribut active
que l'on dépend d'un module mais sans qu'il soit forcement actif (active="false"). Si l'attribut n'est pas renseigné alors c'est comme si il était à true
.
Exemple :
<dependencies> <dependency name="Plugin1" /> <!-- Same as active="true" --> <dependency name="Plugin2" active="true" /> <dependency name="Plugin3" active="false" /> </dependencies>
Afin d'empêcher l'accès aux JSP d'un module désactivé, on contrôle :
Le contrôle est réalisé par la ServletFilter PluginAccessFilter
avec le mapping =/plugin/*=
Les JSP livré en dehors du répertoire plugin/NomDuPlugin/
ne sont pas contrôlées.
JSync
L'activation et la désactivation d'un module nécessite de mettre à jour une propriété. Par ailleurs le module durant son activation peu lui aussi générés des propriétés (eg virtual id d'un shortcut ou de données produites par un ChannelListener).
JSync n'offrant pas de support à la réplication des propriétés, si un module est activé sur un noeud il ne le serait pas sur les autres noeuds.
L'activation ou la désactivation d'un module sur un cluster JSync nécessite donc de l'activé sur le leader puis de recopier les propriétés générés sur l'ensemble des noeud du cluster.
ChannelListener::initBeforeStoreLoad()
Lors de l'activation d'un module à chaud la méthode ChannelListener::initBeforeStoreLoad() n'est pas appelée. Si elle doit être appelé alors il faut redémarrer JCMS une fois le module activé.
webapp-files
Si un module livre des webapp-files (p. ex. des patches) alors il ne seront pas désactivés
ServletFilter
L'activation/désactivation des modules ne prend pas en charge la déclaration des Servlet et ServletFilter. De même si un module est désactivé, cela ne désactive pas ses éventuelles ServletFilter. Le cas échéant, c'est au développeur de faire les contrôle d'activité du module dans les ServletFilter.
Un nouveau mode d'authentification a été ajouté à JPlatform. Il s'agit de l'authentification par certificat SSL client.
Dans le cadre d'une communication SSL, si le client envoit un certificat valide, enfant direct d'une authorité référencé dans JPlatform et contenant le sujet adéquat, il sera alors authentifier sans avoir à fournir de mot de passe.
La description et l'installation de cette fonctionnalité est disponible dans la fiche Authentification par certificat client.
Le compilateur LESS embarqué dans JPlatform 10 utilise une nouvelle librairie : less4j. Cette librairie gère des syntaxes LESS qui n'étaient pas supportées avec l'ancienne librairie (lesscss-engine).
Une nouvelle propriété a été ajoutée dans jcms.prop
pour permettre la génération des fichiers sourcemap
associés aux fichiers CSS générés : channel.less-compile.sourcemap
. Pour activer la génération des fichiers sourcemap
, il faut passer cette propriété à true
.