This content app framework is based on the deprecated Vaadin 7, which
has been replaced with Vaadin 8 since Magnolia 6.0. It is part of the
Magnolia 5 UI framework.
In this tutorial you create an app that operates on data stored outside
the JCR repository. The app uses the
content
app framework but stores data on the local file system. This is an
example of connecting to a custom data source. Editors don’t have to
leave Magnolia in order to work on third-party data.
Background
The
content
app framework allows you to create standardized apps. Standardization
makes apps easy to use and learn. Since all content apps look and behave
the same way, a user who has used one can quickly learn another, even if
the apps operate on different content.
The data that content apps operate on is typically stored in the Java
Content Repository (JCR). However, apps can also operate on data that
resides outside the JCR. Editing and viewing custom data is a common
requirement. For example, editors may need to access product data in a
remote ERP system in order to create content to sell the products. Such
remote data can reside in a relational database, on the filesystem, in a
Web service, or some other data delivery service. For convenience, you
want to make the remote data available inside Magnolia in a familiar
environment so editors don’t need to jump from one system to another.
Read My first content app and the
content
app framework if you are not yet familiar with JCR-based content apps.
In this tutorial you customize an app which requires some Java
programming. You need a development environment and a basic
understanding of Magnolia modules. You will work with interfaces
originating from the Vaadin framework used to build the Magnolia UI.
Create a module
The file system browser app created in this tutorial needs to be
deployed as a Magnolia module. Choose from the following options
depending on your skill level.
Option 1: Clone the project in Git
Choose this option if you know how to work with a Magnolia project and
Git. You get the module code on your local system and can edit it in
your IDE.
Import the project into your IDE. Here’s what the project looks like
in IntelliJ IDEA:
Build the project into a JAR and deploy it to Magnolia instance or run
the project in your IDE. To run it in the IDE, add the module as a
dependency in the POM file of your bundle, see below.
Option 2: Add the project as a dependency to your bundle
Choose this option if you want to add the project to your own Magnolia
bundle. The module code will not be stored on your local system. Add the
following dependency to your
bundle:
Overview
To create a custom content app you need to implement:
Container and related classes.
Custom presenter classes for every view type you want
(ListPresenter, TreePresenter, ThumbnailPresenter, others)
Custom ContentConnector
Action classes to interact with and manipulate your custom content
Custom AvailabilityRule classes (if required)
Configuration
Create a container
A container represents your data source in Vaadin context. The container
provides methods to get, add and remove items and properties in the data
source. The container can hold 0 to n items.
The interface you have to implement for your container is
com.vaadin.data.Container. If you want to have a more sophisticated
container you also may want to implement:
info.magnolia.ui.workbench.container.Refreshable
com.vaadin.data.Container.Sortable
com.vaadin.data.Container.Indexed
The Vaadin framework itself provides some container implementations
which may be helpful for your own custom container. Use them as a source
of inspiration or just as a superclass:
com.vaadin.data.util.BeanContainer
com.vaadin.data.util.sqlcontainer.SQLContainer
com.vaadin.ui.Table
com.vaadin.ui.TreeTable
File system container
The container class for the file system browser app is
info.magnolia.filesystembrowser.app.contentview.RefreshableFSContainer.
The class delegates most of the work to
com.vaadin.data.util.FilesystemContainer which again is a container
implementation provided by the Vaadin framework. When creating your own
custom container, study the interface and related classes.
Workbench
Workbench is a view that displays content items in a workspace. It is
part of the content app framework, typically defined in the browser
subapp. The workbench contains a list of content views. Common view
types are tree, list and thumbnail.
Your custom app can use the same views as a typical JCR content app such
as tree, list and thumbnail but other views are possible too.
To implement a presenter:
Provide a concrete implementation of
info.magnolia.ui.workbench.AbstractContentPresenterBase.
Implement the initializeContainer() method. This method is a link to
your custom container. Instantiate and initialize the container in the
method.
The code fragment above is simplified. The package declaration, imports
and some comments have been removed.
The other presenter used for the fs-browser-app is very similar; it
extends info.magnolia.ui.workbench.thumbnail.ThumbnailPresenter, but
the method initializeContainer() is a little bit more complicated, but
still easy.
When you have the custom-presenters, you also should create definition
classes:
The tree above is just a part of the whole configuration of the
fs-browser-app. However, it contains the relevant parts for the content
views and presenters.
Create a custom content connector
The
content
connector is one of the core pieces for the your custom content app
with non-JCR content. You need a custom implementation and
contentConnector node in the configuration.
In the fs-browser-app, the custom implementation is
info.magnolia.filesystembrowser.app.contentconnector.FileSystemContentConnector.
Its definition class is
info.magnolia.filesystembrowser.app.contentconnector.FSContentConnectorDefinition.
The contentConnector node of your own custom content app can have more
properties. It depends on the implementation of your definition class.
Here FSContentConnectorDefinition has just one bean-property: the root
folder. The other property class comes from the superclass of the
definition class
(info.magnolia.ui.vaadin.integration.contentconnector.ConfiguredContentConnectorDefinition).
You must always provide the property class when creating a custom
content app.
Implement action classes to operate on custom content
Now that you have a container and a content connector, your data source
is anchored in the content app and is now ready to be used. As you
already know from JCR-related content apps, to work with the items, you
have to create
action
definitions and configure the app with the available actions.
Start with info.magnolia.filesystembrowser.app.action.RefreshFSAction:
This action does not do a lot. The execute method is only firing an
event which leads to a refresh of the content view. Imagine that you
have added a file to a root folder which is represented by your
fs-browser-app and you want your app to reflect the changes in the
filesystem. You can inject the contentConnector into the constructor
which is really handy.
The next example shows the typical pattern where the scenario is started
with OpenEditDialogAction and where a dialog must be provided. In that
case, the custom action
info.magnolia.filesystembrowser.app.action.SaveFileActionDefinition is
defined as the commit action in the dialog.
In your custom content-app you would have more sophisticated action -
e.g. you could implement actions to create, update and delete (CRUD)
items.
Implement custom availability rules
Availability rules are optional. Generally, availability classes
implement info.magnolia.ui.api.availability.AvailabilityRule, most of
them by extending
info.magnolia.ui.api.availability.AbstractAvailabilityRule.
Note, that the older version was depending on javax.jcr.Item to
compare, whereas the newer version is less strict typed - which allows
it to implement availability rule classes for non-JCR related content.
The fs-browser-app has such an availability rule class, too:
The rule class itself has a definition class -
info.magnolia.filesystembrowser.app.action.availability.IsImageRuleDefinition
- which then is used in the configuration:
In the above tree, you can see that it is possible to combine more than
one availability rule classes. The 2nd and the 3rd one under the node
filename doesn’t exist and is just an example. When using more then one
class, their results are combined with AND-operator.
Instead of using the class-property, which points to a definition-class,
you also can use the implementationClass-property, which then must point
directly to the rule-implementation-class,
Finally assemble
Now all parts are ready and if not already done - the app can be
configured. If you are unsure about how to do that, have a look at
Configuration.
Some of the details of the configuration have been shown above. To
finish, have a look at the screenshot of the configuration of the
fs-browser-ap: