Tag Archives: axios

Simplified delivery of react.js from apache karaf

This article is about a new servlet base class I have created to simplify serving up javascript frontends from the OSGi web whiteboard.

This article won’t go into the structure of the files that must be served. See Deliver react.js from apache karaf and A Java programmers guide to delivering webapp frontends to get an overview of files.

The short story is that the servlet needs to deliver two files:

  1. An index.html containing the initial DOM tree of the web application (if loaded in a web browser that will be all that’s shown), e.g. like this
    <html xmlns="http://www.w3.org/1999/xhtml">
    <title>Frontend Karaf Test</title>
    <meta name="viewport" content="width=device-width, initial-scale=1.0"></meta>
    <div id="root"></div>
    <script src="bundle.js" type="application/javascript"></script>
    <noscript>This webpage requires javascript in the browser!</noscript>
    view raw index.html hosted with ❤ by GitHub
  2. A bundle.js file containing the javascript of the application as well as all dependencies, all packed together to be as compact as possible

The index.html file and the bundle.js files are added as classpath resources in the OSGi bundle containing the servlet.

The index.html file is added by putting it into src/main/resources of the maven project for the OSGi bundle.

The bundle.js file is added to the classpath by letting the frontend-maven-plugin drop the created bundle.js into target/classes/

<id>install node and npm</id>
<id>npm install</id>
<id>webpack build</id>
view raw pom.xml hosted with ❤ by GitHub

Everything covered so far is identical to what’s described in the first blog post.

The difference is how much simpler creating the servlet component is.

A web whiteboard DS component for serving a frontend without any routing could look like this:

@Component(service={Servlet.class}, property={"alias=/frontend-karaf-demo"})
public class ReactServlet extends FrontendServlet {
public void setLogservice(LogService logservice) {
view raw ReactServlet.java hosted with ❤ by GitHub

The LogService service injection is passed to the FrontendServlet base class, where it is used to report problems when serving files.

If the web application has a router that can be used to edit the local part, like e.g. so

<Provider store={store}>
<div className="App">
<Route exact path="/frontend-karaf-demo/" component={Home} />
<Route path="/frontend-karaf-demo/counter" component={Counter} />
<Route path="/frontend-karaf-demo/about" component={About} />
view raw routes.jsx hosted with ❤ by GitHub

then the servlet needs to have matching routes (that’s the setRoutes() call in the constructor):
@Component(service={Servlet.class}, property={"alias=/frontend-karaf-demo"})
public class ReactServlet extends FrontendServlet {
public ReactServlet() {
setRoutes("/", "/counter", "/about");
view raw ReactServlet.java hosted with ❤ by GitHub

The paths are used when reloading a subpage, e.g. by pressing F5 in the web browser. All paths will return the index.html file which in turn will load the bundle.js which will navigate to the correct sub-page based on the path.

Note that the react paths have the application web context, while the paths on the java side are without the application web part:

React routes Java routes
/frontend-karaf-demo/ /
/frontend-karaf-demo/counter /counter
/frontend-karaf-demo/about /about

Deliver react.js from apache karaf

Edit: delivering react.js has been made simpler, see Simplified delivery of react.js from apache karaf for details.

A small barebones demo application/testbed, delivering a single-page web application from apache karaf, can be found at https://github.com/steinarb/frontend-karaf-demo

The JavaScript framework used to write the application is react.js

Screenshot of the demo open on the “counter” page

The frontend application is webpack‘d into a single bundle.js file. The packing is done by the frontend-maven-plugin (i.e. no local node.js installation required).

The bundle.js and its wrapping index.xhtml page, are served as static resources from the OSGi bundle’s classpath by a DS component that registers a Servlet service with the web whiteboard extender on the path /frontend-karaf-demo

The react.js features featured in this application, are:

  • react.js to render the application’s page
  • redux to hold the application’s state
  • redux-saga and axios for REST API communication and asynchronous update of the application’s state (the REST service used by axios, is provided by an OSGi DS whiteboard Servlet)
  • react-router to route between different pages (however this requires hardcoding the ReactServlet’s path into the react app, and requires the ReactServlet to return the top level index.html from all routes)
  • react-bootstrap and bootstrap v3 to style the application in a responsive way (I haven’t made any effort to make it look good. I just include the boostrap style and activate the responsive formatting in a meta header tag in the index.html page)

To try out the application:

  1. Clone this project and build it:
    git clone https://github.com/steinarb/frontend-karaf-demo.git
    cd frontend-karaf-demo/
    git checkout release/1.0.0
    mvn clean install
  2. Install apache karaf and start it  according to the karaf quick start guide (alternatively, see Develop OSGi applications using karaf)
  3. At the karaf command line give the following commands
    feature:repo-add mvn:no.priv.bang.demos/frontend-karaf-demo/LATEST/xml/features
    feature:install frontend-karaf-demo
  4. Open http://localhost:8181/frontend-karaf-demo in a web browser and try it out