All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.openl.rules.maven.AppServer Maven / Gradle / Ivy

There is a newer version: 5.27.9
Show newest version
package org.openl.rules.maven;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.time.Duration;
import java.util.Collection;
import java.util.stream.Collectors;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.ClassMatcher;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;

public class AppServer {

    /**
     * Checks that the OpenL application can be run successfully.
     * It is called via reflection in the isolated classloader.
     *
     * @param pathDeployment - location of the zipped OpenL projects
     * @param jars           - OpenL classpath
     * @param workDir        - folder location for temporary or working files
     * @throws Exception if any errors
     */
    public static void check(String pathDeployment, Collection jars, String workDir) throws Exception {
        var libs = jars.stream().map(Resource::newResource).collect(Collectors.toList());
        var webAppContext = new WebAppContext();
        webAppContext.setResourceBase(""); // No resources
        webAppContext.addSystemClassMatcher(new ClassMatcher("org.slf4j.")); // For logging via Maven SLF4J
        webAppContext.addSystemClassMatcher(new ClassMatcher("-javax.activation."));
        webAppContext.setExtraClasspath(libs); // WebAppClassLoader

        webAppContext.setInitParameter("openl.config.location", ""); // to be not affected by external configurations
        webAppContext.setInitParameter("user.home", workDir); // to be not affected by external configurations
        webAppContext.setInitParameter("production-repository.factory", "repo-zip");
        webAppContext.setInitParameter("production-repository.archives", pathDeployment);

        webAppContext.setAttribute(MetaInfConfiguration.WEBINF_JAR_PATTERN, ".*ruleservice.ws[^/]*\\.jar$"); // For scanning annotations of the RuleService WS

        var server = new Server(0); // Random port
        server.setHandler(webAppContext);

        var backupProperties = System.getProperties();
        try {
            System.setProperty("groovy.use.classvalue", "false"); // Prevent memory leak via JDK ClassValue. See GROOVY-7591
            server.start();

            int port = ((ServerConnector) server.getConnectors()[0]).getLocalPort();
            var client = HttpClient.newBuilder()
                    .executor(Runnable::run) // To prevent memory leak via the default thread pool
                    .version(HttpClient.Version.HTTP_1_1)
                    .connectTimeout(Duration.ofSeconds(60)) // wait a minute, it is usual enough a second
                    .build();
            var uri = new URL("http", "localhost", port, "/admin/healthcheck/readiness").toURI();
            var req = HttpRequest.newBuilder()
                    .uri(uri)
                    .timeout(Duration.ofSeconds(60)) // wait a minute, it is usual enough a second
                    .GET()
                    .build();
            var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
            if (resp.statusCode() != 200 || !resp.body().equals("READY")) {
                throw new IOException("Server startup failure: " + resp);
            }
        } finally {
            server.stop();
            server.destroy();
            System.setProperties(backupProperties);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy