org.rapidpm.microservice.optionals.service.ServiceWrapper.java Source code

Java tutorial

Introduction

Here is the source code for org.rapidpm.microservice.optionals.service.ServiceWrapper.java

Source

/**
 * Copyright  2013 Sven Ruppert (sven.ruppert@gmail.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.rapidpm.microservice.optionals.service;

import static org.rapidpm.microservice.Main.deploy;
import static org.rapidpm.microservice.MainUndertow.CONTEXT_PATH_REST;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import javax.ws.rs.Path;

import org.apache.commons.io.IOUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.rapidpm.dependencies.core.logger.Logger;
import org.rapidpm.dependencies.core.logger.LoggingService;
import org.rapidpm.dependencies.core.system.ExitHandler;
import org.rapidpm.dependencies.core.system.SystemExitHandler;
import org.rapidpm.microservice.MainUndertow;
import org.rapidpm.microservice.rest.optionals.admin.BasicAdministration;

public class ServiceWrapper {

    private static final LoggingService LOGGER = Logger.getLogger(ServiceWrapper.class);
    public static final String SHUTDOWN = "SHUTDOWN";
    public static final int DELAY = 1000;
    public static final java.nio.file.Path MICROSERVICE_REST_FILE = Paths.get("microservice.rest");

    public static ExitHandler exitHandler = new SystemExitHandler();

    private ServiceWrapper() {
    }

    public static void main(String[] args) {
        boolean shutdown = Arrays.stream(args).anyMatch(s -> s.equals(SHUTDOWN));
        if (!shutdown) {
            startMicroservice(args);
        } else {
            shutdownMicroservice();
        }
    }

    private static void startMicroservice(String[] args) {
        checkPortFileExists();
        deploy(Optional.ofNullable(args));
        writeRestPortToFile();
    }

    private static void checkPortFileExists() {

        if (Files.exists(MICROSERVICE_REST_FILE)) {
            LOGGER.warning("File " + MICROSERVICE_REST_FILE + "already exists.");
            LOGGER.warning("Service seems to be running. Make sure the service terminated and remove the file.");
            LOGGER.warning("Then restart the service");
            exitHandler.exit(1);
        }
    }

    private static void writeRestPortToFile() {
        String restPort = System.getProperty(MainUndertow.REST_PORT_PROPERTY, MainUndertow.DEFAULT_REST_PORT + "");
        try {
            Files.write(MICROSERVICE_REST_FILE, Collections.singletonList(restPort));
        } catch (IOException e) {
            LOGGER.warning("Can not write to File " + MICROSERVICE_REST_FILE
                    + "check permissions and restart the service");
            exitHandler.exit(1);
        }

    }

    private static void shutdownMicroservice() {

        String restBaseUrl = buildBaseUrl();

        Optional<Annotation> pathAnnotation = getAnnotation();

        if (pathAnnotation.isPresent()) {
            sendShutdownToService(restBaseUrl, pathAnnotation);
        } else {
            LOGGER.warning(
                    "Could not locate Path of rest service. Could it be you forgot to add the admin optional?");
            exitHandler.exit(1);
        }

        try {
            Files.delete(MICROSERVICE_REST_FILE);
        } catch (IOException e) {
            LOGGER.warning("Could not delete file " + MICROSERVICE_REST_FILE + "Cleanup file before restart");
            exitHandler.exit(1);
        }

    }

    private static void sendShutdownToService(String restBaseUrl, Optional<Annotation> pathAnnotation) {
        String adminRestPath = getAdminRestPath(pathAnnotation);

        LOGGER.fine("Sending SHUTDOWN message to microservice");

        String returnedValue = null;
        try {
            returnedValue = callRest(restBaseUrl, adminRestPath);
        } catch (IOException e) {
            LOGGER.warning("Failed to call rest endpoint");
            exitHandler.exit(1);
        }
        LOGGER.warning("Received answer, Server shutting down");

        if (!returnedValue.toLowerCase().contains("ok")) {
            LOGGER.warning("Service returned <" + returnedValue + ">");
            LOGGER.warning("Something went wrong, exiting");
            exitHandler.exit(1);
        }
    }

    private static String buildBaseUrl() {
        try {
            String restPortFromFile = getRestPortFromFile();
            return String.format("http://127.0.0.1:%d/%s", Integer.valueOf(restPortFromFile), CONTEXT_PATH_REST);

        } catch (FileNotFoundException e) {
            LOGGER.warning("The file " + MICROSERVICE_REST_FILE
                    + " was not found. \n It seems like your service wasn't started");
            exitHandler.exit(1);
        } catch (IOException e) {
            LOGGER.warning("The file " + MICROSERVICE_REST_FILE + " wasn't read/writeable. \n" + e.getMessage());
            exitHandler.exit(1);
        } catch (NumberFormatException e) {
            LOGGER.warning(
                    "The file " + MICROSERVICE_REST_FILE + " contained no readable port. \n" + e.getMessage());
            LOGGER.warning("Remove the file and start the service again");
            exitHandler.exit(1);
        }

        return null; //never reached
    }

    private static String getRestPortFromFile() throws IOException {
        List<String> lines = Files.readAllLines(MICROSERVICE_REST_FILE, Charset.defaultCharset());
        if (lines.size() != 1) {
            throw new NumberFormatException("File does not contain a number. It is empty");
        }
        return lines.get(0);
    }

    private static Optional<Annotation> getAnnotation() {
        return Arrays.stream(BasicAdministration.class.getAnnotations())
                .filter(a -> a.annotationType().equals(Path.class)).findFirst();
    }

    private static String getAdminRestPath(Optional<Annotation> pathAnnotation) {
        Path annotation = (Path) pathAnnotation.get();
        return annotation.value();
    }

    private static String callRest(String restBaseUrl, String adminRestPath) throws IOException {
        CloseableHttpClient httpClient = HttpClients.createMinimal();
        HttpGet httpGet = new HttpGet(restBaseUrl + adminRestPath + "/" + DELAY);
        final CloseableHttpResponse response = httpClient.execute(httpGet);
        return IOUtils.toString(response.getEntity().getContent());
    }
}