cancel
Showing results for 
Search instead for 
Did you mean: 

Accessing Alfresco's JCR

hananherzog
Champ in-the-making
Champ in-the-making
Hello,
    I have an existing CMS. I would like to use Alfresco's implementation of JSR-170 to be the back-end store. Can you point me to the most straight-forward code-sample with which I can "instantiate/initialize" the JCR back-end (I guess through some sort of factory)? In the meantime, I will try to find out by going through the code.

Thanks,

Hanan
10 REPLIES 10

rdanner
Champ in-the-making
Champ in-the-making
Hello,
    I have an existing CMS. I would like to use Alfresco's implementation of JSR-170 to be the back-end store. Can you point me to the most straight-forward code-sample with which I can "instantiate/initialize" the JCR back-end (I guess through some sort of factory)? In the meantime, I will try to find out by going through the code.

Thanks,

Hanan

Is your application already expecting to consume a jcr repository?  At the moment alfresco only supports level I of the JCR spec (read only is the easiest way to describe it.)   They are working on level II at the moment. 

How are you planning to run the repository?  In the same jvm?  rebuild the app on top of a jcr implementation?  pick up a jcr reference from JNDI?

just curious.

The best example is the simple example located in the alfresco jcr project  located in the eamples folder in the alfresco source distribution.


In case you dont want to get that… here is a fragment for reading a document:


   public byte[] retrieveContent(String pContentMoniker)
   throws RetrievalFailureException
   { 
      /* define locals */
      byte[] vRetContentBytes = null;
      Repository vInstJcrRepository = null;
      String vInstUsername = null;
      String vInstPassword = null;
      TransactionProvider vInstTransactionProvider = null;
      Session vSession = null;
      Credentials vCredentials = null;
      UserTransaction vTransaction = null;
      Node vContentNode = null;
      Property vContentProperty = null;
      Value vContentPropertyValue = null;
      int vByteCount = 0;
     
      /* initialize */
      vInstJcrRepository = getJavaContentRepository();
      vInstTransactionProvider = getTransactionProvider();
      vInstUsername = getUsername();
      vInstPassword = getPassword();
     
      try
      {
         vCredentials = new SimpleCredentials(vInstUsername, vInstPassword.toCharArray());
         vSession = vInstJcrRepository.login(vCredentials);

         if(vInstTransactionProvider!=null)
         {
            vTransaction = vInstTransactionProvider.provideUserTransaction();
            vTransaction.begin();
         }

         vContentNode = vSession.getNodeByUUID(pContentMoniker);  

         if(vContentNode!=null)
         {           
            vContentProperty = vContentNode.getProperty("cm:content");
            vContentPropertyValue = vContentProperty.getValue();
           
            vByteCount = vContentPropertyValue.getStream().available();
            vRetContentBytes = new byte[vByteCount];
           
            vContentPropertyValue.getStream().read(vRetContentBytes);
         }
      }
      catch(Exception eRepositoryFailure)
      {
         System.out.println("repository failure ["+eRepositoryFailure+"]");

         try{ if(vTransaction!=null){ vTransaction.rollback(); } }catch(Exception eMuted){}        
      }
      finally
      {
         try{ if(vTransaction!=null){ vTransaction.commit(); } }catch(Exception eMuted){}        
      }

      return vRetContentBytes;
   };

Initializing the repository (in the case of the example: the value behind getJavaContentRepository()) is a matter of implementation.  Like I said before you can do it any number of a hundred different way.

The easiest is to build right on top of alfresco by including alfrescos jars and spring configuration in you app.  In this case you would just wire the jcr interface to your consuming classes with spring.

This approach is not so hot unless you are looking to embed alfresco or unless you just want to play.

An alternative approach is to load alfresco in one context, register the alfresco jcr repository implemenation bean in JNDI and load you app up in a different context looking to JNDI for a repository.

In addition to that you can put any number of remote mechanisms between your application and the real deal so to speak.  RMI will work well if you are geographically close and have no firewalls to deal with.  Web services works as well if you have to talk on port 80.  Both will incurr a performance penalty.

Hope this helps

hananherzog
Champ in-the-making
Champ in-the-making
Hello,
    I have an existing CMS. I would like to use Alfresco's implementation of JSR-170 to be the back-end store. Can you point me to the most straight-forward code-sample with which I can "instantiate/initialize" the JCR back-end (I guess through some sort of factory)? In the meantime, I will try to find out by going through the code.

Thanks,

Hanan

