Introduzione a CDO

Questo framework, che è un componente del progetto EMF, permette la condivisione di un modello EMF.
Se con Teneo quindi possiamo fare in modo che ciascun client possa accedere ad un database (realizzando un client/server a due livelli), con CDO abbiamo la possibilità che i vari client accedano ad un server che mette loro a disposizione la medesima istanza, condivisa, del modello EMF.
In questo tutorial vedremo come:

  • installare CDO
  • creare un server CDO
  • creare un client CDO

Per una documentazione dettagliata su CDO potete consultare il seguente link http://www.eclipse.org/cdo/documentation/
Mentre qui potete scaricare le varie versioni http://www.eclipse.org/cdo/downloads/

Installazione di CDO

Vediamo quindi come installare CDO partendo dalla versione Eclipse 4.3 (Kepler) Modeling. CDO può essere utilizzato con diversi tipi di Store; in questo caso installeremo i necessari plugins per l’utilizzo di DBStore.

Inoltre visto che useremo un database MySQL dovremo anche assicurarci di aver installato il plug-in che contiene il JDBC driver corrispondente (se avete seguito il tutorial Setup Teneo per Eclipse 4.2 ÔÇô Juno potete saltare questo step).
(Nota: per l’esecuzione corretta di questo tutorial si consiglia di usare una versione di MySQL non superiore alla 5.5)

Update Site => http://www.elver.org/eclipse/2.0.0/update/

  • MySQL Connector/J

A questo punto installiamo Net4j DB Adapter per MySQL
Update Site =>
http://download.eclipse.org/modeling/emf/cdo/updates/releases

Espandiamo la categoria pi├╣ recente e selezioniamo:

CDO R
> Net4j DB Framework
>> Net4j DB Framework MYSQL Adapter

Creare un server CDO

In questa sezione vedremo come realizzare un prodotto Eclipse, basato su features, in grado di lanciare un server CDO attraverso un file di configurazione XML.

In terminologia Eclipse una feature rappresenta un gruppo di plug-ins che collaborano per la realizzazione di una determinata funzionalità.

Creiamo quindi un Feature Project selezionando File -> New -> Project… -> Plug-in Development -> Feature Project

premiamo Next e allo step successivo diamo un nome al nostro progetto, ad es. it.rcpvision.rcptutorial.cdo.server

poi Finish.

Quello che abbiamo ottenuto è una feature vuota; andiamo quindi a specificare (tab Plug-ins) da quali plug-ins è composta premendo il bottone Add… e aggiungendo i seguenti

Per comodità riportiamo di seguito il contenuto testuale del file feature.xml, modificabile attraverso il tab “feature.xml




   
      [Enter Feature Description here.]
   

   
      [Enter Copyright Description here.]
   

   
      [Enter License Description here.]
   

	
	
	
	
	
	 
	
	
	 
	 
	 
	 
	
	
	
	
	
	 
	 
	 
	 
	
	
	
	
	
	


A questo punto creiamo un product basato su questa feature, selezionando il progetto, tasto destro New -> Other… -> Plug-in Development -> Product Configuration

premiamo Next.

Allo step successivo diamo un nome al nostro Prodotto, ad es. CDO-Server.product,

selezioniamo il radio-button “Use an existing product” e nella combo a fianco del radio-button selezionato impostiamo il valore “org.eclipse.emf.cdo.server.product.tcp_h2“, poi Finish.

Ciò che abbiamo ottenuto è un prodotto, basato però su plug-ins.

per basarlo su features dobbiamo selezionare il secondo radio-button

a questo punto, per indicare da quali features è composto il prodotto, selezioniamo il tab Dependencies

premiamo il bottone Add…

e selezioniamo la feature creata in precedenza (it.rcpvision.rcptutorial.cdo.server)

e salviamo il prodotto (Ctrl-S).

Dobbiamo ora definire il file XML di configurazione per CDO. Selezioniamo quindi il progetto e creiamo una cartella chiamata “rootfiles” con tasto destro New -> Folder

e poi un’altra sottocartella chiamata “configuration

all’interno di quest’ultima creiamo un file (tasto destro, New -> File) chiamato cdo-server.xml e copiamo all’interno del file il seguente contenuto



 
    
    
 
    
 
        
            
            
            
        
    
 


In pratica questo file di configurazione indica che il server CDO sarà attivo sulla porta TCP 2036 e metterà a disposizione un repository CDO chiamato “demo“. Seguono le coordinate per l’accesso al database.

Notate che al primo avvio o dopo modifiche al modello, è opportuno effettuare un preventivo drop del database; esso verrà creato all’avvio del server.

Prima di lanciare il server dobbiamo ancora indicare il valore del parametro che specifica la posizione del file di configurazione appena creato. Per fare questo selezioniamo nuovamente il prodotto, andiamo nel tab Launching e nella sezione VM Arguments indichiamo

-Dnet4j.config=${resource_loc:/it.rcpvision.rcptutorial.cdo.server/rootfiles/configuration}

salviamo il prodotto, torniamo sul tab Overview e lanciamo, con

Launch An Eclipse Application

La console dovrebbe presentare un output che termina con

!MESSAGE CDO server started

Verificate ora che il database sia stato creato correttamente.

(Nota: se ricevete messaggi di errore assicuratevi che il firewall di sistema non stia bloccando le porte 2036 e 3306)

Bene, ora all’indirizzo di rete della macchina in questione, alla porta di Net4j configurata (2036) è a disposizione il CDO repositorydemo“.

Un’ultima osservazione: in vista di un successivo deploy del prodotto è opportuno indicare che esso deve comprendere anche il file di configurazione. Per fare ciò apriamo il file build.properties, andiamo sul tab Build e nella sezione “Binary Build” selezioniamo la cartella “rootfiles“.

Creare un client CDO

Useremo anche qui lo stesso modello EMF (il plug-in it.rcpvision.rcptutorial.model) usato in precedenza e illustrato nel tutorial Eclipse EMF: Progettare il Modello. Nel caso stiate per rifare quel tutorial, tenete conto che stavolta, al momento della creazione dell’EMF Generator Model (.genmodel), allo step “Select a Model Importer” dovrete selezionare “Ecore model (CDO Native)“.

Altrimenti, se avete già pronto il precedente plugin di model (creato senza la compatibilità con CDO) potete convertirlo selezionando il file .genmodel e premendo tasto destro CDO -> Migrate EMF Generator Model (dynamic feature delegation)

e naturalmente rigenerando i sorgenti

inoltre è necessario in questo caso aggiungere, nel plug-in it.rcpvision.rcptutorial.model, la dipendenza da CDO

Siamo finalmente pronti per realizzare il nostro client. Creiamo quindi un’applicazione RCP nel solito modo (vedi Come creare unÔÇÖapplicazione Eclipse RCP) e aggiungiamo le seguenti dipendenze:

  • it.rcpvision.rcptutorial.model
  • org.eclipse.emf.cdo.net4j
  • org.eclipse.net4j.tcp
  • org.junit

Creiamo ora una classe chiamata “TestCdoClient” nel package principale, con il seguente contenuto

package it.rcpvision.rcptutorial.application;

import library.Author;
import library.Book;
import library.Library;
import library.LibraryFactory;

import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.net4j.CDONet4jSession;
import org.eclipse.emf.cdo.net4j.CDONet4jSessionConfiguration;
import org.eclipse.emf.cdo.net4j.CDONet4jUtil;
import org.eclipse.emf.cdo.transaction.CDOTransaction;
import org.eclipse.emf.cdo.util.CommitException;
import org.eclipse.net4j.Net4jUtil;
import org.eclipse.net4j.connector.IConnector;
import org.eclipse.net4j.tcp.TCPUtil;
import org.eclipse.net4j.util.container.IPluginContainer;
import org.eclipse.net4j.util.lifecycle.ILifecycle;
import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter;
import org.junit.BeforeClass;
import org.junit.Test;

