org.openl.rules.maven.AppServer Maven / Gradle / Ivy
The 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 builder = HttpClient.newBuilder();
if (Runtime.version().feature() >= 13) {
// The leak memory fix is failed under Java 11 when multi-thread maven build.
// So add the check, when the issue was fixed
// See https://bugs.openjdk.org/browse/JDK-8217264
builder.executor(Runnable::run); // To prevent memory leak via the default thread pool
}
var client = builder
.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);
}
}
}