Run a CDO container inside eclipse runtime

From Eclipsepedia

Jump to: navigation, search

Contents

Run a CDO container inside eclipse runtime

If you want to use the CDO container inside an eclipse runtime, create a plug-in project managing the resouces (e.g. the connection) and use this code to prepare your activator.

Core code

The plugin's activator class could look like this:

package your.packagename.here;
 
import java.util.HashMap;
import java.util.Map;
 
import org.eclipse.emf.cdo.CDOSession;
import org.eclipse.emf.cdo.CDOSessionConfiguration;
import org.eclipse.emf.cdo.CDOTransaction;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.server.CDOServerUtil;
import org.eclipse.emf.cdo.server.IRepository;
import org.eclipse.emf.cdo.server.IStore;
import org.eclipse.emf.cdo.server.IRepository.Props;
import org.eclipse.emf.cdo.server.hibernate.teneo.TeneoHibernateMappingProvider;
import org.eclipse.emf.cdo.server.internal.hibernate.HibernateStore;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.teneo.PersistenceOptions;
import org.eclipse.net4j.connector.IConnector;
import org.eclipse.net4j.jvm.IJVMAcceptor;
import org.eclipse.net4j.jvm.IJVMConnector;
import org.eclipse.net4j.jvm.JVMUtil;
import org.eclipse.net4j.util.container.IManagedContainer;
import org.eclipse.net4j.util.container.IPluginContainer;
import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
 
public class Activator extends AbstractUIPlugin {
 
	/**
	 * The shared instance
	 */
	private static Activator plugin;
 
	/**
	 * The Plugin ID
	 */
	public static final String PLUGIN_ID = "your.plugin.id.here";
 
	/**
	 * The repository name
	 */
	private static final String REPOSITORY_NAME = "your_repositoryname";
 
	/**
	 * Returns the shared instance
	 * 
	 * @return the shared instance
	 */
	public static Activator getDefault() {
		return plugin;
	}
 
	private IJVMAcceptor acceptor = null;
	private IConnector connector = null;
	private IRepository repository = null;
	private CDOResource resource = null;
	private CDOSession session = null;
	private CDOTransaction transaction = null;
 
	/**
	 * The constructor
	 */
	public Activator() {
	}
 
 
	/**
	 * The usual start implementation ...
	 */
	public void start(BundleContext context) throws Exception {
		super.start(context);
		plugin = this;
	}
 
	/**
	 * The usual stop implementation ... BUT including some CDO cleanup.
	 */
	public void stop(BundleContext context) throws Exception {
		plugin = null;
 
		if (resource != null)
			LifecycleUtil.deactivate(resource);
 
		if (transaction != null)
			LifecycleUtil.deactivate(transaction);
 
		if (session != null)
			LifecycleUtil.deactivate(session);
 
		if (acceptor != null)
			LifecycleUtil.deactivate(acceptor);
 
		if (connector != null)
			LifecycleUtil.deactivate(connector);
 
		if (repository != null)
			LifecycleUtil.deactivate(repository);
 
		super.stop(context);
	}
 
	/**
	 * Getter for session including lazy initialization
	 * 
	 * @return the CDO session
	 */
	public CDOSession getSession() {
		if (session == null) {
			IManagedContainer container = IPluginContainer.INSTANCE;
 
			// initialize acceptor
			if (acceptor == null)
				acceptor = JVMUtil.getAcceptor(container, "default");
 
			if (repository == null) {
				repository = createRepository();
				CDOServerUtil.addRepository(container, repository);
			}
 
			if (connector == null)
				connector = JVMUtil.getConnector(container, "default");
 
			CDOSessionConfiguration config = CDOUtil
					.createSessionConfiguration();
			config.setConnector(connector);
			config.setRepositoryName(REPOSITORY_NAME);
			config.setLegacySupportEnabled(false);
 
			// see explanation below
			config.setLazyPopulatingPackageRegistry();
 
			session = config.openSession();
		}
		return session;
	}
 
	/**
	 * Getter for transaction including lazy initialization
	 * 
	 * @return the transaction
	 */
	public CDOTransaction getTransaction() {
		if (transaction == null) {
			transaction = getSession().openTransaction();
		}
 
		return transaction;
	}
 
	/**
	 * Getter for resource (e.g. if you use only one central resource)
	 * 
	 * @return the resource
	 */
	public CDOResource getResource() {
		if (resource == null) {
			/*
			 * getOrCreateResource will handle both loading existing resources
			 * (equivalent to transaction.getResource()) and
			 * creating/initializing a new one (equivalent to
			 * transaction.createResource())
			 */
			resource = getTransaction().getOrCreateResource("/test");
		}
 
		return resource;
	}
 
