package org.lucares.pdbui; import java.io.IOException; import java.nio.file.Paths; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; 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.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.resource.PathResourceResolver; @Configuration public class WebConfiguration implements WebMvcConfigurer, HardcodedValues, PropertyKeys { private final String outputDir; public WebConfiguration(@Value("${" + PATH_GENERATED_IMAGES + "}") final String outputDir) { this.outputDir = outputDir; } @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { addResourceHandlerForPlottedImages(registry); // addResourceHandlerForAngular(registry); } private void addResourceHandlerForPlottedImages(final ResourceHandlerRegistry registry) { final String pathPattern = "/" + WEB_IMAGE_OUTPUT_PATH + "/**"; final String resourceLocation = "file:" + Paths.get(outputDir).toAbsolutePath() + "/"; registry.addResourceHandler(pathPattern).addResourceLocations(resourceLocation); } /** * This is one way to make Angular and SpringBoot play together. The other * described in {@link #addViewControllers(ViewControllerRegistry)}. * * Other solutions: * https://stackoverflow.com/questions/38516667/springboot-angular2-how-to-handle-html5-urls/46854105#46854105 * * @param registry */ @SuppressWarnings("unused") private void addResourceHandlerForAngular(final ResourceHandlerRegistry registry) { // Redirect all to Angular for all non existing resources. // This way Angular's routing & navigation (https://angular.io/guide/router) can // work. Without it SpringBoot would only show 404 pages for all of Angular's // pages, because the request would not even be send to Angular. // // Technically we are answering all requests for which SpringBoot does not find // a resource with Angular's index.html. The Angular will then use its routing // to determine which sub-page to show. // // This makes Angular also responsible for all 404 pages. registry.addResourceHandler("/**").addResourceLocations("classpath:/resources/").resourceChain(true) .addResolver(new PathResourceResolver() { @Override protected Resource getResource(final String resourcePath, final Resource location) throws IOException { final Resource requestedResource = location.createRelative(resourcePath); return requestedResource.exists() && requestedResource.isReadable() ? requestedResource : new ClassPathResource("/resources/index.html"); } }); } /** * This is one way to make Angular and SpringBoot play together. The other * described in {@link #addResourceHandlerForAngular(ResourceHandlerRegistry)} * * Other solutions: * https://stackoverflow.com/questions/38516667/springboot-angular2-how-to-handle-html5-urls/46854105#46854105 */ @Override public void addViewControllers(final ViewControllerRegistry registry) { // Redirect requests to Angular. // This works by returning Angular's index.html for requests that should be // handled by Angular. // // Using this solution SpringBoot is responsible for 404s. registry.addViewController("/").setViewName("forward:/index.html"); registry.addViewController("/vis").setViewName("forward:/index.html"); registry.addViewController("/upload").setViewName("forward:/index.html"); registry.addViewController("/help").setViewName("forward:/index.html"); } }