Book Image

jBPM6 Developer Guide

Book Image

jBPM6 Developer Guide

Overview of this book

Table of Contents (21 chapters)
jBPM6 Developer Guide
Credits
About the Author
Acknowledgments
About the Author
About the Author
About the Reviewers
www.PacktPub.com
Preface
Index

UberFire


UberFire is a JBoss-based framework developed and maintained by the Drools and jBPM team. UberFire creates a rich client platform built on top of GWT (http://www.gwtproject.org) and Errai (http://erraiframework.org). It is also the technology on top of which the KIE workbench project is built. It provides a series of components for a pluggable user administration, virtual file system management, and configurable perspectives and user interfaces. It is thought of as a work on top of an application server, and depends on JEE6 specifications (such as CDI, for dependency injection).

UberFire defines a few default implementations for a few of its services, but they are all highly configurable. For example, for user management, they use a user properties file as default, but the KIE workbench uses Java as a service implementation configured with a file in the classpath at META-INF/services/org.uberfire.security.auth.AuthenticationSource with the actual implementation to use for authentication.

We will discuss only a few of the components of UberFire here due to the need of perhaps a full book to cover every component. However, if you wish to go deeper into the framework utilities, visit http://www.uberfireframework.org.

Some of the most important functionalities that UberFire provides from our perspective are follows:

  • Integration of components

  • Existing components and services used by jBPM6

  • How to extend and reuse components

Tip

As I'm writing this book, UberFire is still in Alpha state, so some things might change in the near future. I'll try to cover the most important architecture components of UberFire you will more likely use, and that are less likely to change in the future.

Integrating components

As we mentioned before, UberFire is heavily dependent on GWT and Errai, integrated internally through a series of CDI injected events that each component either fires or captures to decide actions that need to be taken.

Context and Dependency Injection (CDI) is a standard defined by Java Enterprise Edition 6 to compose different components based on their types, names, and specific centralized configurations. The idea behind it is remove the need of writing legacy code to initialize and bind together different implementations of components, but allow them to be managed through specific annotations in classes and by configuration files.

Google Web Toolkit (GWT) is a framework created by Google that is used to define smart user interfaces using Java code, which are later (during project compilation) translated into JavaScript in order to run in a web browser without the need of having any plugins installed. Its goal is to enable productive development of high-performance web applications without the developer having to be an expert in browser quirks, Ajax requests, and JavaScript.

The main problem that a GWT translation of Java to JavaScript has is that it doesn't translate everything. There is a point where you have to split which classes run in the client as JavaScript and which classes run in the server as Java. Connectivity between the server and client don't take advantage of other frameworks such as CDI to inject communication stubs.

That's where Errai comes in. Errai provides several GWT extensions for UI templating, binding, and server communication through simple events. Errai allows users to define CDI annotations on GWT code and provides a way to translate those annotations and use them even if the actual component implementations are only server-side (that means, they weren't translated to JavaScript).

This allows components to directly communicate using events irrespective of whether they were server components or client components that will later on be translated to JavaScript. The level of unification in the design that this framework allowed made UberFire an incredibly powerful framework.

Thanks to all the already existing components in the workbench and the fact that all communication can be handled through events, extending components to listen to new events is very simple and new components that interact with other actions taken by the user or the server can be written with very loose coupled code.

The existing components and services

There are many existing components in the UberFire framework, and covering them all will take a book by itself. We will explore the most important components from the BPM perspective, and how they help in the generation of a BPM system for jBPM6.

Some of the backend features that UberFire has that are important for jBPM6 are as follows:

  • Security framework: UberFire security is highly pluggable and assumes very little by default. Any class that implements the org.uberfire.security.auth.AuthenticationSource interface can tell the framework which credentials are valid and which are not. The framework comes with a starter set of AuthenticationSource implementations, but you can implement your own, add it to your workbench class path, and configure it using Java's standard ServiceLoader facility, by simply writing the full class name in the META-INF/services/org.uberfire.security.auth.AuthenticationSource file. If you want more than one authentication source at a time, list each fully qualified class name on its own line in the file; if your AuthenticationSource implementation also implements RoleProvider, then it can also provide role authorization.

  • Virtual File System API: UberFire provides a configurable virtual file system and an implementation of said configurations using Git software configuration management (http://git-scm.com). This allows UberFire to store not only the knowledge assets created with the KIE workbench, but also perspective definitions and geometries for users' customized layouts. The interface provided for the virtual file system is created by backporting the NIO.2 API defined for Java 8 (https://jcp.org/en/jsr/detail?id=203) into the code base of UberFire. Just as the security framework, it can be configured using Java's standard ServiceLoader facility by writing content to the META-INF/services/org.uberfire.java.nio.file.spi.FileSystemProvider file. However, this isn't a recommended practice unless you know exactly what you're doing.

Thanks to these backend features, a lot of other features can be easily provided. Among the frontend features, we have the following:

  • Perspective generation: Perspectives provide a powerful mechanism for task-oriented interaction with resources, multi-tasking, and information filtering. It provides the possibility of having different visual components arranged in multiple different ways with little or no code at all.

  • Flexible layout: This, combined with the perspective generation utilities, provides the final user with a way of defining a particular view for him or her that can be utilized later on in future when he or she logs in. Thanks to the filesystem and security management features combined, the UberFire framework can internally store the preferences for each user's perspectives.

  • Event intercommunication between components: Thanks to Errai and CDI, all components (both client and server side) can easily interact using events.

Event intercommunication is a very important and simple-to-use component that generates events that can be shared by the client and server. The first thing we need to do is to define our event objects. Let's examine how we defined NewMessageEvent in our uberfire-demo-api project:

@org.jboss.errai.common.client.api.annotations.Portable
public class NewMessageEvent implements Serializable {
    public NewMessageEvent() { … }
    …
}

In the previous code fragment, which we reduced to the most important sections, you can see that our event doesn't have to extend any specific class. All it needs is a @Portable annotation from Errai to be shared between client and server. Inside the event, any kind of serializable information can be placed to be shared between a client and server.

Later on, these events are captured or fired by specific instances, but the configuration to use them is almost trivial. In the following code fragment, we see how the MessageListViewImpl class in the uberfire-demo-client project listens for NewMessageEvent firings and how it fires another type of event called NotificationEvent:

public class MessageListViewImpl … {
    …
    @javax.inject.Inject
    public javax.enterprise.event.Event<NotificationEvent> notification;
    …
    public void requestCreated(@javax.enterprise.event.Observes NewMessageEvent e ){
        …
    }

    public void displayNotification( String text ) {
        notification.fire( new NotificationEvent( text ) );
    }
   …
}

As you can see, all it took to listen to event firings was the creation of a method that had a parameter with the @Observes annotation. In the previous code fragment, the method is called requestCreated.

Meanwhile, we need two things to fire events:

  • A javax.enterprise.event.Event object

  • A fire method needs to be invoked with a new event instance

In the previous code fragment, the fire method is invoked from inside the displayNotification method. Using the Event object is quite simple. Thanks to CDI and Errai, we don't need to do anything else than to inject the instance with the @Inject annotation, and then let the framework take care of creating the actual object and setting it to any component.