React, Web Applications, WildFly

Hosting a React Application on WildFly

Introduction

As part of an upcoming development item I am going to be working with a React application deployed to the WildFly application server and invoking JAX-RS / Rest endpoint to interact with a server side of the application.

I thought others might find it useful to see the steps I have taken. This blog post describes my steps up until the point I have the default React application deployed to WildFly, I may then follow up with some blogs of my subsequent steps.

Generating The Maven Project

The WildFly project now publishes a set of Guides demonstrating how to accomplish some tasks quickly, I am going to start from the Getting Started with WildFly which quickly generates a new Maven project which includes a HTML page with some JavaScript to invoke a JAX-RPC endpoint also contained within the deployment.

The first step is to use Maven to generate the project using the defaults provided:

mvn archetype:generate \
    -DarchetypeGroupId=org.wildfly.archetype \
    -DarchetypeArtifactId=wildfly-getting-started-archetype

At this stage it is possible to build and run the default application but I am not going to cover that here as it is already covered in the guide.

The next stage to generate the React application will require Node.js to be installed locally, however once the project has been created other developers will be able to work on it without installing Node.js as the Maven project will manage it’s own installation.

The newly generate Maven project should have given you a structure similar to:

We will add the React part of the project under src/main, in the terminal navigate to this directory and execute the following command:

npx create-react-app getting-started

This will take some time to complete but once completed there will be a new directory getting-started which will be populated with a template React application.

The next step is to add building of the React application to the build and then include the resulting build in the war that is being built, first add the following plugin to the projects pom.xml:

<plugin>
    <groupId>com.github.eirslett</groupId>
    <artifactId>frontend-maven-plugin</artifactId>
    <version>1.15.0</version>
    <configuration>
        <installDirectory>target</installDirectory>
        <workingDirectory>src/main/getting-started</workingDirectory>
    </configuration>
    <executions>
        <!-- Install node and npm -->
        <execution>
            <id>Install Node and NPM</id>
            <goals>
                <goal>install-node-and-npm</goal>
            </goals>
            <configuration>
                <nodeVersion>v20.10.0</nodeVersion>
            </configuration>
        </execution>
        <!-- clean install -->
        <execution>
            <id>npm install</id>
            <goals>
                <goal>npm</goal>
            </goals>
        </execution>
        <!-- build app -->
        <execution>
            <id>npm run build</id>
            <goals>
                <goal>npm</goal>
            </goals>
            <configuration>
                <arguments>run build</arguments>
            </configuration>
        </execution>
    </executions>
</plugin>    

This plugin performs three steps:

  1. Install node and npm under /target/node
  2. Run npm install within the React application to update the dependencies.
  3. Build the React application.

Next the following configuration is added to the maven-war-plugin:

<configuration>
    <!-- Jakarta EE doesn't require web.xml, Maven needs to catch up! -->
    <failOnMissingWebXml>false</failOnMissingWebXml>
    <webResources>
        <resource>
            <!-- this is relative to the pom.xml directory -->
            <directory>src/main/getting-started/build</directory>
        </resource>
    </webResources>
</configuration>               

Now the project can be built and started as described in the WildFly Getting Started guide:

mvn package
./target/server/bin/standalone.sh

You can now connect your web browser to http://localhost:8080/ and you should be presented with the spinning React logo.

NOTE: When the project was generated under src/main there was a directory called, webapp, this contains the original web content and the contents of this directory can be safely deleted.

Storing the project in a Git respository

If you would like to store the project in a git repository there are a couple of additional steps to perform.

When the React application was created it was created with a default Git repository, this can be used if you would like to treat the React part of the deployment as a submodule but at this stage I will contain the whole example in a single repository.

The following directory and file should be deleted:

  • src/main/getting-started/.git
  • src/main/getting-started/.gitignore

In the root of the project initialise a new repository with git init.

Add a .gitignore with the following content:

target
.settings
.vscode

# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
node_modules
.pnp
.pnp.js

# testing
/coverage

# production
build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*

Now all files can be added and committed to the repository.

I have created a GitHub repository wildfly-react-getting-started which contains the project I created as I assembled this post.

Next Steps

The project I have published is as it was created writing this point, in a future update I will restore the HTML page which was communicating with the JAX-RS endpoint deployed to the application server and update it to use React for the user interface portion of the page.