Java Foundation API

Document created by resplin Employee on Jun 6, 2015
Version 1Show Document
  • View in full screen mode

Obsolete Pages{{Obsolete}}

The official documentation is at: http://docs.alfresco.com



Java_APIOverview


Introduction


Alfresco's Java Foundation API is a set of services providing full access to the capabilities of the Alfresco repository. It is an in-process API meaning that the client must sit within the same process as the repository. For example, the Alfresco Explorer Web Client uses this API and is packaged together with the repository in a single .war file for deployment to an application server.


Java Foundation API Reference


For reference material on the Java Foundation API, the first port of call is the Java Doc for the repository project which is updated with each nightly build.


Access to Java Foundation API


The Java Foundation API is in fact a set of interfaces; each interface represents a function of the repository. A Spring Framework Bean is provided as the implementation for each interface.

The list of available public services (that is, Spring beans) can be found in:


  1. the configuration file /projects/repository/config/alfresco/public-services-context.xml
  2. the service interface org.alfresco.service.ServiceRegistry

There are three approaches to accessing the interfaces in your own code:


  1. Use standard Spring dependency injection (recommended, if your client code is also Spring based)
  2. Manual access via the Spring getBean() method
  3. Indirectly via Alfresco's ServiceRegistry

Spring provides excellent documentation on how to bind Beans together, so that will not be duplicated here.


Alfresco ServiceRegistry


The ServiceRegistry maintains a list of available repository services and some meta-data about each. In particular, the ServiceRegistry provides access to each service interface. The registry is a service itself and therefore is accessed using either method 1 or 2 as described above.

The static variable SERVICE_REGISTRY found on the interface org.alfresco.service.ServiceRegistry provides the Spring Bean name to lookup by.

The following example demonstrates how to get hold of the Registry, determine if the Node Service is supported, and then access it, if it is.



  ApplicationContext appContext = new ClassPathXmlApplicationContext('alfresco/application-context.xml');

  ServiceRegistry registry = (ServiceRegistry)appContext.getBean(ServiceRegistry.SERVICE_REGISTRY);
  if (registry.isServiceProvided(ServiceRegistry.NODE_SERVICE)
  {
    NodeService nodeService = registry.getNodeService();
    ...

User Transaction


By default, each invocation of a Service method is wrapped in its own transaction. This has been configured via Spring.
To control the transaction boundary in your own client code, the following approaches may be taken:


  1. Use Spring declarative transaction demarcation (recommended, if your client is also Spring)
  2. Use Alfresco's UserTransaction support

Excellent documentation for method 1 can be found at the Spring Framework site.


Using RetryingTransactionHelper


The prefered method of manually controlling transactions is via the RetryingTransactionHelper.



                RetryingTransactionCallback<Object> txnWork = new RetryingTransactionCallback<Object>()
                {
                    public Object execute() throws Exception
                    {
                        // Do stuff
                        Object result = ...
                        return result;
                    }
                };
                TransactionService transactionService = serviceRegistry.getTransactionService();
                Object result = transactionService.getRetryingTransactionHelper().doInTransaction(txnWork, true);

By using the RetryingTransactionHelper the various concurrency strategies are automatically enforced, transaction rollback scenarios are properly handled and extensive logging can be switched on.

Transactions can be read-only or read-write and optionally continue with any existing transaction or start a completely new transaction.



    /**
     * Execute a callback in a transaction until it succeeds, fails
     * because of an error not the result of an optimistic locking failure,
     * or a deadlock loser failure, or until a maximum number of retries have
     * been attempted.
     *
     * It is possible to force a new transaction to be created or to partake in
     * any existing transaction.
     *
     * @param cb                The callback containing the unit of work.
     * @param readOnly          Whether this is a read only transaction.
     * @param requiresNew       true to force a new transaction or
     *                          false to partake in any existing transaction.
     * @return                  Returns the result of the unit of work.
     * @throws                  RuntimeException  all checked exceptions are converted
     */
    public <R> R doInTransaction(RetryingTransactionCallback<R> cb, boolean readOnly, boolean requiresNew)

Handling UserTransaction Directly


Alfresco's UserTransaction may be accessed via the ServiceRegistry as follows:



   UserTransaction trx = serviceRegistry.getTransactionService().getUserTransaction();

With a UserTransaction in hand, it is possible to mark the beginning and end of a transaction, thus forcing any service calls within the begin and end to be included in that transaction.  For example, the following two NodeService calls are wrapped in the same transaction.  Without the UserTransaction, the default behaviour would be for each NodeService call to be in its own transaction.



   NodeService nodeService = serviceRegistry.getNodeService();
   try
   {
     trx.begin();
     nodeService.createNode(...);
     nodeService.createNode(...);
     trx.commit();
   }
   catch(Throwable e)
   {
     try
     {
       if (trx.getStatus() == Status.STATUS_ACTIVE)
       {
          trx.rollback();
       }
     }
     catch(Throwable ee)
     {
       // Handle double exception in whatever way is appropriate eg. log it
     }

     throw e;
   }

Although the example shows the usage of one service, any mixture of Alfresco's public services can be pulled into the same transaction.

It is important to note that a UserTransaction cannot be re-used.  That is, once a commit or rollback has been issued, a new UserTransaction has to be retrieved (via getUserTransaction()) to begin another.

1 person found this helpful

Attachments

    Outcomes