Eclipse EMF: un CRUD immediato per database

Eclipse EMF: un CRUD immediato per database

Il presente tutorial presuppone che siano stati seguiti prima i seguenti altri articoli nell’ordine indicato:

  1. Eclipse EMF: Progettare il Modello
  2. Eclipse EMF: un CRUD a costo zero

ed ha l’obiettivo di dimostrare come, con pochissime modifiche al codice generato da EMF, sia possibile ottenere la persistenza del solito modello usato nei tutorial precedenti su un database relazionale. Useremo MySQL come target database, quindi verificate di averlo a disposizione (in locale o in rete) e di potervi accedere (eventualmente potete scaricarlo all’indirizzo http://www.mysql.com/downloads/mysql). Assumeremo di usare il database schema “test” (precaricato vuoto durante l’installazione di MySQL), tuttavia potete usare uno schema diverso semplicemente modificando le proprietà di connessione al database.

Per poter seguire questo tutorial è necessario disporre di alcuni plugin aggiuntivi per Eclipse. In questa guida trovate tutti i dettagli su come aggiornare correttamente il vostro IDE:

Setup Teneo per Eclipse 4.2 ÔÇô Juno

Partiamo quindi dal punto in cui eravamo rimasti dall’ultimo tutorial e apriamo il file plugin.xml del plugin di editor generato in modo automatico da EMF (it.rcpvision.rcptutorial.model.editor).

Selezioniamo il tab Dependencies

e aggiungiamo le seguenti dipendenze (premendo il bottone Add… nella sezione Required Plug-ins):

  • org.eclipse.emf.teneo.hibernate
  • org.hibernate
  • com.mysql.jdbc

salviamo (Ctrl-S) e apriamo la classe LibraryEditorAdvisor.java, in corrispondenza del metodo initialize().

introducendo le seguenti modifiche:

innanzitutto marchiamo il metodo come @generated not, in modo tale che una eventuale successiva rigenerazione del codice (ad es. resa necessaria da una modifica del modello) non sovrascriva le modifiche che andremo ad apportare

e aggiugiamo il seguente blocco di codice dopo l’istruzione

configurer.setSaveAndRestore(true);

Le import necessarie sono:

 

 

Non entreremo nel dettaglio delle singole operazioni che esegue questa parte di codice (questo sarà eventualmente oggetto di altri articoli), ma ecco sintetizzate le azioni che vengono effettuate:

  • viene inizializzato l’Hibernate DataStore di Teneo indicando le coordinate del database (URL, credenziali, tipo, ecc…). Qui potreste ritenere opportuno modificare il parametro Environment.URL per farlo corrispondere al nome dello schema MySQL (nell’esempio “test“) che intendete utilizzare, mentre dovete assicurarvi che le credenziali (USER e PASS) per l’accesso al database siano le quelle giuste per voi.
    Il parametro HBM2DDL_AUTO impostato al valore “update” permette al database di “adattarsi” (per quanto possibile attraverso opportune istruzioni SQL di ALTER TABLE automatiche) all’evoluzione del modello. Un valore di “create-drop” invece provocherebbe una creazione da zero del database ad ogni avvio (sebbene questa operazione possa sembrare inutile, risulta invece fondamentale durante le sessioni di test in quanto le condizioni iniziali in quel caso devono essere sempre le stesse)
  • viene realizzata una connessione al ResourceSet (un concetto proprio di EMF e trasversale rispetto all’implementazione scelta per la persistenza!) verso il DataStore appena inizializzato. Questo viene fatto in quanto, prima di partire, dobbiamo assicurarci di avere un oggetto Library persistito, che farà da contenitore per tutto ciò che gestiremo. Quindi carichiamo, con resource.load(null), le risorse e verifichiamo che esista una Library; in caso negativo (la prima volta) la creiamo.
  • viene aperto un Editor (proprio quello generato da EMF per il nostro modello) passando come input l’URI verso il DataStore creato.

Ecco fatto: non vi resta che lanciare l’applicazione.

Nota: dovreste avere a disposizione il lancio in Run
-> Run History
-> it.rcpvision.rcptutorial.model.editor.LibraryEditorAdvisorApplication
dall’ultimo tutorial.

In ogni caso potete sempre effettuare il lancio aprendo il file plugin.xml dell’Editor, tab Overview, hyperlink Launch an Eclipse Application.

 

Se il lancio avviene con successo (altrimenti effettuate un Clean e un Controllo del lancio) dovreste vedere, la prima volta, i seguenti messaggi sulla console

questo significa che l’inserimento iniziale dell’oggetto Library è avvenuto con successo.

L’applicazione invece dovrebbe presentarsi così:

e a questo punto potete iniziare a popolare la Library con oggetti di tipo Author e Book opportunamente relazionati fra loro, come nel precedente tutorial Eclipse EMF: un CRUD a costo zero.
Solo che stavolta i dati vengono resi persistenti sul database, come potete verificare dai messaggi in console e sul database stesso!

Vedremo prossimamente come sviluppare velocemente applicazioni RCP basate su EMF utilizzando il designer visuale WindowBuilder.

Torna all’indice

org.hibernate.cfg.

Environment

2013-01-20T10:57:25+00:00By |

14 Comments

  1. Glen 28 luglio 2012 at 19:58 - Reply

    Hi,

    I can’t get this to work with Juno, I keep getting:

    org.eclipse.emf.teneo.hibernate.HbMapperException: No HbDataStore can be found using the uri hibernate://dsname=MyDb
    at org.eclipse.emf.teneo.hibernate.resource.HibernateResource.(HibernateResource.java:145)
    at org.eclipse.emf.teneo.hibernate.resource.HibernateResourceFactory.createResource(HibernateResourceFactory.java:36)
    at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.createResource(ResourceSetImpl.java:434)
    at org.eclipse.emf.ecore.resource.impl.ResourceSetImpl.createResource(ResourceSetImpl.java:423)

    The URI is correct in the code (with the ? – in fact I copied and pasted the above code to make sure) but collapses when trying to open the editor.

    Any ideas?

    • Vincenzo 16 agosto 2012 at 10:50 - Reply

      Hi Glen,
      the URI should be
      hibernate://?dsname=MyDb
      Do you have a running MySQL instance with the following parameters?

      props.setProperty(Environment.DRIVER, "com.mysql.jdbc.Driver");
      props.setProperty(Environment.URL, "jdbc:mysql://localhost:3306/test");
      props.setProperty(Environment.USER, "root");
      props.setProperty(Environment.PASS, "your-password");
      props.setProperty(Environment.DIALECT, org.hibernate.dialect.MySQL5Dialect.class.getName());

  2. Glen 29 luglio 2012 at 10:38 - Reply
    • Vincenzo 16 agosto 2012 at 10:58 - Reply

      Glen,
      in this cases try to create a brand new workspace and then Import the projects from old workspace.
      Sometimes the .metadata folder within the workspace may become inconsistent (especially if you use it with different Eclipse versions or different versions of other plugins). Creating a new workspace (or deleting .metadata in current workspace) will reset the setup.

  3. Glen 29 luglio 2012 at 10:39 - Reply

    Tried to post a URL to an Eclipse bug in there; bug 381555, didn’t seem to work.

  4. Darren 30 maggio 2013 at 17:06 - Reply

    I couldn’t get this working due to a ClassNotFoundException

    java.lang.ClassNotFoundException: org.eclipse.emf.teneo.hibernate.HbMapperException
    at org.eclipse.osgi.internal.loader.BundleLoader.findClassInternal(BundleLoader.java:501)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:421)
    at org.eclipse.osgi.internal.loader.BundleLoader.findClass(BundleLoader.java:412)
    at org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader.loadClass(DefaultClassLoader.java:107)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at example2.presentation.Example2EditorAdvisor.initialize(Example2EditorAdvisor.java:563)

    Whilst doing:
    (HbDataStore) HbHelper.INSTANCE
    .createRegisterDataStore(“MyDb”);

    On closer inspection, the class
    org.eclipse.emf.teneo.hibernate.HbMapperException

    is not present in the org.eclipse.emf.teneo.hibernate plug-in (which is present as a dependency of my plug-in).

    Any idea what this is all about?

    Thanks,

    Darren

  5. Darren 30 maggio 2013 at 18:07 - Reply

    Sorry, I had wrong versions of some stuff loaded. It’s working fine now.
    It can be tricky getting a consistent set of features/plug-ins together in Eclipse, but fortunately all is well now.
    I must say that the off-the-shelf database integration (hibernate MySQL in this case) is very cool.

    Darren

  6. Leo 17 settembre 2013 at 05:48 - Reply

    Hi Vincenzo,

    So far your tutorials are the only tutorials that I know that are integrating EMF with other tools. However, I still have to do more research in order to get it works beautifully so it have not reached to the ‘one stop solution’ yet. But nonetheless, your tutorials are very great for beginner like myself and I wouldn’t get to experience EMF in a good way without them, so thank you for that.

    I use Eclipse 4.2 (Juno) and when I try this one (integrating EMF with Teneo/Hibernate with MySQL), sometimes it works just like your tutorial and sometime I encounter errors and cannot show the runtime (it’s frustrating when I encounter that error). I do find a solution for my problem when I see http://www.eclipse.org/articles/Article-EMF-goes-RCP/rcp.html especially in “Testing the application” section. Using new configuration, the runtime will always work every time, so the first problem is solved now.

    Now for the second problem, I try to implement OCL using OCLinEcore with this Teneo/Hibernate but unfortunately I couldn’t do that. If I didn’t use RCP and Teneo (for example Eclipse Runtime or creating Dynamic Instance), my OCL validation works. But when I run this in RCP with Teneo/Hibernate, I got this error when validating (or saving):
    “Unable to find delegate to evaluate the ‘….’ constraint on ‘….’: http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot
    Then I searched around and add some code in initialize method of my xxxEditorAdvisor.java:
    super.initialize(configurer);
    configurer.setSaveAndRestore(true);

    //***************** OCL ******************/
    org.eclipse.ocl.examples.pivot.model.OCLstdlib.install();
    org.eclipse.ocl.examples.pivot.OCL.initialize(null);
    String oclDelegateURI = OCLDelegateDomain.OCL_DELEGATE_URI;
    EOperation.Internal.InvocationDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI, new OCLInvocationDelegateFactory.Global());
    EStructuralFeature.Internal.SettingDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI, new OCLSettingDelegateFactory.Global());
    EValidator.ValidationDelegate.Registry.INSTANCE.put(oclDelegateURI, new OCLValidationDelegateFactory.Global());

    //*************** Initialize Teneo Hibernate DataStore *************************************
    // The rest are your code for establishing connection with MySQL.
    Frankly I didn’t understand what it is, just copy paste it from somewhere. However I get different error when I validate it on runtime:
    “an exception occured while delegating evaluation of the ‘…..’ constraint on ‘….’: org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl cannot be cast to org.eclipse.ocl.examples.pivot.utilites.BaseResource”

    Basically I’m stuck there and couldn’t combine OCL with Teneo. And I’m not sure whether my added code is doing a good progression with what I’m trying to do or make it worse. In any case, it is still not working right now. I would appreciate if you can help me with my situation.

    Thanks,
    Leo

    • Vincenzo 17 settembre 2013 at 22:48 - Reply

      Hi Leo,
      before getting into code, could you explain better what is your goal with OCL?
      Can you simplify this goal and translate it for the Library model of tutorials?
      Thanks
      Vincenzo

      • Leo 18 settembre 2013 at 03:16 - Reply

        Hi Vincenzo,

        For example if I want to add constraint for the length of the author’s name; it must be more than one character. From my understanding is, I can add that constraint in OCL by open the ecore file using OCLinEcore, then add this one line inside the author class:
        “invariant nameMustBeMoreThanOneChar : name.size() > 1;”
        When I run this as RCP, and do validation, it will give me this error:
        “Unable to find delegate to evaluate the ‘nameMustBeMoreThanOneChar’ constraint on ‘Author ab’: http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot

        But if I run it as an IDE (change the runtime platform in genmodel) then validate it, it works just like I expect it.

        Little update regarding my first post: It turns out the problem is not with the Teneo/Hibernate, so I’m sorry if it confuses you. The problem is I can’t really integrate OCL in RCP. Is there any way to work around this? Or is it impossible to begin with?

        Regards,
        Leo

        • Vincenzo 18 settembre 2013 at 13:19 - Reply

          Hi Leo,
          I applied the constraint you are referring and obtain correctly the message:

          The ‘nameMustBeMoreThanOneChar’ constraint is violated on ‘library.impl.AuthorImpl@191f64b{hibernate://?dsname=MyDb#Author|id=1}’

          You can follow the instructions here:
          http://wiki.eclipse.org/MDT/OCLinEcore

          Please note that the URL you are using (http://www.eclipse.org/emf/2002/Ecore/OCL/Pivot) sounds not correct.
          If the problem persists, please write me in private: you’ll find my email in Contacts.

          • Leo 19 settembre 2013 at 12:51

            Hi Vincenzo,

            it turns out there are pivot OCL and non-pivot OCL. I think yours it the non-pivot while mine is using pivot.

            After looking around, here is the answer for my OCL problem:
            //***************** OCL ******************/
            // register Pivot globally (resourceSet == null)
            org.eclipse.ocl.examples.pivot.OCL.initialize(null);

            String oclDelegateURI = OCLDelegateDomain.OCL_DELEGATE_URI_PIVOT;
            EOperation.Internal.InvocationDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI, new OCLInvocationDelegateFactory.Global());
            EStructuralFeature.Internal.SettingDelegate.Factory.Registry.INSTANCE.put(oclDelegateURI, new OCLSettingDelegateFactory.Global());
            EValidator.ValidationDelegate.Registry.INSTANCE.put(oclDelegateURI, new OCLValidationDelegateFactory.Global());

            // add org.eclipse.ocl.examples.xtext.oclinecore into dependencies in plugin.xml
            OCLinEcoreStandaloneSetup.doSetup();
            // install the OCL standard library
            OCLstdlib.install();

            Anyway thank you for your reply even though you don’t explain about OCL in this tutorial. I appreciate it very much 🙂

            Regards,
            Leo

    • Leo 18 settembre 2013 at 11:20 - Reply

      Hi Vincenzo,
      After I looked around carefully, you do have a tutorial about the configuration regarding the launch error.
      “If the launch is correct (otherwise do a Clean and Launch checking) you should see (just the first time, when the Library object is created) the following messages on the console”
      Well since you have it, I’ll take back my word about not being a one stop solution, I’m very sorry if that somehow offended you. Your tutorial is The one stop solution for my modeling experience 🙂 I’m just a beginner in java, especially EMF. But I have gained so much in knowledge EMF using your tutorials.
      Thanks,
      Leo

      • Vincenzo 18 settembre 2013 at 11:32 - Reply

        Hi Leo,
        I will never be offended by this kind of useful comments 😉
        They are key parts in the process of improving tutorials.
        So thank to you!
        Cheers
        Vincenzo

Leave A Comment