Is your application already expecting to consume a jcr repository?  At the moment alfresco only supports level I of the JCR spec (read only is the easiest way to describe it.)   They are working on level II at the moment. 

How are you planning to run the repository?  In the same jvm?  rebuild the app on top of a jcr implementation?  pick up a jcr reference from JNDI?

just curious.

The best example is the simple example located in the alfresco jcr project  located in the eamples folder in the alfresco source distribution.


In case you dont want to get that… here is a fragment for reading a document:


   public byte[] retrieveContent(String pContentMoniker)
   throws RetrievalFailureException
   { 
      /* define locals */
      byte[] vRetContentBytes = null;
      Repository vInstJcrRepository = null;
      String vInstUsername = null;
      String vInstPassword = null;
      TransactionProvider vInstTransactionProvider = null;
      Session vSession = null;
      Credentials vCredentials = null;
      UserTransaction vTransaction = null;
      Node vContentNode = null;
      Property vContentProperty = null;
      Value vContentPropertyValue = null;
      int vByteCount = 0;
     
      /* initialize */
      vInstJcrRepository = getJavaContentRepository();
      vInstTransactionProvider = getTransactionProvider();
      vInstUsername = getUsername();
      vInstPassword = getPassword();
     
      try
      {
         vCredentials = new SimpleCredentials(vInstUsername, vInstPassword.toCharArray());
         vSession = vInstJcrRepository.login(vCredentials);

         if(vInstTransactionProvider!=null)
         {
            vTransaction = vInstTransactionProvider.provideUserTransaction();
            vTransaction.begin();
         }

         vContentNode = vSession.getNodeByUUID(pContentMoniker);  

         if(vContentNode!=null)
         {           
            vContentProperty = vContentNode.getProperty("cm:content");
            vContentPropertyValue = vContentProperty.getValue();
           
            vByteCount = vContentPropertyValue.getStream().available();
            vRetContentBytes = new byte[vByteCount];
           
            vContentPropertyValue.getStream().read(vRetContentBytes);
         }
      }
      catch(Exception eRepositoryFailure)
      {
         System.out.println("repository failure ["+eRepositoryFailure+"]");

         try{ if(vTransaction!=null){ vTransaction.rollback(); } }catch(Exception eMuted){}        
      }
      finally
      {
         try{ if(vTransaction!=null){ vTransaction.commit(); } }catch(Exception eMuted){}        
      }

      return vRetContentBytes;
   };

Initializing the repository (in the case of the example: the value behind getJavaContentRepository()) is a matter of implementation.  Like I said before you can do it any number of a hundred different way.

The easiest is to build right on top of alfresco by including alfrescos jars and spring configuration in you app.  In this case you would just wire the jcr interface to your consuming classes with spring.

This approach is not so hot unless you are looking to embed alfresco or unless you just want to play.

An alternative approach is to load alfresco in one context, register the alfresco jcr repository implemenation bean in JNDI and load you app up in a different context looking to JNDI for a repository.

In addition to that you can put any number of remote mechanisms between your application and the real deal so to speak.  RMI will work well if you are geographically close and have no firewalls to deal with.  Web services works as well if you have to talk on port 80.  Both will incurr a performance penalty.

Hope this helps

Thanks for pointing out that the current implementation of JCR, as it is Level 1 compliant only, would be read-only. I just read through the JSR-170 spec. Should've done so yesterday, before posting.

Currently our app does not consume a JCR repository. We have our own content repository API, which itself is a wrapper for WebDAV. The in-house API is strikingly similar, but inferior to JCR. It would not be a major hassle to change our code to the JCR API.

I  could use JCR Level 1 for read access and use the Hibernate Content  Management API for update/modify functionality. When Level 2 is out, I will redo the update/modify methods against that API. Alternatively, I could implement the level 2 functionality that we need, and simply throw that  code away when Level 2 is provided by Alfresco (or contribute my code back if Level 2 release is delayed). So many decisions…

To answer your questions:

