What are Models?

Models are representations of objects in your application's domain. Models contain the domain data and related business logic. EasyWeb4J recommends having all business logic within your model classes to avoid the Anaemic Domain Model anti-pattern.

All Model classes in an EasyWeb4J application must inherit from the Model class. This class provides methods which facilitate the operations of domain models in your application.

Tips for Models

  • Do not add accessors or mutators (getters or setters) in your model classes.
  • Code all business logic pertaining to a domain object in the corresponding model class.
  • Use annotations for mapping the models to database. This will make moving from Hibernate to JPA for ORM easier.
  • Not all models are persistent and the Model class does not provide any persistence facility.
  • Do not add presentation or data access logic to your models.
  • Perform all validations within your model classes.
  • Override the validate() method to validate the value of fields of the model instance after their values have been updated.
  • Do not add actual error messages in your models. Instead, add error keys, the exact message for which can be looked up from a resource bundle later.
  • Use validateRequired() method to check for presence of values in fields.
  • Many other common validations can be achieved easily using Commons Validator.

Built-in Validations

EasyWeb4J performs validation of input formats automatically while updating the model's fields. When a validation fails, an error key of this format is added to the model's errors. The exact error message for this error key can be specified in a message bundle. EasyWeb4J applications are created with a default message bundle initially. More on message bundles will be discussed in the "Views" section of this tutorial.

formatError.<simple_name_of_field_type>

Here are few sample error keys and the types applicable,

Key Type
formatError.Integer java.lang.Integer
formatError.BigDecimal java.math.BigDecimal
formatError.Date java.util.Date

Models' Relationships

The models acting in the tutorial we'are building are as below,

  • Paradigm (The various programming paradigms).
  • ExecutionEnvironment (The possible execution environments).
  • Language (The programming languages being cataloged).

The relationships between these models would be,

Models Relationship
Language - Paradigm Many to Many
Language - ExecutionEnvironment Many to One

Models' Code

It is to be noted that the models use standard JPA annotations for mapping their properties to the tables in database and do not have accessors and mutators.

src/main/java/org/languages/models/Paradigm.java:

package org.languages.models;

// import statements hidden

@Entity
@Table(name = "paradigm")
public class Paradigm extends Model {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String name;
    private String description;

    @Override
    protected void validate() {
        validateRequired("name", name);
        validateRequired("description", description);
    }
}

src/main/java/org/languages/models/ExecutionEnvironment.java:

package org.languages.models;

// import statements hidden

@Entity
@Table(name="execution_environment")
public class ExecutionEnvironment extends Model {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    
    private String name;
    private String description;
    
    @Override
    protected void validate() {
        validateRequired("name", name);
        validateRequired("description", description);
    }
}

src/main/java/org/languages/models/Language.java:

package org.languages.models;

// import statements hidden

@Entity
@Table(name = "language")
public class Language extends Model {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String name;

    @Column(name = "statically_typed")
    private Boolean staticallyTyped;
    @Column(name = "dynamically_typed")
    private Boolean dynamicallyTyped;

    @ManyToOne
    @JoinColumn(name = "execution_environment_id")
    private ExecutionEnvironment executionEnvironment;

    @ManyToMany
    @JoinTable(name = "language_paradigm", joinColumns = @JoinColumn(name = "language_id"), inverseJoinColumns = @JoinColumn(name = "paradigm_id"))
    private List<Paradigm> paradigms;

    @Override
    protected void validate() {
        validateRequired("name", name);
        validateRequired("executionEnvironment", executionEnvironment);
        validateRequired("paradigms", paradigms);

        if ((staticallyTyped == null || !staticallyTyped)
                && (dynamicallyTyped == null || !dynamicallyTyped))
            addError("typing", "typing.required");
    }
}

Adding the Mappings

Add mappings for the entities created above, in the session-factory element within your project's hibernate.xml as shown below.

<mapping class="org.languages.models.Paradigm" />
<mapping class="org.languages.models.ExecutionEnvironment" />
<mapping class="org.languages.models.Language" />