public class TestCdoClient {

    private static CDONet4jSession cdoSession;

    @BeforeClass
    public static void init() {
        //The following lines are not needed if the extension 
        //registry (OSGi/Equinox) is running
        Net4jUtil.prepareContainer(IPluginContainer.INSTANCE);
        TCPUtil.prepareContainer(IPluginContainer.INSTANCE);

        cdoSession = openSession("demo");
    }

    @Test
    public void popola() {
        try {
            CDOTransaction transaction = cdoSession.openTransaction();
            CDOResource resource = transaction.getOrCreateResource("/myResource");
            Library library = LibraryFactory.eINSTANCE.createLibrary();

            Book book = LibraryFactory.eINSTANCE.createBook();
            book.setTitle("Eclipse Modeling Framework (2nd edition)");
            library.getListBook().add(book);

            Author author = LibraryFactory.eINSTANCE.createAuthor();
            author.setName("Ed");
            author.setSurname("Merks");
            library.getListAuthor().add(author);
            book.getAuthor().add(author);

            author = LibraryFactory.eINSTANCE.createAuthor();
            author.setName("Marcelo");
            author.setSurname("Paternostro");
            library.getListAuthor().add(author);
            book.getAuthor().add(author);

            author = LibraryFactory.eINSTANCE.createAuthor();
            author.setName("Frank");
            author.setSurname("Budinsky");
            library.getListAuthor().add(author);
            book.getAuthor().add(author);

            author = LibraryFactory.eINSTANCE.createAuthor();
            author.setName("David");
            author.setSurname("Steinberg");
            library.getListAuthor().add(author);
            book.getAuthor().add(author);

            resource.getContents().add(library);
            transaction.commit();
            cdoSession.close();

        } catch (CommitException e) {
            e.printStackTrace();
        } finally {
            cdoSession.close();
        }
    }

    public static CDONet4jSession openSession(String repoName) {
        final IConnector connector = (IConnector) IPluginContainer.INSTANCE
                .getElement( //
                        "org.eclipse.net4j.connectors", // Product group
                        "tcp", // Type
                        "localhost"); // Description

        CDONet4jSessionConfiguration config = CDONet4jUtil
                .createNet4jSessionConfiguration();
        config.setConnector(connector);
        config.setRepositoryName(repoName);

        CDONet4jSession session = config.openNet4jSession();

        session.addListener(new LifecycleEventAdapter() {
            @Override
            protected void onDeactivated(ILifecycle lifecycle) {
                connector.close();
            }
        });

        return session;
    }

}

Come potete osservare si tratta di un test JUnit che si connette al repository “demo” disponibile all’indirizzo “localhost” (se il client viene eseguito su una macchina diversa questo indirizzo deve ovviamente essere quello dove gira il server CDO). Vengono poi create istanze degli oggetti del modello e salvate all’interno di una transazione CDO.

Lanciamola con tasto destro Run As -> JUnit Test

Se il tutto ha girato correttamente dovreste vedere un esito positivo sulla View di JUnit

e sul database troverete i dati inseriti.

Notate che abbiamo creato un’applicazione RCP e poi abbiamo in realtà utilizzato CDO da una semplice classe (standalone) di JUnit. Questo è stato fatto per due ragioni:

  • per brevità di tutorial (ci è bastato aggiungere alcune dipendenze nel tab Dependencies)
  • per dimostrare la facilità con cui è possibile accedere ad un server CDO (non è necessario avere OSGi/Equinox in esecuzione)

Nei tutorial che seguiranno peraltro ci troveremo spesso a realizzare applicazioni RCP che accedono ad un CDO server repository.

Per sviluppo o consulenza su CDO   info@rcp-vision.com

Per informazioni sulla formazione su CDO   training@rcp-vision.com

Torna allÔÇÖindice