Gestion des contenus : Java Content Repository (JCR 2.0) & Spring (Part 1)

La gestion de contenus ( formulaires, documentation, procédures) est généralement désigné par le terme GED (Gestion électronique de documents) comme synonyme d'ECM (Enterprise Content Management).

JCR 2.0 est la dernière version de l'API d'entrepôt documentaire standard appelée aussi JSR 283 (anciennement appelée JSR 170).

jackrabbit est l'implémentation open source de référence utilisée par de nombreux projets (Par ex. Alfresco). La version 2.9.0, release sortie en aout 2014, est utilisée dans la démo ci-après.

La solution Jackrabbit de la fondationapacheFondation est lancée, en 2005, par l'ancienne équipe technique d'ECM Documentum (la solution propriétaire riche dans ce domaine).

La figure ci-dessous résume l'architecture de Jackrabbit répartie essentiellement en trois couches :

jcr_jackrabbit_overview

 

Dans ce billet, nous avons préféré éviter les détails de l'API JCR pour aborder le cœur du sujet, c'est à dire, montrer comment afficher/créer un nœud. En d'autres termes illustrer les opérations CRUD par la pratique.

Nombreux sont les articles qui expliquent comment configurer JCR avec spring-modules mais très peu abordent JCR 2.0 sans spring-module ni spring-extensions. C'est bien ce qu'on va réaliser.

Cette démo est réalisée sans spring-module ni spring-extensions car spingr-module est inactif depuis 2009!

Et spring-extensions n'apporte pas grand chose à notre démo.

Ce billet vous présente une démo permettant, en 20 minutes, d'aborder les parties suivantes:

  • Créer projet maven web de démo,
  • Configurer le pom du projet,
  • Configurer le web.xml pour Spring MVC,
  • Configurer JCR dans Spring (sans spring-modules ni spring-extensions),
  • Tester quelques fonctionnalités JCR.

Pour ce faire, voici une synthèse des étapes à venir:

  • Création d'un projet maven web,
  • Configuration du pom et du web.xml,
  • Configuration de Jackrabbit dans Spring,
  • Réalisation d'une page jsp nommée "affiche.jsp".
  • Réalisation d'un peu de code java:  interface et son implémentation, un controlleur mvc.

D'autres étapes intermédiaires de configuration JCR/Jackrabbit sont abordées plus loin.

PARTIE 1. Créer le projet web avec maven

Dans le workspace de l'IDE Eclipse, lancer la commande, en une seule ligne, dans la console :

mvn archetype:create -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp -DgroupId=fr.netapsys.demos -DartifactId=jcrdemos -Dversion=1.0 -Dpackage=fr.XXXXXXX.demos

Avant de lancer la commande, penser à remplacer fr.XXXXXXX.demos par le nom de package qui vous convient!

Résultat: dans le worskpace un nouveau projet est créé nommé 'jcrdemos'

Importer le projet maven dans Eclipse (ou STS ).

Compléter le pom.xml avec ces dépendances:

...<properties>
<jackrabbit.version>2.9.0</jackrabbit.version>
<spring.version>4.0.1.RELEASE</spring.version>
</properties>
<dependencies>
<!-- jcr -->
<dependency>
<groupId>javax.jcr</groupId>
<artifactId>jcr</artifactId>
<version>2.0</version>
</dependency>

