Obsolete Pages{{Obsolete}}
The official documentation is at: http://docs.alfresco.com
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.
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.
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:
There are three approaches to accessing the interfaces in your own code:
Spring provides excellent documentation on how to bind Beans together, so that will not be duplicated here.
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();
...
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:
Excellent documentation for method 1 can be found at the Spring Framework site.
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)
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.