I expect that Alfresco Repository would sit in the same JVM as the CMS application code.  But at this point, I don't want to use Alfresco Web-Client code. We want to maintain our current UI. Additionally, we don't have time to take the learning curve on Spring and JSF (too much uncertainty and we're on an aggressive schedule).

I would be embedding the Alfresco Reposistory our app. This is the same thing as replacing Alfresco's Web-Client (web front end), with our own.

Thanks for your time on this… I really need to bounce these ideas around. What approach would you take to 'porting' and existing CMS to Alfresco, under a tight  deadline and with the whole sales force waiting for the new release?

Cheers,

Hanan

andy
Champ on-the-rise
Champ on-the-rise
Hi

I may be missing the point here …. and you may want the JCR170 API….

Could you use the WebDAV interface to the repository instead?
It sounds like you may be able to reuse your existing wrapper.

Regards

Andy

hananherzog
Champ in-the-making
Champ in-the-making
Hi

I may be missing the point here …. and you may want the JCR170 API….

Could you use the WebDAV interface to the repository instead?
It sounds like you may be able to reuse your existing wrapper.

Regards

Andy
Hi Andy,
   That was my initial approach, but it seems that the WebDAV implementation isn't complete yet; it is missing some methods such as PROPPATCH and VERSIONCONTROL, to mention two.

As my next alternative, I considered using the JCR170 API. Of course, there would be a loss of some flexibility because I lose remote-api, and perhaps have to put the repo into the same JVM as my CMS. However, the JSR170 API is currently only Level 1 compliant, from my understanding (read-only). So it's also incomplete in a sense.

I am now trying to figure out what complete API, which would give me all the access to read/write properties (incl. content), move, copy, delete, etc. I would be eternally grateful if you pointed me in the right direction.

Cheers,

Hanan

davidc
Star Contributor
Star Contributor
There are three public Alfresco API's:

- Web Services (remote access)
- Java Services (local access, full implementation as used by our own Web Client)
- JCR (standards based, level 1 now, level 2 in development)

For information on the Java Service API take a look at http://www.alfresco.org/mediawiki/index.php/Alfresco_Content_Management_Java_API

hananherzog
Champ in-the-making
Champ in-the-making
Superb. This cut down my research time. Frankly, haven't had much uninterrupted time to work on this. Tomorrow first thing, I will try these out, following the examples in the WIKI link you provided.

The Web Services seems intriguing. Is it well tested? At least more than the WebDAV (in which there were a few bugs)?

Thanks so much for your quick response, wish I could pay part of your salary. Smiley Happy

Hanan

There are three public Alfresco API's:

- Web Services (remote access)
- Java Services (local access, full implementation as used by our own Web Client)
- JCR (standards based, level 1 now, level 2 in development)

For information on the Java Service API take a look at http://www.alfresco.org/mediawiki/index.php/Alfresco_Content_Management_Java_API

rdanner
Champ in-the-making
Champ in-the-making
Superb. This cut down my research time. Frankly, haven't had much uninterrupted time to work on this. Tomorrow first thing, I will try these out, following the examples in the WIKI link you provided.

The Web Services seems intriguing. Is it well tested? At least more than the WebDAV (in which there were a few bugs)?

Thanks so much for your quick response, wish I could pay part of your salary. Smiley Happy

Hanan

There are three public Alfresco API's:

- Web Services (remote access)
- Java Services (local access, full implementation as used by our own Web Client)
- JCR (standards based, level 1 now, level 2 in development)

For information on the Java Service API take a look at http://www.alfresco.org/mediawiki/index.php/Alfresco_Content_Management_Java_API

It seems to me that you have a large number of options available to you.    Since you already hava a wapper (your own api) you intend to sit behind you can mix and match APIs. 

For example, if you want alfresco in a different jvm use the JCR standard for level one behind RMI and the alfresco remote api where you need it.

Spring (used as a bean factory) does not have a very high barrier to entry.  If you start using it, it should actually speed up your development and make it easier to change out your implementation when the time comes.

Anyway it sounds like you have some options.
-R

hananherzog
Champ in-the-making
Champ in-the-making
There are three public Alfresco API's:

- Web Services (remote access)
- Java Services (local access, full implementation as used by our own Web Client)
- JCR (standards based, level 1 now, level 2 in development)

For information on the Java Service API take a look at http://www.alfresco.org/mediawiki/index.php/Alfresco_Content_Management_Java_API


When I try to run the example, projects/alfresco/nightly/29112005/projects/jcr/source/java/org/alfresco/jcr/example/SimpleExample.java, I get the following exception:

So, I added the following to my buildpath (in Eclipse 3.2):
1. projects/alfresco/nightly/29112005/projects/repository/config
2. alfresco/nightly/29112005/projects/jcr/config

I am assuming not all the config file necessary are findable.  There is something more I need to do. Can you point me in the right direction?


The huge exception stack is below:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'descriptorComponent' defined in class path resource [alfresco/application-context.xml]: Can't resolve reference to bean 'systemBootstrap' while setting property 'systemBootstrap'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nodeIndexer' defined in class path resource [alfresco/node-services-context.xml]: Can't resolve reference to bean 'policyComponent' while setting property 'policyComponent'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'policyComponent' defined in class path resource [alfresco/application-context.xml]: Can't resolve reference to bean 'dictionaryService' while setting property 'constructor argument with index 0'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dictionaryBootstrap' defined in class path resource [alfresco/application-context.xml]: Initialization of bean failed; nested exception is org.alfresco.service.cmr.dictionary.DictionaryException: Could not import bootstrap model alfresco/model/dictionaryModel.xml
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'nodeIndexer' defined in class path resource [alfresco/node-services-context.xml]: Can't resolve reference to bean 'policyComponent' while setting property 'policyComponent'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'policyComponent' defined in class path resource [alfresco/application-context.xml]: Can't resolve reference to bean 'dictionaryService' while setting property 'constructor argument with index 0'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dictionaryBootstrap' defined in class path resource [alfresco/application-context.xml]: Initialization of bean failed; nested exception is org.alfresco.service.cmr.dictionary.DictionaryException: Could not import bootstrap model alfresco/model/dictionaryModel.xml
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'policyComponent' defined in class path resource [alfresco/application-context.xml]: Can't resolve reference to bean 'dictionaryService' while setting property 'constructor argument with index 0'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dictionaryBootstrap' defined in class path resource [alfresco/application-context.xml]: Initialization of bean failed; nested exception is org.alfresco.service.cmr.dictionary.DictionaryException: Could not import bootstrap model alfresco/model/dictionaryModel.xml
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dictionaryBootstrap' defined in class path resource [alfresco/application-context.xml]: Initialization of bean failed; nested exception is org.alfresco.service.cmr.dictionary.DictionaryException: Could not import bootstrap model alfresco/model/dictionaryModel.xml
org.alfresco.service.cmr.dictionary.DictionaryException: Could not import bootstrap model alfresco/model/dictionaryModel.xml
   at org.alfresco.repo.dictionary.DictionaryBootstrap.bootstrap(DictionaryBootstrap.java:94)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
   at java.lang.reflect.Method.invoke(Method.java:585)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeCustomInitMethod(AbstractAutowireCapableBeanFactory.java:971)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:941)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:334)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:222)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:146)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:281)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:222)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:146)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:281)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:222)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:146)
   at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:176)
   at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:105)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveConstructorArguments(AbstractAutowireCapableBeanFactory.java:591)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:497)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:298)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:222)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:146)
   at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:176)
   at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:105)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:891)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:707)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:316)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:222)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:146)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:281)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:222)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:146)
   at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:176)
   at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:105)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:891)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:707)
   at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:316)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:222)
   at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:146)
   at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeansOfType(DefaultListableBeanFactory.java:205)
   at org.springframework.context.support.AbstractApplicationContext.getBeansOfType(AbstractApplicationContext.java:583)
   at org.springframework.context.support.AbstractApplicationContext.registerListeners(AbstractApplicationContext.java:466)
   at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:307)
   at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:80)
   at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:65)
   at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:56)
   at org.alfresco.jcr.example.SimpleExample.main(SimpleExample.java:48)
Caused by: org.alfresco.service.cmr.dictionary.DictionaryException: Failed to parse model
   at org.alfresco.repo.dictionary.M2Model.createModel(M2Model.java:91)
   at org.alfresco.repo.dictionary.DictionaryBootstrap.bootstrap(DictionaryBootstrap.java:89)
   … 47 more
Caused by: org.jibx.runtime.JiBXException: Unable to access binding information for class org.alfresco.repo.dictionary.M2Model
Make sure the binding has been compiled
   at org.jibx.runtime.BindingDirectory.getBindingList(BindingDirectory.java:77)
   at org.jibx.runtime.BindingDirectory.getFactory(BindingDirectory.java:189)
   at org.alfresco.repo.dictionary.M2Model.createModel(M2Model.java:84)
   … 48 more

davidc
Star Contributor
Star Contributor
Hi,

The dictionary service uses an xml library called JibX to map XML to Java (and vice-versa).  However, it requires a post-compilation step on the Java classes to be mapped and it seems this has been missed out in your build.

If you take a look at /projects/repository/project-build.xml, you'll see a target called 'compile-jibx'

Also, the Repository Eclipse project has a custom builder called 'Jibx'.

Hope that helps.