9 nov. 2021 15:25:34 Thomas Dumont avatar

Créer un nouveau type de Portlet

Les pages de Lutèce sont composées de portlets. Il est possible de définir de nouveaux types de portlets qui seront alors disponibles pour la composition des pages et permettront d'ajouter de nouvelles fonctions. Les nouveaux portlets doivent être "packagés", avec leurs éventuelles fonctions d'administration associées, sous la forme de Plugins.

Ce document a pour but de décrire les étapes du processus de création d'un nouveau type de portlet. Les modifications à prévoir concernent l'ensemble de l'application; java, base de données, templates html, xsl, jsp.

On adoptera par convention dans l’ensemble du document la notation <type> pour indiquer le nom du nouveau type de portlet.

Les classes à définir en JAVA

En java, l'ajout d'un nouveau type de portlet implique la création de trois classes métiers : Portlet.java,PortletHome.java, PortletDAO.java appartenant au package fr.paris.lutece.portal.business.portlet et un bean servant à l'affichage Web : PortletJspBean.java appartenant au package fr.paris.lutece.plugins.<myplugin>.web.portlet dont suit le descriptif :

<type>Portlet.java

Elle doit dériver de la classe abstraite : Portlet qui elle-même implémente l'interface : XmlContent (package fr.paris.lutece.plugins.<myplugin>.business ).

Déclaration :
public class Portlet extends Portlet

Cet héritage impose à la classe <type>Portlet l'implémentation de deux méthodes :

  • public String getXml();
  • public String getXmlDocument(); qui retournent le contenu du portlet au format xml.

De même, elle hérite des accesseurs (méthodes set et get) sur les propriétés caractérisant un portlet regroupés dans la classe Portlet ainsi que des constantes (tags) définis dans l'interface XmlContent .

Enfin, il faut également prévoir deux autres méthodes nécessaires pour la mise à jour du portlet :

  • public void update()
  • public void remove() qui appellent les méthodes de mise à jour de la classe DAO associée ainsi que les différents accesseurs qui caractérisent le nouveau type de portlet.

<type>PortletHome.java

Elle doit dériver de la classe abstraite : PortletHome qui elle-même implémente l'interface PortletHomeInterface .

Déclaration :
public class MyPortletHome extends PortletHome

Elle doit donc implémenter les deux méthodes :

  • public InterfaceDAO getDAO() : renvoie l'instance unique de la classe PortletDAO décrite ci-dessous
  • public int getPortletTypeId() : renvoie l'identifiant du type de portlet stocké dans la base

Celle classe devant fonctionner comme un singleton, la méthode :

  • public static PortletHome getInstance() est nécessaire pour accéder à l’instance unique.

<type>PortletDAO.java

Elle doit implémenter l'interface : I<type>PortletDAO .

Déclaration :
public class PortletDAO implements I<type>PortletDAO

Elle doit donc implémenter les méthodes suivantes d'accès aux données :

  • public void insert( Portlet portlet ) throws AppException;
  • public void delete( int nPortletId ) throws AppException;
  • public void store( Portlet portlet ) throws AppException;
  • public Portlet load( int nPortletId ) throws AppException;

Outre ces méthodes indispensables, le développeur est libre d'ajouter dans cette classe autant de méthodes d'accès aux données qu'il désire et qui lui sont nécessaires pour la gestion du nouveau portlet.

<type>PortletJspBean.java

Elle doit dériver de la classe : PortletJspBean qui elle-même implémente l’interface PortletJspBeanInterface .

Déclaration :
public class PortletJspBean extends PortletJspBean

Ceci implique l'implémentation des méthodes suivantes pour la gestion des formulaires de saisie d'un portlet :

  • public String getCreate( HttpServletRequest request ); : Affichage du formulaire de création du portlet
  • public String doCreate( HttpServletRequest request ); : Traitement de création du portlet
  • public String getModify( HttpServletRequest request ); : Affichage du formulaire de modification du portlet
  • public String doModify( HttpServletRequest request ); : Traitement de modification du portlet (doit appeler la méthode update de la classe <type>Portlet)
  • public String getPropertiesPrefix(); : Renvoie le préfixe des propriétés du portlet définies dans le fichier de configuration lutece.properties

