32
Salvatore Incandela Everything is content Spring JCR (JSR170) Spring Framework Meeting 31 Ottobre 2009

Spring Jcr Extension

Embed Size (px)

DESCRIPTION

Everything si content. La produzione frenetica di contenuti a cui siamo abituati ci impone di utilizzare strumenti, semantiche, metadati sempre più avanzati. Tutti i CR implementati in java aderiscono alla specifica JSR170 per standardizzare accesso ai dati e rappresentazione del dato, tuttavia la specifica in se stessa non è sufficiente a ridurre i costi di implementazione di integrazioni. Spring JCR Extension si pone come obbiettivo quello di applicare l'approccio JDBC Template al mondo dei CR.

Citation preview

Page 1: Spring Jcr Extension

Salvatore Incandela

Everything is contentSpring JCR (JSR170)

Spring Framework Meeting 31 Ottobre 2009

Page 2: Spring Jcr Extension

Agenda

• Introduzione ai Content Repository.• Java Content Repository API.• Repository Model.• Esempio pratico.• Vantaggi Spring JCR.• Links.

Page 3: Spring Jcr Extension

Caratteristiche di File system e database

●Versioning●Controllo accessi●Classifcazione contenuti●Monitoraggio eventi●Ricerche testuali

Introduzine ai content repository

Page 4: Spring Jcr Extension

Con API proprietarie

Java Content Repository API

Page 5: Spring Jcr Extension

Con JCR

Java Content Repository API

Page 6: Spring Jcr Extension

Why JCR 170?

Più di 800 vendor sul mercatoStandard API

Riduzione costi

API semplici

Swappability

Java Content Repository API

Page 7: Spring Jcr Extension

•Level 1• Traversing tree • Getting value of properties • Namespace remapping

(transient) • Export to XML • Query by Xpath

Java Content Repository API

Page 8: Spring Jcr Extension

• Level 2• Adding, removing items • Writing to properties • Persistent namespace changes • Import from XML • Assigning node types to nodes

Java Content Repository API

Page 9: Spring Jcr Extension

•Transactions (JTA) •Versioning •Observation (events) •Locking •SQL syntax for queries

Java Content Repository API

Page 10: Spring Jcr Extension

Java Content Repository API

Page 11: Spring Jcr Extension

Il content model è costituito da più workspace, ognuno di essi contiene un albero composto da più item (nodi o property).

Nodo : one parent more childProperty: one parent no child

Repository model

Page 12: Spring Jcr Extension

Percorso xpathAbsolute : /a/b/c Relative: ../../b/c

UUID

Navigazione dell'albero

Repository model

Page 13: Spring Jcr Extension

●Ogni nodo ha un primary type● jcr:primaryType

●Più mixing types, opzionali contenuti nella proprietà jcr:mixingTypes

● mix:versionable● mix:lockable● mix:referencable

●Possono avere fratelli uguali● /nodo/nodofglio[2]

Nodo

Repository model

Page 14: Spring Jcr Extension

Un content repository deve supportare il tipo nt:base Può inoltre supportare dei tipi opzionali

–nt:unstructured –nt:hierarchyNode (sottotipi: nt:fle,nt:folder) –nt:resource –nt:version, nt:versionHistory –nt:query

Tipi di nodo

Repository model

Page 15: Spring Jcr Extension

Un content repository deve supportare il tipo nt:base Può inoltre supportare dei tipi opzionali

–nt:unstructured –nt:hierarchyNode (sottotipi: nt:fle,nt:folder) –nt:resource –nt:version, nt:versionHistory –nt:query

Tipi di nodo

Repository model

Page 16: Spring Jcr Extension

Tipi di nodo

NodeTypeName nt:file Supertypes nt:hierarchyNode IsMixin false HasOrderableChildNodes false PrimaryItemName jcr:content ChildNodeDefinition Name jcr:content RequiredPrimaryTypes [nt:base] DefaultPrimaryType null AutoCreatefalse Mandatory true OnParentVersion COPY Protected false SameNameSiblings false

NodeTypeName mix:lockable Supertypes [] IsMixin true HasOrderableChildNodes false PrimaryItemName null PropertyDefinition Name jcr:lockOwner RequiredType STRING ValueConstraints [] DefaultValues null AutoCreated false Mandatory false OnParentVersion IGNORE Protected true Multiple false PropertyDefinition Name jcr:lockIsDeep RequiredType BOOLEAN ValueConstraints [] DefaultValues null AutoCreatefalse Mandatory false OnParentVersion IGNORE Protectedtrue Multiple false

Repository model

Page 17: Spring Jcr Extension

Proprietà

– LONG, DATE, STRING, DOUBLE, BOOLEAN – PATH: percorso nel workspace – REFERENCE: contiene l'UUID del nodo (mix:referenceable)– NAME: nome del tipo di nodo

