openxava / documentation / Lesson 2: Basic domain model - Part 1

Course: 1. Getting started | 2. Basic domain model (1) | 3. Basic domain model (2) | 4. Refining the user interface | 5. Agile development | 6. Mapped superclass inheritance | 7. Entity inheritance | 8. View inheritance | 9. Java properties | 10. Calculated properties | 11. @DefaultValueCalculator in collections | 12. @Calculation and collections totals | 13. @DefaultValueCalculator from file | 14. Manual schema evolution | 15. Multi user default value calculation | 16. Synchronize persistent and computed propierties | 17. Logic from database | 18. Advanced validation | 19. Refining the standard behavior | 20. Behavior & business logic | 21. References & collections | A. Architecture & philosophy | B. Java Persistence API | C. Annotations | D. Automated testing

Table of contents

Lesson 2: Basic domain model - Part 1
Domain model
Reference (ManyToOne) as descriptions list (combo)
Stereotypes
Embeddable
Summary
In this lesson you will start to create the entities required for your project in order to get your invoicing application working.
By now I assume that you know how to create a new entity with OpenXava Studio and how to run the application, because you have already read Lesson1: Getting started, right?

If you don't like videos follow the instructions below.

Domain model

First, we'll create the entities for your Invoicing application. The domain model is rather basic, but enough to learn a lot of interesting things:
modeling_en010.png
We'll start with six classes. Later on we'll add a few more to it. Remember that you already have an initial version of Customer and Product.

Reference (ManyToOne) as descriptions list (combo)

Let's start with the most simple case. We are going to create a Category entity and associate it to the Product, displaying it as a combo.
The code for Category entity is:
package com.yourcompany.invoicing.model;
 
import javax.persistence.*;
import org.hibernate.annotations.GenericGenerator;
import org.openxava.annotations.*;
import lombok.*;
 
@Entity @Getter @Setter
public class Category {
 
    @Id
    @Hidden // The property is not shown to the user. It's an internal identifier
    @GeneratedValue(generator="system-uuid") // Universally Unique Identifier (1)
    @GenericGenerator(name="system-uuid", strategy = "uuid")
    @Column(length=32)
    String oid;
 
    @Column(length=50)
    String description;
 
}
It only has an identifier and a description property. In this case we use the Universally Unique Identifier (shown as 1) algorithm to generate the id. The advantage of this id generator is that you can migrate your application to another database (DB2, MySQL, Oracle, Informix, etc) without touching your code. The other id generators of JPA rely on the database to generate the id thereby making them not so portable as UUID.
Execute the Category module and add some categories:
modeling_en035.png
Now, we'll associate Product with Category: Add the next category reference declaration in your Product entity:
public class Product {
 
    ...
 
    @ManyToOne( // The reference is persisted as a database relationship
        fetch=FetchType.LAZY, // The reference is loaded on demand
        optional=true) // The reference can have no value
    @DescriptionsList // Thus the reference is displayed using a combo
    Category category; // A regular Java reference
 
}
This is a plain JPA many-to-one relationship, the one that you can learn more about in appendix B. In this case, thanks to the @DescriptionsList annotation it is displayed as a combo:
modeling_en020.png
Now it's time to complete your Product entity.

Stereotypes

Product entity at least needs to have attributes such as price, etc. Also it would be nice to have photos and a field for remarks. We are going to use stereotypes to do that. A stereotype specifies a special use of a type. For example, you can use String to store names, comments or identifiers, and you can use a BigDecimal to store percentages, money or quantities. Different uses of stereotypes is to mark this specific use.
The best way to understand what a stereotype is, is to see it in action. Let's add price, photos and remarks properties to your Product entity:
@Stereotype("MONEY") // The price property is used to store money
BigDecimal price; // BigDecimal is typically used for money
 
@Stereotype("IMAGES_GALLERY") // A complete image gallery is available
@Column(length=32) // The 32 length string is for storing the key of the gallery
String photos;
 
@Stereotype("MEMO") // This is for a big text, a text area or equivalent will be used
String remarks;
You have seen how to use stereotypes. Now you only have to use the name of the stereotype and OpenXava will apply special treatment. Execute the module for the Product now, and you will see:
modeling_en040.png
As you can see, each stereotype produces an effect in the user interface. Stereotypes have effects in sizes, validations, editors, etc. Stereotypes also allow you to reuse built-in functionality easily. For example, with a mere marking of a simple string property as @Stereotype(“IMAGES_GALLERY”) you have a full images gallery available.
Apart from these, OpenXava has many other useful built in stereotypes such as PHOTO, LABEL, BOLD_LABEL, TIME, DATETIME, ZEROS_FILLED, HTML_TEXT, IMAGE_LABEL, EMAIL, TELEPHONE, WEBURL, IP, ISBN, CREDIT_CARD, EMAIL_LIST, PASSWORD, MAC, FILE, FILES, ICON, COORDINATES, etc.
Also you can use specific annotations as alternative to stereotypes, that is instead of @Stereotype("MONEY") you can write just @Money, with the same effect. Using annotations the above properties could be written in this way:
// Annotations as alternative to stereotypes
      
@Money // Instead of @Stereotype("MONEY") 
BigDecimal price; 
 
@Files // Instead of @Stereotype("IMAGES_GALLERY") 
@Column(length=32)
String photos;
 
@TextArea // Instead of @Stereotype("MEMO") 
String remarks;
Some of the annotations available are @Password, @Money, @TextArea, @Label, @DateTime, @Discussion, @Icon, @Telephone, @IP, @EmailList, @MAC , @StringTime, @HtmlText, @Coordinates, @Files, @File, etc.
Now you have Product ready to use. Let's refine the Customer now.

Embeddable

We are going to add Address to our until now pretty naked Customer. The customer address is not shared by other customers, and when the customer is removed his address is removed too. Therefore we'll model the address concept as an embeddable class in this case. You can learn more about this in appendix B.
Add the Address class to your project:
package com.yourcompany.invoicing.model;
 
import javax.persistence.*;
import lombok.*;
 
@Embeddable // We use @Embeddable instead of @Entity
@Getter @Setter
public class Address {
 
    @Column(length = 30) // The members are annotated as in entity case
    String street;
 
    @Column(length = 5)
    int zipCode;
 
    @Column(length = 20)
    String city;
 
    @Column(length = 30)
    String state;
 
}
You can see how the regular class has been annotated as @Embeddable. Its properties are annotated in the same way as entities, though embeddable classes do not support all functionality of entities.
Now, you can use Address in any entity. Just add a reference to your Customer entity:
public class Customer {
 
    ...
 
    @Embedded // This is the way to reference an embeddable class
    Address address; // A regular Java reference
 
}
The Address data is stored in the same table as the Customer data. And from a user interface perspective you have a frame around address. If you do not like the frame you only have to annotate the reference with @NoFrame thus:
@Embedded @NoFrame // With @NoFrame no frame is shown for address
Address address;
Here's the user interface for an embedded reference with and without @NoFrame:
modeling_en060.png

Summary

In this lesson you have learned how to create references that are displayed with combos with @DescriptionsList, how to use stereotypes and @Embeddable. Now that we have the basic entities running, it's time to face the core entity of your application, the Invoice entity. Let's do it step by step in the next lesson.

Any problem with this lesson? Ask in the forum Everything fine? Go to Lesson 3