diff --git a/gradle.properties b/gradle.properties index bdaf57b686dfa2fac67c5c71995222642f26e0b7..33598f7ffed788a097bc6f9a5b46a6b151af8411 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,6 +11,6 @@ nshmpLibVersion = 1.5.4 nshmpUtilsJavaVersion = 0.4.0 openApiVersion = 4.0.0 shadowVersion = 7.1.2 -spotbugsVersion = 4.7.0 +spotbugsVersion = 4.7.3 spotlessVersion = 6.0.4 swaggerParserVersion = 2.1.21 diff --git a/gradle/dependencies.gradle b/gradle/dependencies.gradle index d2b2fdb4639a6b5f55d5d6ba0d3e0e963a88937c..5c0b8b387c366a23250769226f6d2d3509c9a87f 100644 --- a/gradle/dependencies.gradle +++ b/gradle/dependencies.gradle @@ -35,4 +35,7 @@ dependencies { testImplementation "io.micronaut.test:micronaut-test-junit5" testImplementation "io.micronaut.test:micronaut-test-spock" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine" + + spotbugs("com.github.spotbugs:spotbugs:${spotbugsVersion}") + spotbugsPlugins("software.amazon.lambda.snapstart:aws-lambda-snapstart-java-rules:0.2.1") } diff --git a/gradle/spotbugs.gradle b/gradle/spotbugs.gradle index 51f1a63a2462892bd53bd2c7ebb05a6a6636653e..6a40a2ce765a4b92e961ea351dabb93649bdea43 100644 --- a/gradle/spotbugs.gradle +++ b/gradle/spotbugs.gradle @@ -8,4 +8,6 @@ apply plugin: "com.github.spotbugs" spotbugs { excludeFilter = file("${projectDir}/gradle/spotbugs-filter.xml") effort = "max" + ignoreFailures.set(false) + showStackTraces.set(true) } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/PrimingResource.java b/src/main/java/gov/usgs/earthquake/nshmp/www/PrimingResource.java index c852f32a8cd8e73a5fd46bfbf953dbd676d5f629..da2ef9e140fa4bc2e5c1bd51df043f0be2b340bb 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/PrimingResource.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/PrimingResource.java @@ -1,6 +1,15 @@ package gov.usgs.earthquake.nshmp.www; +import java.net.URI; +import java.net.URL; +import java.nio.file.FileSystem; +import java.nio.file.FileSystemNotFoundException; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.HashMap; import java.util.Optional; +import java.util.concurrent.Executors; import java.util.logging.Logger; import org.crac.Context; @@ -8,6 +17,7 @@ import org.crac.Resource; import com.amazonaws.serverless.proxy.internal.testutils.MockLambdaContext; import com.amazonaws.serverless.proxy.model.AwsProxyRequest; +import com.google.common.util.concurrent.MoreExecutors; import io.micronaut.context.annotation.Value; import io.micronaut.crac.OrderedResource; @@ -20,6 +30,9 @@ import jakarta.inject.Singleton; @Singleton public class PrimingResource implements OrderedResource { + @Value("${nshmp-haz.model-path}") + private Path modelPath; + @Value("${nshmp-haz.context-path}") String contextPath; @@ -27,6 +40,7 @@ public class PrimingResource implements OrderedResource { public void beforeCheckpoint(Context<? extends Resource> context) throws Exception { Logger log = Logger.getAnonymousLogger(); log.info("Before checkpoint"); + ServletUtil.model(ServletUtil.loadModel(modelPath)); Optional<String> location = Optional.ofNullable(System.getenv("TEST_LOCATION")); @@ -35,38 +49,43 @@ public class PrimingResource implements OrderedResource { getAwsProxyRequest(contextPath + "/hazard"), new MockLambdaContext()); - log.info("Test location"); - if (location.isPresent()) { - log.info("Location: " + location.get()); - handler.handleRequest( - getAwsProxyRequest(contextPath + "/hazard" + location.get()), - new MockLambdaContext()); - } + // log.info("Test location"); + // if (location.isPresent()) { + // log.info("Location: " + location.get()); + // handler.handleRequest( + // getAwsProxyRequest(contextPath + "/hazard" + location.get()), + // new MockLambdaContext()); + // } // handler.handleRequest( - // getAwsProxyRequest(contextPath + "/probability"), - // new MockLambdaContext()); + // getAwsProxyRequest(contextPath + "/probability"), + // new MockLambdaContext()); // handler.handleRequest( - // getAwsProxyRequest(contextPath + "/rate"), - // new MockLambdaContext()); + // getAwsProxyRequest(contextPath + "/rate"), + // new MockLambdaContext()); // handler.handleRequest( - // getAwsProxyRequest(contextPath + "/disagg"), - // new MockLambdaContext()); + // getAwsProxyRequest(contextPath + "/disagg"), + // new MockLambdaContext()); // handler.handleRequest( - // getAwsProxyRequest(contextPath + "/map"), - // new MockLambdaContext()); + // getAwsProxyRequest(contextPath + "/map"), + // new MockLambdaContext()); // handler.handleRequest( - // getAwsProxyRequest(contextPath), - // new MockLambdaContext()); + // getAwsProxyRequest(contextPath), + // new MockLambdaContext()); } } @Override - public void afterRestore(Context<? extends Resource> context) throws Exception {} + public void afterRestore(Context<? extends Resource> context) throws Exception { + ServletUtil.CALC_EXECUTOR.shutdown(); + ServletUtil.TASK_EXECUTOR.shutdown(); + ServletUtil.CALC_EXECUTOR = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(ServletUtil.THREAD_COUNT)); + ServletUtil.TASK_EXECUTOR = Executors.newSingleThreadExecutor(); + } private static AwsProxyRequest getAwsProxyRequest(String path) { @@ -75,4 +94,5 @@ public class PrimingResource implements OrderedResource { awsProxyRequest.setPath(path); return awsProxyRequest; } + } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/ServletUtil.java b/src/main/java/gov/usgs/earthquake/nshmp/www/ServletUtil.java index 02203d880b29d9f4ba572fd6ba05ec420b918d0f..a3d1a7b08787855786e7768ae3be568198518565 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/ServletUtil.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/ServletUtil.java @@ -11,6 +11,7 @@ import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; +import java.util.Optional; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -52,8 +53,8 @@ public class ServletUtil { public static final Gson GSON; public static final Gson GSON2; - public static final ListeningExecutorService CALC_EXECUTOR; - public static final ExecutorService TASK_EXECUTOR; + public static ListeningExecutorService CALC_EXECUTOR; + public static ExecutorService TASK_EXECUTOR; public static final int THREAD_COUNT; @@ -62,6 +63,8 @@ public class ServletUtil { private static HazardModel HAZARD_MODEL; + private static Optional<String> awsRuntime = Optional.ofNullable(System.getenv("AWS_LAMBDA_RUNTIME_API")); + static { THREAD_COUNT = getRuntime().availableProcessors(); CALC_EXECUTOR = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(THREAD_COUNT)); @@ -89,13 +92,17 @@ public class ServletUtil { } + static void model(HazardModel model) { + HAZARD_MODEL = model; + } + public static HazardModel model() { return HAZARD_MODEL; } @EventListener void shutdown(ShutdownEvent event) { - Logger log = LoggerFactory.getLogger(getClass()); + var log = java.util.logging.Logger.getAnonymousLogger(); log.info("on shutdown"); CALC_EXECUTOR.shutdown(); @@ -104,13 +111,17 @@ public class ServletUtil { @EventListener void startup(StartupEvent event) { - Logger log = LoggerFactory.getLogger(getClass()); + var log = java.util.logging.Logger.getAnonymousLogger(); - log.info("on startup: load model"); - HAZARD_MODEL = loadModel(modelPath); + log.info("on startup"); + + if (!awsRuntime.isPresent()) { + log.info("not aws"); + HAZARD_MODEL = loadModel(modelPath); + } } - private HazardModel loadModel(Path path) { + static HazardModel loadModel(Path path) { URL url; URI uri; String uriString; diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerController.java index 41e30233bf47b55380433de92f6ea11c76fe6d0b..f629ac32d218346ad4e35e132291fd4ed8056b68 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerController.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/SwaggerController.java @@ -1,14 +1,14 @@ package gov.usgs.earthquake.nshmp.www; +import java.math.BigDecimal; import java.util.List; +import java.util.logging.Logger; -import org.slf4j.LoggerFactory; - +import gov.usgs.earthquake.nshmp.geo.Location; import gov.usgs.earthquake.nshmp.model.HazardModel; import gov.usgs.earthquake.nshmp.www.source.FeaturesService; import io.micronaut.http.HttpRequest; -import io.micronaut.http.HttpResponse; import io.micronaut.http.MediaType; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; @@ -16,6 +16,7 @@ import io.swagger.v3.core.util.Yaml; import io.swagger.v3.oas.annotations.Hidden; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.parameters.Parameter; import io.swagger.v3.parser.OpenAPIV3Parser; import jakarta.inject.Inject; @@ -35,24 +36,28 @@ public class SwaggerController { private NshmpMicronautServlet servlet; @Get(produces = MediaType.TEXT_EVENT_STREAM) - public HttpResponse<String> doGet(HttpRequest<?> request) { + public String doGet(HttpRequest<?> request) { try { var model = ServletUtil.model(); var openApi = getOpenAPI(request, model); - return HttpResponse.ok(Yaml.pretty(openApi)); + return Yaml.pretty(openApi); } catch (Exception e) { - return ServletUtil.error( - LoggerFactory.getLogger("Swagger"), - e, "Swagger", request.getUri().toString()); + return e.getMessage(); + // return ServletUtil.error( + // LoggerFactory.getLogger("Swagger"), + // e, "Swagger", request.getUri().getPath()); } } private OpenAPI getOpenAPI( HttpRequest<?> request, HazardModel model) { + Logger log = Logger.getAnonymousLogger(); var openApi = new OpenAPIV3Parser().read("META-INF/swagger/nshmp-haz.yml"); var bounds = model.bounds(); - SwaggerUtils.addLocationBounds(openApi, bounds.min, bounds.max); + log.info("a"); + // SwaggerUtils.addLocationBounds(openApi, bounds.min, bounds.max); + log.info("b"); var components = openApi.getComponents(); var schemas = components.getSchemas(); SwaggerUtils.siteClassSchema(schemas, List.copyOf(model.siteClasses().keySet())); @@ -68,4 +73,34 @@ public class SwaggerController { return openApi; } + public static OpenAPI addLocationBounds(OpenAPI openApi, Location min, Location max) { + openApi.getPaths().values().stream() + .flatMap(path -> path.readOperations().stream()) + .forEach(operation -> addLocationBounds(operation.getParameters(), min, max)); + + return openApi; + } + + public static List<Parameter> addLocationBounds( + List<Parameter> parameters, + Location min, + Location max) { + var latitudeDescription = String.format(" [%s, %s]", min.latitude, max.latitude); + var longtudeDescription = String.format(" [%s, %s]", min.longitude, max.longitude); + + parameters.forEach(parameter -> { + if (parameter.getName().equals("latitude")) { + parameter.setDescription(parameter.getDescription() + latitudeDescription); + parameter.getSchema().setMinimum(BigDecimal.valueOf(min.latitude)); + parameter.getSchema().setMaximum(BigDecimal.valueOf(max.latitude)); + } else if (parameter.getName().equals("longitude")) { + parameter.setDescription(parameter.getDescription() + longtudeDescription); + parameter.getSchema().setMinimum(BigDecimal.valueOf(min.longitude)); + parameter.getSchema().setMaximum(BigDecimal.valueOf(max.longitude)); + } + }); + + return parameters; + } + } diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java index a0bdb002b8be81bd0a4f31bf275aea0b632de2a5..5775030b59229cf55f8d38a0a9aa864cfe6129bd 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/DisaggService.java @@ -79,7 +79,7 @@ public final class DisaggService { } static HttpResponse<String> getMetadata(HttpRequest<?> request) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var usage = new Metadata(ServletUtil.model()); var response = ResponseBody.usage() .name(NAME) diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardController.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardController.java index b78c842ceb7450ebf47cc41ae8eee07d5f083ec1..7a32636719eec5b78d998e1fff7db59fa3673bae 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardController.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardController.java @@ -1,6 +1,7 @@ package gov.usgs.earthquake.nshmp.www.hazard; import java.util.Set; +import java.util.logging.Logger; import gov.usgs.earthquake.nshmp.gmm.Imt; import gov.usgs.earthquake.nshmp.www.NshmpMicronautServlet; @@ -102,6 +103,9 @@ public class HazardController { defaultValue = "false") @Nullable Boolean maxdir, @QueryValue @Nullable Set<Imt> imt) { try { + Logger log = Logger.getAnonymousLogger(); + log.info("Hazard call"); + log.info("Thread count: " + ServletUtil.THREAD_COUNT); Set<Imt> imts = HazardService.readImts(http); HazardService.Request request = new HazardService.Request( http, longitude, latitude, vs30, imts, truncate, maxdir); diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java index 42830d66d40218da8e34f8686dbcc699787f5754..8cedf4fd8231151cfcfed27a6888327fafdca643 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/hazard/HazardService.java @@ -63,7 +63,7 @@ public final class HazardService { private static final String TOTAL_KEY = "Total"; public static HttpResponse<String> getMetadata(HttpRequest<?> request) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var usage = new Metadata(ServletUtil.model()); var body = ResponseBody.usage() .name(NAME) diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/FeaturesService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/FeaturesService.java index a7ce6e5423567449f4550aba80e8bbaf84d12b24..1477b2204e4c5aa44e9bf77cf85c9b2cca7dc71b 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/FeaturesService.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/FeaturesService.java @@ -91,7 +91,7 @@ public class FeaturesService { private static HttpResponse<String> processResponse( HttpRequest<?> request, RequestData requestData) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var features = requestData.featureType == FeatureType.ALL ? Models.features(ServletUtil.model(), Optional.empty()) @@ -120,7 +120,7 @@ public class FeaturesService { } private static HttpResponse<String> metadata(HttpRequest<?> request) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var metadata = new Metadata(ServletUtil.model()); var response = ResponseBody.usage() .name(NAME) diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesService.java index 3d961d8bd07493b2bb00e95a939e0779720c1c90..ce64d2d41838c4d665860481d190a1f86d9bd631 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesService.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/LogicTreesService.java @@ -27,7 +27,7 @@ public class LogicTreesService { static final Logger LOG = LoggerFactory.getLogger(LogicTreesService.class); public static HttpResponse<String> getMetadata(HttpRequest<?> request) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var metadata = new Metadata(ServletUtil.model()); var response = ResponseBody.usage() .name(NAME) @@ -40,7 +40,7 @@ public class LogicTreesService { } public static HttpResponse<String> getFeatureTree(HttpRequest<?> request, Integer id) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var featureTree = Models.features(ServletUtil.model(), id); var requestData = new RequestData(id); var response = ResponseBody.success() @@ -54,7 +54,7 @@ public class LogicTreesService { } public static HttpResponse<String> getMfdTree(HttpRequest<?> request, Integer id) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var mfdTree = Models.tree(ServletUtil.model(), id); var requestData = new RequestData(id); var response = ResponseBody.success() diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java index 4acad3ac39db553762e4cfc548e9c39368173128..b445bb90d3422a6038f0138000e1047110c1b032 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/MfdsService.java @@ -32,7 +32,7 @@ public class MfdsService { static final Logger LOG = LoggerFactory.getLogger(LogicTreesService.class); public static HttpResponse<String> getMetadata(HttpRequest<?> request) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var metadata = new Metadata(ServletUtil.model()); var response = ResponseBody.usage() .name(NAME) @@ -49,7 +49,7 @@ public class MfdsService { TectonicSetting setting, Optional<SourceType> type) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var mfd = Models.mfd(ServletUtil.model(), setting, type); var requestData = new RequestData(setting, type.orElse(null)); var response = ResponseBody.success() diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/RateService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/RateService.java index 0907b014c71b1bb890cc9b372d119b58e8222774..69916006ec2fc422e1c7e00a09d42d1f97e33ec3 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/RateService.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/RateService.java @@ -332,7 +332,7 @@ public final class RateService { } public static HttpResponse<String> getRateMetadata(HttpRequest<?> request) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var usage = new Metadata(ServletUtil.model()); var body = ResponseBody.usage() .name(NAME_RATE) @@ -346,7 +346,7 @@ public final class RateService { } public static HttpResponse<String> getProbMetadata(HttpRequest<?> request) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var usage = new ProbMetadata(ServletUtil.model()); var body = ResponseBody.usage() .name(NAME_PROBABILITY) diff --git a/src/main/java/gov/usgs/earthquake/nshmp/www/source/SourceService.java b/src/main/java/gov/usgs/earthquake/nshmp/www/source/SourceService.java index dd1bc2ed9c11a4fa753979ede1db8dec5070aaff..2cae2b306756b9ecc17b371e5afe3d9c5a22b422 100644 --- a/src/main/java/gov/usgs/earthquake/nshmp/www/source/SourceService.java +++ b/src/main/java/gov/usgs/earthquake/nshmp/www/source/SourceService.java @@ -35,7 +35,7 @@ public class SourceService { static final Logger LOG = LoggerFactory.getLogger(SourceService.class); static HttpResponse<String> getMetadata(HttpRequest<?> request) { - var url = request.getUri().toString(); + var url = request.getUri().getPath(); var response = ResponseBody.usage() .name(NAME) .url(url) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index bda22c4f5f0c6f79f1dbb4b4b52cd3472d50be52..5d7de4be46c10fdb1a84c794b507392ad54febb3 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -21,5 +21,5 @@ nshmp-haz: # To specify the model to use: # java -jar build/libs/nshmp-haz.jar --model=<path/to/model> # - model-path: ${MODEL:nshms/nshm-conus-2018} + model-path: ${MODEL:nshms/nshm-alaska-2007} context-path: ${CONTEXT_PATH:}