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
You can use inheritance not only for reusing the Java code and mapping,
but also for reusing the user interface definition, the
@View
definitions. This lesson shows how view inheritance works.
If you don't like videos follow
the instructions below.
The extendsView
attribute
Both
Order and
Invoice use a user interface generated
by default with all its members one in each line. Note that the annotation
@View that we have declared in
CommercialDocument is
not inherited by default. That is, if you do not define a view for an
entity a default one is generated, and the
@View of the parent
entity is not used. Just in this way:
@View(members = "a, b, c;") // This view is used to display Parent, but not for Child
public class Parent { ... }
public class Child extends Parent { ... } // Child is displayed using an automatically
// generated view, not the view from Parent
Usually the view of the parent entity “as is” is not very useful
because it does not contain the new properties that the current entity
has. So this behavior is good for default behavior.
Although, in a non-trivial entity you may need to refine the user
interface, and it might be useful to inherit (instead of copy and paste)
the view from the parent. You can do it using the
extendsView
attribute in
@View:
@View(members = "a, b, c;") // This view with no name is the DEFAULT view
public class Parent { ... }
@View(name="A" members = "d", // Adds d to the inherited view
extendsView = "super.DEFAULT") // Extends the default view from Parent
@View(name="B" members = "a, b, c; d") // View B is equals to view A
public class Child extends Parent { ... } // Child is displayed using an automatically
// generated view, not the view from Parent
Using
extendsView the members that appear will be those
of the extended view plus those declared in members of the current one.
We are going to use this feature for defining the views for
CommercialDocument,
Order and
Invoice.
View for Invoice
using inheritance
Given that the
@View of
CommercialDocument has not
inherited the current user interface for
Invoice it's pretty
ugly to see, all the members, each in a line. We are going to define a
better user interface. A view similar to the one we defined previously,
but adding a tab for orders, thus:

Note that we have put all the members from the
CommercialDocument
part of the
Invoice in the header and the first tab (data), and
the collection of orders in the other tab. The next code shows the way to
define this view without inheritance.
@View( members=
"year, number, date;" +
"data {" +
"customer;" +
"details;" +
"remarks" +
"}" +
"orders { orders } "
)
public class Invoice extends CommercialDocument {
You can note how all except the orders part is common for every
CommercialDocument.
Therefore, we are going to move this part to
CommercialDocument
and then redefine this view using view inheritance.
Remove the old
@View in
CommercialDocument, and write
this one:
@View(members=
"year, number, date," + // The members for the header part in one line
"data {" + // A tab 'data' for the main data of the document
"customer;" +
"details;" +
"remarks" +
"}"
)
abstract public class CommercialDocument extends Identifiable {
This view indicates how to layout the common data for all
commercial documents. Now we can redefine the view for
Invoice
from this one:
@View(extendsView="super.DEFAULT", // Extends from the CommercialDocument view
members="orders { orders }" // We add the orders inside a tab
)
public class Invoice extends CommercialDocument {
In this way declaring the view for
Invoice is shorter.
What's more, the common layout for
Order,
Invoice and
all other possible
CommercialDocument objects are all in one
place. So if you add a new property to
CommercialDocument you
only need to touch the view for
CommercialDocument.
View for Order using
inheritance
Now that you have a suitable view in
CommercialDocument,
declararing the view for
Order is plain vanilla. We want
something like this:

To get this result, you can define the view for
Order by
extending the default view for
CommercialDocument, adding the
referenced invoice in a new tab:
@View(extendsView="super.DEFAULT", // Extends from the CommercialDocument view
members="invoice { invoice } " // We add the invoice inside a tab
)
public class Order extends CommercialDocument {
With this we get all the data from
CommercialDocument
plus a tab with the invoice.
Using
@ReferenceView and @CollectionView to refine views
When an order is to be viewed from
the
Invoice user interface, we want the view used to do so to be
simple, with no customer or invoice information, because this data is
redundant in this case:

To get this result define a simpler view in
Order:
@View( extendsView="super.DEFAULT", // The default view
members="invoice { invoice } "
)
@View( name="NoCustomerNoInvoice", // A view named NoCustomerNoInvoice
members= // that does not include customer and invoice.
"year, number, date;" + // Ideal to be used from Invoice
"details;" +
"remarks"
)
public class Order extends CommercialDocument {
This new view defined in
Order named
NoCustomerNoInvoice
can be referenced from
Invoice to display the individual
elements of the orders collection using
@CollectionView:
public class Invoice extends CommercialDocument {
...
@OneToMany(mappedBy="invoice")
@CollectionView("NoCustomerNoInvoice") // This view is used to display orders
private Collection<Order> orders;
And with this code only, the orders collection will use a more
appropriate view from
Invoice to display individual elements.
Moreover, we do not want to display the customer and order information
from the
Order user interface because it is redundant data in
this case. To do so, we are going to define a simpler view in
Invoice:
@View( extendsView="super.DEFAULT", // The default view
members="orders { orders }"
)
@View( name="NoCustomerNoOrders", // A view named NoCustomerNoOrders
members= // that does not include customer and orders
"year, number, date;" + // Ideal to be used from Order
"details;" +
"remarks"
)
public class Invoice extends CommercialDocument {
This new view defined in
Invoice named
NoCustomerNoOrders
can be referenced from
Order to display the reference to
Invoice
using
@ReferenceView:
public class Order extends CommercialDocument {
@ManyToOne
@ReferenceView("NoCustomerNoOrders") // This view is used to display invoice
private Invoice invoice;
...
Now the
invoice reference will be displayed from
Order
without customers and orders so you'll get a simpler user interface:
Summary
This lesson has shown you how to use inheritance to simplify the
definition of the user interface, by using the
extendsView
attribute of
@View. Along the way you also have seen some examples
of simplifying the way the references and collections are displayed using
@ReferenceView and
@CollectionView.
Download source code of this lesson
Any problem with this lesson? Ask in the forum Everything fine?
Go to Lesson 9