4

I am trying to configure Spring Boot using annotations. I have class

@EnableWebMvc
@Configuration
@ComponentScan({
    ...
})
@EnableTransactionManagement
@EnableAutoConfiguration
@Import({ SecurityConfig.class })
public class AppConfig extends SpringBootServletInitializer {...}

which contains this View resolver which works fine.

@Bean
public InternalResourceViewResolver internalViewResolver() {
    InternalResourceViewResolver viewResolver
            = new InternalResourceViewResolver();
    viewResolver.setViewClass(JstlView.class);
    viewResolver.setPrefix("/WEB-INF/pages/");
    viewResolver.setSuffix(".jsp");
    viewResolver.setOrder(1);
    return viewResolver;
}

But after receiving name of JSP file application raise this error: No mapping found for HTTP request with URI [/WEB-INF/pages/MainPage.jsp] in DispatcherServlet with name 'dispatcherServlet'.

I found solution for XML configuration:

<servlet-mapping>
    <servlet-name>mvc-dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping> 

But I am using annotation configuration, so this soultion is not suitable for me.

I tried to resolve this problem extending AbstractAnnotationConfigDispatcherServletInitializer

public class SpringMvcInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { AppConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    //  I thought this method will be equivalent to XML config solution described above
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

}

But nothing has changed after this. By the way I looked at few examples with AbstractAnnotationConfigDispatcherServletInitializer, but I still don't understand how application can use this class when it's not annotated and no instances of this class are created. It's just declared and that's all. Maybe I need to create an instance of this class and attach it anywhere?

Anyway I see in log this line: Mapping servlet: 'dispatcherServlet' to [/] So it looks like I have right servlet configuration.

I tried this solution but it doesn't help. I removed InternalResourceViewResolver and created application.properties with such content:

spring.view.prefix: /WEB-INF/jsp/
spring.view.suffix: .jsp

But after that I received: javax.servlet.ServletException: Could not resolve view with name 'MainPage' in servlet with name 'dispatcherServlet'

So what is the proper way to resolve this problem?

UPDATE I tried to create a new simple project from scratch.

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>edu.springtest</groupId>
    <artifactId>SpringTest</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.2.0.RELEASE</version>
        <relativePath/>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    </dependencies>
</project>

Main.java:

@Controller
@Configuration
@ComponentScan
@EnableAutoConfiguration
@SpringBootApplication
public class Main {
    @RequestMapping("/")
    String home() {
        return "hello";
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Main.class, args);
    }
}

application.properties:

spring.view.prefix: /WEB-INF/jsp/
spring.view.suffix: .jsp

Project's structure:

Project's structure

I run project with command mvn spring-boot:run and receive edu.test.Main: Started Main in 2.365 seconds (JVM running for 5.476) in output. But when I'm opening localhost:8080 I receive:

Whitelabel Error Page

This application has no explicit mapping for /error, so you are seeing this as a fallback.
Sat Dec 20 11:25:29 EET 2014
There was an unexpected error (type=Not Found, status=404).
No message available

But now I'm not receiving "No mapping found..." error in output. When I am opening localhost:8080 nothing is printed to output at all. So what am I doing wrong?

Community
  • 1
  • 1
Toro Boro
  • 377
  • 5
  • 16
  • On one side I see /WEB-INF/jsp and on the other : /WEB-INF/pages – yunandtidus Dec 19 '14 at 13:24
  • Yes, It was a mistake. But I corrected it and it still not working: javax.servlet.ServletException: Could not resolve view with name 'MainPage' in servlet with name 'dispatcherServlet' – Toro Boro Dec 19 '14 at 13:28
  • Package as war works for me. See http://stackoverflow.com/questions/22121918/package-a-spring-boot-application-including-jsps-and-static-resources – barryku Feb 10 '15 at 20:12

4 Answers4

1

Getting rid of your custom view resolver and setting the application properties was the right start. The whole point of Spring Boot is that it does a pretty good job of wiring these things up for you! :)

You should have a controller with the request mappings. Something like:

@RequestMapping("/")
public String mainPage() {
    return "MainPage";
}

... which would use your MainPage.jsp template for any requests to /.

However, it's worth noting that by default, the contents of src/main/webapp don't get built into the executable application jar. To deal with his there are a couple of options I know of.

Option 1 - Move everything from /src/main/webapp/ to src/main/resources/static. I think this works for JSPs too. The only trouble here is that you can hot-replace code unless you're running the application in an IDE.