<!-- jackrabbit -->
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-core</artifactId>
<version>${jackrabbit.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-rmi</artifactId>
<version>${jackrabbit.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-jcr-server</artifactId>
<version>${jackrabbit.version}</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.jackrabbit</groupId>
<artifactId>jackrabbit-webapp</artifactId>
<version>${jackrabbit.version}</version>
<scope>runtime</scope>
</dependency>

<!-- spring -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</exclusion>
</exclusions>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>

<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
<scope>provided</scope>
</dependency>

<!-- jstl -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.1.2</version>
</dependency>
<!-- standard.jar -->
<dependency>
<groupId>taglibs</groupId>
<artifactId>standard</artifactId>
<version>1.1.2</version>
</dependency>
</dependencies>

Ce qui est intéressant dans ce pom est l'ajout de la dépendance sur l'API JCR v2.0 et les dépendances, scope runtime, de jackrabbit ainsi que celles de Spring 4. Certaines dépendances transitives sont déclarées aussi indépendamment.

PARTIE 2. Configurer la webapp démo

Le fichier web.xml doit contenir uniquement la déclaration de Spring-MVC:

<web-app>

<!-- Spring MVC   -->
<servlet>
<servlet-name>jcrdemos</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jcrdemos</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>

</web-app>

 

L'essentiel ici est la dispatcherServlet nommée "jcrdemos" ainsi le fichier de configuration de Spring sera nommé, par convention, "jcrdemos-servlet.xml". Au lancement de l'application web Spring chargera automatiquement les beans déclarés dans ce fichier.

PARTIE 3. Configuration JCR dans Spring

Créer un fichier xml nommé "jcrdemos-servlet" et placer le dans le répertoire "/WEB-INF".

Voici son contenu :


<?xml version="1.0" encoding="UTF-8"?>
<context:annotation-config />
<context:component-scan base-package="fr.XXXXX.samples"/>
<!--  JCR config repo and repository.xml-->
<bean id="jcrConfiguration"
factory-method="create" lazy-init="true">
<constructor-arg index="0" type="java.io.InputStream"
value="classpath:repository.xml" />
<constructor-arg index="1" type="java.lang.String" value="/var/jcr/myRepo"/>
</bean>
<bean id="jcrRepository"
class="org.apache.jackrabbit.core.TransientRepository" lazy-init="true">
<constructor-arg ref="jcrConfiguration"/>
</bean>
<!--  jcr session -->
<bean id="jcrSession" factory-bean="jcrRepository"
factory-method="login" destroy-method="logout" lazy-init="true">
</bean>
<!--  view resolver -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix"><value>/WEB-INF/jsp/</value></property>
<property name="suffix"><value>.jsp</value></property>
</bean>
</beans>


Explications
:

Penser à remplacer "fr.XXXXX.samples" par le nom de package déclaré à l'étape de création du projet maven.

Le bean jcrConfiguration utilise deux paramètres :
- le fichier repository.xml détaillé ci-après,
- un repository situé dans /var/jcr/myRepo qui sera créé au lancement de l'appli.

On voit que le bean jcrRepository est défini en référençant la configuration citée.

Enfin, le bean jcrSession déclare le singleton session jcr. Celui-ci nous permettra par la suite de faire les manipulations du repo.

A noter le bean jcrSession crée une connexion anonyme, via la méthode factory login, qui ne permet pas de modifier le repository. Dans la seconde partie de ce billet, nous verrons comment ouvrir une connexion avec les droits permettant de faire les opérations CRUD dans JCR.  Par exemple, créer un nouveau noeud.

PARTIE 4. Configurer le repo de JCR

Dans cette partie, nous revenons au fichier "repository.xml" déjà cité précédamment.

Ce fichier est situé dans "src\main\resources" et voici son contenu:


<Repository>
<FileSystem>
<param name="path" value="${rep.home}/repository" />
</FileSystem>
<Security appName="Jackrabbit">
<AccessManager
class="org.apache.jackrabbit.core.security.SimpleAccessManager" />
<LoginModule />
</Security>
<Workspaces rootPath="${rep.home}/workspaces"
defaultWorkspace="default" />
<Workspace name="${wsp.name}">
<FileSystem>
<param name="path" value="${wsp.home}" />
</FileSystem>
<PersistenceManager
class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager" />
<SearchIndex>
<param name="path" value="${wsp.home}/index" />
</SearchIndex>
</Workspace>
<Versioning rootPath="${rep.home}/versions">
<FileSystem>
<param name="path" value="${rep.home}/versions" />
</FileSystem>
<PersistenceManager
class="org.apache.jackrabbit.core.state.xml.XMLPersistenceManager" />
</Versioning>
</Repository>

En principe il n'y a rien à changer dans ce fichier. Son détail n'est pas l'objet de cet article.

PARTIE 5. Écrire la page jsp

C'est une page simple située dans /WEB-INF/jsp nommée affiche.jsp qui déclare la librairie jstl et dont le code est simple:

<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<html>
<body>
Résultat:
<c:out value="${jcrContents}"/>
....

PARTIE 6. Test les fonctionnalités JCR

Résumons les actes à faire dans cette partie:

  • 6.1. Ecrire le service
  • 6.2. Ecrire le controller mvc
  • 6.3 Ecrire la page jsp : affiche.jsp
  • 6.4. Afficher un noeud JCR

6.1 Ecrire l'interface de notre service et son implementation. Le code de l'interface:

 

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
public interface JcrService {

Session getSession();

Node  getRootNode() throws RepositoryException;

String printContents(Node n,  String padding) throws RepositoryException;

}

 

Puis son implémentation:

 

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.springframework.stereotype.Component;
import fr.netapsys.samples.JcrService;

@Component("jcrService")
public class JcrServiceImpl implements JcrService {

@Autowired
private Session jcrSession;

public Node getRootNode() throws RepositoryException {
return getSession().getRootNode();
}

public String printContents(Node n,  String padding) throws RepositoryException  {
StringBuilder sb=new StringBuilder(padding + n.getPath() + "(" +

n.getPrimaryNodeType().getName() + ")");
NodeIterator it = n.getNodes();
while (it.hasNext()) {
sb.append(printContents(it.nextNode(), padding + " "));
}
return sb.toString();
}

public void setJcrSession(Session jcrSession) {
this.jcrSession = jcrSession;
}

public Session getSession() {
return jcrSession;
}

}

 

6.2. Ecrire le controller mvc

 

import java.io.IOException;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import fr.netapsys.samples.JcrService;

@Controller
public class JcrController {

@Autowired
JcrService jcrService;

@RequestMapping("/afficheNode")
public ModelAndView afficheNode(@RequestParam(defaultValue="root") String nameNode) throws RepositoryException, IOException {
Node node=null;
if("root".equals(nameNode)){
node=jcrService.getRootNode();
}else{
node=jcrService.getRootNode().getNode(nameNode);
}
String contenu=jcrService.printContents(node,"\n");
return new ModelAndView("affiche", "jcrContents",contenu);
}
}

 

Explications:

- La méthode afficheNode accessible via l'url localhost:8080/afficheNode.html?nodeName=xxx permet d'afficher le contenu du repo à partir du node donné.
En l'absence de ce param, c'est tout le repo qui est affiché.

6.3. Tester la fonctionnalités JCR

A) Tester l'affichage du repo
lancer tomcat et déployer la webapp jcrdemos puis
saisir dans le browser l'url http://localhost:8080/afficheNode.html
L'arborescence du repo s'affiche depuis le noeud racine.

On peut aussi cibler un noeud particulier via l'url
http://localhost:8080/afficheNode.html?nameNode=xxxxxx

Dans la seconde partie nous testons d'autres fonctionnalités dont la création d'un noeud avec un utilisateur ayant les droits appropriés. Et nous l'affichons en appelons la méthode afficheNode.

Pour cela, on complètera les classes de service et du controller .

Un commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.