Impostare un valore null ad una property equivale ad eliminarla

Repository model

Page 18: Spring Jcr Extension

Namespace

Il nome di una property come in xml può essere preceduto da un prefsso (namespace):

●jcr (eg. jcr:primaryNode)●nt – per i tipi di nodi (es. nt:version) ●mix – per i mixing types (es. mix:versionable) ●xml – per la compatibilità con xml

Repository model

Page 19: Spring Jcr Extension

Eseguire una query Workspace workspace = session.getWorkspace(); Node node = session.getRootNode(); workspace.getNamespaceRegistry().registerNamespace("pnx", "http://pronetics.jcrexample/1.0"); QueryManager queryManager = workspace.getQueryManager(); Query query = queryManager.createQuery("//pnx:rubrica/pnx:contact[@pnx:name='christian')]", Query.XPATH); QueryResult queryResult = query.execute(); NodeIterator nodeIterator = queryResult.getNodes();

Esportare File file = new File("backup.xml"); FileOutputStream fileOutputStream = new FileOutputStream(file); session.exportSystemView("/pnx:rubrica", fileOutputStream, false, false);

Importare File file = new File("backup.xml"); FileInputStream fileInputStream = new FileInputStream(file); session.importXML("/", fileInputStream, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);

Esempi

Page 20: Spring Jcr Extension

Considerato l'albero in fgura

Esempio pratico

Page 21: Spring Jcr Extension

Autenticazione al repository

Traversal access di una property

Esempio pratico

//Get repositoryRepository repository = (Repository) ctx.lookup("myrepo");//Get CredentialsCredentials credentials = new SimpleCredentials("MyName", "MyPassword".toCharArray());//Get SessionSession mySession = repository.login(credentials, "MyWorkSpace");

Node root = mySession.getRootNode();Node myNode = root.getNode("a/e");//mySession.getNodeByUUID("123456789")Property property = myNode.getProperty("k");Value value = property.getValue();double myDouble = value.getDouble();

Page 22: Spring Jcr Extension

Proviamo a creare un nodo

Per eliminare una property

Esempio pratico

Session mySession; Node root = mySession.getRootNode(); Node myNode = root.getNode("a/e"); myNode.addNode("Y"); session.save();

Session mySession; Node root = mySession.getRootNode(); Node myNode = root.getNode("a/e"); myNode.setProperty("p", (Value) null); session.save();

Page 23: Spring Jcr Extension

Inserimento e stampa property

Repository r = new TransientRepository(); Session session = r.login(new SimpleCredentials("pippo", "pluto".toCharArray())); try { Workspace workspace = session.getWorkspace(); Node node = session.getRootNode(); workspace.getNamespaceRegistry().registerNamespace("pnx", "http://pronetics.jcrexample/1.0");

Node rubrica = node.addNode("pnx:rubrica"); Node contact = rubrica.addNode("pnx:contact"); contact.setProperty("pnx:name", "christian"); contact.setProperty("pnx:tel", "000000"); contact.setProperty("pnx:category", new String[] { "professional", "metal" }); // IMPORTANTE session.save();

rubrica = node.getNode("pnx:rubrica"); node.getProperty("pnxs:rubrica/pnx:contact[1]/pnx:name");

NodeIterator nodeIterator = node.getNodes(); while (nodeIterator.hasNext()) { Node cnt = nodeIterator.nextNode(); PropertyIterator propertyIterator = cnt.getProperties(); while (propertyIterator.hasNext()) { Property property = propertyIterator.nextProperty(); LOG.info("Property name: {} property value: {}", property.getName(), property.getValue()); } }

} finally { session.logout(); }

Esempio pratico

Page 24: Spring Jcr Extension

L'interfaccia SessionFactory descrive come ottenere una session, agisce come wrapper del javax.jcr.Repository. Per ottenere una sessionFactory abbiamo bisogno del repository bean e delle credenziali:

<bean id="jcrSessionFactory" class="org.springframework.extensions.jcr.JcrSessionFactory"> <property name="repository" ref="repository"/> <property name="credentials"> <bean class="javax.jcr.SimpleCredentials"> <constructor-arg index="0" value="bogus"/> <constructor-arg index="1" value="pass"/> </bean> </property> </bean>

JcrSessionFactory permette inoltre la registrazione di namespaces, agiungere listener per ulteriori informazioni fare riferimento ai javadoc.

Session Factory

Page 25: Spring Jcr Extension

Per effettuare la registrazione di namespaces custom basta semplicemente passarli come property, la key rappresenta il prefsso e il valore rappresenta il namespace:

<bean id="sessionFactory" class="org.springframework.extensions.jcr.JcrSessionFactory"> ... <property name="namespaces"> <props> <prop key="foo">http://bar.com/jcr</prop> <prop key="hocus">http://pocus.com/jcr</prop> </props> </property></bean>

