Spring boot, possible causes of View cannot be resolved issue - java

What could be the problem if Spring Boot cannot resolve view with specific name?
I have developed many Spring Boot applications before and have never encountered this problem.
I have following folder structure:
/src/main/java
/src/main/resources/config
/src/main/resources/static
/src/main/resources/static/partials
/src/main/resources/static/resources
Image:
/src/main/resources/static/resources folder is not making problems for having resources name. I tried renaming it and it didn't solve problem.
I am using Maven and I have parent project which has multiple children projects.
Module for the rest api contains many configuration classes, including configurations for security.
Everything is working as it should, application can be started without errors, but when I tried to add static content I encountered this problem.
From the following example (example) we can see that Spring Boot should automatically maps src/main/resources/static/index.html to the root path, but that is not happening in my application. From the log I can see that Spring didn't find mapping for /.
I am able to run that example normally, but in my application it is not working.
Because Spring didn't map automatically I created WelcomeController which should return view:
#Controller
public class WelcomeRestController {
#RequestMapping("/")
public String welcome() {
return "index.html";
}
}
After I did that, mapping is found, but Spring reports that it couldn't resolve view with name index.html even if it exists.
I tried adding static content to src/main/webapp/static folder even if it is not recommended and it also didn't work, same problem, cannot resolve view.
I also tried to configure using
#Configuration
public class WebMvcConfiguration extends WebMvcConfigurerAdapter {
#Override public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index.html");
}
}
Again, view cannot be resolved.
My application's start point:
#Import(MyRestServiceConfiguration.class)
#SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(final String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(Application.class);
}
}
I am using embedded Tomcat.
Is it possible that security configurations or some other configurations except WebMvcConfigurerAdapter are having influence on views?
I am trying to resolve this issue for hours but I can't find soulution. Any help would be appreciated.
EDIT:
I am not building application using Maven, just running Application.java as Java Application, so Maven should not be a problem.
EDIT:
Content of index.html:
<!DOCTYPE html>
<html >
<head lang="en">
</head>
<body>
<div>Hello</div>
</body>
</html>

I have found a solution, but I am not really sure why this makes problem. Please post your answer if you know why is this happening.
The problem was #EnableWebMvc annotation in MyRestServiceConfiguration
#Configuration
// #EnableWebMvc
#Import(MyServiceConfiguration.class)
public class MyRestServiceConfiguration {
}
After removing it, everything works as it should.
From Spring Boot guide:
Normally you would add #EnableWebMvc for a Spring MVC app, but Spring Boot adds it automatically when it sees spring-webmvc on the classpath. This flags the application as a web application and activates key behaviors such as setting up a DispatcherServlet.
It's clear that #EnableWebMvc annotation is not needed, but why does it make problems?
EDIT:
From Spring Boot reference:
The easiest way to take complete control over MVC configuration is to provide your own #Configuration with the #EnableWebMvc annotation. This will leave all MVC configuration in your hands.
From Spring's #EnableWebMvc documentation:
Adding this annotation to an #Configuration class imports the Spring MVC configuration from WebMvcConfigurationSupport, e.g.:
#Configuration
#EnableWebMvc
#ComponentScan(basePackageClasses = { MyConfiguration.class })
public class MyWebConfiguration {
}
So, the problem was that #EnableWebMvc annotation dissabled default Spring Boot's configuration and because of that Spring didn't know where to look for static resources. If I got something wrong, please correct me.

Related

Spring boot - Cannot access dynamically generated external fi;es

I need to serve dynamically generated jar files with spring boot. What I am trying to do is access these generated files without having to restart my spring boot application.
I have added the following config class according to many forum posts :
#Configuration
public class StaticFileConfig implements WebMvcConfigurer {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**").addResourceLocations("file:<path>/");
WebMvcConfigurer.super.addResourceHandlers(registry);
}
}
While this allows me to access files located at the specified path, I can not do so until after I restart my spring boot application.
Any suggestions as to how to access dynamically generated files without restarting the application ?
Thanks

How to make a custom spring boot starter loadable while integration test?

