Is there any way of making Spring Boot with Jersey serve static content? I've been through a series of tutorials and code samples on integrating Swagger into a Spring Boot's application. I can make it deliver the basic swagger.json, but I can't make Swagger UI work.
I can't even make it deliver a simple hello.txt
static file.
The relevant parts of my pom.xml are:
<!--Spring Boot-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Jersey -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-spring3</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.ext</groupId>
<artifactId>jersey-bean-validation</artifactId>
<version>${jersey.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-servlet</artifactId>
<version>${jersey.version}</version>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.7</version>
</dependency>
And my code:
@Configuration
@EnableAutoConfiguration
@ComponentScan({"com.xxxx"})
public class AdminApplication {
public static void main(String[] args) {
ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(AdminApplication.class)
.run(args);
}
@Bean
public ServletRegistrationBean jerseyServlet() {
ServletRegistrationBean registration = new ServletRegistrationBean(new ServletContainer(), "/*");
registration.addInitParameter(ServletProperties.JAXRS_APPLICATION_CLASS, JerseyConfig.class.getName());
return registration;
}
}
package com.xxxxxx.admin.config;
import com.xxxxxx.admin.resource.Status;
import org.glassfish.jersey.filter.LoggingFilter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.glassfish.jersey.server.spring.scope.RequestContextFilter;
import io.swagger.jaxrs.config.BeanConfig;
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(RequestContextFilter.class);
packages("com"); // TODO needs more detailed level
register(LoggingFilter.class);
// Validation
this.property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
this.property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true);
configureSwagger();
}
private void configureSwagger() {
register(io.swagger.jaxrs.listing.ApiListingResource.class);
register(io.swagger.jaxrs.listing.SwaggerSerializers.class);
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.0");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/"); // tried other things like "/api", but doesn't change anything
beanConfig.setResourcePackage("com.xxxxxx.admin");
beanConfig.setPrettyPrint(true);
beanConfig.setScan(true);
}
}
//other imports
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@Service
@Path("/status")
@Api(value = "status", description = "Check status")
public class Status {
@GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation("Return status")
public Response status() {
return Response.ok("Up").build();
}
}
I also tried making Jersey run as a filter (with spring.jersey.type=filter
) and changing Jersey's servlet pattern as stated in this answer, but that doesn't seem to affect anything.
@ApplicationPath("/rootPath")
public class JerseyConfig extends ResourceConfig {
I have a hello.txt file under /src/main/resources/public and Swagger UI's static files under /src/main/resources/public/swagger.
As I said, my application works fine, and GET http://localhost:8080/swagger.json shows me the plain json documentation, but both http://localhost:8080/hello.txt and http://localhost:8080/swagger/index.html return 404.
I'm using Jersey 2.8 and Spring Boot 1.3.0
I also tried changing Jersey's servlet pattern
@ApplicationPath("/rootPath") public class JerseyConfig extends ResourceConfig {
The way you are configuring your app, the @ApplicationPath
doesn't matter. The reason it worked for this answer you linked to, is because the Spring Boot auto configuration sets the servlet mapping when it extracts the @ApplicationPath
value from your resource config.
You are currently not using the ServletRegistrationBean
provided by Spring Boot, that accomplishes this. If you goal, by using your own ServletRegistrationBean
, was so that you can register your ResourceConfig
, you could've have done the same simply by either
ResourceConfig
with @Component
to make it a Spring bean, orMake it a Spring bean in your configuration class
@Bean
public ResourceConfig config() {
return new JerseyConfig();
}
Spring Boot will then inject your ResourceConfig
into the JerseyAutoConfiguration
, where it will get the @ApplicationPath
value (if present) on the ResourceConfig
, and use it to register its own ServletRegistrationBean
.
You can see the JerseyAutoConfiguration
to get an idea of everything you get for free, when you let Spring Boot handle the configuration.
Of if you want to keep your current SpringRegistrationBean
, just change the path you are using. You are using /*
, which is mentioned to be the problem in the linked answer. So just change to /rooPath/*
if that's what you want.