Alfresco – Erreur sur le webscript membership.js

logo Alfresco
Version Enterprise 3.4.2

I. Problème

Lorsque l’on définit de nouveau rôles dans la gestion de ses permissions il est fréquent d’observer ce genre de traces dans les log d’Alfresco. Ce n’est à priori pas bloquant mais à répétition on perd de la visibilité dans les logs.

ERROR [org.springframework.extensions.webscripts.AbstractRuntime] Exception from executeScript - redirecting to status template error: 03270128 Wrapped Exception (with status template): 03270625 Failed to execute script 'classpath*:alfresco/templates/webscripts/org/alfresco/repository/site/membership/membership.get.js': null
org.springframework.extensions.webscripts.WebScriptException: 03270128 Wrapped Exception (with status template): 03270625 Failed to execute script 'classpath*:alfresco/templates/webscripts/org/alfresco/repository/site/membership/membership.get.js': null
...
Caused by: java.lang.NullPointerException
at org.alfresco.repo.site.RoleComparatorImpl.compare(RoleComparatorImpl.java:39)
at org.alfresco.repo.site.RoleComparatorImpl.compare(RoleComparatorImpl.java:24)
at java.util.TreeMap.put(TreeMap.java:530)
at java.util.TreeSet.add(TreeSet.java:238)
at org.alfresco.repo.site.SiteServiceImpl.getMembersRole(SiteServiceImpl.java:1316)
at org.alfresco.repo.site.script.Site.getMembersRole(Site.java:334)
at sun.reflect.GeneratedMethodAccessor648.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.mozilla.javascript.MemberBox.invoke(MemberBox.java:155)
at org.mozilla.javascript.NativeJavaMethod.call(NativeJavaMethod.java:243)
at org.mozilla.javascript.optimizer.OptRuntime.call1(OptRuntime.java:66)
at org.mozilla.javascript.gen.c36._c1(file:/C:/TomcatAlf/webapps/alfresco/WEB-INF/classes/alfresco/templates/webscripts/org/alfresco/repository/site/membership/membership.get.js:40)
at org.mozilla.javascript.gen.c36.call(file:/C:/TomcatAlf/webapps/alfresco/WEB-INF/classes/alfresco/templates/webscripts/org/alfresco/repository/site/membership/membership.get.js)
at org.mozilla.javascript.optimizer.OptRuntime.callName0(OptRuntime.java:108)
at org.mozilla.javascript.gen.c36._c0(file:/C:/TomcatAlf/webapps/alfresco/WEB-INF/classes/alfresco/templates/webscripts/org/alfresco/repository/site/membership/membership.get.js:54)
at org.mozilla.javascript.gen.c36.call(file:/C:/TomcatAlf/webapps/alfresco/WEB-INF/classes/alfresco/templates/webscripts/org/alfresco/repository/site/membership/membership.get.js)

II. Solution

L’erreur vient de la classe RoleComparatorImpl, la map rolePrecedence n’est pas peuplée avec les nouveaux rôles et donc getRolePrecedence().get(first); peut retourner null. Cette map est peuplée par Spring via le fichier de configuration site-services-context.xml, il faut donc y ajouter les nouveaux rôles:

<!--  Site role precedence - higher number - more important role -->
<bean id="siteRoleComparator" class="org.alfresco.repo.site.RoleComparatorImpl" init-method="init">
 <property name="rolePrecedence">
  <map>
   <entry key="MonRole" value="5" />
   <entry key="SiteManager" value="4" />
   <entry key="SiteCollaborator" value="3" />
   <entry key="SiteContributor" value="2" />
   <entry key="SiteConsumer" value="1" />
  </map>
 </property>
</bean>

A vous de jouer !

Alfresco – Affichage de la document library avec getChildren()

logo Alfresco
Version Enterprise 3.4.2
Source de cet article: Jeff Potts

I. Problème

Lorsqu’il y a une volumétrie trop grande d’Alfresco on peut observer un dégradation des temps d’affichage de la document library (et ses sous espaces) des sites Share. Dans notre cas nous gérons plus de 1000 sites, plus de 2.000.000 de documents pour un peu plus d’1To et l’affichage de la document library prend en moyenne un bonne dizaine de secondes.

