Skip to main content
Jump to: navigation, search

Wire EMF Databinding RCP

Revision as of 15:24, 28 July 2007 by Tom.schindl.bestsolution.at (Talk | contribs) (Generate Stub-Objects)

THIS IS AN ARTICLE WORK IN PROGRESS (Bug 195163)

Abstract/Requirements Definition

I'm trying to implement a fairly simple address book application on top of RCP using frameworks provided by Eclipse in 3.3. There's also focus on how to structure and design an RCP to be as extensible and as flexible as possible, including theming, internationalization, datastorage independency, ... .

Setup the Toolchain

  1. Eclipse 3.3 for RCP-Developers (available from http://www.eclipse.org/downloads)
  2. EMF using the Update-Manager (Help>Software Updates>Find and Install)
  3. Derby-Plugins (available from http://db.apache.org/derby/derby_downloads.html)
    To install:
    1. Stop your eclipse (if running)
    2. Unzip „derby.zip“s (as of this writing derby_core_plugin_10.2.2.485682.zip and derby_ui_plugin_1.1.0.zip) into your %ECLIPSE_HOME/plugin directory
    3. Start up eclipse
  4. iBatis (available from http://ibatis.apache.org)
  5. Fetch application icons (e.g. available from http://websvn.kde.org/trunk/KDE/kdelibs/pics/oxygen/ using your favorite SVN-Client)
  6. (Optional) Visual-Database Design
    1. Install Clay for Eclipse (available from http://www.azzurri.jp/en/software/clay/)
    2. Download Clay-Utils used for creation of DDL and documentation (available from http://publicsvn.bestsolution.at/repos/java/clayUtils/release/at.bestsolution.clayutils-nodeps-0.0.7.jar)
    3. DDL-Utils to create database DDL for any database you want (available from http://db.apache.org/ddlutils)
  7. (Optional) Subclipse for Version-Control (available from http://subclipse.tigris.org)

Application Design

Plugin-Design

At the beginning of every project is the package design or in RCP/OSGI Environment this breaks down to the design of the various plugins and their responsibilities. One of most important things when it comes to plugin-design is to split all your plugins into UI and NONE-UI (with the business logic) parts this makes automated testing of the business logic using JUnit tests easier.

at.bestsolution.addressbook

The main RCP-Application

at.bestsolution.addressbook.ui

This plugin provides the UI bits (ViewPart, ...) for the addressbook application.

at.bestsolution.addressbook.ui.theme

This plugin addresses the themeability of the application by providing a plugable theme-API. It will by default provide a standard theme.

at.bestsolution.addressbook.core

This plugin provides the none GUI bits for the application like Command-Definitions, handlers, ...

at.bestsolution.addressbook.core.model

This plugin provides the model implementation created using EMF

at.bestsolution.addressbook.core.datasource

This plugin will provide the API to provide plugable datasources

at.bestsolution.addressbook.core.datasource.xmi

This plugin provides a datasource implementation on top of XMI (directly supported by EMF)

at.bestsolution.addressbook.core.datasource.iBatis

This plugin provides a datasource implementation on top of iBatis

Plugin Overview

EMF RCP PluginOverview.png

Domain Model

The domain model is fairly simple and can be represented by 2 classes as shown in the diagram below. The only interesting thing is that there's a bidirectional relationship between Person(Attribute: primaryAddress) and Address(Attribute: person).

EMF RCP Domain.png

Hands on practice or „Let's begin our journey“

Implementing at.bestsolution.addressbook.core.model

Create an EMF-Project

  1. Open the "New Project Wizard"
  2. Select Eclipse Modeling Framework
    EMF RCP EMF1.png
  3. Name the project "at.bestsolution.addressbook.core.model"
    EMF RCP EMF2.png
  4. The resulting workspace looks like this
    EMF RCP EMF3.png

Create the Ecore-Model

Create the Ecore file
  1. Select Example EMF Model Creation Wizards > Ecore Model
    EMF RCP EMF4.png
  2. Name the model "addressbook.ecore"
    EMF RCP EMF5.png
  3. Open the Properties-View (Window > Show View > Others ...)
    EMF RCP EMF6.png
  4. Select the root node currently shown in the editor as null
    EMF RCP EMF7.png
  5. Editing the properties in the property view
    EMF RCP EMF8.png
Create the Classes and Attributes

Now we have to add our Domain-Objects Person and Address to the Ecore-Model:

  1. Right click on the addressbook-package you have created above and select "New Child > EClass"
  2. Set the following properties (in the Properties View)
    Name: Person
  3. Right click the Person and select "New Child > EAttribute"
  4. Set the following properties (in the Properties View)
    Name: surname
    EType: EString
  5. Right click the Person and select "New Child > EAttribute"
  6. Set the following properties (in the Properties View)
    Name: givenname
    EType: EString
  7. Right click the Person and select "New Child > EAttribute"
  8. Set the following properties (in the Properties View)
    Name: birthday
    EType: EDate
  9. Right click on the addressbook-package you have created above and select "New Child > EClass"
  10. Set the following properties (in the Properties View)
    Name: Address
  11. Right click the Address and select "New Child > EAttribute"
  12. Set the following properties (in the Properties View)
    Name: street
    EType: EString
  13. Right click the Address and select "New Child > EAttribute"
  14. Set the following properties (in the Properties View)
    Name: zip
    EType: EString
  15. Right click the Address and select "New Child > EAttribute"
  16. Set the following properties (in the Properties View)
    Name: city
    EType: EString
  17. Right click the Address and select "New Child > EAttribute"
  18. Set the following properties (in the Properties View)
    Name: country
    EType: EString

You'll notice that the types used for the attributes are not the standard classes provided by the JDK but wrappers defined by EMF. EMF provides wrappers for the most import JDK classes.

After having done this your model should look like the following:

EMF RCP EMF9.png

EMF holds META-Informations about your model and that's why all classes part of an Ecore-model have to be known to EMF. Those META-Informations are used by EMF to do fancy things but can also be of use for you when you want to get informations about an your model (or the model of someone different).

There are different ways to get EMF to recognize classes:

  1. You create a new EClass in your model
  2. You define a new EData Type to wrap an existing class e.g. provided by the JDK

EMF Explained:

  1. EClass: This represents a Class in EMF terminology TODO more information about EClass
  2. EAttribute: This represents an Attribute in EMF terminology TODO more information about EAttribute You'll notice that the types used for the attributes are not the standard classes provided by the JDK but wrappers defined by EMF. EMF provides wrappers for the most import JDK classes and want to use another classes coming from the JDK you'll have to add an EData Type to your Ecore-model. We'll see this later on.
Model the (bidirectional) relation ship between Person and Address

Next thing we have to model is the bidirectional relation between Person and Address like we defined it in our UML-Class Diagramm. In EMF such a relation can be expressed as an EReference in conjunction with an EOpposite:

  1. Right click the Person and select "New Child > EReference"
  2. Set the following properties (in the Properties View)
    Name: primaryAddress
    EType: Address
    Containment: true
  3. Right click the Address and select "New Child > EReference"
  4. Set the following properties (in the Properties View)
    Name: person
    EType: Person
    EOpposite: primaryAddress
    Transient: true

The Ecore model should look like this now:

EMF RCP EMF10.jpg

EMF Explained:

  1. EReference: TODO explain EReference
  2. Containment: TODO explain Containment
  3. EOpposite: TODO explain EOpposite
  4. Transient: TODO explain Transient
Model PropertyChangeSupport for Databinding

At this point we have implemented our original Domain-Model in Ecore but we are not finished because when we are working with JFace' Databinding Framework that ships with 3.3 we need to follow the JavaBean specification which means our domain objects have to implement java.bean.PropertyChangeSupport. The best way to model this is that all our Domain-Model-Objects inherit from a super-class named BaseObject. Because there are no wrapper for the Classes and Interfaces needed to implement PropertyChangeSupport and friends we need to create them our own by defining "EData Types":

  1. Right click on the addressbook-package you have created above and select "New Child > EData Type"
  2. Set the following properties (in the Properties View)
    Name: PropertyChangeSupport
    Instance Class Name: java.beans.PropertyChangeSupport
  3. Right click on the addressbook-package you have created above and select „New Child > EData Type“
  4. Set the following properties (in the Properties View)
    Name: PropertyChangeListener
    Instance Class Name: java.beans.PropertyChangeListener
  5. Right click on the addressbook-package you have created above and select „New Child > EData Type“
  6. Set the following properties (in the Properties View)
    Name: PropertyChangeEvent
    Instance Class Name: java.beans.PropertyChangeEvent

Now we are able to create our BaseObject:

  1. Right click on the addressbook-package you have created above and select "New Child > EClass"
  2. Set the following properties (in the Properties View)
    Name: BaseObject
  3. Right click the BaseObject and select „New Child > EAttribute“
  4. Set the following properties (in the Properties View)
    Name: id
    Etype: EInt
  5. Right click the BaseObject and select „New Child > EAttribute“
  6. Set the following properties (in the Properties View)
    Name: propertyChangeSupport
    Etype: PropertyChangeSupport
    Changeable: false
  7. Right click the BaseObject and select „New Child > EOperation“
  8. Set the following properties (in the Properties View)
    Name: addPropertyChangeListener
  9. Right click the addPropertyChangeListener and select „New Child > EParameter“
  10. Set the following properties (in the Properties View)
    Name: listener
    Etype: PropertyChangeListener
  11. Right click the BaseObject and select „New Child > EOperation“
  12. Set the following properties (in the Properties View)
    Name: removePropertyChangeListener
  13. Right click the removePropertyChangeListener and select „New Child > EParameter“
  14. Set the following properties (in the Properties View)
    Name: listener
    Etype: PropertyChangeListener

The final Ecore-Diagramm looks like this:

EMF RCP EMF11.jpg

EMF Explained:

  1. EData Type: TODO Explain EData Type
  2. EOperation: TODO Explain EOperation
  3. EParameter: TODO Explain EParameter

Create the Java-Code from the Ecore-model

Instead of writing the Java-Model-Objects our own we use EMFs codegeneration features do this boring task for us. EMF creates Stub-Objects for us which we are going to customize and implement the stub methods.

Generate Stub-Objects
  1. Select the addressbook.ecore in the Project-Explorer
  2. Right Click
  3. Select New > Other ...
  4. Select EMF Model
    EMF RCP EMF12.jpg
  5. Click Next until you reach this window where you press "Load"
    EMF RCP EMF13.jpg
  6. Click "Next" and afterwards "Finish"

We have no created a so called genmodel which gives us control over how EMF generates Java-Code. E.g. we could define to use Java5 generics, ... . We will make some minor changes like e.g. the name of the base package and suppressing of EMF Types in our public API.

  1. Free public API from EMF Types
    1. Select the 1st Addressbook in the Tree
    2. Scroll in "Properties View" to the section "Model Feature Defaults"
    3. Change "Suppress EMF Types" to true
  2. Modify Base package name
    1. Select the 2nd Addressbook in the Tree
    2. Change the „base package“ to „at.bestsolution.core.model“

Time for code generation:

  1. Select the 1st Addressbook in the Ǵenmodel-Editor
  2. Right Click
  3. Select „Generate Model Code“

In the end your project looks like this:
EMF RCP EMF14.jpg

Analyize the generated Java-Code
Implement PropertyChangeSupport

Back to the top