Ces différentes méthodes seront appelées par les jsp en charge de la création et de la modification d'un portlet. Ces dernières sont décrites ci-dessous.

De plus, <type>PortletJspBean hérite des nombreuses méthodes de la classe PortletJspBean permettant de récupérer des propriétés sur les formulaires à afficher.

Enfin, cette classe peut accueillir la définition d'autres méthodes nécessaires à des portlets qui ont besoin de traitements supplémentaires (par exemple, le traitement de l'enregistrement d'un fichier dans un portlet de type Téléchargement : DownloadFilePortlet).

Il est à noter que le traitement de la suppression d’un nouveau portlet n’a pas besoin d’être géré par le développeur car cela est pris en charge par le bean AdminJspBean qui appelle la méthode delete redéfinit dans <type>Portlet .

Le traitement est donc analogue quelque soit le type de portlet.

JSP

Les jsp indispensables à la gestion du nouveau portlet sont au nombre de 4 :

  • CreatePortlet<type>.jsp
  • DoCreatePortlet<type>.jsp
  • ModifyPortlet<type>.jsp
  • DoModifyPortlet<type>.jsp

Ils font appel aux méthodes de la classe <type>PortletJspBean décrites précédemment :

JSPMéthode de la classe <type>PortletJspBean
CreatePortlet<type>.jsppublic String getCreate( HttpServletRequest request )
DoCreatePortlet<type>.jsppublic String doCreate( HttpServletRequest request );
ModifyPortlet<type>.jsppublic String getModify( HttpServletRequest request );
DoModifyPortlet<type>.jsppublic String doModify( HttpServletRequest request );

Ces JSP doivent également gérer l'authentification de l'administration.

Exemple de JSP d'affichage : CreatePortlet<Type>.jsp

<%@ include file="../PluginAdminHeader.jsp" %>
<jsp:useBean id="<type>Portlet" scope="session" class="fr.paris.lutece.portal.web.portlet.Portlet<Type>JspBean" />
<jsp:useBean id="user" scope="session" class="fr.paris.lutece.portal.web.user.UserJspBean" />
<%
if( user.check( "DEF_ADMIN" ) )
{
%>
<%= <type>Portlet.getCreate( request ); >
<%
}
else
{
     response.sendRedirect( user.getUrlAccesRefuse() );
}
%>
<%@ include file="../../AdminFooter.jsp" %>

Exemple de JSP de traitement : DoCreatePortlet<Type>.jsp

<%@ include file="../PluginAdminHeader.jsp" %>
<jsp:useBean id="<type>Portlet" scope="session" class="mdp.portail.web.rubrique.Portlet<Type>JspBean" />
<jsp:useBean id="user" scope="session" class="mdp.portail.web.user.UserJspBean" />
<%
if( user.check( "DEF_ADMIN" ) )
{
     response.sendRedirect( <type>Portlet.doCreate( request ) );
}
else
{
     response.sendRedirect( user.getAccessDeniedUrl() );
}
%>
<%@ include file="../../AdminFooter.jsp" %>

Les autres fichiers

Feuilles de style XSL

Plusieurs feuilles de style sont à développer pour la gestion de l'affichage du nouveau type de portlet.

Une première catégorie concerne l’affichage du portlet sur le site. Par convention, son nom est :

  • portlet_<type>_<suffixe>.xsl où <suffixe> caractérise la spécification de la feuille de style (par exemple : portlet_html_no_title.xsl).

La seconde catégorie sert à afficher le portlet en mode administration du site. Il faut que chaque feuille de style de la première catégorie ait une feuille de style correspondante dans l'administration. En effet, cette feuille de style est utilisée pour la prévisualisation de la rubrique dans le module d'administration. Par convention, son nom est portlet_<type>_<suffixe>_adm.xsl .
C’est une copie de portlet_<type>_<suffixe>.xsl à laquelle il faut rajouter les boutons ‘Modifier cette rubrique’, ‘Supprimer cette rubrique’.

Toutes ces feuilles de style devront être stockées en base depuis l'interface d'administration (cf paragraphe Base de données)

Templates HTML