En cherchant un peu sur les différentes communautés je suis tombé sur un article (http://ecmarchitect.com/archives/2011/04/13/1331) de Jeff Potts (en personne !) qui correspond exactement au problème observé.

II. Solution

Comme l’explique Jeff la solution proposée se contente de résoudre le problème de temps de réponse sans vraiment identifier (ni expliquer) sa cause réelle.

L’affichage de la document library est en partie pilotée par le webscript doclist.get.js (webscripts\org\alfresco\slingshot\documentlibrary) d’Alfresco et c’est ici, pendant la requête de récupération des nœuds correspondant à un filtre, que l’on peut observer 90% du temps de traitement de l’affichage.

Voici le bout de code en question :

// Query the nodes - passing in sort and result limit parameters
if (query !== "")
{
allNodes = search.query(
{
query: query,
language: filterParams.language,
page:
{
maxItems: (filterParams.limitResults ? parseInt(filterParams.limitResults, 10) : 0)
},
sort: filterParams.sort,
templates: filterParams.templates,
namespace: (filterParams.namespace ? filterParams.namespace : null)
});
}

Afin d’améliorer les temps de réponse dans la navigation de la document library, il faut se concentrer sur le filtre path. Dans ce cas précis on récupère le nœud correspondant au chemin puis grâce à la méthode getChildren() on récupère tous les nœuds enfants (dans les autres cas on laisse le comportement par défaut):

// if filter is on PATH we use getChildren method
// else we use the default behaviour for filters
if(filter.indexOf("path") > -1)
{
if (parsedArgs.path == "")
{
parentNode = parsedArgs.rootNode;
}
else
{
parentNode = parsedArgs.rootNode.childByNamePath(parsedArgs.path);
}
allNodes = parentNode.getChildren();
}
else
{
// Query the nodes - passing in sort and result limit parameters
if (query !== "")
{
allNodes = search.query(
{
query: query,
language: filterParams.language,
page:
{
maxItems: (filterParams.limitResults ? parseInt(filterParams.limitResults, 10) : 0)
},
sort: filterParams.sort,
templates: filterParams.templates,
namespace: (filterParams.namespace ? filterParams.namespace : null)
});
}
}

Avec cette modification du webscript doclist.get.js le temps d’affichage de la document library est passé d’une dizaine de seconde à moins d’une seconde !!

A vous de jouer !

Alfresco – Désactiver le SWF Preview

logo Alfresco
Version Enterprise 3.4.2

I. Problème

La prévisualisation des documents dans Share engendre un certains nombre de problèmes. Lorsque l’on affiche les détails d’un document la prévisualisation est demandée (de manière asynchrone) et il arrive que le thread qui gère cette action ne se termine jamais. En plus d’être un “mort-vivant” ce thread maintient un verrou sur le nœud correspondant au document, il est alors impossible y accéder en écriture.

De plus des soucis de performances (charge CPU) ont été remontés à Alfresco (voir ALF-10412)

Si la prévisualisation n’est pas essentielle à l’utilisation de votre gestion documentaire il est alors conseillé de la désactiver.

II. Solution

Ajouter cette configuration dans le fichier share-config-custom.xml
<config evaluator="string-compare" condition="DocumentDetails" replace="true">
 <document-details>
  <!-- display web previewer on document details page -->
  <display-web-preview>false</display-web-preview>
 </document-details>
</config>

A vous de jouer !

Alfresco – Créer un tableau de bord statique

logo Alfresco
Version Enterprise 3.4.2

I. Besoin

Le besoin est de mettre en place un tableau de bord utilisateur (et/ou site) unique (donc identique pour tous) et de pouvoir le mettre à jour facilement.

II. Problème

Une réponse simple à notre besoin est de configurer le fichier preset.xml qui définit les éléments par défaut qui seront instanciés sur le tableau de bord utilisateur puis de limiter l’accès à l’action de personnalisation.

Cette réponse n’est pas complète car le tableau de bord par défaut, défini dans preset.xml, est pris en compte uniquement pour les nouveaux utilisateurs ou nouveaux sites. Cette solution ne s’applique donc qu’au démarrage du projet. De plus, il sera compliqué d’ajouter un dashlet ou tout autre affichage sur TOUS les tableaux de bord à l’avenir.

Il existe tout de même des solutions, je vous invite à consulter un très bon article à cette adresse : http://charles.torda.net/2012/01/01/souhaitez-une-bonne-annee-a-vos-utilisateurs-12/

III. Solution

Modifier le tableau de bord

La solution est de modifier directement le template dashboard.ftl qui affiche de tableau de bord.

  • Copier le template vers web-extension/templates/org/alfresco/
  • Remplacer la ligne <@layout.grid gridColumns gridClass "component" /> par ce que vous souhaitez afficher sur le tableau de bord.

Différencier les tableaux de bord de sites et d’utilisateurs

Pour différencier l’affichage des deux tableaux de bord il suffit d’utiliser <#if page.url.templateArgs.site??>
Si par exemple on souhaite uniquement que le tableau de bord utilisateur soit statique :

<#if page.url.templateArgs.site??>
<@layout.grid gridColumns gridClass "component" />
<#else>
Le code de mon tableau de bord utilisateur statique
</#if>

Cacher le bouton qui permet de personnaliser le tableau de bord

Il suffit de commenter le bout de code qui affiche le bouton de configuration des tableaux de bord (ou d’ajouter une clause qui afficherait le bouton aux administrateurs) et de bloquer l’accès aux pages de personnalisation en posant une restriction.

site-webscript/org/alfresco/components/title/user-dashboard-title.get.html.ftl
<!--span>
<span>
<a href="${url.context}/page/customise-user-dashboard"
${linkClass}>${msg("link.customiseDashboard")}</a>
</span>
</span-->

site-data/pages/customise-user-dashboard.xml

<authentication>admin</authentication>

site-webscript/org/alfresco/components/title/collaboration-title.get.html.ftl
<!--span>
<span>
<a href="${url.context}/page/site/${page.url.templateArgs.site!}/customise-site-dashboard"
${linkClass}>${msg("link.customiseDashboard")}</a>
</span>
</span-->

site-data/pages/customise-site-dashboard.xml

<authentication>admin</authentication>

Afficher des dashlets

Il serait quand même plus propre d’utiliser des dashlets que du code non ?
La première chose à faire est de créer un composant global pour le dashlet qu’on souhaite afficher (mydashlet ici).

  • Créer un fichier global.mydashlet.xml dans web-extension/site-data/components/

<?xml version="1.0" encoding="UTF-8"?>
<component>
<scope>global</scope>
<region-id>mydashlet</region-id>
<source-id>global</source-id>
<url>/components/dashlets/my-dashlet</url>
</component>

  • Depuis le template dashboard.ftl vous pouvez maintenant appeler <@region id="mydashlet" scope="global" protected=true />

Il s’agit de la solution la plus simple que j’ai trouvé pour résoudre ce problème, je reste ouvert à d’autres solutions :)