Option 2 - The alternative (which I tend to use) is to set up my Maven build to copy the contents of src/main/webapp into the classpath static folder when I build.

<plugin>
    <artifactId>maven-resources-plugin</artifactId>
    <version>2.6</version>
    <executions>
        <execution>
            <id>copy-resources</id>
            <phase>validate</phase>
            <goals>
                <goal>copy-resources</goal>
            </goals>
            <configuration>
                <outputDirectory>${basedir}/target/classes/static</outputDirectory>
                <resources>
                    <resource>
                        <directory>src/main/webapp</directory>
                        <filtering>true</filtering>
                    </resource>
                </resources>
            </configuration>
        </execution>
    </executions>
</plugin>

For further reading (although this looks quite a bit like what you're already doing), there's a sample project, showing a Spring Boot app using JSP for templating:

https://github.com/spring-projects/spring-boot/blob/master/spring-boot-samples/spring-boot-sample-web-jsp/

Steve
  • 9,270
  • 5
  • 47
  • 61
  • This is exactly what I am doing. My controller returns "MainPage", then ViewResolver translate it to "/WEB-INF/pages/MainPage.jsp" and then I receive: No mapping found for HTTP request with URI [/WEB-INF/pages/MainPage.jsp] in DispatcherServlet with name 'dispatcherServlet'. But when I delete View resolver and add application.properties instead I receive: Could not resolve view with name 'MainPage' in servlet with name 'dispatcherServlet'. So It looks like application.properties file is ignored. Maybe It's not enough to put it in resource dir and I need to write it's path somewhere? – Toro Boro Dec 19 '14 at 14:22
  • I take it that from the root of your project, the JSP is in `src/main/webapp/WEB-INF/jsp/MainPage.jsp`? – Steve Dec 19 '14 at 14:56
  • Also ... how are you running the app? I just got to thinking that the problem may be that you're putting the JSP in `src/main/webapp`. By default that doesn't get built into the executable jar. – Steve Dec 19 '14 at 15:05
  • I'm running my app from IntelliJ IDEA. I tried to run it like Application and using mvn spring-boot: run. Yes, "src/main/webapp/WEB-INF/jsp/MainPage.jsp" is the path of my MainPage.jsp. Options that you offered also doesn't help. I updated my questions. Maybe now It will be easier to find a problem. – Toro Boro Dec 20 '14 at 09:37
0

I have the same problem, however I have not fix it yet, but more information can be provided for your investigation

With tracing in the source code of CachedResource in tomcat-embed-core.jar, I found if you run the application from development environment, for example Eclipse, the resource path will points to the project directory likes the following:

"C:/MyProject/MyApplication/src/main/webapp/WEB-INF/views/jsp/index.jsp"

where must contains this resource, but when I run it from the server with command of "java -jar ...", the resource path will be set to temp folder likes:

"/tmp/tomcat-docbase.3976292633605332325.8080/WEB-INF/views/jsp/index.jsp"

but /tmp/tomcat-docbase.3976292633605332325.8080 is empty. However I have no idea how to setup the resource path, but both of above shows the InternalResourceViewResolver will only deal with resources from a physical directory, not from classpath. It doesn't matter how you setup ResourceHandler.

I have this

@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
    registry.addResourceHandler("/WEB-INF/**").addResourceLocations("classpath:/WEB-INF/");
}

And packaged all resources to the package, the static resource is find, but jsp resource keeps saying 404.

user3593261
  • 560
  • 4
  • 17
0

For me, the solution was in Intellij IDEA.

In my tomcat server configuration, under the Deployment tab, I was missing the expected Application context entry. E.g. /myroot

Hope that helps someone!

b-rad
  • 31
  • 2
-1
  • Have you check that MainPage.jsp is present in WEB-INF/pages/ folder.
  • change public class AppConfig extends WebMvcConfigurerAdapter

Change Bean as :

 @Bean
 public ViewResolver getInternalResourceViewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/pages/"); 
    resolver.setSuffix(".jsp");
    return resolver;
 }

May this will help you

yunandtidus
  • 3,847
  • 3
  • 29
  • 42
HiteshR
  • 64
  • 5
  • This didn't help. MainPage.jsp is present in WEB-INF/pages/folder. But anyway thank you – Toro Boro Dec 19 '14 at 13:43
  • This resolved my issue but only in combibation with http://stackoverflow.com/questions/29585553/spring-boot-could-not-resolve-view-with-name – RoutesMaps.com Mar 14 '17 at 11:39