2

I have a daemon process, written in Java, which I would like to be configurable at runtime via an HTTP-based API.

For a number of reasons, I'd rather keep the admin API separate from the daemon process itself:

  • resilience: if the admin API fails, the daemon must continue running.
  • separation of concerns: the admin API and daemon are two separate (but interrelated) components of the overall application.
  • loose coupling: it's easier to upgrade one or the other component if they're not tightly coupled.

At present, the approaches I have considered include:

  • Incorporate both daemon and admin API in a JAX-WS application. This would work, but fails on all of the above points.
  • Have the daemon process expose the admin API via an embedded web service (e.g. Jetty). This would be better than the previous approach (the daemon is no longer dependent on a web container), but otherwise shares many of the same issues.
  • Have two separate applications (daemon and API), sharing a common configuration database. This would achieve loose coupling, but lead to awkward interaction between the components (e.g. each component needing to poll the database for changes made by the other).
  • Have two separate applications, communicating via a low-level socket- or pipe-based interface. This is the best in terms of achieving loose coupling efficiently, but (presumably) at an increased cost in terms of code complexity.

If we accept that it's preferable to keep the two components loosely coupled, what is the best (i.e. most flexible and idiomatic) approach to achieving this in Java? Is there an alternative I haven't considered?

1

The challenge is that the Daemon needs to continually run, but update it's configuration on demand in a robust but in a way that can be explained over coffee. In many ways, it really depends on what the daemon needs to do and how often these configurations need to be updated. There's a few options that I've used that can help.

Batch Processing

I had a job that I essentially broke into separate pieces:

  • Scheduler daemon--responsible for determining if work is to be done, and managing the processor's process.
  • Processor command line app--responsible for reading the configuration at start up and doing the actual processing.

This arrangement was incredibly simple to understand, and we were able to live with the configuration remaining the same while a file was being processed. Some of the configuration had to do with mapping fields in document on disk to fields in a database. We would delay reading the configuration for that piece until just before processing that type of information. When we got to the next document, we just checked if there were any changes to the mapping.

Near Real Time Processing

We had an application that had both reporting and control requirements for a remote engine. The engine had to be run close to the hardware it was monitoring so that it could read the telemetry and summarize it. Due to the nature of the problem we had to provide a very simple UDP interface with small JSON packets.

Both the client and the engine had to have 2 open connections: one for receipt and one for broadcast. We had a series of well defined messages to handle the simple communications necessary:

  • Ping: message from client to engine to register or provide a keep-alive function. Any message from client to engine served this purpose.
  • Pong: message from engine to client to respond and provide a keep-alive function. Any message from engine to client served this purpose.
  • Update: message from engine to client of summarized telemetry data for display.
  • Command: message from client to engine to perform an action (could be configuration change, cease monitoring command, start monitoring command, etc.)

The needs of this tool were relatively simple, so there really wasn't a lot of reconfiguration that had to happen. Most commands dealt with managing the connection with the client and most state had to reset to default when the engine restarted anyway.


The last option would be to embed a JSON microservice (Spring Boot comes to mind) to handle your configuration API needs. The UI itself would be a single page app (SPA) that only really needs a file system to serve up the files.

1

To figure out what's the best solution you'll have to determine / define your non functional requirements.

Some of the non functional requirements may be:

  • Availability (changing the configuration must be possible at 99.9xxx% of a year).

  • Security (changing the configuration must be permitted only to admin users)

  • Time for the configuration change to become effective (a configuration change must be become effective immediately after pressing the submit button)

  • Network Topologies (daemon services must not be accessible from the internet / via HTTP)
  • ...

Other things that influence the design decisions are the number of daemons running. Do the daemons also modify the configuration? How many configuration changes per day / seconds / month do you have? Do daemon and Web Service run on the same machine, ...

A very simple solution for your problem is to have a shared configuration file (database) and HTTP Admin Interface and a Separate daemon Java process. If you don't want to pull the configuration for changes send a notification event (RMI, WebSocket, ...) to the daemon so that he knows when to reconfigure itself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.