Introducing AppFormer.js: React components in Red Hat Business Central
Recently AppFormer.js initiative PRs were merged into KIE master branches. This means that it’s now possible to write React componentes and use them inside Business Central! 🎉
In this post, I’ll show how we achieved this and what needs to be done to create your own AppFormer.js components using React and integrate them in Business Central.
Content
- The programming model
- Setting up your environment
- Creating a Maven module for your NPM package
- Creating your AppFormer.js component
- Integrating into Business Central
- Running and live-reloading your changes during development
The programming model
AppFomer.js was created with the goal of being a next generation of the AppFormer programming model. By implenting a well-defined contract, components can be reused by different platforms and abstract their underlying technologies.
If you’re familiar with UberFire, you know that Perspectives, Screens, Editors (and others) are what make this programming model consistent. With AppFormer.js, it’s no different. We chose Perspectives and Screens as the first two contracts to be defined, but it can be extended to cover more of it, like Editors, for instance.
In this first moment, we built these contracts having React and GWT components in mind so we could end up with an abstraction that covered both bases. We’re also going to use TypeScript in order to keep our types explicit and have a good understanding of the programming model.
So what does an AppFormer.js component look like? It’s pretty straightforward. Imagine you have a React component like this.
Turning it into an AppFormer.Screen
or AppFormer.Perspective
is simple:
A few things are worth noting in these examples:
this.af_isReact = true
is what indicates that a component is a React component.- the
super
constructor call is what defined the uniqueid
of the component. - AppFormer.js has its own lifecycle. I encourage you to explore the
AppFormer.Screen
definition to see which methods are available. - React components that translate into AppFormer.js components must be class components, so you can integrate it with AppFormer.js lifecycle.
- This prop called
self
is what exposes the React component to AppFormer.js. Although that is an antipattern, it's very useful here. Be aware that you should not abuse this construction and always try and keep the single directional data-flow consistent. AppFormer.register[Screen/Perspective]
is what actually creates your components. Remember to call it!
Setting up your environment
If you already have the kiegroup repositories set up, you can skip this section.
First, make sure you have these:
Now clone this repo https://github.com//tiagobento/kiegroup-all
and follow the instructions on the README.md file. Instead of a normal mvn clean install
, use this command:
mvn clean install -Denforcer.skip -Dgwt.compiler.skip -DskipTests -Dgwt.skipCompilation
It will speed up the compilation a bit.
You should see a BUILD SUCCESS
message.
Great!
We’re ready to create a new Mavenzied NPM Package integrated with Business Central’s build!
Creating a Maven module for your NPM package
We’ll be creating a very simple AppFormer.Screen
inside Business Central's Library, just like the new Spaces Screen. But before we start coding, we need to configure our Mavenized NPM package inside Business Central's build. Because Business Central's Library is inside kie-wb-common
, that's where we're going to add our new module.
The first thing we need is an NPM package where our TypeScript code will be, I’ll provide an starter NPM package configuration with the tools we encourage you to use, but feel free to make your own configuration. We’re gonna call our NPM package kie-wb-common-library-afjs-first-screen
.
Two things are very important, though:
- You must use the same
react
andreact-dom
versions that Business Central provides:16.6.0
React
andReactDOM
themselves must NOT be inside your final component bundle, so if you're using Webpack, make sure that bothreact
andreact-dom
are marked as external.
One other very important thing is that appformer-js
must be fetched using mvn
, not npm
. How does that work? We create a pom.xml
file that will fetch the org.ubefire:appformer-js:[version]
JAR for us and will extract it inside a directory on the root of our NPM package. Then we will alter our NPM package's package.json
to point to appformer-js as a local NPM package instead of a NPM package coming from the NPM registry. Like this:
So you if feel more comfortable downloading a starter Mavenized NPM package, click here.
If you want to configure it by yourself, make sure to call your directory kie-wb-common-library-afjs-first-screen
.
Now, move the kie-wb-common-library-afjs-first-screen
directory to kiegroup-all/kie-wb-common/kie-wb-common-screens/kie-wb-common-library
.
We just have to change kiegroup-all/kie-wb-common/kie-wb-common-screens/kie-wb-common-library/pom.xml
to see our new module, so apply this:
On kiegroup-all
root, run:
mvn clean install -DskipTests -f kie-wb-common/kie-wb-common-screens/kie-wb-common-library/pom.xml
.
You should see a BUILD SUCCESS
message.
Great!
We already have our NPM package configured and integrated as a Maven module inside kiegroup/kie-wb-common
build. Now it's time for us to create our AppFormer.js component inside it!
Creating your AppFormer.js component
On your favorite editor, open kie-wb-common-library-afjs-first-screen/src/index.tsx
. For the sake of simplicity, we're going to create our AppFormer.Screen
and our sub-components on the same file. You can download the file here.
The first thing we have to do is create a class extending AppFormer.Screen
an make sure to register it. Like so:
Now, we can get creative and create a React component to go along with our screen. If you’re familiar with React tutorials, you know that we’re creating a Counter component 🙂
More than just a Counter, this is a Counter Card, as it contains CSS that will match Business Central’s look & feel. At last, we can use the CounterCard
component we just created inside our AppFormer.Screen
. So apply these changes to AfjsFirstScreen
Like the CounterCard
component we just created, these changes also contain CSS to match Business Central's look & feel.
On kiegroup-all
root, run:
mvn clean install -DskipTests -f kie-wb-common/kie-wb-common-screens/kie-wb-common-library/kie-wb-common-library-afjs-first-screen/pom.xml
.
You should see a BUILD SUCCESS
message.
Great!
Your first AppFormer.js component is ready to be used in Business Central! Let’s do this with some very simple configurations.
Integrating into Business Central
For the sake of this tutorial, we’re not going to use the full sized Business Central version. Instead, we’re going to work with Drools Workbench, which is an application that has some of the features Business Central and is optimized for development. Don’t worry! The process of adding an AppFormer.js component on Business Central is exactly the same.
Note that because Business Central and Drools Workbench both already have AppFormer.js components integrated, there’s already a line of code to “activate” the AppFormer.js capabilities. It’s usually located on an @EntryPoint
class for AppFormer.js to be available at the very beginning of the app. You can take a look at the @PostConstruct
-annotated method on org/drools/workbench/client/DroolsWorkbenchEntryPoint.java
if you want. The argument to AppFormerJsBridge#init
should be the exact same name of the GWT module being compiled because we'll use that to assemble the URL to lazyly load the AppFormer.js components.
The repository where we’re going to work now is drools-wb
, and the module is drools-wb-webapp
. Open it on your favorite editor or IDE and apply the changes below.
On kiegroup-all/drools-wb/drools-wb-webapp/pom.xml
, add this execution configuration on the maven-dependency-plugin
executions tag:
On the same file, add this execution configuration on the maven-resources-plugin
executions tag.
These togheter will unpack kie-wb-common-library-afjs-first-screen
JAR, which contains our component's bundled JavaScript and copy this bundle to the application's output directory. It's conventioned that every AppFormer.js component bundle must be under /org/uberfire/jsbridge/public
, or it won't work.
Last configuration we have to do before changing the application to have some way to access our new screen is to pur our component’s information on AppFormer.js registry. All AppFormer.js components are lazily loaded, so we have to register it so AppFormer.js knows when and what to fetch.
On kiegroup-all/drools-wb/drools-wb-webapp/src/main/resources/org/uberfire/jsbridge/public/AppFormerComponentsRegistry.js
, add this entry:
We’re almost there. To make our screen accessible, we’re going to add an item to the Menu of the application. Go to org.drools.workbench.client.DroolsWorkbenchEntryPoint
and add these lines on the setupMenu
method.
Now let’s bring the application up so we can (finally! 🎉) see our new screen.
On kiegroup-all
root, run:
mvn clean gwt:run -f drools-wb/drools-wb-webapp
Wait for the “errai bus started.” message on your console and go to “ http://localhost:8888". Log in with admin/admin
and wait for the compilation to finish. When the application starts, go to Menu > AppFormer.js First Screen
. Voilà! There it is. Click around so you can see that our component actually works.
That’s what you should see:
Great!
Your AppFormer.js component is up and running inside Business Central! Now let’s see how to speed up the development workflow.
Running and live-reloading your changes during development
This only works on macOS and Linux at the moment.
If we want to change something on our recently created AppFormer.js component without bringing Business Central (or Drools Workbench in this case) down, everything we have to do it to change the bunlded JavaScript file inside the running application. To do that, we can simply execute a “copy” command. With a bit of bash scripting knowledge, we can achieve this:
Go to kiegroup-all/kie-wb-common/kie-wb-common-screens/kie-wb-common-library/kie-wb-common-library-afjs-first-screen
and run:
npx watch 'yarn run live-reload-on ~/redhat/kiegroup-all/drools-wb/drools-wb-webapp' ./src
This will run the watch
command inside /node_modules/.bin
and execute the command yarn run live-reload-on ~/redhat/kiegroup-all/drools-wb/drools-wb-webapp
everytime something on ./src
changes. The argument yo yarn run live-reload-on
is the location of your running application. In my case it was ~/redhat/kiegroup-all/drools-wb/drools-wb-webapp
. Pretty handy!
If you’re curious you can see how it’s done on kie-wb-common-library-afjs-first-screen/package.json
.
To see that it works, change something on kie-wb-common-library-afjs-first-screen/src/index.tsx
, wait for the build to finish, go to your browser and refresh the page. After navigating to AppFormer.js First Screen, you should see your changes there.
Great!
Now you can easily change and see the changes you made inside Business Central!