Nel precedente articolo Single sourcing con Eclipse RAP abbiamo visto come realizzare un’applicazione Eclipse per poi eseguirla sia come applicazione Desktop (RCP) sia come applicazione Web (RAP).

Ora vedremo come spingerci oltre per sviluppare un’applicazione orientata ai database con lo stesso approccio duale Desktop/Web. Useremo EMF e Teneo per questo, nello stesso modo illustrato nella serie di tutorial “Dal Modello alla Persistenza” alla pagina Sviluppare con EMF.

Nelle seguenti istruzioni occorre fare una chiara distinzione fra installare delle feature nell’IDE oppure nella Target Platform (RAP nel nostro caso). L’installazione nell’IDE si esegue selezionando il menu Help -> Install New Software, mentre l’installazione nella Target Platform si esegue selezionando Window -> Preferences -> Plug-in Development -> Target Platform (vedi articolo Single sourcing con Eclipse RAP).

Iniziamo installando sul nostro IDE tutti i tool necessari:

Update site: Indigo (incluso) – http://download.eclipse.org/releases/indigo
Categoria: Modeling
Feature: EMF – Eclipse Modeling Framework SDK

Update site: Indigo (incluso) – http://download.eclipse.org/releases/indigo
Categoria: General Purpose Tools
Feature: Tutte le feature SWT Designer eccetto SWT Designer XWT Support (requires Eclipse WTP/WST) e tutte le feature WindowBuilder eccetto WindowBuilder XML Core

Update site: Elver (non incluso) – http://www.elver.org/eclipse/update
Categoria: Teneo/Texo Dependencies
Feature: tutte

Update site: Teneo 1.2.0 (non incluso) – http://download.eclipse.org/modeling/emf/teneo/updates/1.2.0/interim/
Categoria
: EMF Teneo – Hibernate
Feature: tutte

Ora aggiungiamo sulla RAP Target Platform i seguenti (tenendo presente che abbiamo già installato Rich Ajax Platform (RAP) Target Components e EMF RAP Target Components nel precedente tutorial):

Software site: Elver (non incluso) – http://www.elver.org/eclipse/update
Categoria
: Teneo/Texo Dependencies
Feature: tutte

Software site: Teneo 1.2.0 (non incluso) – http://download.eclipse.org/modeling/emf/teneo/updates/1.2.0/interim/
Categoria
: EMF Teneo – Hibernate
Feature: tutte

Ok ora siamo pronti per lo sviluppo in single sourcing. Per quanto riguarda il modello possiamo semplicemente Importare il plug-in di modello che abbiamo realizzato nel tutorial Eclipse EMF: modifiche al Modello. Mentre dobbiamo modificare l’attuale applicazione RCP/RAP (it.rcpvision.rcprap.application) nel modo seguente.

Nell’Activator effettuiamo la connessione al database e carichiamo i dati (c’è una sezione che effettua il popolamento solo la prima volta, quando il database è stato appena creato)

 

import java.io.IOException;
import java.util.Properties;

import library.Author;
import library.Library;
import library.LibraryFactory;
import library.LibraryPackage;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.teneo.hibernate.HbDataStore;
import org.eclipse.emf.teneo.hibernate.HbHelper;
import org.eclipse.emf.teneo.hibernate.resource.HibernateResource;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.hibernate.cfg.Environment;
import org.osgi.framework.BundleContext;

...

	public void start(BundleContext context) throws Exception {
		super.start(context);
		plugin = this;

		loadResource();
	}

	private void loadResource() {
		// *************** Initialize Teneo Hibernate DataStore *************************************
		HbDataStore hbds = (HbDataStore) HbHelper.INSTANCE.createRegisterDataStore("MyDb");
		// Set Database properties
		Properties props = new Properties();
		props.setProperty(Environment.DRIVER, "com.mysql.jdbc.Driver");
		props.setProperty(Environment.URL, "jdbc:mysql://localhost:3306/test5?createDatabaseIfNotExist=true");
		props.setProperty(Environment.USER, "root");
		props.setProperty(Environment.PASS, "admin");
		props.setProperty(Environment.DIALECT, org.hibernate.dialect.MySQL5Dialect.class.getName());
		props.setProperty(Environment.SHOW_SQL, "true");
		props.setProperty(Environment.HBM2DDL_AUTO, "update");
		hbds.setDataStoreProperties(props);
		// Register EMF package
		hbds.setEPackages(new EPackage[] { LibraryPackage.eINSTANCE });
		hbds.initialize();

		// *************** Initialize Database Content Data *************************************
		// (the first time a new Library object container is persisted, otherwise it is just loaded)
		String uriStr = "hibernate://?"+HibernateResource.DS_NAME_PARAM+"=MyDb";
		final URI uri = URI.createURI(uriStr);
		ResourceSet resourceSet = new ResourceSetImpl();
		resource = resourceSet.createResource(uri);
		try {
		    resource.load(null);
		    if (resource.getContents().size() == 0) {
		    	Library library = LibraryFactory.eINSTANCE.createLibrary();
		        resource.getContents().add(library);

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

	            author = LibraryFactory.eINSTANCE.createAuthor();
	            author.setName("Lars");
	            author.setSurname("Vogel");
	            library.getListAuthor().add(author);

	            author = LibraryFactory.eINSTANCE.createAuthor();
	            author.setName("Eike");
	            author.setSurname("Stepper");
	            library.getListAuthor().add(author);

	            author = LibraryFactory.eINSTANCE.createAuthor();
	            author.setName("Ralf");
	            author.setSurname("Sternberg");
	            library.getListAuthor().add(author);

	            author = LibraryFactory.eINSTANCE.createAuthor();
	            author.setName("Tom");
	            author.setSurname("Schindl");
	            library.getListAuthor().add(author);

	            resource.save(null);
		    }
		} catch (IOException e) {
		    // TODO Auto-generated catch block
		    e.printStackTrace();
		}
	}

