cancel
Showing results for 
Search instead for 
Did you mean: 

Step by Step - Access Alfresco JSR 170 From another Portlet

trupoet
Champ in-the-making
Champ in-the-making
So I've successfully deployed JBoss / JBoss Portal and Alfresco.

Now I'm trying to write a portlet that simply accesses the Alfresco repository to display content.

I've read some forum threads and wiki pages about setting it up as a web service and looked into some of the SDK code and tried to implement some of it via a portlet unsuccessfully.

I guess I'm just looking for some step-by-step help to implement this as a webservice or however it should be done.

I started with the FirstJCRClient class and made it into a portlet but I'm not sure exactly what needs to be included in the portlet war that I'm deploying. So far, I have the repository and spring jar files, and the jcr-api-context.xml file (also tried the application-context.xml file) but both of them seem to want to point towards some alfresco context within the same web application. But I want to point to the Alfresco portlet context that's not contained within the same web app.

Now I'm running into an exception saying it cannot find the AlfrescoRuntimeException class so I'm guessing I need to include the alfresco api jar(s) in the web app too but I've seen previous problems with including the same jars in different web apps before so wondering how that will affect this.

Any help appreciated.

Basic code is:


public class FirstJCRClient extends GenericPortlet
{
   
    protected void doView(RenderRequest rRequest, RenderResponse rResponse)
       throws PortletException, IOException, UnavailableException
   {
       // access the Alfresco JCR Repository (here it's via programmatic approach, but it could also be injected)
       ApplicationContext context = new ClassPathXmlApplicationContext("classpath:jcr-api-context.xml");
       Repository repository = (Repository)context.getBean("JCR.Repository");
   
       // login to workspace (here we rely on the default workspace defined by JCR.Repository bean)
       Session session = null;
       try
       {
          session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
           // first, access the company home
           Node rootNode = session.getRootNode();
           Node companyHome = rootNode.getNode("app:company_home/index.html");
             
           rResponse.setContentType("text/html");
          
           PrintWriter writer = rResponse.getWriter();
           String content = companyHome.getProperty("cm:content").toString();
          
           writer.write("Content:<P>");
           writer.write(content);
           writer.close();
           session.save();
       }
       catch(RepositoryException re)
       {
          
       }
       finally
       {
           session.logout();
           System.exit(0);
       }
   }
2 REPLIES 2

trupoet
Champ in-the-making
Champ in-the-making
Alright well I haven't gotten this fully working yet but it's a start.

I started out by editing the jcr-api-context.xml for Alfresco and adding a bean that would export the JCR.Repository bean via RMI:


<!– Expose the bean via RMI (http://www.springframework.org/docs/reference/remoting.html - JKT&JDP) –>
    <bean class="org.springframework.remoting.rmi.RmiServiceExporter">
      <!– does not necessarily have to be the same name as the bean to be exported –>
      <property name="serviceName" value="AlfrescoJcrRepository"/>
      <property name="service" ref="JCR.Repository"/>
      <property name="serviceInterface" value="javax.jcr.Repository"/>
      <!– defaults to 1099 –>
      <property name="registryPort" value="1199"/>
   </bean>

Next I edited the web.xml for my portlet project and added the following within the web-app tags:


<context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>
         classpath:com/raf/portal/drippy/firstclient/context.xml
      </param-value>
      <description>Spring config file locations</description>
   </context-param>

   <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>

Next I created my own context.xml continaing my RMI Proxy bean:


<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE beans PUBLIC '-//SPRING//DTD BEAN//EN' 'http://www.springframework.org/dtd/spring-beans.dtd'>

<beans>
   <bean id="repositoryUser" class="com.raf.portal.drippy.firstclient.RepositoryUser">
      <property name="alfrescoJcrRepository" ref="alfrescoJcrRepositoryProxy"/>
   </bean>
   <bean id="alfrescoJcrRepositoryProxy" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
      <property name="serviceUrl" value="rmi://localhost:1199/AlfrescoJcrRepository"/>
      <property name="serviceInterface" value="javax.jcr.Repository"/>
   </bean>
</beans>

Next, I created a new class, called RepositoryUser which will contain a setter for the proxy bean:


package com.raf.portal.drippy.firstclient;

import javax.jcr.Repository;

public class RepositoryUser {
   private Repository alfrescoJcrRepository;

   /**
    * IoC setter
    * @param alfrescoJcrRepository
    */
   public void setAlfrescoJcrRepository(Repository alfrescoJcrRepository) {
      this.alfrescoJcrRepository = alfrescoJcrRepository;
   }

   public Repository getAlfrescoJcrRepository() {
      return alfrescoJcrRepository;
   }
}

Finally I updated the original sample code (that I converted to a portlet) to use this proxy bean.


/*
* Copyright (C) 2005 Alfresco, Inc.
*
* Licensed under the Mozilla Public License version 1.1
* with a permitted attribution clause. You may obtain a
* copy of the License at
*
*   http://www.alfresco.org/legal/license.txt
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific
* language governing permissions and limitations under the
* License.
*/
package com.raf.portal.drippy;

import javax.jcr.Item;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.SimpleCredentials;

import org.alfresco.jcr.api.JCRNodeRef;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.repository.ContentData;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.web.context.WebApplicationContext;

import com.raf.foundation.log.Log;
import com.raf.portal.drippy.firstclient.RepositoryUser;

import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.UnavailableException;
import java.io.IOException;
import java.io.PrintWriter;




/**
* Simple client example demonstrating the use of the Alfresco JCR (JSR-170) API.
*
* The client creates a content node in the "Company Home" folder.  The content
* may be viewed and operated on within the Alfresco Web Client.  Note: the web client
* will need to be re-started after executing this sample to see the changes in
* effect.
*
* This client demonstrates the "Embedded Repository" deployment option as described
* in the Alfresco Respotiory Architecture docucment -
* http://wiki.alfresco.com/wiki/Alfresco_Repository_Architecture
*/
public class FirstJCRClient extends GenericPortlet
{
   
    protected void doView(RenderRequest rRequest, RenderResponse rResponse)
       throws PortletException, IOException, UnavailableException
   {
       // access the Alfresco JCR Repository (here it's via programmatic approach, but it could also be injected)
       WebApplicationContext context = (WebApplicationContext)getPortletContext().getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
       RepositoryUser user = (RepositoryUser)context.getBean("repositoryUser");
       Repository repository = user.getAlfrescoJcrRepository();
   
       // login to workspace (here we rely on the default workspace defined by JCR.Repository bean)
       Session session = null;
       try
       {
          session = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
           // first, access the company home
           Node rootNode = session.getRootNode();
           Node companyHome = rootNode.getNode("app:company_home/index.html");
             
           rResponse.setContentType("text/html");
          
           PrintWriter writer = rResponse.getWriter();
           String content = companyHome.getProperty("cm:content").toString();
          
           writer.write("Content:<P>");
           writer.write(content);
           writer.close();
      
           // save changes
           session.save();
       }
       catch(Exception e)
       {
          Log.error(this,"Something bad happened: ",e);
       }
   }   

   

So all of that done…the good news is it seems to get the JCR.Repository bean successfully via RMI.

The bad news is I'm getting Invalid credentials supplied for admin/admin. I tried this from the front-end and same deal.

I've seen this before and the solution has been to remove the alf_data folder and wipe the database…..but once this goes into production that won't exactly be a good solution.

Why does this happen if I start JBoss up in the same place I started it up before? I could understand it happening if I started it up in a different working dir than before because it would then create a new  alf_data folder.

trupoet
Champ in-the-making
Champ in-the-making
well looks like RMI isn't going to work after all because no objects (in JSR170 or Alfresco) implement Serializable

Now I'm looking into the webservice via SOAP to accomplish what I need to do.

Found some examples in the code and wiki but I can't seem to find the best/easiest way to just pull some content out that's already in there.

one example shows how to write and then read….I just want to read whats already in there.