sd_notify() from Java
Asked Answered
H

3

11

I have a Java service (implemented using Dropwizard) which I'm launching from a user instance of systemd. So far so good. Now I would like to use systemd's notification features to make it aware of the service state (available as a C library function or shell script but eventually both methods talk to a socket referenced by an environment variable). I can run arbitrary code when the service has finished starting up, but I'm not sure how best to notify systemd from within Java.

Other developers run this service on Windows, so for bonus points it would be really useful if my notification code were discreet and didn't cause any output if not running with systemd.

Haha answered 27/11, 2014 at 17:37 Comment(1)
Since that notification feature requires native code, you'll need to use JNI and/or JNA.Loveliesbleeding
J
3

I found this implementation which does use system hooks, but at least doesn't require JNA/JNI.

https://gist.github.com/yrro/18dc22513f1001d0ec8d

As you say, systemd uses sockets referenced by an environment variable (System.getenv("NOTIFY_SOCKET") in the code), so I'd imagine there may also be a way to use a Java Socket, although I'd imagine a lot of research and/or trial-and-error would be required.

Jury answered 19/2, 2016 at 3:20 Comment(3)
Good call -- I've yet to find a better solution. I've removed your link, as it's actually referencing a SO clone's copy of this question.Haha
This class uses something, forking a child systemd-notify process, that is notoriously unreliable. There is a better way.Farcy
I've taken the answer from @Farcy and turned it into something a little more generic: gist.github.com/juur/048cc3d0554953b717e9c6867970f30eAudy
C
0

There is Java + JNI implementation:

https://github.com/faljse/SDNotify

The Notify protocol uses datagram unix sockets, which are not accessible via Java; Therefore SDNotify includes a JNA wrapper of the socket API.

Checkpoint answered 25/1, 2023 at 15:8 Comment(0)
D
0

I created an implementation which does not use either systemd-notify as a subprocess nor require JNA/JNI. However, as Java does not support AF_UNIX Datagram sockets natively I had to pull in junixsocket as a depenency (though this can likely be replaced with a smaller library, it was just the first one which I found).

import java.io.IOException;
import java.nio.ByteBuffer;

import org.newsclub.net.unix.AFUNIXDatagramSocket;
import org.newsclub.net.unix.AFUNIXSocketAddress;

public class SdNotify {
    public static void main(String[] args) {
        ready();
    }

    public static void ready() {
        notify("READY=1");
    }

    public static void status(String status) {
        notify("STATUS=" + status);
    }

    /// ...implement other well-known sd_notify(3) messages as needed...

    private static void notify(String arg) {
        var socketPath = System.getenv("NOTIFY_SOCKET");
        if (socketPath == null)
            return;

        if (!(socketPath.startsWith("/") || socketPath.startsWith("@"))) {
            throw new UnsupportedOperationException("Unsupported socket type");
        }

        if (socketPath.startsWith("@")) {
            socketPath = "\0" + socketPath.substring(1);
        }

        try (var socket = AFUNIXDatagramSocket.newInstance()) {
            socket.connect(AFUNIXSocketAddress.of(socketPath.getBytes()));

            try (var out = socket.getChannel()) {
                out.write(ByteBuffer.wrap(arg.getBytes()));
            }
        } catch (IOException e) {
            System.err.printf("Failed to notify systemd of service readiness: %s", e.toString());
        }
    }
}

https://gist.github.com/septatrix/dcb1d7763c941be399da5dc97397e6c3

Determinism answered 14/8 at 22:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.