We have created a custom spring boot starter which holds several common feature reusable cross internal projects.
The starter is working fine as expected. However, while integration test, the projects using the starter are not able to find all beans created by the custom starter.
NB: The internal project are using in their integration test class the annotation #SpringBootTest in order to load the whole spring context.
without more information, I would say your custom spring-boot-starter has not the same namespace, so the components are not scanned from your internal Application.
Lets say your internal Project namespace is: com.hello.package.p1 and your Spring-boot-starter has the namespace: net.greeting.package.p1
Try perhaps something like this:
#SpringBootTest(classes = TestConfiguration.class)
and in your TestConfiguration.class:
#Configuration
#ComponentScan(basePackages = "net.greeting.package.p1")
public static class TestConfiguration {
// ...
}
Thanks for your answer.
When executing the internal project normally, I see clearly that they are getting the bean instances without the need to add any custom component scan. We have just added the custom starter to their dependencies. I don't see why it's not loaded while integration test. (I think that it should be reported to Spring community)
I have found a workaround which I consider not the best solution, by importing the CommonAutoConfiguration class to the internal project integration class.
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { InternalProjectbootApplication.class })
#DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
#Import(CommonAutoConfiguration.class)
public class ArchiveUnitServiceITTest implements ServiceInterfaceIT {...

Reloading CORS settings at runtime

I recently implemented a Spring Cloud Config Server. My application (client) is able to retrieve application profiles and refresh them in flight.
Unfortunately, CORS settings, which are also declared there, are not reloaded by Spring during runtime. I did a small investigation and check that in terms of refresh everything looks good - ConfigurationPropertiesRebinder rebind() method successfully destroys old bean holding CORS setup and creates a new with up-to-date settings. I also see that Environment bean is holding new settings in propertySources field.
Is there any way to force Spring to reload CORS during runtime or should I need to reload application context?
Use below code for resolve CORS issue.
#Configuration
#EnableWebMvc
class WebConfig implements WebMvcConfigurer {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}

How to force Spring Boot to use Tomcat server in integration tests?

I use default Tomcat embedded container. However, in some of my tests I use Wiremock (using Jetty underneath). This makes my integration tests run against Jetty server, not Tomcat.
Is there any way to force Spring Boot to stick with Tomcat ?
As Stéphane Nicoll stated here you should define an empty TomcatEmbeddedServletContainerFactory #Bean
Simply adding such bean was not sufficient for me. I got 'multiple beans' exception. As I was adding that to a custom test starter I just had to make sure, it is added before EmbeddedServletContainerAutoConfiguration resolution took place, i.e:
#Configuration
#AutoConfigureBefore(EmbeddedServletContainerAutoConfiguration.class)
public class ForceTomcatAutoConfiguration {
#Bean
TomcatEmbeddedServletContainerFactory tomcat() {
return new TomcatEmbeddedServletContainerFactory();
}
}
Edit: In Spring Boot 2.0 this works for me:
#Configuration
#AutoConfigureBefore(ServletWebServerFactoryAutoConfiguration.class)
public class ForceTomcatAutoConfiguration {
#Bean
TomcatServletWebServerFactory tomcat() {
return new TomcatServletWebServerFactory();
}
}
With Spring Boot 2.3 the above solution hasn't worked for me.
Perhaps I have special circumstances with not having a SpringBootApplication in the main classes. I have only a SpringBootApplication in the test classes.
Anyhow this has worked for me:
#SpringBootApplication(exclude = org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration.class)
public class TestApplication {
}
with Spring Boot 2.5.10
#AutoConfigureBefore(ServletWebServerFactoryAutoConfiguration.class)
didn't work for me.
but as sven doring mentioned excluding EmbeddedWebServerFactoryCustomizerAutoConfiguration worked for me.
it even worked for external tomcat
code is below
#SpringBootApplication(exclude = org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration.class)

How to register listener in Spring without deployment descriptor

I'm slowly stepping in Java world through Spring Framework (4.1.0) and need your help with Listeners.
I have created application without deployment descriptor, all Spring related configuration is managed in #Configuration annotated classes. Everything is working but I can't find a way to register listeners.
Question: How I can register listeners in Spring (4.1.0) based on Java #Configuration annotated classed ?
You do that with the help of the WebApplicationInitializer class. #Configuration is for Spring configurations, not for the deployment descriptor.
public class MyWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) {
container.addListener(...);
...
}
}
You can find more explanations here: How to use Spring's WebApplicationInitializer.

Categories

Resources