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:
- 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 This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
<html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>Frontend Karaf Test</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"></meta> </head> <body> <div id="root"></div> <script src="bundle.js" type="application/javascript"></script> <noscript>This webpage requires javascript in the browser!</noscript> </body> </html> - 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/
<project> | |
<build> | |
<plugins> | |
<plugin> | |
<groupId>com.github.eirslett</groupId> | |
<artifactId>frontend-maven-plugin</artifactId> | |
<version>1.6</version> | |
<configuration> | |
<nodeVersion>v10.4.0</nodeVersion> | |
<workingDirectory>src/main/frontend</workingDirectory> | |
<installDirectory>target</installDirectory> | |
</configuration> | |
<executions> | |
<execution> | |
<id>install node and npm</id> | |
<goals> | |
<goal>install-node-and-npm</goal> | |
</goals> | |
</execution> | |
<execution> | |
<id>npm install</id> | |
<goals> | |
<goal>npm</goal> | |
</goals> | |
</execution> | |
<execution> | |
<id>webpack build</id> | |
<goals> | |
<goal>webpack</goal> | |
</goals> | |
</execution> | |
</executions> | |
</plugin> | |
</plugins> | |
</build> | |
</project> |
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 { | |
@Reference | |
public void setLogservice(LogService logservice) { | |
super.setLogService(logservice); | |
} | |
} |
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}> | |
<Router> | |
<div className="App"> | |
<Switch> | |
<Route exact path="/frontend-karaf-demo/" component={Home} /> | |
<Route path="/frontend-karaf-demo/counter" component={Counter} /> | |
<Route path="/frontend-karaf-demo/about" component={About} /> | |
</Switch> | |
</div> | |
</Router> | |
</Provider> |
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() { | |
super(); | |
setRoutes("/", "/counter", "/about"); | |
} | |
... | |
} |
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 |
4 thoughts on “Simplified delivery of react.js from apache karaf”