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:

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:
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:

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:

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:
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