logo

ShrimpWorks

// why am I so n00b?

There’s a strong tendency to want to run everything in Docker these days, especially if you’re trying to run something as an always-on service, since passing --restart=always to your run invocation or Docker Compose configuration ensures that running containers start back up after reboots or failures, and seems to involve a little less “black magic” than actually configuring software to run as services directly on a host.

The downside to this is the approach is that running a service in a container leads to significantly longer startup times, more memory and CPU overhead, lost logs, and in my opinion offer a false sense of security and isolation since most images are still configured to run as root, and more often than not large swathes of the host filesystem are mounted as volumes to achieve simple tasks.

There’s also a belief that your software will magically run anywhere - but if you’re writing Java (or any JVM language) code - that’s one of Java’s biggest selling points - it already has its own VM your code is running in, no most platforms!

Therefore, let’s see how easy it actually is to configure our software to run as a standard system service, providing us with the ability to run it as a separate restricted user, complete with standard logging configuration, and give us control over via standard service myservice start|status|restart|stop commands.

arrow Continue Reading ...

Some thing I’ve been using for a while, and which recently became useful at work as well, is a simple HTTP service written in plain Java with existing JRE functionality, using an HttpServer.

Here’s a simple “main()” which sets up two basic “pages”, a root (/) and one which echoes your browser’s request headers (/headers/).

public class SimpleHTTPService {

    public static void main(String[] args) throws IOException {
        HttpServer server = HttpServerProvider.provider().createHttpServer(new InetSocketAddress(8080), 0);

        server.createContext("/", new HttpHandler() {
            @Override
            public void handle(HttpExchange he) throws IOException {
                byte[] output = "Hello world!".getBytes();
                he.sendResponseHeaders(200, output.length);
                he.getResponseBody().write(output);
            }
        });

        server.createContext("/headers", new HttpHandler() {
            @Override
            public void handle(HttpExchange he) throws IOException {
                StringBuilder result = new StringBuilder("Request Headers");
                for (Entry< String, List< String>> header : he.getRequestHeaders().entrySet()) {
                    result.append(String.format("%s", header.getKey()));
                    for (String val : header.getValue()) {
                        result.append(String.format("%s", val));
                    }
                    result.append("");
                }

                byte[] output = result.toString().getBytes();
                he.sendResponseHeaders(200, output.length);
                he.getResponseBody().write(output);
            }
        });

        server.setExecutor(Executors.newCachedThreadPool());

        server.start();

        System.out.println("HTTP Listening on port " + server.getAddress().getPort());
    }
}

Running this as-is will allow you to load up the URLs http://localhost:8080/ and http://localhost:8080/headers/ and see some output generated by the two registered contexts.

I’ve defined simple anonymous inner class contexts here, as it’s easy to play with, but obviously you can go wild and develop proper structures for these.

Combined with something like FreeMarker, and you’ve got a pretty neat way to deploy simple stand-alone HTTP applications written in Java with minimal external dependencies.

It’s also extremely useful for creating mock-ups services for use in unit tests for HTTP clients.