From 2a7328f7cbe9c761ee1b505942bd4543cbecf442 Mon Sep 17 00:00:00 2001 From: Geir Sagberg Date: Thu, 27 Jun 2024 23:13:16 +0200 Subject: [PATCH] Clean up base URLs, simplify SPA fallbacks for MVC and WebFlux. By handling SPA fallbacks in WebConfigurer classes, we can more easily and correctly serve static assets, while falling back to index.html for client side routing. --- db-scheduler-ui-frontend/index.html | 2 +- db-scheduler-ui-frontend/main.tsx | 4 +- db-scheduler-ui-frontend/vite.config.ts | 2 +- db-scheduler-ui-starter/pom.xml | 20 +-- .../autoconfigure/UiApiAutoConfiguration.java | 25 +++- db-scheduler-ui/pom.xml | 21 +-- .../ui/controller/SpaFallbackMvc.java | 50 +++++++ .../ui/controller/UIController.java | 32 ----- example-app-webflux/pom.xml | 71 +++++----- .../bekk/exampleapp/config/WebConfig.java | 37 ----- .../src/main/resources/application.properties | 1 + example-app/pom.xml | 65 ++++----- pom.xml | 126 ++++++++++-------- 13 files changed, 231 insertions(+), 225 deletions(-) create mode 100644 db-scheduler-ui/src/main/java/no/bekk/dbscheduler/ui/controller/SpaFallbackMvc.java delete mode 100644 db-scheduler-ui/src/main/java/no/bekk/dbscheduler/ui/controller/UIController.java delete mode 100644 example-app-webflux/src/main/java/com/github/bekk/exampleapp/config/WebConfig.java diff --git a/db-scheduler-ui-frontend/index.html b/db-scheduler-ui-frontend/index.html index 0c13f851..6a0ca084 100644 --- a/db-scheduler-ui-frontend/index.html +++ b/db-scheduler-ui-frontend/index.html @@ -2,7 +2,7 @@ - + DB Scheduler UI diff --git a/db-scheduler-ui-frontend/main.tsx b/db-scheduler-ui-frontend/main.tsx index 09186bc0..c9def5a7 100644 --- a/db-scheduler-ui-frontend/main.tsx +++ b/db-scheduler-ui-frontend/main.tsx @@ -15,8 +15,10 @@ import ReactDOM from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import App from './src/App'; +const basename = import.meta.env.BASE_URL; + ReactDOM.createRoot(document.getElementById('root')!).render( - + , ); diff --git a/db-scheduler-ui-frontend/vite.config.ts b/db-scheduler-ui-frontend/vite.config.ts index b1320661..abc078d9 100644 --- a/db-scheduler-ui-frontend/vite.config.ts +++ b/db-scheduler-ui-frontend/vite.config.ts @@ -16,7 +16,7 @@ import { defineConfig } from 'vite'; import eslintPlugin from 'vite-plugin-eslint'; const BASE_URL: string = - process.env.NODE_ENV === 'production' ? '/db-scheduler-ui' : '/db-scheduler'; + process.env.NODE_ENV === 'production' ? '/db-scheduler' : '/'; export default defineConfig({ base: BASE_URL, diff --git a/db-scheduler-ui-starter/pom.xml b/db-scheduler-ui-starter/pom.xml index be112855..912e754c 100644 --- a/db-scheduler-ui-starter/pom.xml +++ b/db-scheduler-ui-starter/pom.xml @@ -1,6 +1,5 @@ - 4.0.0 @@ -15,18 +14,6 @@ https://github.com/bekk/db-scheduler-ui - - org.springframework.boot - spring-boot-starter-test - test - - - - org.projectlombok - lombok - provided - - com.github.kagkarlsson db-scheduler-spring-boot-starter @@ -36,5 +23,10 @@ db-scheduler-ui ${project.version} + + org.springframework.boot + spring-boot-starter-test + test + diff --git a/db-scheduler-ui-starter/src/main/java/no/bekk/dbscheduler/uistarter/autoconfigure/UiApiAutoConfiguration.java b/db-scheduler-ui-starter/src/main/java/no/bekk/dbscheduler/uistarter/autoconfigure/UiApiAutoConfiguration.java index 075769af..ff9f8ec4 100644 --- a/db-scheduler-ui-starter/src/main/java/no/bekk/dbscheduler/uistarter/autoconfigure/UiApiAutoConfiguration.java +++ b/db-scheduler-ui-starter/src/main/java/no/bekk/dbscheduler/uistarter/autoconfigure/UiApiAutoConfiguration.java @@ -19,14 +19,15 @@ import javax.sql.DataSource; import no.bekk.dbscheduler.ui.controller.ConfigController; import no.bekk.dbscheduler.ui.controller.LogController; +import no.bekk.dbscheduler.ui.controller.SpaFallbackMvc; import no.bekk.dbscheduler.ui.controller.TaskController; -import no.bekk.dbscheduler.ui.controller.UIController; import no.bekk.dbscheduler.ui.service.LogLogic; import no.bekk.dbscheduler.ui.service.TaskLogic; import no.bekk.dbscheduler.ui.util.Caching; import no.bekk.dbscheduler.uistarter.config.DbSchedulerUiProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -34,6 +35,12 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; +import org.springframework.core.io.Resource; +import org.springframework.http.MediaType; +import org.springframework.web.reactive.function.server.RequestPredicates; +import org.springframework.web.reactive.function.server.RouterFunction; +import org.springframework.web.reactive.function.server.RouterFunctions; +import org.springframework.web.reactive.function.server.ServerResponse; @AutoConfiguration @ConditionalOnProperty(value = "db-scheduler-ui.enabled", matchIfMissing = true) @@ -95,10 +102,20 @@ LogController logController(LogLogic logLogic) { } @Bean - @ConditionalOnMissingBean @ConditionalOnWebApplication(type = Type.SERVLET) - UIController uiController() { - return new UIController(); + @ConditionalOnMissingBean + SpaFallbackMvc spaFallbackMvc() { + return new SpaFallbackMvc(); + } + + @Bean + @ConditionalOnWebApplication(type = Type.REACTIVE) + @ConditionalOnMissingBean + public RouterFunction dbSchedulerRouter( + @Value("classpath:/static/db-scheduler/index.html") Resource indexHtml) { + return RouterFunctions.route( + RequestPredicates.GET("/db-scheduler/**").and(request -> !request.path().contains(".")), + request -> ServerResponse.ok().contentType(MediaType.TEXT_HTML).bodyValue(indexHtml)); } @Bean diff --git a/db-scheduler-ui/pom.xml b/db-scheduler-ui/pom.xml index c0172385..61994283 100644 --- a/db-scheduler-ui/pom.xml +++ b/db-scheduler-ui/pom.xml @@ -1,7 +1,5 @@ - + 4.0.0 no.bekk.db-scheduler-ui @@ -16,21 +14,24 @@ - org.projectlombok - lombok - provided + com.fasterxml.jackson.core + jackson-databind + + + com.github.kagkarlsson + db-scheduler org.springframework spring-web - com.github.kagkarlsson - db-scheduler + org.springframework + spring-webflux - com.fasterxml.jackson.core - jackson-databind + org.springframework + spring-webmvc org.springframework.boot diff --git a/db-scheduler-ui/src/main/java/no/bekk/dbscheduler/ui/controller/SpaFallbackMvc.java b/db-scheduler-ui/src/main/java/no/bekk/dbscheduler/ui/controller/SpaFallbackMvc.java new file mode 100644 index 00000000..e4e54976 --- /dev/null +++ b/db-scheduler-ui/src/main/java/no/bekk/dbscheduler/ui/controller/SpaFallbackMvc.java @@ -0,0 +1,50 @@ +/* + * Copyright (C) Bekk + * + *

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 no.bekk.dbscheduler.ui.controller; + +import java.io.IOException; +import lombok.NonNull; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; +import org.springframework.web.servlet.resource.PathResourceResolver; + +public class SpaFallbackMvc implements WebMvcConfigurer { + + public static final String DEFAULT_STARTING_PAGE = "static/db-scheduler/index.html"; + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry + .addResourceHandler("/db-scheduler", "/db-scheduler/**") + .addResourceLocations("classpath:/static/db-scheduler/") + .resourceChain(true) + .addResolver(new SpaFallbackResolver()); + } + + static class SpaFallbackResolver extends PathResourceResolver { + @Override + protected Resource getResource(@NonNull String resourcePath, Resource location) + throws IOException { + var requestedResource = location.createRelative(resourcePath); + + if (requestedResource.exists() && requestedResource.isReadable()) { + return requestedResource; + } + + return new ClassPathResource(DEFAULT_STARTING_PAGE); + } + } +} diff --git a/db-scheduler-ui/src/main/java/no/bekk/dbscheduler/ui/controller/UIController.java b/db-scheduler-ui/src/main/java/no/bekk/dbscheduler/ui/controller/UIController.java deleted file mode 100644 index 39657ed7..00000000 --- a/db-scheduler-ui/src/main/java/no/bekk/dbscheduler/ui/controller/UIController.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) Bekk - * - *

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 no.bekk.dbscheduler.ui.controller; - -import org.springframework.stereotype.Controller; -import org.springframework.web.bind.annotation.CrossOrigin; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; - -@Controller -@CrossOrigin -@RequestMapping("/db-scheduler") -public class UIController { - - public UIController() {} - - @GetMapping("/**") - public String index() { - return "forward:/db-scheduler-ui/index.html"; - } -} diff --git a/example-app-webflux/pom.xml b/example-app-webflux/pom.xml index ef70f7ee..1a7c27de 100644 --- a/example-app-webflux/pom.xml +++ b/example-app-webflux/pom.xml @@ -1,7 +1,5 @@ - + 4.0.0 no.bekk.db-scheduler-ui @@ -17,55 +15,65 @@ true - + - org.springframework.boot - spring-boot-starter-webflux + com.h2database + h2 + 2.2.220 - - org.springframework.boot - spring-boot-starter-jdbc + io.rocketbase.extension + db-scheduler-log-spring-boot-starter + 0.7.0 + + + no.bekk.db-scheduler-ui + db-scheduler-ui-starter + main-SNAPSHOT + + + org.flywaydb + flyway-core org.springframework.boot spring-boot-devtools - - com.h2database - h2 - 2.2.220 + org.springframework.boot + spring-boot-starter-actuator + - org.flywaydb - flyway-core + org.springframework.boot + spring-boot-starter-jdbc org.springframework.boot - spring-boot-starter-actuator + spring-boot-starter-webflux - io.rocketbase.extension - db-scheduler-log-spring-boot-starter - 0.7.0 + org.assertj + assertj-core + test - org.junit.jupiter - junit-jupiter + org.hsqldb + hsqldb test + org.junit.jupiter - junit-jupiter-api + junit-jupiter test - org.springframework.boot - spring-boot-test + org.junit.jupiter + junit-jupiter-api test @@ -74,21 +82,10 @@ test - org.assertj - assertj-core - test - - - - org.hsqldb - hsqldb + org.springframework.boot + spring-boot-test test - - no.bekk.db-scheduler-ui - db-scheduler-ui-starter - main-SNAPSHOT - diff --git a/example-app-webflux/src/main/java/com/github/bekk/exampleapp/config/WebConfig.java b/example-app-webflux/src/main/java/com/github/bekk/exampleapp/config/WebConfig.java deleted file mode 100644 index 021fbc12..00000000 --- a/example-app-webflux/src/main/java/com/github/bekk/exampleapp/config/WebConfig.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) Bekk - * - *

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 com.github.bekk.exampleapp.config; - -import static org.springframework.web.reactive.function.server.RequestPredicates.GET; -import static org.springframework.web.reactive.function.server.RouterFunctions.route; -import static org.springframework.web.reactive.function.server.ServerResponse.ok; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.io.Resource; -import org.springframework.http.MediaType; -import org.springframework.web.reactive.function.server.RouterFunction; -import org.springframework.web.reactive.function.server.ServerResponse; - -@Configuration -public class WebConfig { - @Bean - public RouterFunction dbSchedulerRouter( - @Value("classpath:/static/db-scheduler-ui/index.html") final Resource indexHtml) { - return route( - GET("/db-scheduler/**"), - request -> ok().contentType(MediaType.TEXT_HTML).bodyValue(indexHtml)); - } -} diff --git a/example-app-webflux/src/main/resources/application.properties b/example-app-webflux/src/main/resources/application.properties index 9eb49d48..d543cdad 100644 --- a/example-app-webflux/src/main/resources/application.properties +++ b/example-app-webflux/src/main/resources/application.properties @@ -5,3 +5,4 @@ db-scheduler-log.enabled=true db-scheduler-log.table-name=scheduled_execution_logs db-scheduler-ui.history=true db-scheduler-ui.task-data=true +#logging.level.org.springframework=DEBUG \ No newline at end of file diff --git a/example-app/pom.xml b/example-app/pom.xml index d98ed93e..b72e1df9 100644 --- a/example-app/pom.xml +++ b/example-app/pom.xml @@ -1,7 +1,5 @@ - + 4.0.0 no.bekk.db-scheduler-ui @@ -17,56 +15,43 @@ true - - - org.springframework.boot - spring-boot-starter-web - - - - org.springframework.boot - spring-boot-starter-jdbc - com.h2database h2 2.2.220 - - org.flywaydb - flyway-core - org.springframework.boot - spring-boot-starter-actuator + spring-boot-devtools io.rocketbase.extension db-scheduler-log-spring-boot-starter 0.7.0 - - org.junit.jupiter - junit-jupiter - test + no.bekk.db-scheduler-ui + db-scheduler-ui-starter + main-SNAPSHOT - org.junit.jupiter - junit-jupiter-api - test + org.flywaydb + flyway-core org.springframework.boot - spring-boot-test - test + spring-boot-starter-actuator + org.springframework.boot - spring-boot-starter-test - test + spring-boot-starter-jdbc + + + org.springframework.boot + spring-boot-starter-web org.assertj @@ -79,10 +64,26 @@ hsqldb test + - no.bekk.db-scheduler-ui - db-scheduler-ui-starter - main-SNAPSHOT + org.junit.jupiter + junit-jupiter + test + + + org.junit.jupiter + junit-jupiter-api + test + + + org.springframework.boot + spring-boot-starter-test + test + + + org.springframework.boot + spring-boot-test + test diff --git a/pom.xml b/pom.xml index 1baacc3d..82f6f821 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,5 @@ - + 4.0.0 no.bekk.db-scheduler-ui db-scheduler-ui-parent @@ -13,14 +11,6 @@ https://github.com/bekk/db-scheduler-ui 2023 - - 11 - 2.7.18 - 14.0.0 - UTF-8 - - - The Apache Software License, Version 2.0 @@ -52,25 +42,46 @@ + + db-scheduler-ui + db-scheduler-ui-starter + example-app + example-app-webflux + + scm:git:https://github.com/bekk/db-scheduler-ui.git scm:git:https://github.com/bekk/db-scheduler-ui.git - https://github.com/bekk/db-scheduler-ui.git HEAD + https://github.com/bekk/db-scheduler-ui.git + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + + + 11 + 2.7.18 + 14.0.0 + UTF-8 + - com.github.kagkarlsson - db-scheduler - ${db-scheduler.version} - - - com.github.kagkarlsson - db-scheduler-spring-boot-starter - ${db-scheduler.version} + org.junit + junit-bom + 5.10.2 + pom + import @@ -81,15 +92,26 @@ import - org.junit - junit-bom - 5.10.2 - pom - import + com.github.kagkarlsson + db-scheduler + ${db-scheduler.version} + + + com.github.kagkarlsson + db-scheduler-spring-boot-starter + ${db-scheduler.version} + + + org.projectlombok + lombok + provided + + + @@ -149,8 +171,10 @@ - src/main/java/**/*.java - src/test/java/**/*.java + src/test/java/**/*.java + @@ -165,9 +189,22 @@ - + + com.github.ekryd.sortpom + sortpom-maven-plugin + 3.3.0 + + 4 + false + scope,groupId,artifactId + false + + maven-javadoc-plugin + + none + attach-javadocs @@ -176,9 +213,6 @@ - - none - org.apache.maven.plugins @@ -214,9 +248,7 @@ ALWAYS https://oss.sonatype.org/service/local/ - - https://oss.sonatype.org/content/repositories/snapshots - + https://oss.sonatype.org/content/repositories/snapshots true true target/staging-deploy @@ -296,10 +328,10 @@ npm-build - generate-resources exec + generate-resources npm @@ -317,13 +349,13 @@ copy-files-to-backend - process-classes copy-resources + process-classes UTF-8 - db-scheduler-ui/src/main/resources/static/db-scheduler-ui + db-scheduler-ui/src/main/resources/static/db-scheduler db-scheduler-ui-frontend/dist @@ -337,24 +369,6 @@ - - db-scheduler-ui - db-scheduler-ui-starter - example-app - example-app-webflux - - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - - publication @@ -398,4 +412,4 @@ - \ No newline at end of file +