ora riscriviamo la View come segue (come avete visto in altri nostri tutorial, abbiamo utilizzato un TableViewer con bind al contenuto della risorsa EMF caricata)

 

 

package it.rcpvision.rcprap.application;

import library.Author;
import library.Library;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.PojoObservables;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.jface.databinding.viewers.ObservableListContentProvider;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.part.ViewPart;

public class View extends ViewPart {
	public View() {
	}
	public static final String ID = "it.rcpvision.rcprap.application.view";
	private TableViewer viewer;
	private Table table;
	private WritableList writableList = new WritableList();
	private DataBindingContext m_bindingContext;

	public void createPartControl(Composite parent) {
		Library library = (Library) Activator.getDefault().getResource().getContents().get(0);
		writableList.addAll(library.getListAuthor());
		parent.setLayout(new GridLayout(1, false));

		viewer = new TableViewer(parent, SWT.BORDER | SWT.FULL_SELECTION);
		table = viewer.getTable();
		table.setLinesVisible(true);
		table.setHeaderVisible(true);
		table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1));

		TableViewerColumn tableViewerColumnName = new TableViewerColumn(viewer, SWT.NONE);
		TableColumn tblclmnName = tableViewerColumnName.getColumn();
		tblclmnName.setWidth(100);
		tblclmnName.setText("Name");

		TableViewerColumn tableViewerColumnSurname = new TableViewerColumn(viewer, SWT.NONE);
		TableColumn tblclmnSurname = tableViewerColumnSurname.getColumn();
		tblclmnSurname.setWidth(100);
		tblclmnSurname.setText("Surname");

		m_bindingContext = initDataBindings();
	}

	public void setFocus() {
	}
	protected DataBindingContext initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		ObservableListContentProvider listContentProvider = new ObservableListContentProvider();
		IObservableMap[] observeMap = PojoObservables.observeMaps(listContentProvider.getKnownElements(), Author.class, new String[]{"name", "surname"});
		viewer.setLabelProvider(new ObservableMapLabelProvider(observeMap));
		viewer.setContentProvider(listContentProvider);
		//
		viewer.setInput(writableList);
		//
		return bindingContext;
	}
}

 

è anche necessario aggiungere le seguenti dipendenze nel MANIFEST.MF

 

Require-Bundle: org.eclipse.ui;resolution:=optional,
 org.eclipse.core.runtime,
 org.eclipse.rap.ui;resolution:=optional,
 it.rcpvision.rcptutorial.model,
 org.eclipse.emf.teneo.hibernate,
 org.hibernate,
 com.mysql.jdbc,
 org.eclipse.emf.ecore.xmi,
 org.eclipse.core.databinding,
 org.eclipse.core.databinding.beans,
 org.eclipse.core.databinding.observable,
 org.eclipse.core.databinding.property,
 org.eclipse.jface.databinding;resolution:=optional,
 org.eclipse.rap.jface.databinding;resolution:=optional

 

come vedete abbiamo impostato come Opzionali le dipendenze verso org.eclipse.jface.databinding e org.eclipse.rap.jface.databinding.

Se ora lanciate questo stesso codice sorgente dal workspace RCP vedrete questo

 

mentre dal workspace RAP vedrete questo (Nota: in entrambi i casi potreste dover verificare che il lancio includa tutti i necessari plug-in/bundle; vedete il tab “Plug-ins“, tasto “Add Required Plug-ins” nel caso di RCP e il tab “Bundles“, tasto “Add Required Bundles” nel caso di RAP)

 

niente male, che ne dite?

 

Torna all’indice