Les formulaires HTML de saisie d’un nouveau portlet et de modification sont découpés en plusieurs fichiers :

  • create_portlet.html et modify_portlet.html : contiennent respectivement le code commun aux formulaires de saisie et de modification des différentes portlets
  • des templates propres au portlet concerné qui viennent compléter le formulaire de saisie en ajoutant des champs et des traitements javascript qui leur sont spécifiques.

Ces templates sont à rajouter pour chaque nouveau type de portlet dans le répertoire WEB-INF/templates/admin/plugins/<type>/ et doivent être spécifié dans le fichier properties du plugin :

PropriétéDescription
portlet.<type>.create.titleTitre du formulaire d'ajout de rubrique du type <type>
portlet.<type>.create.urlUrl de la jsp qui prend en charge l'ajout d'une rubrique de type <type>
portlet.<type>.create.scriptScript javascript spécifique au formulaire d'ajout de rubrique de type <type>.
portlet.<type>.create.specificNom du fichier de template qui contient du code spécifique pour le type de rubrique <type>
portlet.<type>.create.specificformNom du fichier de template qui contient le code d'un autre formulaire à accoler au formulaire d'ajout de rubrique de type <type>..
portlet.<type>.modify.titleTitre du formulaire de modification de rubrique du type <type>
portlet.<type>.modify.url Url de la jsp qui prend en charge la modification d'une rubrique de type <type>
portlet.<type>.modify.scriptScript javascript spécifique au formulaire de modification de rubrique de type <type>.
portlet.<type>.modify.specificNom du fichier de template qui contient du code spécifique pour le type de rubrique <type>
portlet.<type>.modify.specificformNom du fichier de template qui contient le code d'un autre formulaire à accoler au formulaire de modification de rubrique de type <type>..

Seules les propriétés portlet.<type>.create.title , portlet.<type>.create.url , portlet.<type>.modify.title et portlet.<type>.modify.url sont obligatoires.

Néanmoins il est à noter que la méthode Submit() en javascript doit être définie car elle est appelée sur validation du formulaire.

Pour cela, le développeur peut procéder ainsi :

  • soit utiliser les scripts standards utilisés par la plupart des rubriques : script_create_portlet.html et script_modify_portlet.html (dans le répertoire WEB-INF/templates/admin/portlet/)
  • soit définir la méthode dans le formulaire spécifique (à l'instar de la rubrique html).

Base de données

Les modifications dans la base de données concernent 4 tables :

Table portlet_type :

Nom du champDescription
id_portlet_typeIdentifiant du type de portlet.
nameLibellé du type de portlet(c'est ce libellé qui apparaîtra dans les listes déroulantes)
url_creationUrl de la JSP qui affiche le formulaire de saisie du portlet
url_updateUrl de la JSP qui affiche le formulaire de modification du portlet
home_classNom complet (package compris) de la classe <type>PortletHome du nouveau type de rubrique

Exemple d'enregistrement : Rubrique HTML

id_portlet_typenameurl_creationurl_updatehome_class
EXEMPLE_TYPEClef i18nCreatePortletHtml.jspModifyPortletHtml.jspfr.paris.lutece.plugins.html.business.portlet.HtmlPortletHome

Ces données sont initialisées dans la base à l'installation du plugin.

Le fichier de configuration du plugin devra donc contenir ces informations sous la forme

<portlet>
    <portlet-class>fr.paris.lutece.plugins.myportlet.business.portlet.MyPortletHome</portlet-class>
    <portlet-type-name>MyNew Portlet</portlet-type-name>
    <portlet-creation-url>plugins/article/CreatePortletMyPortlet.jsp</portlet-creation-url>
    <portlet-update-url>plugins/article/ModifyPortletMyPortlet.jsp</portlet-update-url>
</portlet>

Table style :

Il faut définir les styles associés à ce nouveau style de rubrique. Pour cela, il faut utiliser l'interface d'administration de Lutèce : Gestion des Styles .

Tables stylesheet et style_mode_stylesheet : L'interface d'administration de Lutèce : Gestion des feuilles de style xsl permet de définir de nouvelles feuilles de style et de les associer aux styles stockés dans la base.Toutes les feuilles de style développées conformément au paragraphe : Feuilles de style XSL) devront être sauvegardés dans la base via cette interface.