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.
Sidebar vs Modal Dialogs
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:
-
while the modal dialog looks like:
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:
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.
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:
@DomainObject
public class Company { /* ... */ }
@DomainObject
public class Employee {
@PropertyLayout(navigable=Navigable.PARENT) // annotated field with e.g. lombok provided getter
@Getter
Company myCompany;
}
@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:
-
Any use of
@PropertyLayout(navigable=Navigable.PARENT)
with Java interfaces is simply ignored. These do not contribute to the domain meta model. -
Any class (abstract or concrete) may at most have one
@PropertyLayout
annotation, havingnavigable=Navigable.PARENT
'flag' set (on either a method or a field); otherwise meta-model validation will fail. -
The annotated member (method or field), when …
-
... a method: then must be a no-arg method returning a non-primitive type (e.g. a getter)
-
... 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)
-
-
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.)
Related functionality
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:
so that Customer
has a collection of Order
s:
public class Customer {
public Set<Order> getOrders() { /* ... */ }
...
}
and Product
also has a collection of Order
s:
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 Order
s, 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 Order
s would suppress product (but would show the customer).
This feature is a close cousin of the
|
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 user registration service, which provides an API to create the user account
-
the email notification service, which provides an API for to send the verification emails
-
the email service, that is used by the email notification service to actually send the email.
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:
Navigate to the sign up page. Complete the page, and verify:
Back to the login page:
Email arrives, with link:
Follow the link, complete the page:
Automatically logged in:
Configuration
There are two prerequisites:
-
register an implementation of the user registration service
The SecMan extension provides an abstract subclass implementation that does most of the work.
-
configure the email service
This is required by the default email notification service.
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.