Features/end-user usage

This chapter highlights a number of features of the wicket viewer from the perspective of an end-user actually using your Apache Causeway application.

The Wicket viewer supports two different styles of dialog prompts for actions that have parameters: as a sidebar, and as a (movable) modal dialog.

  • The sidebar prompt style looks like this:

    sidebar
  • while the modal dialog looks like:

    modal

The sidebar is the default prompt style, and its benefit is that it doesn’t obscure the rest of the information shown on the page; it also doesn’t interrupt the end-user’s context so much (they are more likely to remember why they invoked the action).

The causeway.viewer.wicket.prompt-style can be used to change the default style if required.

Bookmarked pages

The Wicket viewer supports the automatic bookmarking of domain objects, as per @DomainObjectLayout#bookmarking(). However, it does not support bookmarking of action prompts (@ActionLayout#bookmarking()).

Whenever a bookmarkable object/action is visited, then a bookmark is created. To avoid the number of bookmarks from indefinitely growing, bookmarks that have not been followed after a while are automatically removed (an MRU/LRU algorithm). The number of bookmarks to preserve can be configured.

Screenshots

The following screenshot shows how bookmarks are rendered in the Wicket viewer:

panel estatio

This screenshot demonstrates that bookmarks can be nested. Some - like Property and Lease - are root nodes. However, Unit is bookmarkable as a child of Property. This parent/child relationship is reflected in the layout.

Domain Code

To indicate a class is bookmarkable, use the @DomainObjectLayout annotation:

@DomainObjectLayout(
    bookmarking=BookmarkPolicy.AS_ROOT
)
public class Lease { /* ... */ }

To indicate a class is bookmarkable but only as a child of some parent bookmark, specify the bookmark policy:

@DomainObjectLayout(
    bookmarking=BookmarkPolicy.AS_CHILD
)
public class LeaseItem { /* ... */ }

User Experience

The sliding panel appears whenever the mouse pointer hovers over the thin blue tab (to the left of the top header region).

Alternatively, alt+[ will toggle open/close the panel; it can also be closed using Esc key.

Configuration

The maximum number of bookmarks that are shown can be overridden using the causeway.viewer.wicket.bookmarked-pages.max-size configuration property.

Where am I? (Navigable trees)

The Wicket viewer provides a secondary navigation scheme that allows users to quickly access domain objects, that are organized in a hierarchical manner.

This hierarchy can be understood as a navigable tree-structure, where the navigable tree-nodes are either domain objects or domain views. Domain objects that take part in such a navigable-tree-structure need to declare their actual navigable parent within this hierarchy using the @PropertyLayout#navigable() annotation.

Screenshots

The following screenshot (from the reference app) shows the navigation links below the top menu bar.

hello grey bg

Domain Code

To declare a domain object’s (or view’s) navigable parent, add a @PropertyLayout(navigable=Navigable.PARENT) annotation to a field (that has an associated getter) or a no-arg method, that returns the parent object:

Company.java
@DomainObject
public class Company { /* ... */ }
Employee.java
@DomainObject
public class Employee {

    @PropertyLayout(navigable=Navigable.PARENT) // annotated field with e.g. lombok provided getter
    @Getter
    Company myCompany;
}
PhoneNumber.java
@DomainObject
public class PhoneNumber {

    @PropertyLayout(navigable=Navigable.PARENT)  // annotated no-arg supplier
    Employee employee(){
        return ...
    }
}

This results in a navigable tree-structure …​

Company > Employee > PhoneNumber

Notes:

  1. Any use of @PropertyLayout(navigable=Navigable.PARENT) with Java interfaces is simply ignored. These do not contribute to the domain meta model.

  2. Any class (abstract or concrete) may at most have one @PropertyLayout annotation, having navigable=Navigable.PARENT 'flag' set (on either a method or a field); otherwise meta-model validation will fail.

  3. The annotated member (method or field), when …​

    1. ... a method: then must be a no-arg method returning a non-primitive type (e.g. a getter)

    2. ... a field: then the field must be of non-primitive type and must also have a getter (as specified by the Java Beans Standard, particularly to allow @PropertyLayout(navigable=Navigable.PARENT) annotations on fields that use the lombok @Getter annotation)

  4. Starting from the current domain-object, we search the object’s class inheritance hierarchy (super class, super super class, …​), until we find the first class that has a @PropertyLayout(navigable=Navigable.PARENT) annotation. That’s the one we use to resolve the current domain-object’s navigable parent.

User Experience

When viewing a domain object that is part of a hierarchical structure, one can easily navigate to any parent of this object. Horizontally arranged text links separated by the 'greater than' symbol (>) are provided below the main menu. (Traditionally called breadcrumbs.)

The navigable tree-structure, as provided by the "where am i" feature, is declared at compile-time (predefined by the programmer), whereas Bookmarked Pages) are populated at runtime only after user interaction.

Titles in Tables

Object titles can often be quite long if the intention is to uniquely identify the object. While this is appropriate for the object view, it can be cumbersome within tables.

If an object’s title is specified with from @Title annotation then the Wicket viewer will (for parented collections) automatically "contextualize" a title by excluding the part of the title corresponding to a reference to the owning (parent) object.

For example, suppose we have:

Diagram

so that Customer has a collection of Orders:

public class Customer {
    public Set<Order> getOrders() { /* ... */ }
    ...
}

and Product also has a collection of Orders:

public class Product {
    public Set<Order> getOrders() { /* ... */ }
    ...
}

and where the Order class references both Customer and Product.

The Order's might involve each of these:

public class Order {
    @Title(sequence="1")
    public Customer getCustomer() { /* ... */ }
    @Title(sequence="2")
    public Product getProduct() { /* ... */ }
    @Title(sequence="3")
    public String getOtherInfo() { /* ... */ }
    ...
}

In this case, if we view a Customer with its collection of Orders, then in that parented collection’s table the customer’s property will be automatically excluded from the title of the Order (but it would show the product). Conversely, if a Product is viewed then its collection of Orders would suppress product (but would show the customer).

This feature is a close cousin of the @PropertyLayout(hidden=Where.REFERENCES_PARENT) annotation, which will cause the property itself to be hidden as a column in the table. An Apache Causeway idiom is therefore:

public class Order {
    @Title(sequence="1")
    @PropertyLayout(hidden=Where.REFERENCES_PARENT)
    public Customer getCustomer() { /* ... */ }
    ...
}

The above annotations mean that titles usually "just work", altering according to the context in which they are viewed.

It is also possible to configure the Wicket viewer to abbreviate titles or suppress them completely.

User Registration

The Wicket viewer provides the ability for users to sign-up by providing a valid email address:

  • from the login page the user can instead follow a link to take them to a sign-up page, where they enter their email address.

  • a verification email is sent using this service; the email includes a link back to the running application.

  • the user then completes the registration process by choosing a user name and password.

  • the Wicket viewer then creates an account for them and logs them in.

In a similar way, if the user has forgotten their password then they can request a reset link to be sent to their email, again by providing their email address.

To support this the framework requires three services to be registered and configured:

The Apache Causeway core framework provides a default implementation of both the email notification service and the email service. The Security Manager extension provides a partial implementation of user registration service that you can complete for your own applications.

Screenshots

The user is presented with a login page:

login page default

Navigate to the sign up page. Complete the page, and verify:

sign up page

Back to the login page:

sign up login page after sign up

Email arrives, with link:

sign up email with verification link

Follow the link, complete the page:

sign up registration page

Automatically logged in:

sign up after registration

Configuration

There are two prerequisites:

It is also possible to configure the Wicket viewer to suppress the sign-up page link and/or the password reset page, see here for further details.