A vous de jouer !

Jira – Atlassian Unite Paris

Atlassian Unite Paris

Merci à GFU!

Habituellement cantonnée aux USA, Atlassian a organisé pour la première fois une série de conférences à travers l’Europe dont une à Paris (le 15 mars dernier) !!
A l’instar d’un user group classique, cette journée a été animée par des développeurs d’Atlassian, des éditeurs de plugins, le partenaire français Valiantys avec notre ami Nathan, et bien entendu des utilisateurs pour échanger autour de l’ensemble des solutions Atlassian.

Pour faire court, la matinée fut consacrée aux présentations des nouveautés (Jira 5, Confluence) et l’après-midi a, pour sa part, été réservée aux retours d’expérience. Vous pouvez retrouver un descriptif plus complet de cette journée sur le blog de Valiantys.

Jira – Arrivée de la version 5

Logo Jira

Atlassian vient de lancer Jira 5 et je vais essayer d’introduire les nouveautés et principales améliorations que cette nouvelle version apporte.

Un outil plus social

À l’image de nombreux autres outils (tel qu’Alfresco par exemple) Atlassian a voulu faire de Jira un outil plus orienté vers le partage. Aujourd’hui, on peut amener les utilisateurs à participer en les mentionnant avec un @ à la manière de Twitter (les personnes seront aussitôt notifiées par mail) ou en les alertant directement depuis une demande ou une recherche par le biais d’une nouvelle action de partage. Ces nouvelles fonctionnalités ajoutées à un existant qui permet déjà aux différents acteurs d’être au courant des changements d’état des demandes font de Jira un outil de plus en plus complet en matière d’alertes et de notifications.

