001package org.consensusj.jsonrpc.daemon; 002 003import io.micronaut.runtime.event.annotation.EventListener; 004import io.micronaut.runtime.server.EmbeddedServer; 005import io.micronaut.runtime.server.event.ServerShutdownEvent; 006import io.micronaut.runtime.server.event.ServerStartupEvent; 007import org.consensusj.jsonrpc.introspection.AbstractJsonRpcService; 008import org.consensusj.jsonrpc.introspection.JsonRpcServiceWrapper; 009import org.slf4j.Logger; 010import org.slf4j.LoggerFactory; 011 012import jakarta.inject.Singleton; 013 014import java.io.Closeable; 015import java.lang.invoke.MethodHandles; 016import java.lang.reflect.Method; 017import java.util.Map; 018import java.util.concurrent.CompletableFuture; 019 020/** 021 * Simple Echo JSON-RPC Service 022 */ 023@Singleton 024public class EchoJsonRpcService extends AbstractJsonRpcService implements Closeable { 025 private static final Logger log = LoggerFactory.getLogger(EchoJsonRpcService.class); 026 private static final Map<String, Method> methods = JsonRpcServiceWrapper.reflect(MethodHandles.lookup().lookupClass()); 027 private static final String helpString = """ 028 echo message 029 help 030 stop 031 """; 032 033 private EmbeddedServer embeddedServer; 034 035 public EchoJsonRpcService() { 036 super(methods); 037 } 038 039 @EventListener 040 public void onStartup(ServerStartupEvent event) { 041 log.info("Saving reference to embeddedServer"); 042 embeddedServer = event.getSource(); 043 } 044 045 @EventListener 046 public void onShutdown(ServerShutdownEvent event) { 047 log.info("Shutting down"); 048 this.close(); 049 } 050 051 @Override 052 public void close() { 053 log.info("Closing"); 054 } 055 056 public CompletableFuture<String> echo(String message) { 057 log.debug("EchoJsonRpcService: echo {}", message); 058 return result(message); 059 } 060 061 public CompletableFuture<String> help() { 062 log.debug("EchoJsonRpcService: help"); 063 return result(helpString); 064 } 065 066 /** 067 * Initiate server shutdown. This is a JSON-RPC method and will initiate but not 068 * complete server-shutdown because it must return a response to the client. 069 * @return A status string indicating the server is stopping 070 */ 071 public CompletableFuture<String> stop() { 072 log.info("stop"); 073 embeddedServer.stop(); 074 var appName = embeddedServer.getApplicationConfiguration().getName().orElse("server"); 075 return result(appName + " stopping"); 076 } 077}