	/** 
	 * Create and initialize/configure a repository 
	 * 
	 * @return the CDO repository created
	 */
	private IRepository createRepository() {
                // see below 
        }
 
	/** 
	 * create the CDO store 
	 * @return the CDO store to use with the repository 
	 */
	private IStore createStore() {
                // see below
	}	
}

Package Registry selection

In the code above, we use the config.setLazyPopulatingPackageRegistry(); call. CDO keeps track of packages in its own registry which is separate from the general EMF package registry. To populate the registry, you have three possibilities:

Manual package registration

You can do manual package registration. With this, the package registry is empty by default and you can manually register the packages you need using code like this:

session.getPackageRegistry().putEPackage(YourModelPackage1.eINSTANCE);
session.getPackageRegistry().putEPackage(YourModelPackage2.eINSTANCE);

Using the manual package registration is the default if you omit the config.setLazyPopulatingPackageRegistry(); call in the code above.

Automatic package registration based on EMF registry

If you use config.setEagerPopulatingPackageRegistry(); instead of config.setLazyPopulatingPackageRegistry(); in the code above, you activate the automatic package registration based on the EMF registry.

The EMF registry itself is populated by looking for all plugins which extend the generated_package extension point. The declaraion of the extension is automagically generated during the regular EMF model code generation process. So if your package is not being registered you should check the plugin.xml of the model plugin.

The self-populating package registry queries the EMF package registry when it is activated and registers all packages currently registered with the EMF registry.

Automatic package registration on demand

If you use config.setLazyPopulatingPackageRegistry();, like in the code above, you activate CDO package registration on demand. This registers packages on the fly, as soon as a class of an unknown package is added to the database.

Store configuration

In the code above, the methods createRepository and createStore have been left out. In these methods, you can configure the store which is going to be used to store CDO objects.

There are three possibilities here:

Memory store

The memory store is transient in the sense that elements are lost when the application ends. So this store is mostly useful for testing purposes, as the memory store is the fastest storing strategy.

You configure it like this:

private IRepository createRepository() {
	Map<String, String> props = new HashMap<String, String>();
	    props.put(Props.PROP_SUPPORTING_REVISION_DELTAS, "false"); 
	    props.put(Props.PROP_CURRENT_LRU_CAPACITY, "10000");
	    props.put(Props.PROP_REVISED_LRU_CAPACITY, "10000");
	return CDOServerUtil.createRepository(REPOSITORY_NAME, createStore(), props); 
}
 
private IStore createStore() {
	return StoreUtil.createMEMStore();
        // In CDO >4.0 the respective entry is rg.eclipse.emf.cdo.server.mem.MEMStoreUtil.createMEMStore();
}

For an explanation of the Props.* configuration options see CDO Server Configuration.

CDO Database store

The CDO database store can be used to store models in databases. The mapping is determined and configured with the mapping strategy. CDO currently supports MySQL, Derby, and HSQLDB. Using this store you are able to use all CDO features including full persistent model versioning.

To initialize the store (here with MySQL), use the createRepository method from the memory store above, but replace createStore with:

private IStore createStore() {
	final String DATABASE_NAME = "mydatabase";
	final String DATABASE_USER = "scott";
	final String DATABASE_PASS = "tiger";
 
	MysqlDataSource myDataSource = new MysqlDataSource();
	myDataSource.setUser(DATABASE_USER);
	myDataSource.setPassword(DATABASE_PASS);
	myDataSource.setAutoReconnect(true);
	myDataSource.setDatabaseName(DATABASE_NAME);
	myDataSource.setPort(3306);
	myDataSource.setServerName("localhost");
		IMappingStrategy mappingStrategy = 
	    CDODBUtil.createMappingStrategy("horizontal");
	IDBStore store = CDODBUtil.createStore(
	               mappingStrategy,
	                DBUtil.getDBAdapter("mysql"),
	                DBUtil.createConnectionProvider(myDataSource),
                       CDODBUtil.createNonPreparedStatementJDBCDelegateProvider());
 
	mappingStrategy.setStore(store); 
 
	return store;
}

Hibernate store

The hibernate store uses Hibernate for storing CDO objects. In addition the Hibernate store supports HQL querying on the client. You can either define a model<->DB mapping yourself or let CDO generate a mapping on the fly using the model<->DB mapping technology from the Teneo project. The automatic mapping can be manually overridden using JPA annotations in the model or in a separate XML file. Basically all JPA annotations (and several Hibernate extensions) are supported.

The CDO Hibernate Store is described in much more detail in the following page (and its subpages): CDO Hibernate Store description and tutorials