Un outil plus connecté

En parallèle à Jira il est courant d’utiliser de nombreux autres outils pour de la documentation (Confluence), des retours client (Get Satisfaction), la gestion des tests (Zephyr) ou autres…
Il est donc intéressant de voir que Jira propose de créer des liens avec un certain nombre d’outils et permet, grâce à sa nouvelle API REST, de créer de nouveaux liens (un article intéressant sur le sujet ici). De plus, de nombreuses informations issues des ces liens peuvent maintenant enrichir les flux d’activité et donc appuyer le côté social de cette nouvelle version.

Autres améliorations

  • JQL se voit amélioré par de nouveaux prédicats tels que CHANGED, FROM, BEFORE…
  • La création et modification des demandes est beaucoup plus rapide grâce à un système de formulaires personnalisés et une fonctionnalité de création à la chaîne.
  • Une meilleure gestion des ressources grâce à un nouveau suivi temporel.
  • … Je n’ai pas encore pu tester moi même Jira 5 mais ils y a sûrement des améliorations intéressantes d’ergonomie et d’administration.

En conclusion, certains pourraient être déçus par cette nouvelle version (ceux qui attendent de la multi-assignation, des sous composants, l’internationalisation des champs personnalisés…) mais les nouvelles API (Java et REST) vont ouvrir de nouvelle possibilités en terme d’intégration avec d’autres outils et rendre le développement de plugins plus simple, rien que pour ça, la migration vaut peut être le coup :)

Note : L’annonce de Jira 5 est accompagnée par un changement majeur dans la facturation des licences qui risque de ne pas plaire à tout le monde !!

Eclipse – Déboguer une webapp Tomcat

Logo Eclipse
Merci à GFU!

Je vais aujourd’hui présenter une fonctionnalité très utile de l’environnement de développement Eclipse qui permet de déboguer localement une application s’exécutant sur un serveur d’application distant (Tomcat dans notre cas).

Le principe du débogage distant est le suivant :

  • La JVM avec laquelle fonctionne le serveur applicatif ouvre un socket sur un port spécifique
  • Eclipse va pouvoir se connecter sur ce socket afin d’intercepter les points d’arrêt et de communiquer avec la JVM distante

Configurer Tomcat

Pour utiliser une JVM en mode débogage distant il faut lui paramétrer le port d’attente et la configurer en mode debug. Pour ce faire le plus simple est de modifier certaines variables d’environnement qu’utilise Tomcat. Il est ainsi possible de spécifier le port d’attente de la socket de debug (JPDA_ADDRESS) lors du démarrage du serveur.

  • Dans le fichier startup.bat de votre Tomcat ajouter le paramètre jpda à la ligne de commande qui exécute catalina.bat
Ajout du paramètre JPDA

Ajout du paramètre JPDA

Note : Par défaut la configuration de Tomcat affecte le socket de debug au port 8000, il n’est pas nécessaire de changer cette configuration

Configurer Eclipse

Maintenant il suffit de configurer le debugger d’Eclipse afin qu’il communique avec la JVM.

  • Ouvrir une nouvelle perspective : depuis le menu Windows cliquer sur Open perspective puis sur Others…
  • Sélectionner la vue « Debug » :
Perspective Eclipse : Choisir Debug

Perspective Eclipse : Choisir Debug

  •  La nouvelle perspective devient accessible depuis les raccourcis en haut à droite :

    Perspective Debug

    Perspective Debug

  • Créer un nouveau profil de débogage associé à un projet : depuis le menu Run cliquer sur Debug configuration…
  • Créer un nouveau profil de type “Remote Java Application”, préciser son nom et le projet java qui lui est associé comme dans l’exemple ci-dessous :

    Debug Configuration

    Debug Configuration

Les paramètres Host et Port sont normalement bien configurés par défaut c’est à dire avec “localhost”» et “8000″. De toute façon le port doit impérativement correspondre à celui qui est spécifié via le paramètre JPDA_ADDRESS de la configuration de Tomcat.

