From 6927c51885bb3073b310150c4f40c64eea44a919 Mon Sep 17 00:00:00 2001 From: Fabian Mastenbroek Date: Sun, 22 Jan 2023 00:30:51 +0000 Subject: refactor(web/server): Convert resources to Java This change converts the resource classes of the OpenDC web server to use Java, The Quarkus integration for Java is more mature and the programming quality of experience is not that much worse. --- .../opendc/web/server/rest/SchedulerResource.java | 52 ++++++++ .../org/opendc/web/server/rest/TraceResource.java | 70 ++++++++++ .../MissingKotlinParameterExceptionMapper.java | 46 +++++++ .../rest/error/WebApplicationExceptionMapper.java | 51 +++++++ .../opendc/web/server/rest/runner/JobResource.java | 103 +++++++++++++++ .../web/server/rest/user/PortfolioResource.java | 120 +++++++++++++++++ .../rest/user/PortfolioScenarioResource.java | 89 +++++++++++++ .../web/server/rest/user/ProjectResource.java | 118 +++++++++++++++++ .../web/server/rest/user/ScenarioResource.java | 94 +++++++++++++ .../web/server/rest/user/TopologyResource.java | 146 +++++++++++++++++++++ .../opendc/web/server/rest/user/UserResource.java | 73 +++++++++++ .../org/opendc/web/server/service/JobService.java | 8 +- .../opendc/web/server/service/ScenarioService.java | 9 +- .../opendc/web/server/service/TraceService.java | 55 -------- .../org/opendc/web/server/service/UserService.java | 58 -------- .../web/server/util/KotlinModuleCustomizer.java | 39 ++++++ 16 files changed, 1016 insertions(+), 115 deletions(-) create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/SchedulerResource.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/TraceResource.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/runner/JobResource.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioResource.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioScenarioResource.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ProjectResource.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ScenarioResource.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/TopologyResource.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/UserResource.java delete mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/TraceService.java delete mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/UserService.java create mode 100644 opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/KotlinModuleCustomizer.java (limited to 'opendc-web/opendc-web-server/src/main/java/org/opendc/web/server') diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/SchedulerResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/SchedulerResource.java new file mode 100644 index 00000000..0fd58182 --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/SchedulerResource.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest; + +import java.util.List; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; + +/** + * A resource representing the available schedulers that can be used during experiments. + */ +@Produces("application/json") +@Path("/schedulers") +public final class SchedulerResource { + /** + * Obtain all available schedulers. + */ + @GET + public List getAll() { + return List.of( + "mem", + "mem-inv", + "core-mem", + "core-mem-inv", + "active-servers", + "active-servers-inv", + "provisioned-cores", + "provisioned-cores-inv", + "random"); + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/TraceResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/TraceResource.java new file mode 100644 index 00000000..2b1efb02 --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/TraceResource.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest; + +import java.util.List; +import java.util.stream.Stream; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import org.opendc.web.server.model.Trace; + +/** + * A resource representing the workload traces available in the OpenDC instance. + */ +@Produces("application/json") +@Path("/traces") +public final class TraceResource { + /** + * Obtain all available traces. + */ + @GET + public List getAll() { + Stream entities = Trace.streamAll(); + return entities.map(TraceResource::toUserDto).toList(); + } + + /** + * Obtain trace information by identifier. + */ + @GET + @Path("{id}") + public org.opendc.web.proto.Trace get(@PathParam("id") String id) { + Trace trace = Trace.findById(id); + + if (trace == null) { + throw new WebApplicationException("Trace not found", 404); + } + + return toUserDto(trace); + } + + /** + * Convert a {@link Trace] entity into a {@link org.opendc.web.proto.Trace} DTO. + */ + public static org.opendc.web.proto.Trace toUserDto(Trace trace) { + return new org.opendc.web.proto.Trace(trace.id, trace.name, trace.type); + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.java new file mode 100644 index 00000000..3b6be42e --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/MissingKotlinParameterExceptionMapper.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest.error; + +import com.fasterxml.jackson.module.kotlin.MissingKotlinParameterException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import org.opendc.web.proto.ProtocolError; + +/** + * An [ExceptionMapper] for [MissingKotlinParameterException] thrown by Jackson. + */ +@Provider +public final class MissingKotlinParameterExceptionMapper implements ExceptionMapper { + @Override + public Response toResponse(MissingKotlinParameterException exception) { + return Response.status(Response.Status.BAD_REQUEST) + .entity(new ProtocolError( + Response.Status.BAD_REQUEST.getStatusCode(), + "Field " + exception.getParameter().getName() + " is missing from body.")) + .type(MediaType.APPLICATION_JSON) + .build(); + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.java new file mode 100644 index 00000000..ad1bb05e --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/error/WebApplicationExceptionMapper.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest.error; + +import javax.ws.rs.WebApplicationException; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; +import org.opendc.web.proto.ProtocolError; + +/** + * Helper class to transform a {@link WebApplicationException} into an JSON error response. + */ +@Provider +public final class WebApplicationExceptionMapper implements ExceptionMapper { + @Override + public Response toResponse(WebApplicationException exception) { + int code = exception.getResponse().getStatus(); + + String message = exception.getMessage(); + if (message == null) { + message = "Unknown error"; + } + + return Response.status(code) + .entity(new ProtocolError(code, message)) + .type(MediaType.APPLICATION_JSON) + .build(); + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/runner/JobResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/runner/JobResource.java new file mode 100644 index 00000000..134c6814 --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/runner/JobResource.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest.runner; + +import java.util.List; +import javax.annotation.security.RolesAllowed; +import javax.transaction.Transactional; +import javax.validation.Valid; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import org.opendc.web.server.service.JobService; + +/** + * A resource representing the available simulation jobs. + */ +@Produces("application/json") +@Path("/jobs") +@RolesAllowed("runner") +public final class JobResource { + /** + * The {@link JobService} responsible for managing the jobs. + */ + private final JobService jobService; + + /** + * Construct a {@link JobResource} instance. + * + * @param jobService The {@link JobService} responsible for managing the jobs. + */ + public JobResource(JobService jobService) { + this.jobService = jobService; + } + + /** + * Obtain all pending simulation jobs. + */ + @GET + public List queryPending() { + return jobService.listPending(); + } + + /** + * Get a job by identifier. + */ + @GET + @Path("{job}") + public org.opendc.web.proto.runner.Job get(@PathParam("job") long id) { + org.opendc.web.proto.runner.Job job = jobService.findById(id); + if (job == null) { + throw new WebApplicationException("Job not found", 404); + } + + return job; + } + + /** + * Atomically update the state of a job. + */ + @POST + @Path("{job}") + @Consumes("application/json") + @Transactional + public org.opendc.web.proto.runner.Job update( + @PathParam("job") long id, @Valid org.opendc.web.proto.runner.Job.Update update) { + try { + var job = jobService.updateState(id, update.getState(), update.getRuntime(), update.getResults()); + if (job == null) { + throw new WebApplicationException("Job not found", 404); + } + + return job; + } catch (IllegalArgumentException e) { + throw new WebApplicationException(e, 400); + } catch (IllegalStateException e) { + throw new WebApplicationException(e, 409); + } + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioResource.java new file mode 100644 index 00000000..e8e05f97 --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioResource.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest.user; + +import io.quarkus.security.identity.SecurityIdentity; +import java.util.List; +import javax.annotation.security.RolesAllowed; +import javax.transaction.Transactional; +import javax.validation.Valid; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import org.opendc.web.server.service.PortfolioService; + +/** + * A resource representing the portfolios of a project. + */ +@Produces("application/json") +@Path("/projects/{project}/portfolios") +@RolesAllowed("openid") +public final class PortfolioResource { + /** + * The service for managing the user portfolios. + */ + private final PortfolioService portfolioService; + + /** + * The identity of the current user. + */ + private final SecurityIdentity identity; + + /** + * Construct a {@link PortfolioResource}. + * + * @param portfolioService The {@link PortfolioService} instance to use. + * @param identity The {@link SecurityIdentity} of the current user. + */ + public PortfolioResource(PortfolioService portfolioService, SecurityIdentity identity) { + this.portfolioService = portfolioService; + this.identity = identity; + } + + /** + * Get all portfolios that belong to the specified project. + */ + @GET + public List getAll(@PathParam("project") long projectId) { + return portfolioService.findByUser(identity.getPrincipal().getName(), projectId); + } + + /** + * Create a portfolio for this project. + */ + @POST + @Transactional + public org.opendc.web.proto.user.Portfolio create( + @PathParam("project") long projectId, @Valid org.opendc.web.proto.user.Portfolio.Create request) { + var portfolio = portfolioService.create(identity.getPrincipal().getName(), projectId, request); + if (portfolio == null) { + throw new WebApplicationException("Project not found", 404); + } + + return portfolio; + } + + /** + * Obtain a portfolio by its identifier. + */ + @GET + @Path("{portfolio}") + public org.opendc.web.proto.user.Portfolio get( + @PathParam("project") long projectId, @PathParam("portfolio") int number) { + var portfolio = portfolioService.findByUser(identity.getPrincipal().getName(), projectId, number); + if (portfolio == null) { + throw new WebApplicationException("Portfolio not found", 404); + } + + return portfolio; + } + + /** + * Delete a portfolio. + */ + @DELETE + @Path("{portfolio}") + @Transactional + public org.opendc.web.proto.user.Portfolio delete( + @PathParam("project") long projectId, @PathParam("portfolio") int number) { + var portfolio = portfolioService.delete(identity.getPrincipal().getName(), projectId, number); + if (portfolio == null) { + throw new WebApplicationException("Portfolio not found", 404); + } + + return portfolio; + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioScenarioResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioScenarioResource.java new file mode 100644 index 00000000..a6db7c54 --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/PortfolioScenarioResource.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest.user; + +import io.quarkus.security.identity.SecurityIdentity; +import java.util.List; +import javax.annotation.security.RolesAllowed; +import javax.transaction.Transactional; +import javax.validation.Valid; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.WebApplicationException; +import org.opendc.web.proto.user.Scenario; +import org.opendc.web.server.service.ScenarioService; + +/** + * A resource representing the scenarios of a portfolio. + */ +@Path("/projects/{project}/portfolios/{portfolio}/scenarios") +@RolesAllowed("openid") +public final class PortfolioScenarioResource { + /** + * The service for managing the user scenarios. + */ + private final ScenarioService scenarioService; + + /** + * The identity of the current user. + */ + private final SecurityIdentity identity; + + /** + * Construct a {@link PortfolioScenarioResource}. + * + * @param scenarioService The {@link ScenarioService} instance to use. + * @param identity The {@link SecurityIdentity} of the current user. + */ + public PortfolioScenarioResource(ScenarioService scenarioService, SecurityIdentity identity) { + this.scenarioService = scenarioService; + this.identity = identity; + } + + /** + * Get all scenarios that belong to the specified portfolio. + */ + @GET + public List get(@PathParam("project") long projectId, @PathParam("portfolio") int portfolioNumber) { + return scenarioService.findAll(identity.getPrincipal().getName(), projectId, portfolioNumber); + } + + /** + * Create a scenario for this portfolio. + */ + @POST + @Transactional + public org.opendc.web.proto.user.Scenario create( + @PathParam("project") long projectId, + @PathParam("portfolio") int portfolioNumber, + @Valid org.opendc.web.proto.user.Scenario.Create request) { + var scenario = scenarioService.create(identity.getPrincipal().getName(), projectId, portfolioNumber, request); + if (scenario == null) { + throw new WebApplicationException("Portfolio not found", 404); + } + + return scenario; + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ProjectResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ProjectResource.java new file mode 100644 index 00000000..b0b8eb4e --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ProjectResource.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest.user; + +import io.quarkus.security.identity.SecurityIdentity; +import java.util.List; +import javax.annotation.security.RolesAllowed; +import javax.transaction.Transactional; +import javax.validation.Valid; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import org.opendc.web.server.service.ProjectService; + +/** + * A resource representing the created projects. + */ +@Produces("application/json") +@Path("/projects") +@RolesAllowed("openid") +public final class ProjectResource { + /** + * The service for managing the user projects. + */ + private final ProjectService projectService; + + /** + * The identity of the current user. + */ + private final SecurityIdentity identity; + + /** + * Construct a {@link ProjectResource}. + * + * @param projectService The {@link ProjectService} instance to use. + * @param identity The {@link SecurityIdentity} of the current user. + */ + public ProjectResource(ProjectService projectService, SecurityIdentity identity) { + this.projectService = projectService; + this.identity = identity; + } + + /** + * Obtain all the projects of the current user. + */ + @GET + public List getAll() { + return projectService.findByUser(identity.getPrincipal().getName()); + } + + /** + * Create a new project for the current user. + */ + @POST + @Transactional + @Consumes("application/json") + public org.opendc.web.proto.user.Project create(@Valid org.opendc.web.proto.user.Project.Create request) { + return projectService.create(identity.getPrincipal().getName(), request.getName()); + } + + /** + * Obtain a single project by its identifier. + */ + @GET + @Path("{project}") + public org.opendc.web.proto.user.Project get(@PathParam("project") long id) { + var project = projectService.findByUser(identity.getPrincipal().getName(), id); + if (project == null) { + throw new WebApplicationException("Project not found", 404); + } + + return project; + } + + /** + * Delete a project. + */ + @DELETE + @Path("{project}") + @Transactional + public org.opendc.web.proto.user.Project delete(@PathParam("project") long id) { + try { + var project = projectService.delete(identity.getPrincipal().getName(), id); + if (project == null) { + throw new WebApplicationException("Project not found", 404); + } + + return project; + } catch (IllegalArgumentException e) { + throw new WebApplicationException(e.getMessage(), 403); + } + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ScenarioResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ScenarioResource.java new file mode 100644 index 00000000..a6838148 --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/ScenarioResource.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest.user; + +import io.quarkus.security.identity.SecurityIdentity; +import javax.annotation.security.RolesAllowed; +import javax.transaction.Transactional; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import org.opendc.web.server.service.ScenarioService; + +/** + * A resource representing the scenarios of a portfolio. + */ +@Produces("application/json") +@Path("/projects/{project}/scenarios") +@RolesAllowed("openid") +public final class ScenarioResource { + /** + * The service for managing the user scenarios. + */ + private final ScenarioService scenarioService; + + /** + * The identity of the current user. + */ + private final SecurityIdentity identity; + + /** + * Construct a {@link ScenarioResource}. + * + * @param scenarioService The {@link ScenarioService} instance to use. + * @param identity The {@link SecurityIdentity} of the current user. + */ + public ScenarioResource(ScenarioService scenarioService, SecurityIdentity identity) { + this.scenarioService = scenarioService; + this.identity = identity; + } + + /** + * Obtain a scenario by its identifier. + */ + @GET + @Path("{scenario}") + public org.opendc.web.proto.user.Scenario get( + @PathParam("project") long projectId, @PathParam("scenario") int number) { + var scenario = scenarioService.findOne(identity.getPrincipal().getName(), projectId, number); + if (scenario == null) { + throw new WebApplicationException("Scenario not found", 404); + } + + return scenario; + } + + /** + * Delete a scenario. + */ + @DELETE + @Path("{scenario}") + @Transactional + public org.opendc.web.proto.user.Scenario delete( + @PathParam("project") long projectId, @PathParam("scenario") int number) { + var scenario = scenarioService.delete(identity.getPrincipal().getName(), projectId, number); + if (scenario == null) { + throw new WebApplicationException("Scenario not found", 404); + } + + return scenario; + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/TopologyResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/TopologyResource.java new file mode 100644 index 00000000..54afc1ce --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/TopologyResource.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest.user; + +import io.quarkus.security.identity.SecurityIdentity; +import java.util.List; +import javax.annotation.security.RolesAllowed; +import javax.transaction.Transactional; +import javax.validation.Valid; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.WebApplicationException; +import org.opendc.web.server.service.TopologyService; + +/** + * A resource representing the constructed datacenter topologies. + */ +@Produces("application/json") +@Path("/projects/{project}/topologies") +@RolesAllowed("openid") +public final class TopologyResource { + /** + * The service for managing the user topologies. + */ + private final TopologyService topologyService; + + /** + * The identity of the current user. + */ + private final SecurityIdentity identity; + + /** + * Construct a {@link TopologyResource}. + * + * @param topologyService The {@link TopologyService} instance to use. + * @param identity The {@link SecurityIdentity} of the current user. + */ + public TopologyResource(TopologyService topologyService, SecurityIdentity identity) { + this.topologyService = topologyService; + this.identity = identity; + } + + /** + * Get all topologies that belong to the specified project. + */ + @GET + public List getAll(@PathParam("project") long projectId) { + return topologyService.findAll(identity.getPrincipal().getName(), projectId); + } + + /** + * Create a topology for this project. + */ + @POST + @Consumes("application/json") + @Transactional + public org.opendc.web.proto.user.Topology create( + @PathParam("project") long projectId, @Valid org.opendc.web.proto.user.Topology.Create request) { + var topology = topologyService.create(identity.getPrincipal().getName(), projectId, request); + + if (topology == null) { + throw new WebApplicationException("Topology not found", 404); + } + + return topology; + } + + /** + * Obtain a topology by its number. + */ + @GET + @Path("{topology}") + public org.opendc.web.proto.user.Topology get( + @PathParam("project") long projectId, @PathParam("topology") int number) { + var topology = topologyService.findOne(identity.getPrincipal().getName(), projectId, number); + + if (topology == null) { + throw new WebApplicationException("Topology not found", 404); + } + + return topology; + } + + /** + * Update the specified topology by its number. + */ + @PUT + @Path("{topology}") + @Consumes("application/json") + @Transactional + public org.opendc.web.proto.user.Topology update( + @PathParam("project") long projectId, + @PathParam("topology") int number, + @Valid org.opendc.web.proto.user.Topology.Update request) { + var topology = topologyService.update(identity.getPrincipal().getName(), projectId, number, request); + + if (topology == null) { + throw new WebApplicationException("Topology not found", 404); + } + + return topology; + } + + /** + * Delete the specified topology. + */ + @Path("{topology}") + @DELETE + @Transactional + public org.opendc.web.proto.user.Topology delete( + @PathParam("project") long projectId, @PathParam("topology") int number) { + var topology = topologyService.delete(identity.getPrincipal().getName(), projectId, number); + + if (topology == null) { + throw new WebApplicationException("Topology not found", 404); + } + + return topology; + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/UserResource.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/UserResource.java new file mode 100644 index 00000000..c3fb2866 --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/rest/user/UserResource.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.rest.user; + +import io.quarkus.security.identity.SecurityIdentity; +import javax.annotation.security.RolesAllowed; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import org.opendc.web.proto.user.User; +import org.opendc.web.proto.user.UserAccounting; +import org.opendc.web.server.service.UserAccountingService; + +/** + * A resource representing the active user. + */ +@Produces("application/json") +@Path("/users") +@RolesAllowed("openid") +public final class UserResource { + /** + * The service for managing the user accounting. + */ + private final UserAccountingService accountingService; + + /** + * The identity of the current user. + */ + private final SecurityIdentity identity; + + /** + * Construct a {@link UserResource}. + * + * @param accountingService The {@link UserAccountingService} instance to use. + * @param identity The {@link SecurityIdentity} of the current user. + */ + public UserResource(UserAccountingService accountingService, SecurityIdentity identity) { + this.accountingService = accountingService; + this.identity = identity; + } + + /** + * Get the current active user data. + */ + @GET + @Path("me") + public User get() { + String userId = identity.getPrincipal().getName(); + UserAccounting accounting = accountingService.getAccounting(userId); + + return new User(userId, accounting); + } +} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/JobService.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/JobService.java index eb0982ec..47f44d27 100644 --- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/JobService.java +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/JobService.java @@ -61,7 +61,13 @@ public final class JobService { * Find a job by its identifier. */ public org.opendc.web.proto.runner.Job findById(long id) { - return toRunnerDto(Job.findById(id)); + Job job = Job.findById(id); + + if (job == null) { + return null; + } + + return toRunnerDto(job); } /** diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/ScenarioService.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/ScenarioService.java index bf5206af..6a70db1e 100644 --- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/ScenarioService.java +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/ScenarioService.java @@ -219,6 +219,13 @@ public final class ScenarioService { * Convert a {@link Workload} entity into a DTO. */ public static org.opendc.web.proto.Workload toDto(Workload workload) { - return new org.opendc.web.proto.Workload(TraceService.toUserDto(workload.trace), workload.samplingFraction); + return new org.opendc.web.proto.Workload(toDto(workload.trace), workload.samplingFraction); + } + + /** + * Convert a {@link Trace] entity into a {@link org.opendc.web.proto.Trace} DTO. + */ + public static org.opendc.web.proto.Trace toDto(Trace trace) { + return new org.opendc.web.proto.Trace(trace.id, trace.name, trace.type); } } diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/TraceService.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/TraceService.java deleted file mode 100644 index 94b8340b..00000000 --- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/TraceService.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2023 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service; - -import java.util.List; -import javax.enterprise.context.ApplicationScoped; -import org.opendc.web.server.model.Trace; - -/** - * Service for managing {@link Trace}s. - */ -@ApplicationScoped -public final class TraceService { - /** - * Obtain all available workload traces. - */ - public List findAll() { - List entities = Trace.listAll(); - return entities.stream().map(TraceService::toUserDto).toList(); - } - - /** - * Obtain a workload trace by identifier. - */ - public org.opendc.web.proto.Trace findById(String id) { - return toUserDto(Trace.findById(id)); - } - - /** - * Convert a {@link Trace] entity into a {@link org.opendc.web.proto.Trace} DTO. - */ - public static org.opendc.web.proto.Trace toUserDto(Trace trace) { - return new org.opendc.web.proto.Trace(trace.id, trace.name, trace.type); - } -} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/UserService.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/UserService.java deleted file mode 100644 index b46b799b..00000000 --- a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/service/UserService.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2023 AtLarge Research - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package org.opendc.web.server.service; - -import io.quarkus.security.identity.SecurityIdentity; -import javax.enterprise.context.ApplicationScoped; -import org.opendc.web.proto.user.User; -import org.opendc.web.proto.user.UserAccounting; - -/** - * Service for managing {@link User}s. - */ -@ApplicationScoped -public final class UserService { - /** - * The service for managing the user accounting. - */ - private final UserAccountingService accountingService; - - /** - * Construct a {@link UserService} instance. - * - * @param accountingService The {@link UserAccountingService} instance to use. - */ - public UserService(UserAccountingService accountingService) { - this.accountingService = accountingService; - } - - /** - * Obtain the {@link User} object for the specified identity. - */ - public User getUser(SecurityIdentity identity) { - String userId = identity.getPrincipal().getName(); - UserAccounting accounting = accountingService.getAccounting(userId); - - return new User(userId, accounting); - } -} diff --git a/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/KotlinModuleCustomizer.java b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/KotlinModuleCustomizer.java new file mode 100644 index 00000000..c30edcbf --- /dev/null +++ b/opendc-web/opendc-web-server/src/main/java/org/opendc/web/server/util/KotlinModuleCustomizer.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2023 AtLarge Research + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package org.opendc.web.server.util; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.module.kotlin.KotlinModule; +import io.quarkus.jackson.ObjectMapperCustomizer; +import javax.inject.Singleton; + +/** + * Helper class to register the Kotlin Jackson module. + */ +@Singleton +public final class KotlinModuleCustomizer implements ObjectMapperCustomizer { + @Override + public void customize(ObjectMapper objectMapper) { + objectMapper.registerModule(new KotlinModule.Builder().build()); + } +} -- cgit v1.2.3