Course: 1. Getting started | 2. Modeling with Java | 3. Automated testing | 4. Inheritance | 5. Basic business logic | 6. Advanced validation | 7. Refining the standard behavior | 8. Behavior & business logic | 9. References & collections | A. Architecture & philosophy | B. Java Persistence API | C. Annotations

Lesson 4: Inheritance

Inheritance is a practical way to reuse code in the object oriented world. Using inheritance with JPA and OpenXava is as easy as using it in plain Java. We are going to use inheritance to remove repeated and boring code, like the UUID definition. Also, we'll add a new entity, Order, and we'll use inheritance to do it with minimal code. Moreover, you'll learn how practical it is to use inheritance even for the code used for testing.

Inheriting from a mapped superclass

The Author, Category and Invoice classes have some common code, the oid field definition:
@Id @GeneratedValue(generator="system-uuid") @Hidden
@GenericGenerator(name="system-uuid", strategy = "uuid")
@Column(length=32)
private String oid;
 
public String getOid() {
    return oid;
}
 
public void setOid(String oid) {
    this.oid = oid;
}
This code is just the same for all those classes. You know that copy and paste is a mortal sin, so we have to look for a solution to remove the code repetition, to avoid our way to hell.
An elegant solution for this situation is inheritance. JPA allows you to exploit the concept of inheritance. One of them is to inherit from a mapped superclass. A mapped superclass is a Java class with JPA mapping annotations, but it is not an entity itself. Its only goal is to be used as superclass for an entity. Let's use it, and you'll see its utility quickly.
First, we move this common piece of code to a class marked as @MappedSuperclass. We name it Identifiable:
package org.openxava.invoicing.model;
 
import javax.persistence.*;
import org.hibernate.annotations.*;
import org.openxava.annotations.*;
 
@MappedSuperclass // Marked as mapped superclass instead of entity
public class Identifiable {
 
    @Id @GeneratedValue(generator="system-uuid") @Hidden
    @GenericGenerator(name="system-uuid", strategy = "uuid")
    @Column(length=32)
    private String oid; // Property definition includes OpenXava and JPA annotations
 
    public String getOid() {
        return oid;
    }
 
    public void setOid(String oid) {
        this.oid = oid;
    }
 
}
Now you can define Author, Category and Invoice entities in a more succinct way. To see an example you have the new code for Category here:
package org.openxava.invoicing.model;
 
import javax.persistence.*;
 
@Entity
public class Category extends Identifiable { // Extends from Identifiable
                            // so it does not need to have an id property
    @Column(length = 50)
    private String description;
 
    public void setDescription(String description) {
        this.description = description;
    }
 
    public String getDescription() {
        return description;
    }
}
The refactoring is plain vanilla. Category now extends from Identifiable and we have removed the oid field and the respective getOid() and setOid() methods. This way, not only is your code shorter, but it's more elegant, because you declare that your class is identifiable (the what, not the how), and you removed from your business logic class code that is somewhat technical.
Now, you can apply this same refactoring to the Author and Invoice entities, moreover, from now on you'll extend most of your entities from the Identifiable mapped superclass.
We have created our own Identifiable class to see the advantage of using mapped superclasses, however OpenXava provides for you a ready to use Identifiable class that you can find in the org.openxava.model package. So in your next project you don't need to write the Identifiable class again, just use the one included in OpenXava.
You have learned that a mapped superclass is a regular class with JPA mapping annotations that you can use as a base class for your entities. Moreover, you have learned how to use mapped superclasses to simplify your code.

Entity inheritance

An entity may inherit from another entity. This entity inheritance is a useful tool to simplify your model. We are going to use it to add a new Order entity to your Invoicing application.

New Order entity

We want to add a new concept to the Invoicing application, i. e., order. While an invoice is something you want to charge your customer, an order is something the customer has ordered from us. These two concepts are strongly related, because you will charge the things your customer has ordered from you, and you actually have served him.
It would be nice to manage orders in your application, and to associate those orders with its corresponding invoices. Just as shown in the next UML diagram:
inheritance_en010.png
And with Java code:
@Entity
public class Invoice {
 
    @OneToMany(mappedBy="invoice")
    private Collection<Order> orders;
    ...
}
 
@Entity
public class Order {
 