Utiliser le mode Debug

Après avoir démarré Tomcat et déployé le projet, ouvrir la perspective de débogage et lancer le mode “Debug” de l’application via le menu idoine.

Voici un bref descriptif des fonctionnalités du debugger, son utilisation est assez intuitive:

Mode Debug

Mode Debug

[1] : vue des processus en cours d’exécution Debug Run
(le processus courant à partir duquel l’utilisateur réalise un débogage est à l’état de pause Debug Pause)
[2] : vue du code source, la ligne de code en cours d’exécution est surlignée
[3] : les points d’arrêt se positionnent sur la barre verticale grisée située à gauche du code
[4] : liste des objets et des variables accessibles
[5] : valeur de la variable sélectionnée (elle peut être changée en temps réel avec [Ctrl]+[S])
[6] : liste des points d’arrêt
[7] : log de la console

Le débogage est habituellement piloté par les actions suivantes :

  • Resume [F8]  : reprise de l’exécution Debug Resume
  • Stop [Ctrl]+[F2] : arrêt de l’exécution
  • Step into [F5]  : rentrer dans la prochaine méthode Step Into
  • Step over [F6]  : exécution pas à pas Step Over
  • Step return [F7]  : sortit de la méthode courante Step return
  • Run to line [Ctrl]+[R] : aller jusqu’à la ligne courante (celle du curseur)

A vous de jouer!

MagicDraw – Développer un plugin – 1

logo MagicDraw
Version 17.0

A quoi sert le développement de plugins?

Les plugins permettent d’étendre les fonctionnalités natives de MagicDraw:

  • Ajouter des nouvelles actions (sous forme de menus ou de boutons)
  • Ajouter des nouveaux comportements (sous forme d’écouteurs)
  • Ajouter des validateurs
  • Automatiser des traitements

A savoir

  1. OpenAPI en Java
    • Permet de manipuler les modèles et les diagrammes
    • Facile à utiliser avec un peu d’expérience
  2. Ressources disponibles
    • Documenation MagicDraw OpenAPI UserGuide.pdf disponible dans <MagicDraw_Install_Dir>\manual
    • Exemples et javadoc disponibles dans <MagicDraw_Install_Dir>\openapi

Commencer avec Eclipse

  1. Créer un nouveau projet Java
  2. Créer une “User Library” (Window>Preferences>Java>Build Path>User Libraries) avec tous les .jar de <MagicDraw_Install_Dir>\lib

    User Library

    User Library

  3. Configurer le “Build Path” du projet avec la librairie précédemment créée
  4. Créer un nouveau package et une classe qui hérite de Plugin com.nomagic.magicdraw.plugins.Plugin
  5. Ajouter les méthodes non implémentée
  6. Faire un System.out.println() dans init() et retourner true dans isSupported() et close()

    Classe MyPlugin

    Classe MyPlugin

  7. Récupérer le fichier plugin.xml
    • Vérifier la valeur de l’attribut class (nom complet de la classe plugin)
  8. Récupérer le fichier build.xml
    • Vérifier la valeur de la propriété magicdraw.home (adresse du répertoire d’installation de MagicDraw)
    • Vérifier la valeur de la propriété plugin.dir.name (nom du répertoire plugin, ce nom correspond en général au package du plugin)
  9. Ouvrir la vue “Ant” et déployer le plugin

    Deploy the plugin

    Deploy the plugin

Le plugin est maintenant déployé, on pourrait le tester en lancant directement MagicDraw mais certains préfèrent lancer l’application directement depuis Eclipse.

Lancer MagicDraw depuis Eclipse

  1. Créer une nouvelle “Configuration” (Run>Run Configuration…)
    • Name = MagicDraw 17.0
    • Project = Le projet précédemment créé
    • Main class = com.nomagic.magicdraw.Main
    • Program arguments = -verbose
    • VM arguments = -Dinstall="${MDINSTALL}" -Xms256M -Xmx800M -XX:PermSize=40M -XX:MaxPermSize=150M
      Note : une variable a été utilisée car le répertoire d’installation de MagicDraw contient des points

      Configuration MagicDraw

      Configuration MagicDraw

  2. Exécuter la configuration
    • Vérifier que le message imprimé dans la méthode init()s’affiche bien dans la console Eclipse

      Console Eclipse

      Console Eclipse

