eXo Platform 3.5

## Chapter 48. How-to implement Workspace Data Container

## Short intro about Workspace data container implementation practices:

1. Read a bit about the contract.

2. Start new implementation project pom.xml with org.exoplatform.jcr parent. (optional, but will makes the development easy)

3. Update sources of JCR Core and read JavaDoc on org.exoplatform.services.jcr.storage.WorkspaceDataContainer and org.exoplatform.services.jcr.storage.WorkspaceStorageConnection interfaces. They are the main part for the implemenation.

4. Look at org.exoplatform.services.jcr.impl.dataflow.persistent.WorkspacePersistentDataManager sourcecode, check how data menager uses container and its connections (see in save() method)

5. Create WorkspaceStorageConnection dummy implementation class. It's freeform class, but to be close to the eXo JCR, check how to implement JDBC or SimpleDB containers ( org.exoplatform.services.jcr.impl.storage.jdbc.JDBCStorageConnection and org.exoplatform.services.jcr.aws.storage.sdb.SDBWorkspaceStorageConnection). Take in account usage of ValueStoragePluginProvider in both implementations.Value storage is an useful option for production versions. But leave it to the end of implementation work.

6. Create the connection implementation unit tests to play TTD. (optional, but takes many benefits for the process)

7. Implement CRUD starting from the read to write etc. Test the methods by using the external implementation ways of data read/write in your backend.

8. When all methods of the connection done start WorkspaceDataContainer. Container class is very simple, it's like a factory for the connections only.

9. Care about container reuseConnection(WorkspaceStorageConnection) method logic. For some backends, it cab be same as openConnection(), but for some others, it's important to reuse physical backend connection, e.g. to be in the same transaction - see JDBC container.

10. It's almost ready to use in data manager. Start another test and go on.

When the container will be ready to run as JCR persistence storage (e.g. for this level testing), it should be configured in Repository configuration.

Assuming that our new implementation class name is org.project.jcr.impl.storage.MyWorkspaceDataContainer.

      <repository-service default-repository="repository">

      <repositories>

        <repository name="repository" system-workspace="production" default-workspace="production">

          .............

          <workspaces>

            <workspace name="production">

              <container class="org.project.jcr.impl.storage.MyWorkspaceDataContainer">

                <properties>

                  <property name="propertyName1" value="propertyValue1" />

                  <property name="propertyName2" value="propertyValue2" />

                  .......

                  <property name="propertyNameN" value="propertyValueN" />

                </properties>

                <value-storages>

                  .......

                </value-storages>

              </container>

Container can be configured by using set properties.

## Notes on Value storage usage:

Value storages are pluggable to the container but if they are used, the container implementation should respect set of interfaces and external storage usage principles.

If the container has ValueStoragePluginProvider (e.g. via constructor), it's just a few methods to manipulate external Values data.

    // get channel for ValueData write (add or update)

    ValueIOChannel channel = valueStorageProvider.getApplicableChannel(data,  i);

    if (channel == null) {

      // write

      channel.write(data.getIdentifier(),  vd);

      // obtain storage id,  id can be used for linkage of external ValueData and PropertyData in main backend

      String storageId = channel.getStorageId();

    }

    ....

    // delete all Property Values in external storage

    ValueIOChannel channel = valueStorageProvider.getChannel(storageId);

    channel.delete(propertyData.getIdentifier());

    ....

    // read ValueData from external storage

    ValueIOChannel channel = valueStorageProvider.getChannel(storageId);

    ValueData vdata = channel.read(propertyData.getIdentifier(),  orderNumber,  maxBufferSize);

### Important

After a sequence of write and/or delete operations on the storage channel, the channel should be committed (or rolled back on an error). See ValueIOChannel.commit() and ValueIOChannel.rollback() and how those methods are used in JDBC container.