19

The application uses JDK 8, Spring Boot & Spring Boot Jersey starter and is packaged as a WAR (although it is locally run via Spring Boot Maven plugin).

What I would like to do is to get the documentation I generate on the fly (at build time) as a welcome page.

I tried several approaches:

  1. letting Jersey serving the static contents by configuring in application.properties the proper init parameter as described here
  2. introduce a metadata-complete=false web.xml in order to list the generated HTML document as a welcome-file.

None of that worked out.

I would like to avoid having to enable Spring MVC or creating a Jersey resource just for serving a static file.

Any idea?

Here is the Jersey configuration class (I unsuccessfully tried to add a ServletProperties.FILTER_STATIC_CONTENT_REGEX there):

@ApplicationPath("/")
@ExposedApplication
@Component
public class ResourceConfiguration extends ResourceConfig {

   public ResourceConfiguration() {
      packages("xxx.api");
      packages("xxx.config");
      property(ServerProperties.BV_DISABLE_VALIDATE_ON_EXECUTABLE_OVERRIDE_CHECK, true);
      property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
   }
}

And here is Spring Boot application class (I tried adding an application.properties with spring.jersey.init.jersey.config.servlet.filter.staticContentRegex=/.*html but it didn't work, I'm not exactly sure what the property key should be here):

@SpringBootApplication
@ComponentScan
@Import(DataConfiguration.class)
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Community
  • 1
  • 1
fbiville
  • 8,407
  • 7
  • 51
  • 79

3 Answers3

34

Let me just first state, that the reason the static content won't be served is because of the default servlet mapping of the Jersey servlet, which is /*, and hogs up all the requests. So the default servlet that serves the static content can't be reached. Beside the below solution, the other solution is to simply change the servlet mapping. You can do that by either annotating your ResourceConfig subclass with @ApplicationPath("/another-mapping") or set the application.properties property spring.jersey.applicationPath.


In regards to your first approach, take a look at the Jersey ServletProperties. The property you are trying to configure is FILTER_STATIC_CONTENT_REGEX. It states:

The property is only applicable when Jersey servlet container is configured to run as a Filter, otherwise this property will be ignored

Spring Boot by default configures the Jersey servlet container as a Servlet (as mentioned here):

By default Jersey will be set up as a Servlet in a @Bean of type ServletRegistrationBean named jerseyServletRegistration. You can disable or override that bean by creating one of your own with the same name. You can also use a Filter instead of a Servlet by setting spring.jersey.type=filter (in which case the @Bean to replace or override is jerseyFilterRegistration).

So just set the property spring.jersey.type=filter in your application.properties, and it should work. I've tested this.

And FYI, whether configured as Servlet Filter or a Servlet, as far as Jersey is concerned, the functionality is the same.

As an aside, rather then using the FILTER_STATIC_CONTENT_REGEX, where you need to set up some complex regex to handle all static files, you can use the FILTER_FORWARD_ON_404. This is actually what I used to test. I just set it up in my ResourceConfig

@Component
public class JerseyConfig extends ResourceConfig {

    public JerseyConfig() {
        packages("...");
        property(ServletProperties.FILTER_FORWARD_ON_404, true);
    }
}
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • 1
    Héhé, just done that before reading your answer and it works! :) – fbiville Apr 16 '15 at 09:50
  • 2
    Note there is still an ongoing issue with generated files. https://github.com/spring-projects/spring-boot/issues/2833 tracks the progress. – fbiville Apr 16 '15 at 13:18
  • @Rolf I'm having the same issue, How exactly did you solve it ? – Imtiaz Mirza Apr 24 '15 at 21:12
  • Remaining issue (see above) still to be addressed :/ – fbiville Apr 27 '15 at 13:56
  • Still not works for me, where to put my static file? How can I use a external directory ? – wener Sep 13 '15 at 17:40
  • 1
    @peeskillet I only use boot-starter-jersey and boot-starter-data, so there is no spring-mvc. They jersey finally served my static file under static folder, but is is possible to redirect `/` to `/index.html`, BTW, I use embed tomcat. – wener Sep 14 '15 at 01:36
  • awesome, this was very helpful! – Eddie Martinez Aug 07 '17 at 16:44
  • Is there anyway we can tell jersey to ignore certain paths? – pijushcse Mar 06 '18 at 19:44
  • 1
    You need to also have spring-boot-starter-web to be able to serve the static content. – Paul Samsotha Jul 03 '18 at 05:01
  • 1
    Thre real problem here is, that if you are using jersey starter, the default servlet implementation is NOT DispatcherServlet (org.apache.catalina.servlets.DefaultServlet in my case) so if you use jersey starter, whole MVN is useless. Probably it is possible to configure it somehow, but i have no clue how. – Antoniossss Dec 10 '18 at 19:22
4

For anyone who still can't get this to work, I followed the answer provided by @peeskillet, and had to make an additional change.

Previously I had created the following method in Application.java.

@Bean
public ServletRegistrationBean jerseyServlet() {
    ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "/*");
    registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyConfig.class.getName());
    return registration;
}

The problem is that this registered the servlet for the /* path, and then setup the Jersey ResourceConfig configuration file.

Once I removed the above method, and placed the @Configuration annotation on my ResourceConfig class, I noticed the static resource could be retrieved via Spring Boot.

For completeness, this is a snippet of my ResourceConfig now.

@Configuration
public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        // Application specific settings
        property(ServletProperties.FILTER_FORWARD_ON_404, true);
    }
}

This blog post was helpful in determining the difference approach for the ResourceConfig.

mnd
  • 2,709
  • 3
  • 27
  • 48
  • Good to mention again that in order to make the "property(ServletProperties.FILTER_FORWARD_ON_404, true);" work, we should add "spring.jersey.type: filter " in the "application.property" file. – Elik Dec 05 '19 at 09:59
1

Below setup worked for me

Set

spring .jersey.type: filter

set FILTER_FORWARD_ON_404

@Configuration 
        public class MyResourceConfig extends ResourceConfig  {

            public MyResourceConfig () {
                try {
                    register(XXX.class);
                    property(ServletProperties.FILTER_FORWARD_ON_404, true);

                } catch (Exception e) {
                    LOGGER.error("Exception: ", e);                   
                }
            }       

        } 

Note: Use @Configuration instead of @component

Niraj Sonawane
  • 10,225
  • 10
  • 75
  • 104