Le plugin est maintenant bien détecté par MagicDraw.
La prochaine étape sera donc de voir comment implémenter de nouvelles fonctionnalités.

MagicDraw – Créer un “helper” pour la génération de documents

logo MagicDraw
Version 17.0

I. Besoin

Lorsqu’on essaye de générer un document à l’aide d’un template Velocity il n’est pas toujours évident voir impossible de récupérer l’information souhaitée. Le besoin est donc de pouvoir accéder directement à l’API de MagicDraw en Java et d’offrir au template un ensemble de fonctionnalités/méthodes.

II. Solution

Implémentation

  1. Créer un nouveau projet (Eclipse) ainsi qu’une nouvelle classe Java (test.magicdraw.MyHelper) qui étend com.nomagic.magicreport.engine.Tool
  2. Implémenter des méthodes (qui seront directement accessibles depuis le template Velocity)
    • La documentation de l’API MagicDraw est disponible dans le manuel MagicDraw OpenAPI UserGuide.pdf
    • Des exemples et une JavaDoc MagicDraw sont disponibles sous <INSTALL_MD>/openapi/
  3. Compiler en tant que librairie .jar
    • Références vers les librairies du répertoire <INSTALL_MD>/lib/
    • Références vers les librairies reportwizard.jar et reportwizard_api.jar du répertoire <INSTALL_MD>/plugins/com.nomagic.magicdraw.reportwizard/
    • Référence vers la librairie magicreport.jar du répertoire <INSTALL_MD>/plugins/com.nomagic.magicdraw.reportwizard/lib/
  4. Placer cette librairie sous <INSTALL_MD>/plugins/com.nomagic.magicdraw.reportwizard/extensions/

Appel

Pour appeler le “helper” voici la ligne à ajouter au début du template:
#import("myhelper", "test.magicdraw.MyHelper")
Il suffit ensuite d’appeler les fonctions de la manière suivante:
## Récupération des elements Call Behavior du diagramme d'activité
#set($callbehaviors = $myhelper.getCallBehaviors($diagram))

A vous de jouer!

MagicDraw – Générer un template en ligne de commande

logo MagicDraw
Version 17.0

I. Besoin

Le besoin est de pouvoir lancer la génération d’un rapport directement en ligne de commande avec pour objectif de programmer une tache planifiée qui exécutera la génération d’une rapport. On peut par exemple programmer la génération toutes les nuits et consulter le rapport généré tous les matins.

II. Solution

Interroger un projet local

La génération d’un rapport en ligne de commande se fait via la commande generate. Cette commande se trouve dans <INSTALL_MD>\plugins\com.nomagic.magicdraw.reportwizard.

Voici les options disponible pour cette commande:
-project : spécifie le projet sur lequel on lance la génération
-ouput : spécifie le fichier de sortie
-template : spécifie le nom du template (Le template doit donc être déclaré dans MagicDraw)
-package : spécifie le ou les noms des packages à prendre en compte pour la génération (s’il y a plusieurs packages les nom sont à séparer par des ;)

D’autres options sont disponible, je vous invite à consulter la documentation MagicDraw ReportWizard UserGuide.pdf

Voici un exemple de ligne de commande:
generate -project MyProject.mdzip -output outputFileName.rtf -template templateName -package data

Interroger un projet sur le Teamwork

-server : adresse du serveur Teamwork
-login : nom d’utilisateur pour se connecter au serveur
-password : mot de passe de l’utilsateur

Une note concernant l’option -project :
Pour spécifier une branche ou une sous-branche il faut utiliser ## en tant que séparateur
“MyProject” sans branche = "MyProject"
“MyProject” avec une branche “release” = "MyProject##release"
“MyProject” avec une branche “release et une sous-branche “sp1″ = "MyProject##release##sp1"

Voici un exemple de ligne de commande:
generate -project "MyProject##release" -output outputFileName.rtf -template templateName -package data -server 10.1.1.101 -login username -password secret

A vous de jouer!

Suivre

Get every new post delivered to your Inbox.