Additionally, we needed to be able to add the functionality without adding another framework to make it happen. It needed to be something that was available in the existing Java SE/EE APIs. Again, the ServiceLoader seemed to be a possible solution.
I did a Proof of Concept (POC) for using a ServiceLoader to accomplish adding additional services to our application. That worked, but required a restart of the server, or a reload of the application at a minimum. This assumes that the application was NOT auto-deployed. It turns out that worked, but really was only a half-measure. I wanted to see if I could solve the dynamic reloading part, and I did.
SolutionBefore we see the code, how does it work in general. We use the ServiceLoader which is part of the Service Provider Interface (SPI) functionality of Java. It is a hidden gem for those who need it, and framework creators can take advantage of this simple, easy to use technology. The ServiceLoader is managed by a Singleton that returns an instance of the ServiceLoader that will return our SPI implementations. In my example, I create an interface that is packaged separately in its own jar and is shared between the deployed web application and the service implementations. The ServiceLoader loads this interface and makes the implementations available. The cool part is that our Singleton class also has some cool NIO and NIO.2 help with the ZipFileSystemProvider to load the implementations from newly added jars. It also has some demo of how to use a URLClassLoader to add our new implementations and update the ServiceLoader.
The code for the project can be found here:
- serviceloader-web-example (code)
Log.javaHere is our interface that is common between the web service and the SPI implementations.
LogImpl.javaThis simple interface will allow me to demonstrate the power of the SPI. Here is an implementation of the API.
LogServiceThis class is the magic behind the SPI and allows us to dyanmically reload the new implementations as we add them to the WEB-INF/lib directory.
com.bluelotussoftware.service.spi.LogThe SPI file located in the
META-INF/servicesdirectory of your jar file. This is one version, but each implementation would have its own. The file name is the same as the interface, and the listings on each line are concrete implementations.