CloudTran Home

 
  
 
Contents  >   3.  Tutorials
 


3.3 Entity Tutorial - Entity/Relation Modelling

The 'Entity Tutorial' has been built with a MySQL datasource. The data files used for this example can be downloaded as a zip file from Entity Tutorial Data Files.

Instructions on how to setup and use these data files with MySQL can be found in Chapter 2.

 3.3.1  Introduction
 3.3.2  Modelling Entities and Relations
 3.3.3  Running the Entity Tutorial

3.3.1  Introduction

This tutorial introduces the Entity and Master Entity and Entity Group concepts. In CloudTran entities still embody the notion of persistence. Entities are JAVA objects that are 'persisted' in a distributed space.

Entity Groups are a concept whereby related data is grouped together. GigaSpaces talk of the co-location of data - data is co-located with process. Entity Grouping is an extension of this idea and ensures that closely related data is co-located. For example instance of Customer data (Customer details and Customer Orders) would be located together and Stock data (Stock items, stock levels) may be located in a separate group. What this means in reality is that an Entity Group instance will be located in the same space partition. The idea is that by co-locating closely related avoids lengthy searches across distributed spaces.

A Master Entity is the primary entity in an Entity Group - the one that will determine which partition the entity group will reside. An application can have many entity groups and many processing units. Part of the modeller's job is to determine how to organise the data - to decide which entity groups to have and how they are to be arranged.

The tutorial will build an application with 4 related entities. They entities are

  • Customer
  • Custorder
  • OrderLine
  • ContactDetails

A Customer has a one-to-many relationship with CustOrders which in turn has a one-to-many relationship with OrderLines. Customer, CustOrder and Orderline will all be in the same Entity Group, with Customer being the Master Entity.

Contact Details will be in its own Entity Group and in this example a different Processing Unit. Having different Processing Units allows different deployment scenarios for the two Entity Groups, for instance they could have a different number of partitions.

If you've done the HelloCloud tutorial you should be fairly familiar with the modelling environment. If not the screen shots should make it easy to follow. So lets get started.


3.3.2  Modelling Entities and Relations
Create a new project.....

.. of type CloudTran

Call it 'Entity Tutorial'

Edit the EntityTutorial.osm by double-clicking on the file.

To ensure the Properties View is visible, right-click on the top-level object in the .osm file and select 'Show Properties View'

Rename the application to be EntityApp

Create a datasource on the application. For the purpose of this tutorial all the entities will be persisted to the same physical database. In practice you can created multiple datasource and assign each entity to the appropriate one.

Enter the datasource values - name it entDS so we can identify it later on. Set the following properties on it.

  • Url = jdbc:mysql://localhost:3306/entityExample
  • Name = cloudtran
  • Password = cloudtran

Create a new Processing Unit

Call it PU1 and set the package to be com.cloudtran.ent.pu1

Create a new entity as a child of PU1

Create a new entity as a child of PU1 and set the following properties.

  • Name = Customer
  • Version Control = true
  • Data Source = Data Source entDS

Add an attribute to the Customer

Set the following properties on this new attribute.

  • Name = id
  • Type = int
  • Autokey = true
  • Required = true

Add two more attributes to the Customer. Leave their types as String. Add a constraint to each attribute and make the maxLength=30 in both cases. Constraints can be added to as child object of Attributes. (Constraints can be added to other objects - for example Business-Methods).

At the end of this stage of the modelling Customer should have three attributes

  • id
  • firstName
  • lastName

Create a child entity of Customer and call it Custorder. Set the Version Control=true and the DataSource=Data Source entDS

Note: Custorder is a child entity of Customer. Custorder is a subordinate entity of Customer. Customer is the Master Entity of Custorder.

Create a primary key attribute for the Custorder, exactly as we did for Customer. Its properties should be

  • Name = id
  • Type = int
  • Autokey = true
  • Required = true

create another attribute on Custorder with the following details

  • Name = orderNumber
  • Type = String
  • Required = true
  • Constraint maxLength=20
  • Remember - Constraints are added as children of Attributes

create a third attribute with these orderDate

  • Name = orderDate
  • Type = dateTime
  • Required = true
  • Constraint maxLength=8
  • Remember - Constraints are added as children of Attributes

So Custorder should have three attributes

The create another Entity called OrderLine. This should be a child entity of Custorder, denoting that the route to the Master Entity (Customer) is via Custorder. Create the following attributes on the OrderLine.

Note: Don't forget to set the Data Source and the Version Control as we did with the previous entities

  • name=orderLinePK : autokey=true : type=long
  • name=lineNumber : type=int : constraint - maxValue=9999
  • name=SKU : required=true : constraint - message="The SKU consists of: ALPHA ALPHA NUMBERIC '/' 5NUMERIC's" - regularExpression="[A-Z][A-Z][0-9]/[0-9]\{5\}"
  • name=qty : required=true : type=int
  • name=unitPrice : required=true : type=long
  • name=note : description="Any special instructions on this particular line item"

That concludes the modelling of the entities in the Customer Entity Group. But we still have to do the Relations The first Relation will be between Customer and Custorder. Select Customer and create a new Relation as a child of Customer.

Give the Customer -> Custorder Relation a name of custorders. The name of this Relation will determine the getter/setters used to set the Custorder from Customer. By convention this is lower cased name.

Customer -> Custorder Relation is a one-to-many relationship. This is indicated by setting the Collection Type. Normally the Collection Type will always be a Set

Note. This also the place to set the Type. This is the Type of the other end of the Relation - i.e Custorder. Setting the Type is only strictly necessary if the relationship is one-way. If, as in our case, the relationship is two-way then we will have to create the relationship to Customer from Custorder. In this case it is simpler to use the Inverse property. This allows us to create two relationships and point them at each other (via the Inverse property) and allow the generator to determine the correct Type on both ends It won't hurt to set the Type but bear in mind that if you set the Type and the Inverse and they don't match then the generator will complain.

  • Name = custorders
  • Collection Type = Set
  • Type = Entity Custorder ---- this is not strictly necessary for two-way relationships

As mentioned previously the Customer - Custorder will be a two-way relationship. We've created the Relation on Customer and now we need to do the same on Custorder Add a relation on the Custorder. This will be the Custorder - Customer relation. Its name will be customer. As it is a many-to-one relationship there will be no collection type. Set Required to be true, which indicates that a Customer must exist for the Custorder to exist.

As this is a two-way relation we're going to use the Inverse property. Essentially this links this new Relation with the Customer - Custorder one. This means the generator can determine both ends of the relationship and hence there is no need to set the type.

  • Name = customer
  • Inverse = Relation Customer
  • Required = true
  • Type = Entity Customer ---- this is not strictly necessary for two-way relationships

Add another relation on the Custorder which will point to the OrderLines. Set the following properties

  • Name = orderLines
  • Collection Type = Set
  • Description = orders to orderlines

Add a relation on Orderline. This will be the relation between Orderlines and Custorder - the other half of the two-way relation we just set up on Custorder. Set the following properties

  • Name = order
  • Inverse = Relation orderlines
  • Description = orderlines to custorders
  • Required = true

That is end of the Customer Entity Group. Well done!

The next stage is to add another Processing Unit that will contain the ContactDetails entity. So, create another Processing Unit under the Application call it PU2 Create an entity in PU2 with the following attributes.

  • name=id : autokey=true : required=true : type=int
  • name=address : required=true : constraint - maxLength=60
  • name=postCode : constraint - maxLength=8
  • name="phoneNumber : constraint - maxLength=15

The last thing to model is the relationship between Customer and ContactDetails. This will be a two-way relation.

Create a Relation on Customer that points to ContactDetails and one on ContactDetails that points to Customer Create an entity in PU2 with the following attributes.

That's it. The last thing to do is build the application. This is done by right clicking on the EntityTutorial.osm file.

When the build is complete the structure should look like the diagram below. Note The entities do not end up in the processing units but in the EntityApp_CtFramework project. The EntityApp_CtFramework is common to all projects.


3.3.3  Running the Entity Tutorial

