Building entity views

How entity views work

An EntityView is created by an EntityViewFactory based on an EntityViewRequest. A controller is still responsible for executing (usually rendering) the actual EntityView.

The GenericEntityViewController is responsible for loading and rendering all default views in the AdminWebModule UI.

The path of the web request to GenericEntityViewController will determine:

  • the name of the view that should be rendered

  • which EntityViewRegistry will be used for loading the view (EntityConfiguration or EntityAssociation)

You can force the view being rendered by simply providing the view name as a request parameter with key view.

The controller creates an EntityViewRequest, retrieves the EntityViewFactory and builds the corresponding EntityViewContext and EntityViewCommand.

EntityViewRequest

Wraps together all the information of a specific entity view request:

  • the web request that is creating the view

  • the contextual information of the entity being viewed (represented by the EntityViewContext)

  • the command that should be executed on the EntityViewFactory (represented by the EntityViewCommand)

  • the name of the view being requested and the EntityViewFactory being used

  • the PageContentStructure of the page being rendered (if applicable)

Please refer to the EntityViewRequest javadoc for a description of all available properties.

EntityViewContext

The EntityViewContext contains contextual information and provides access to components that should be used for building a view. Contextual information is for example the entity type, specific entity or entity association being viewed. Components are things like the EntityLinkBuilder, EntityMessages or AllowableActions

Please refer to the EntityViewContext javadoc for a description of all available properties.

EntityViewContext is available as a request-scoped bean but only in case of a request passing through the GenericEntityViewController will the data be loaded. Loading the EntityViewContext attributes manually can be done by using the EntityViewContextLoader bean. You should use the ConfigurableEntityViewContext interface to modify a view context.

EntityViewCommand

The EntityViewCommand represents the command that should be executed on the EntityViewFactory to create the corresponding EntityView. Most often the command represents the form of a view where the request parameters are bound to.

An EntityViewCommand has 2 attributes: the (optional) entity DTO being bound and a map of named extensions. Customizing view processing can be done by registering additional extensions that will be rendered and validated upon binding.

The EntityViewCommand will be validated for every state modifying request: web requests using POST, PUT, PATCH or DELETE.

Please refer to the EntityViewCommand javadoc for a description of all available properties.

EntityViewFactory

Every view is built by an EntityViewFactory. An EntityViewRegistry (like EntityConfiguration or EntiyAssociation) is nothing but a map of EntityViewFactory by view name.

An EntityViewFactory is a stateless controller with 4 controller methods that are expected to be called in a specific order. Please refer to the javadoc for an overview of the different controller methods and their purpose.

DispatchingEntityViewFactory

EntityModule has only a single implementation of EntityViewFactory in the form of the DefaultEntityViewFactory. The DefaultEntityViewFactory:

  • supports ViewElement based rendering model - heavily used by EntityModule for building the HTML markup

  • dispatches its controller methods in a more fine-grained manner to a list of registered and ordered EntityViewProcessor instances.

The default builders when configuring views only register EntityViewProcessor beans on the factory. When an EntityViewFactory controller method is being called, it will be translated into one or more processor methods and those method calls will be dispatched to all processors in order.

The DefaultEntityViewFactory will not execute any of the rendering related methods if any of the previous methods has marked the EntityView as being a redirect or have specified their own ResponseEntity.

EntityViewProcessor

EntityViewProcessor classes allow to hook into the execution of a view request. View processors give access to the configuration of the context for the request and the actual execution of the request. This enables us to perform most, if not all, of the logic executed during a request by using view processors.

Configuring the context

Initialization of the EntityViewContext

prepareEntityViewContext allows for modifications to the EntityViewContext which holds information about the entity configuration or entity that is viewed.

Authorization of the request

An authorizeRequest method is provided that should throw a relevant exception if the request is invalid.

Initialization of the EntityViewCommand

Initializes the EntityViewCommand for the current request. The EntityViewCommand represents the command object to handle the form data. It will hold the DTO for the entity that is being created or updated and supports the configuration of additional extension objects that should be bound and validated as well. initializeCommandObject allows you configure the EntityViewCommand for use in the remainder of the request lifecycle.

Executing a request

The execution of the view request has two aspects, executing the request and rendering elements. A request is handled in various lifecycle steps.

Preprocessing

Actions that should be taken before the request is handled, such as validating the command object. This is done in the preProcess step of an EntityViewProcessor.

Executing the request

The actual execution of the request, performed via the doControl step. In this step, the controller logic is executed, such as saving an entity and building a response.

Rendering

An optional step. If rendering should be applied, three additional methods are used to build the elements that should be rendered on the view.

  • preRender: This is the point where the ViewElementBuilderContext is configured and ViewElementBuilders are created.

  • render: Where the initial rendering happens. At this point, most of the configuration has been executed and the elements that should be rendered are finalized.

  • postRender: Perform render related postprocessing. This step is commonly used to modify the view after all the elements have been created, such as moving items within the layout.

Various utility methods are available through the ContainerViewElementUtils, for manipulating container view elements, and EntityViewElementUtils for working with view elements and view building.

Postprocessing

General purpose postprocessing of the request when the view has been fully processed and is ready to be returned to the user. postProcess is the final step in the execution of a view and is always executed.

For ease of use, several specialized adapter classes have been provided to hook into the rendering process:

  • EntityViewProcessorAdapter for most use cases, it provides several adapter methods that also allow you to hook into the ViewElement generation lifecycle

  • SimpleEntityViewProcessorAdapter if you do not need to hook into the ViewElement generation lifecycle

  • ExtensionViewProcessorAdapter if you want to create a custom view/form that represents a so-called extension object

    • the view is part of the entity configuration but often does not manage properties of the actual entity type

Please refer to the appendix for a list of all available general purpose processors.

Transaction support

The DefaultEntityViewFactory uses a TransactionalEntityViewProcessorRegistry and enables transactions on all state modifying HTTP methods: POST, PUT, PATCH or DELETE. If a transaction manager bean name is available on the EntityConfiguration, transactions will be enabled by default for all form views: create, update, delete and custom form views. This means that all calls in state modifying doControl() methods of all EntityViewProcessor instances will happen in a single transaction.

The transaction manager bean name is registered as an attribute EntityAttributes.TRANSACTION_MANAGER_NAME and is detected automatically for every Spring Data repository based entity.

Manually enabling transactions on a view

You can enable transactions manually on the EntityViewFactoryBuilder by specifying either the PlatformTransactionManager to use, the name of the transaction manager bean or a TransactionTemplate if you need more fine-grained control.

Model attributes

The GenericEntityViewController exposes the following model attributes to the Spring MVC view:

Attribute name Value

entityViewRequest

EntityViewRequest

entityViewCommand

EntityViewCommand

entityViewContext

EntityViewContext

Default view types

EntityModule supports 3 view types by default.

When defining a new view (see the next section) it will be one of these types. The view type determines the base template that will be used to setup the EntityViewFactory.

The following view types are defined:

View type Template name Description

list view

listView (EntityView.LIST_VIEW_NAME)

Base configuration for rendering a list of entities.

form view

updateView (EntityView.UPDATE_VIEW_NAME)

Base configuration for rendering a form for a single entity.

generic view

genericView (EntityView.GENERIC_VIEW_NAME)

Barebone configuration for visualizing a single entity.

The template name can be used to replace the initializer for the EntityViewFactoryBuilder. See the chapter on the EntityViewFactoryBuilderInitializer.

See also the next chapters for more information on list view, form view and generic view.