    @ManyToOne // Without lazy fetching (1)
    private Invoice invoice;
    ...
}
That is, an invoice has several orders, and an order can reference an invoice. Note that we do not use lazy fetching for the invoice reference (1), this is because of a Hibernate bug when the reference owns the bidirectional relationship (that is, it's declared in the mappedBy attribute of the @OneToMany).
What shape does Order have? Well, it has a customer, several detail lines with product and quantity, a year and a number, something like this:
inheritance_en020.png
Incidentally, this UML diagram is identical to the Invoice diagram. That is, to create your Order entity you can just copy and paste the Invoice class, and the work is done. But, wait a moment! “Copy and paste” is a mortal sin. So, we have to find a way to reuse Invoice code for Order.

CommercialDocument as an abstract entity

A practical way to reuse the code for Invoice and Order is by using inheritance, moreover it's an excellent opportunity to learn how easy it is to use inheritance with JPA and OpenXava.
In most object oriented cultures you have to observe the is a rule. It means that we cannot do Invoice extends Order, because an Invoice is not an Order. The solution for this case is creating a base class for both Order and Invoice. We are going to call this class CommercialDocument.
Here you have the UML diagram for CommercialDocument:
inheritance_en030.png
And here you have the same idea expressed with Java:
public class CommercialDocument { ... }
public class Order extends CommercialDocument { ... }
public class Invoice extends CommercialDocument { ... }
Let's start to refactor your current code. First, rename (using Refactor > Rename) Invoice as CommercialDocument. Now, edit the CommercialDocument code to declare it as an abstract class, thus:
abstract public class CommercialDocument // We add the abstract modifier
We want to create instances of Invoice and Order, but we do not want to create instances of CommercialDocument directly, so we declare it as abstract.

Invoice refactored to use inheritance

Now, you have to create the Invoice entity extending it from CommercialDocument. See the new Invoice code:
package org.openxava.invoicing.model;
 
import javax.persistence.*;
 
@Entity
public class Invoice extends CommercialDocument {
 
}
Invoice now has very succinct code, indeed the body of the class is, by now, empty.
This new code requires a slightly different database schema, now invoices and orders will be stored in the same table (the CommercialDocument table) using a discriminator column. Therefore you need to remove the old tables executing the next SQL statements:
DROP TABLE invoice_details;
DROP TABLE invoice;
To execute these SQL statements execute start-manager-hsqldb.bat (or the corresponding .sh if you use Linux/Mac) from openxava/tomcat/bin. It will show a setup dialog, put the database URL (jdbc:hsqldb:hsql://localhost:1666) and accept the dialog:
inheritance040.png
Then:
inheritance_en050.png
Now you can execute the Invoice module and see it working in your browser. Also, execute the InvoiceTest. It must be green.

Creating Order using inheritance

Thanks to CommercialDocument creating the Order entity is dead easy. See the code:
package org.openxava.invoicing.model;
 
import javax.persistence.*;
 
@Entity
public class Order extends CommercialDocument {
 
}
After writing the above Order class, although it is empty by now, you can use the Order module from your browser. Yes, creating a new entity with a structure like Invoice, that is any commercial document entity, is very easy and rapid. You see how good use of inheritance is an elegant way to have simpler code.
Order module works perfectly, but it has a little problem. The new order number is calculated from the last invoice number, not from the last order number. This is because the calculator for the next number is read from the Invoice entity. An obvious solution is to move the number property definition from CommercialDocument to Invoice and Order. Although, we are not going to do it in this way, because in the next lesson we'll refine the way to calculate the next number, for now we simply do a little adjustment in the current code so that it does not fail. Edit the NextNumberForYearCalculator class and in the query change “Invoice” for “CommercialDocument”, leaving the calculate() method, in this way:
public Object calculate() throws Exception {
    Query query = XPersistence.getManager().createQuery(
        "select max(i.number) from " +
        "CommercialDocument i " + // CommercialDocument instead of Invoice
        "where i.year = :year");
    query.setParameter("year", year);
    Integer lastNumber = (Integer) query.getSingleResult();
    return lastNumber == null?1:lastNumber + 1;
}
Now we search for the maximum number of any commercial document of the year in order to calculate the new number, therefore the numbering is shared across all the commercial documents. We'll improve it in the next lesson for having separate numbering for invoices and orders and to have better support for a multiuser environment.

Naming convention and inheritance

Note that you do not need to change the name of any property of Invoice to do the refactoring. This is because we follow the next pragmatic principle: Do not use the class name in member names, e.g., inside an Account class do not use the “Account” word in any method or property:
public class Account { // We'll not use Account in member names
 
    private int accountNumber; // Bad, because it uses “account”
    private int number; // Good, it does not use “account”
 
    public void cancelAccount() { } // Bad, because it uses “Account”
    public void cancel() { } // Good, it does not use “account”
    ...
}
Using this nomenclature you can refactor Account in an inheritance hierarchy without renaming its members, and you can write polymorphic code with Account.

Associating Order with Invoice

By now, Order and Invoice are exactly the same. We are going to do the first extensions on them, that is to associate Order with Invoice. Just as shown in the diagram:
inheritance_en010.png
You only need to add a reference from Order to Invoice:
package org.openxava.invoicing.model;
 
import javax.persistence.*;
 
@Entity
public class Order extends CommercialDocument {
 
    @ManyToOne
    private Invoice invoice; // Reference to invoice added
 
    public Invoice getInvoice() {
        return invoice;
    }
 
    public void setInvoice(Invoice invoice) {
        this.invoice = invoice;
    }
 
}
Conversely in Invoice we add a collection of Order entities:
package org.openxava.invoicing.model;
 
import java.util.*; // Add this import to use Collection
import javax.persistence.*;
 
@Entity
public class Invoice extends CommercialDocument {
 
    @OneToMany(mappedBy="invoice")
    private Collection<Order> orders; // Collection of Order entities added
 
    public Collection<Order> getOrders() {
        return orders;
    }
 
    public void setOrders(Collection<Order> orders) {
        this.orders = orders;
    }
 
}
After writing this simple code you are ready to test the newly created relationship. Open your browser and explore the Order and the Invoice modules. Note that at the end of the Order user interface you have a reference to Invoice. The user can use this reference to associate an invoice with the current order. On the other hand, if you explore the Invoice module, you will see a collection of orders at the end. The user can use it to add orders to the current invoice.
Try to add orders to invoice, and to associate an invoice to an order. It works, although the user interface is a little ugly.

View inheritance

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 section shows how view inheritance works.

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 { ... }
 
@Views({
    @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:
inheritance_en060.png
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:
import org.openxava.annotations.*; // Add this import to use @View
 
@Entity
@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:
inheritance_en070.png
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:
import org.openxava.annotations.*; // Add this import to use @View
 
@Entity
@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:
inheritance_en080.png
To get this result define a simpler view in Order:
@Views({ // In order to declare more than one view
    @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:
@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:
@Views({ // In order to declare more than one view
    @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:
inheritance_en090.png

Inheritance in JUnit tests

Invoice has been refactored to use inheritance, also we have used inheritance to add a new Order entity. Moreover, this Order entity has a relationship with Invoice. You have a lot of new functionality, therefore you must test all the new features.
Because Invoice and Order have a lot of common stuff (the CommercialDocument part) we can refactor the tests in order to use inheritance, thus you avoid the harmful “copy and paste” in your test code as well.

Creating an abstract module test

If you examine the test for creating an invoice, from the testCreate() method of InvoiceTest. You can note that testing the creation of an invoice is exactly the same to testing the creation of an order. Because, both have year, number, date, customer, details and remarks. So, here inheritance is a good tool for code reuse.
We are going to rename InvoiceTest as CommercialDocumentTest, then we'll create InvoiceTest and OrderTest from it. See the UML diagram for this idea:
inheritance_en100.png
First rename your current InvoiceTest class to CommercialDocumentTest, then make the changes indicated in the next code:
package org.openxava.invoicing.tests;
 
import java.text.*;
import java.util.*;
import javax.persistence.*;
import org.openxava.tests.*;
import org.openxava.util.*;
import static org.openxava.jpa.XPersistence.*;
 
abstract public class CommercialDocumentTest // Add abstract to class definition
    extends ModuleTestBase {
 
    private String number;
 
    public CommercialDocumentTest(
        String testName,
        String moduleName) // moduleName added as constructor argument
    {
        super(testName, "Invoicing", moduleName); // Send moduleName
    }
 
    public void testCreate() throws Exception { ... } // As original
 
    private void addDetails() throws Exception { ... } // As original
 
    private String getNumber() {
        if (number == null) {
            Query query = getManager().createQuery(
                "select max(i.number) from " +
                    "CommercialDocument i " + // Invoice changed for CommercialDocument
                    "i where i.year = :year");
            query.setParameter("year", Dates.getYear(new Date()));
            Integer lastNumber = (Integer) query.getSingleResult();
            if (lastNumber == null)    lastNumber = 0;
            number = Integer.toString(lastNumber + 1);
        }
        return number;
    }
 
    private void remove() throws Exception { ... } // As original
 
    private void verifyCreated() throws Exception { ... } // As original
 
    private void save() throws Exception { ... } // As original
 
    private void setOtherProperties() throws Exception { ... } // As original
 
    private void chooseCustomer() throws Exception { ... } // As original
 
    private void verifyDefaultValues() throws Exception { ... } // As original
 
    private String getCurrentYear() { ... } // As original
 
    private String getCurrentDate() { ... } // As original
 
}
As you see you have to do a few changes in order to adapt CommercialDocumentTest. First, you declared it as an abstract class. This way this class is not executed by Eclipse as a JUnit test. It is only valid as base class for creating tests, but it is not a test itself.
Another important change is in the constructor, where you now use moduleName instead of “Invoice”, thus you can use this test for Order, Invoice or whatever other module you want. The other change is a simple detail: you have to change “Invoice” for “ComercialDocument” in the query to get the next number.
Now you have a base class ready to create the module tests for Order and Invoice. Let's do it.

Using the abstract module test to create concrete module tests

Creating your first version of OrderTest and InvoiceTest is just a matter of extending from CommercialDocumentTest. Nothing more. See the InvoiceTest code:
package org.openxava.invoicing.tests;
 
public class InvoiceTest extends CommercialDocumentTest {
 
    public InvoiceTest(String testName) {
        super(testName, "Invoice");
    }
 
}
And OrderTest:
package org.openxava.invoicing.tests;
 
public class OrderTest extends CommercialDocumentTest {
 
    public OrderTest(String testName) {
        super(testName, "Order");
    }
 
}
Execute these two tests and you will see how testCreate(), inherited from CommercialDocumentTest, is executed in both cases, against its corresponding module. With this we are testing the common behavior of Order and Invoice. Let's test the different cases for them.

Adding new tests to the extended module test

So far we tested how to create an invoice and an order. In this section we'll test also how to add orders to an invoice in the Invoice module, and how to set the invoice to an order from the Order module.
To test how to add an order to an invoice, add the testAddOrders() method to InvoiceTest:
public void testAddOrders() throws Exception {
    login("admin", "admin");
    assertListNotEmpty(); // This test assumes that some invoices already exist
    execute("List.orderBy", "property=number"); // To always work with the same order
    execute("Mode.detailAndFirst"); // Goes to detail mode editing the first invoice
    execute("Sections.change", "activeSection=1"); // Changes to tab 1
    assertCollectionRowCount("orders", 0); // This invoice has no orders
    execute("Collection.add", // Clicks on the button for adding a new order, this takes
        "viewObject=xava_view_section1_orders"); // you to a list of orders
    execute("AddToCollection.add", "row=0"); // Chooses the first order in the list
    assertCollectionRowCount("orders", 1); // Order added to the invoice
    checkRowCollection("orders", 0); // Checks the order, to remove it
    execute("Collection.removeSelected", // Removes the recently added order
        "viewObject=xava_view_section1_orders");
    assertCollectionRowCount("orders", 0); // The order has been removed
}
In this case we rely on the fact that there is at least one invoice, and that the first invoice in the list has no orders. Before running this test, if you have no invoices, create one with no orders, or if you already have invoices, be sure that the first one has no orders.
To test how to assign an invoice to an order add the testSetInvoice() method to OrderTest:
public void testSetInvoice() throws Exception {
    login("admin", "admin");
    assertListNotEmpty(); // This test assumes that some orders already exist
    execute("Mode.detailAndFirst"); // Goes to detail mode editing the first invoice
    execute("Sections.change", "activeSection=1"); // Changes to tab 1
    assertValue("invoice.number", ""); // This order has no
    assertValue("invoice.year", ""); // invoice assigned yet
    execute("Reference.search", // Clicks on the button to search the invoice, this
        "keyProperty=invoice.year"); // takes you to a list of invoices
    execute("List.orderBy", "property=number"); // To sort the list of invoices
    String year = getValueInList(0, "year"); // Stores the year and number of
    String number = getValueInList(0, "number"); // the first invoice in the list
    execute("ReferenceSearch.choose", "row=0"); // Chooses the first invoice
    assertValue("invoice.year", year); // On return to order detail we verify
    assertValue("invoice.number", number); // the invoice has been selected
}
In this case we rely on the fact that there is at least one order, and that the first order in the list has no invoice. Before running this test, if you have no orders, create one with no invoice, or if you already have orders, be sure that the first one has no invoice.
With this you have your tests ready. Just execute them, and you'll get the next result:
inheritance_en110.png
Note that the base test CommercialDocumentTest is not shown because it is abstract. And the testCreate() method of CommercialDocumentTest is executed for both InvoiceTest and OrderTest.
Not only have you adapted your testing code to the improved code for Invoicing, but you have also learned how to use inheritance in the test code as well.

Summary

This lesson has shown you some practical examples about how to use the inheritance of Java and JPA to simplify your code. We used the default JPA configuration for inheritance, though you can refine JPA behavior for inheritance using some JPA annotations like @Inheritance, @DiscriminatorColumn, @DiscriminatorValue, etc. To learn more about inheritance in JPA read the documents cited in Appendix B.

Download source code of this lesson

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