Assuming all has gone well you should have a built Entity Tutorial example. So now what! Well the next stage is to test and use the application. What is needed is a client that will use the entities and persist them to a space.

To create a client the simplest way to do this is to create a Client PU. This is simply another processing unit that has no space. Create one now with the name ClientPU and package com.cloudtran.ent.client.

The next thing to do is create a Pulse. This is in essence a mechanism for feeding data into a space. A Pulse can be set to fire once. We will create a pulse and then add some code that will create an Entity tree and persist it to the space in a transaction.

A pulse is a child object of a Processing Unit, so add a pulse to the newly created ClientPU.

Name the pulse clientPulse and change the Initial Delay to 2000 - this how long the pulse will wait until acting. The time is in milli-seconds. The Period=-1 indicates that the pulse will fire just once.

So far so good! Rebuild the application and you notice a new project will appear. It will contain within it a ClientPU_Actions class and it is in this that the client code will be added.

Edit ClientPU_Actions and at about line 114 you will see a method called clientPulse. A few lines below that there is a comment which tells you that this is the where the code goes.

Add the following code into the method - make sure it goes between the two comment lines as it will be preserved between re-generations. At this point you could regenerated but Eclipse will have compiled the code in any case. So let's try to run it....
try
{
    // 1. create a customer
    Customer customer = new Customer( new Integer(1) );
    customer.setFirstName( "John" );
    customer.setLastName("Smith");

    // 2. create an order
    Date date = new Date();
    long l = date.getTime();
    Custorder co1 = new Custorder( new Integer( 200 ) );
    co1.setOrderNumber( "1234" );
    co1.setOrderDate( new java.sql.Timestamp( l ) );
    customer.addCustorders( co1 );

     // 3. create an second order 
    Custorder co2 = new Custorder( new Integer( 201 ) );
    co2.setOrderNumber( "5678" );
    co2.setOrderDate( new java.sql.Timestamp( l + 1000L ) );
    customer.addCustorders( co2 );

    // 4. create contact details for the customer
    ContactDetails cd = new ContactDetails( new Integer( 202 ) );
    cd.setAddress( "our house in the middle of our street");
    cd.setPhoneNumber( "01234-hello" );
    cd.setPostCode("SW1");
    customer.setContactDetails(cd);

    // 5. save the customer
    customer.save();
}
catch (Exception e )
{
    Trace.log( "Exception thrown in client code", e );
}
Finally before you run the application you ought to set up a database. If you don't the application will still run and the data object will be written into the space but they will not be persisted to the database.

If you were watching closely you'd notice that the one we modelled was for a MySql database with the following properties

  • Url = jdbc:mysql://localhost:3306/entityExample
  • Database = entityExample
  • Name = cloudtran
  • Password = cloudtran

As part of the generation a database schema is created and can be found in the main project EntityTutorial. The generated schema is specific to the modelled database type - MySql in this case. If you model another database type such as Oracle then the generated schema will reflect that.

To run the application simply open the Eclipse Run Configurations.

You will see four configurations - one for each modelled Processing Unit and an additional one called EntityApp_CoordinatorPU. This is a generated Processing Unit that as well as coordinating the start up of all the other Processing Units, contains the Transaction Manager.

The Processing Units can be started in any order, so start each one in turn. There will be a lot of output produced on the console. The output of all the processing units is logged to the runtimeLog.txt file in the main project.

As each Processing Unit starts it will register with the CoordinatorPU. When all the Processing Units have done so the coordinator PU declares the application Open For Business. If the CoordingatorPU is not available the other Processing Units will continue to poll the CoordinatorPU checking to see if the application is Open For Business. Before this point and depending on the order in which the Processing Units were started you may see exceptions thrown as a Processing Unit notes that the application is not Open For Business. This is normal and should stop once the application is ready.

Once Open For Business has been declared the real work can begin. The ClientPU will wait 2000 milli-seconds and then fire its pulse. This in turn will create the entities and persist them to the space. This can be viewed in the GigasSpaces UI .....

... or in the database.

And that's it. A working example of entities being persisted to two spaces in one transaction.


Copyright (c) 2001-2011 CloudTran Inc.