Stack Exchange
Getting 404 When Loading Static Resources in Java 8 Spring 4.2.4
I have a Java 8 Spring 4.2.4 app programmatically set up.  However, I'm getting the following in my Tomcat access logs - (CSS and JS):
127.0.0.1 - - [22/Feb/2016:11:54:02 -0600] "GET /javafullstack/ HTTP/1.1"   200     34257
127.0.0.1 - - [22/Feb/2016:11:54:02 -0600] "GET /javafullstack/resources/font-awesome/css/font-awesome.min.css HTTP/1.1" 404 992
127.0.0.1 - - [22/Feb/2016:11:54:02 -0600] "GET /javafullstack/resources/js/classie.js HTTP/1.1" 404 992
127.0.0.1 - - [22/Feb/2016:11:54:02 -0600] "GET /javafullstack/resources/js/jquery.js HTTP/1.1" 404 992
127.0.0.1 - - [22/Feb/2016:11:54:02 -0600] "GET /javafullstack/resources/js/bootstrap.min.js HTTP/1.1" 404 992

etc.
Here's what I have:
package com.thoughtscript.javafullstack.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.thoughtscript.javafullstack")
public class Config {

@Bean
public UrlBasedViewResolver setupViewResolver() {
    UrlBasedViewResolver resolver = new UrlBasedViewResolver();
    resolver.setPrefix("/webapp/");
    resolver.setSuffix(".jsp");
    resolver.setViewClass(JstlView.class);
    return resolver;
}

@Bean
public JpaTransactionManager jpaTransMan() {
    JpaTransactionManager jtManager = new JpaTransactionManager(getEntityManagerFactoryBean().getObject());
    return jtManager;
}

@Bean
public LocalEntityManagerFactoryBean getEntityManagerFactoryBean() {
    LocalEntityManagerFactoryBean lemfb = new LocalEntityManagerFactoryBean();
    lemfb.setPersistenceUnitName("localEntity");
    return lemfb;
}

public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/resources/**").addResourceLocations("/resources/").setCachePeriod(3600)
            .resourceChain(true).addResolver(new PathResourceResolver());
}
}

All the relevant stuff is in exploded war:
javafullstack\resources
Otherwise project setup is:
javafullstack\src\main\webapp\resources
Example .jsp snippet:
           <!-- jQuery -->
            <script src="<c:url value="/resources/js/jquery.js "/>"></script>

            <!-- Bootstrap Core JavaScript -->
            <script src="<c:url value="/resources/js/bootstrap.min.js "/>"></script>

            <!-- Plugin JavaScript -->
            <script src="http://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.3/jquery.easing.min.js"></script>
            <script src="<c:url value="/resources/js/classie.js "/>"></script>
            <script src="<c:url value="/resources/js/cbpAnimatedHeader.js "/>"></script>

            <!-- Contact Form JavaScript -->
            <script src="<c:url value="/resources/js/jqBootstrapValidation.js "/>"></script>
            <script src="<c:url value="/resources/js/contact_me.js "/>"></script>

            <!-- Custom Theme JavaScript -->
            <script src="<c:url value="/resources/js/freelancer.js "/>"></script>

            <!-- Custom -->
            <script src="<c:url value="/resources/js/custom.js "/>"></script>

Any help is much appreciated!

Does it work if you prepend /javafullstack to script refs of the resources in the .jsp that it can't find?

It's actually getting the correct URL - so by prepending I get /javafullstack/javafullstack/...

OK got, it's because I failed to extend WebMvcConfigurerAdapter in the Config class.  By extending I can override addResourceHandlers().
It should look like:
package com.thoughtscript.javafullstack.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalEntityManagerFactoryBean;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.view.JstlView;
import org.springframework.web.servlet.view.UrlBasedViewResolver;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.thoughtscript.javafullstack")
public class Config extends WebMvcConfigurerAdapter{

    @Bean
    public UrlBasedViewResolver setupViewResolver() {
        UrlBasedViewResolver resolver = new UrlBasedViewResolver();
        resolver.setPrefix("/webapp/");
        resolver.setSuffix(".jsp");
        resolver.setViewClass(JstlView.class);
        return resolver;
    }

    @Bean
    public JpaTransactionManager jpaTransMan() {
        JpaTransactionManager jtManager = new JpaTransactionManager(getEntityManagerFactoryBean().getObject());
        return jtManager;
    }

    @Bean
    public LocalEntityManagerFactoryBean getEntityManagerFactoryBean() {
        LocalEntityManagerFactoryBean lemfb = new LocalEntityManagerFactoryBean();
        lemfb.setPersistenceUnitName("localEntity");
        return lemfb;
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**").addResourceLocations("/resources/").setCachePeriod(3600)
                .resourceChain(true).addResolver(new PathResourceResolver());
    }
}


I had the same issue. my class had "extends WebMvcConfigurationSupport", which we've been using since Spring3. Switching to "extends WebMvcConfigurerAdapter" fixes the issue for me as well (it now takes into account the "addResourceHandlers(ResourceHandlerRegistry registry)" method).

Also worth noting, the way to check if the resourceHandlers are picked up by Spring is to check in the logs, Spring, on starting up the application, will log the setup of the resource handlers will logs that look like this: "o.s.w.s.h.SimpleUrlHandlerMapping - Mapped URL path [/resource/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]". Hope this helps someone reaching this page.

Very helpful - I appreciate that a lot. I also ended up writing on this topic later on over at Baeldung: https://www.baeldung.com/spring-dispatcherservlet. Thanks!