Modalità di registrazione:●ForceNamespacesRegistration●KeepNewNamespaces●skipExistingNamespaces

Namespace registration

Page 26: Spring Jcr Extension

La registrazione dei listener permette di identifcare il path del nodo ascoltato, o una espressione regolare

<bean id="sessionFactory" class="org.springframework.extensions.jcr.JcrSessionFactory"> ... <property name="eventListeners"> <list> <bean class="org.springframework.extensions.jcr.EventListenerDefinition"> <property name="listener"> <bean class="org.springframework.extensions.examples.jcr.DummyEventListener"/> </property> <property name="absPath" value="/rootNode/someFolder/someLeaf"/> </bean> </list> </property></property>

Event listeners

Page 27: Spring Jcr Extension

La registrazione dei tipi di nodo è tipica del CR che stiamo usando, in questo caso JackRabbit:

<bean id="jackrabbitSessionFactory" class="org.springframework.extensions.jcr.jackrabbit.JackrabbitSessionFactory"> ... <property name="nodeDefinitions"> <list> <value>classpath:/nodeTypes/wikiTypes.cnd</value> <value>classpath:/nodeTypes/clientATypes.cnd</value> </list> </property></bean>

NodeTypeDefinition

Page 28: Spring Jcr Extension

Inserimento e stampa property

//Repository r = new TransientRepository(); //Session session = r.login(new SimpleCredentials("pippo", "pluto".toCharArray())); //try { Workspace workspace = session.getWorkspace(); Node node = session.getRootNode(); //workspace.getNamespaceRegistry().registerNamespace("pnx", "http://pronetics.jcrexample/1.0");

Node rubrica = node.addNode("pnx:rubrica"); Node contact = rubrica.addNode("pnx:contact"); contact.setProperty("pnx:name", "christian"); contact.setProperty("pnx:tel", "000000"); contact.setProperty("pnx:category", new String[] { "professional", "metal" }); // IMPORTANTE session.save();

rubrica = node.getNode("pnx:rubrica"); node.getProperty("pnxs:rubrica/pnx:contact[1]/pnx:name");

NodeIterator nodeIterator = node.getNodes(); while (nodeIterator.hasNext()) { Node cnt = nodeIterator.nextNode(); PropertyIterator propertyIterator = cnt.getProperties(); while (propertyIterator.hasNext()) { Property property = propertyIterator.nextProperty(); LOG.info("Property name: {} property value: {}", property.getName(), property.getValue()); } }

//} finally { // session.logout(); //}

Esempio SpringJcr

Page 29: Spring Jcr Extension

La maggior parte del lavoro con JCR viene svolta dal Jcrtemplate stesso. Il template richiede una sessionFactory e può essere confgurato in modo da creare nuove sessioni on demand o riusarle.

<bean id="jcrTemplate" class="org.springframework.extensions.jcr.JcrTemplate"> <property name="sessionFactory" ref="sessionFactory"/> <property name="allowCreate" value="true"/></bean>

JcrTemplate contiene molte delle funzioni di javax.jcr.Session e javax.jcr.query.Query. Nel caso in cui queste non siano suffcienti interviene JcrCallback che opera direttamente con la sessione. JcrCallback è thread-safe, apre e chiude sessioni.

public void saveSmth() { template.execute(new JcrCallback() {

public Object doInJcr(Session session) throws RepositoryException { Node root = session.getRootNode(); log.info("starting from root node " \+ root); Node sample = root.addNode("sample node"); sample.setProperty("sample property", "bla bla"); log.info("saved property " \+ sample); session.save(); return null; } }); }

JcrTemplate e JcrCallback

Page 30: Spring Jcr Extension

E' possibile utilizzare JcrDaoSupport analogamente a JdbcDaoSupport.

public class ProductDaoImpl extends JcrDaoSupport {

public void saveSmth() throws DataAccessException, MyException {

Session session = getSession(); try { Node root = session.getRootNode(); log.info("starting from root node " + root); Node sample = root.addNode("sample node"); sample.setProperty("sample property", "bla bla"); log.info("saved property " + sample); session.save(); return null; } catch (RepositoryException ex) { throw convertJcrAccessException(ex); } } }

DAO senza callback

Page 31: Spring Jcr Extension

Q/A

Finish

Page 32: Spring Jcr Extension

JSR-170 http://www.jcp.org/en/jsr/detail?id=170

Jackrabbithttp://jackrabbit.apache.org/

Versione html della specifca http://www.day.com/specs/jcr/1.0/

Spring JCRhttp://se-jcr.sourceforge.net/

Link utili

Authorwww.twitter.com/sincandela

salvatoreincandela.blogspot.comwww.linkedin.com/in/salvatoreincandela