MVC Library

Introduction

La bibliothèque library-mvc est disponible pour développer des XPages en utilisant le paradigme MVC à partir de la version 4.1 de Lutece

Cette bibliothèque propose :

  • Le dispatching des requêtes par le contrôleur pour traitement des actions et affichage des vues
  • L’identification des actions et des vues par annotations,
  • La population et la validation des beans (JSR 303)
  • La gestion des erreurs de validation directement incluse dans le modèle du template (marker « errors »)
  • La gestion des notifications ou messages informatifs incluse dans le modèle du template (marker « infos »)
  • La redirection HTTP des requêtes vers des vues évitant le recours à des JSP

Liens vers exemples de code et démo en ligne disponibles à la fin du document.

Principe de mise en oeuvre du modèle MVC

La library MVC propose une implémentation MVCApplication de l'interface XPageApplication offrant des mécanismes permettant de découper les fonctions selon le pattern Modèle-Vue-Controleur dont voici le schéma :

Le point d'entrée de la XPage joue le rôle de contrôleur. C'est la classe MVCApplication qui prend en charge cette fonction en implémentant la méthode getPage de l'interface.

Les actions et les vues sont désignées par des annotations @Action et @View.

Le contrôleur dispatche les traitements sur les méthodes annotées en fonction des paramètres de la request.

L'annotation @Controller à définir sur la classe dérivée de MVCApplication sert à définir des paramètres de la classe.

La page d'accueil de la XPage doit positionner le paramètre defaultView de l'annotation @View à true.

Exemple de code

Voici le code d'une XPage proposant 2 vues :

  • la page d'accueil affichant une liste de contacts
  • la page de création d'un contact

ainsi que 2 actions :

  • créer un contact
  • supprimer un contact
@Controller( xpageName = "mvcdemo" , pageTitle = "mvcdemo.pageTitle" , pagePath = "mvcdemo.pagePathLabel" )
public class MVCDemoApp extends MVCApplication
{
 
    private static final String TEMPLATE_HOME = "/skin/plugins/mvcdemo/home.html";
    private static final String TEMPLATE_FORM = "/skin/plugins/mvcdemo/form.html";
    private static final String VIEW_HOME = "home";
    private static final String VIEW_ADD_CONTACT = "addContact";
    private static final String ACTION_ADD_CONTACT = "addContact";
    private static final String ACTION_REMOVE_CONTACT = "removeContact";
    private static final String MARK_CONTACTS_LIST = "contacts_list";
    private static final String PARAMETER_ID = "id";
     
     
    @View( value = VIEW_HOME , defaultView = true )
    public XPage viewHome(HttpServletRequest request)
    {
        Map<String,Object> model = getModel();
        model.put( MARK_CONTACTS_LIST , ContactService.getContacts() );
        return getXPage( TEMPLATE_HOME, request.getLocale(  ) , model );
    }
 
    @View( VIEW_ADD_CONTACT )
    public XPage viewAddContact(HttpServletRequest request)
    {
        return getXPage( TEMPLATE_FORM, request.getLocale(  ) );
    }
     
    @Action( ACTION_ADD_CONTACT )
    public XPage addContact(HttpServletRequest request)
    {
        Contact contact = new Contact();
        populate(contact, request);
 
        if ( !validateBean(contact))
        {
            return redirectView( request , VIEW_ADD_CONTACT );
        }
        ContactService.addContact(contact);
        return redirectView( request , VIEW_HOME );
    }
     
    @Action( ACTION_REMOVE_CONTACT )
    public XPage removeContact(HttpServletRequest request)
    {
        String strContact = request.getParameter( PARAMETER_ID );
        ContactService.removeContact( strContact );
        return redirectView( request , VIEW_HOME );
    }                    

Le code source complet de cet exemple est disponible sur le SVN à l'adresse /sandbox/plugin-mvcdemo et consultable à l'adresse http://dev.lutece.paris.fr/viewvc/lutece/sandbox/plugin-mvcdemo/

L'application en action est visible à cette adresse : http://dev.lutece.paris.fr/incubator/jsp/site/Portal.jsp?page=mvcdemo

Le plugin PluginWizard a été réécrit en version 3.1 avec cette library et constitue un exemple avancé de son utilisation.