Download - Spring Jcr Extension
![Page 1: Spring Jcr Extension](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/1.jpg)
Salvatore Incandela
Everything is contentSpring JCR (JSR170)
Spring Framework Meeting 31 Ottobre 2009
![Page 2: Spring Jcr Extension](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/2.jpg)
Agenda
• Introduzione ai Content Repository.• Java Content Repository API.• Repository Model.• Esempio pratico.• Vantaggi Spring JCR.• Links.
![Page 3: Spring Jcr Extension](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/3.jpg)
Caratteristiche di File system e database
●Versioning●Controllo accessi●Classifcazione contenuti●Monitoraggio eventi●Ricerche testuali
Introduzine ai content repository
![Page 6: Spring Jcr Extension](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/6.jpg)
Why JCR 170?
Più di 800 vendor sul mercatoStandard API
Riduzione costi
API semplici
Swappability
Java Content Repository API
![Page 7: Spring Jcr Extension](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/7.jpg)
•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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/8.jpg)
• 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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/9.jpg)
•Transactions (JTA) •Versioning •Observation (events) •Locking •SQL syntax for queries
Java Content Repository API
![Page 11: Spring Jcr Extension](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/11.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/12.jpg)
Percorso xpathAbsolute : /a/b/c Relative: ../../b/c
UUID
Navigazione dell'albero
Repository model
![Page 13: Spring Jcr Extension](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/13.jpg)
●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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/14.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/15.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/16.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/17.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/18.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/19.jpg)
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 21: Spring Jcr Extension](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/21.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/22.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/23.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/24.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/25.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/26.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/27.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/28.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/29.jpg)
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](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/30.jpg)
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 32: Spring Jcr Extension](https://reader033.vdocuments.us/reader033/viewer/2022042614/5583d122d8b42a7c758b55a1/html5/thumbnails/32.jpg)
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