eXo Platform 3.5

## Chapter 6. Using JCR

## 1 Using eXo JCR in an application

### Obtaining a Repository object

A javax.jcr.Repository object can be obtained by:

- Using the eXo Container "native" mechanism. All Repositories are kept with a single RepositoryService component. So it can be obtained from eXo Container, described as the following:

                RepositoryService repositoryService = (RepositoryService) container.getComponentInstanceOfType(RepositoryService.class);

      Repository repository = repositoryService.getRepository("repositoryName");

- Using the eXo Container "native" mechanism with a thread local saved "current" repository (especially if you plan to use a single repository which covers more than 90% of use cases)

      // set current repository at initial time

      RepositoryService repositoryService = (RepositoryService) container.getComponentInstanceOfType(RepositoryService.class);

      repositoryService.setCurrentRepositoryName("repositoryName");

      ....

      // retrieve and use this repository

      Repository repository = repositoryService.getCurrentRepository();

- Using JNDI as specified in JSR-170. This way you have to configure the reference (see eXo JNDI Naming configuration )

      Context ctx = new InitialContext();

      Repository repository =(Repository) ctx.lookup("repositoryName");

### JCR Session common considerations

- Remember that javax.jcr.Session is not a thread safe object. Never try to share it between threads.

- Do not use System session from the user related code because a system session has unlimited rights. Call ManageableRepository.getSystemSession() from process related code only.

- Call Session.logout() explicitly to release resources assigned to the session.

- When designing your application, take care of the Session policy inside your application. Two strategies are possible: Stateless (Session per business request) and Stateful (Session per User) or some mix.

## JCR Application practices

### Simplifying the management of a multi-workspace application

(one-shot logout for all opened sessions)

Use org.exoplatform.services.jcr.ext.common.SessionProvider which is responsible for caching/obtaining your JCR Sessions and closing all opened sessions at once.

    public class SessionProvider {

      /**

       * Creates a SessionProvider for a certain identity

       * @param cred

       */

      public SessionProvider(Credentials cred)

      /**

       * Gets the session from internal cache or creates and caches a new one

       */

      public Session getSession(String workspaceName, ManageableRepository repository)

        throws LoginException, NoSuchWorkspaceException, RepositoryException

      /**

       * Calls a logout() method for all cached sessions

       */

      public void close()

      /**

       * a Helper for creating a System session provider

       * @return System session

       */

      public static SessionProvider createSystemProvider()

      /**

       * a Helper for creating an Anonimous session provider

       * @return System session

       */

      public static SessionProvider createAnonimProvider()

    }

The SessionProvider is per-request or per-user object, depending on your policy. Create it with your application before performing JCR operations, use it to obtain the Sessions and close at the end of an application session(request). See the following example:

    // (1) obtain current javax.jcr.Credentials, for example get it from AuthenticationService

    Credentials cred = ....

    // (2) create SessionProvider for current user

    SessionProvider sessionProvider = new SessionProvider(ConversationState.getCurrent());

    // NOTE: for creating an Anonymous or System Session use  the corresponding static SessionProvider.create...() method

    // Get appropriate Repository as described in "Obtaining Repository object" section for example

    ManageableRepository repository = (ManageableRepository) ctx.lookup("repositoryName");

    // get an appropriate workspace's session

    Session session = sessionProvider.getSession("workspaceName", repository);

     .........

    // your JCR code

     .........

     // Close the session provider

     sessionProvider.close();

### Reusing SessionProvider

As shown above, creating the SessionProvider involves multiple steps and you may not want to repeat them each time you need to get a JCR session. In order to avoid all this plumbing code, we provide the SessionProviderService whose goal is to help you to get a SessionProvider object.

The org.exoplatform.services.jcr.ext.app.SessionProviderService interface is defined as follows:

    public interface SessionProviderService {

      void setSessionProvider(Object key, SessionProvider sessionProvider);

      SessionProvider getSessionProvider(Object key);

      void removeSessionProvider(Object key);

    }

Using this service is pretty straightforward, the main contract of an implemented component is getting a SessionProvider by key. eXo provides two implementations :

Implementation | Description | Typical Use
--- | --- | ---
org.exoplatform.services.jcr.ext.app.MapStoredSessionProviderService | per-user style : keeps objects in a Map | per-user. The usual practice uses a user's name or Credentials as a key.
org.exoplatform.services.jcr.ext.app.ThreadLocalSessionProviderService | per-request style : keeps a single SessionProvider in a static ThreadLocal variable | Always use null for the key.

For any implementation, your code should follow the following sequence :

- Call SessionProviderService.setSessionProvider(Object key, SessionProvider sessionProvider) at the beginning of a business request for Stateless application or application's session for Statefull policy.

- Call SessionProviderService.getSessionProvider(Object key) for obtaining a SessionProvider object

- Call SessionProviderService.removeSessionProvider(Object key) at the end of a business request for Stateless application or application's session for Statefull policy.