I am very new to swagger. I have created a sample JAX-RS project in which I have integrated the swagger 2.0 documentation. After a lot of unsuccessful tries, I am still not able to figure out how will I migrate my swagger 2.0 documentation to swagger 3.0. Also, what is the easiest way to host the swagger UI in my project?
So, in short, I have 2 question
1) How do I migrate this to swagger 3.0 ?
2) What is the easiest way to self-host the swagger UI in this project?
Below the sample code for my project's main files for reference.
I would really appreciate the help. Thank you so much!!!
==================== pom.xml File ====================
<!-- Swagger -->
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.18</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jersey2-jaxrs</artifactId>
<version>1.5.18</version>
</dependency>
==================== web.xml File ====================
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Starbucks Web Application</display-name>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
==================== Main App File ====================
package com.starbucks.app;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Module;
import com.google.inject.Stage;
import com.google.inject.servlet.ServletModule;
import com.starbucks.cors.SimpleCorsFilter;
import com.starbucks.guice.ApiBaseModule;
import com.starbucks.request.ObjectMapperContextResolver;
import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.ServerProperties;
import org.jvnet.hk2.guice.bridge.api.GuiceBridge;
import org.jvnet.hk2.guice.bridge.api.GuiceIntoHK2Bridge;
import javax.inject.Inject;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.HttpHeaders;
#ApplicationPath("api")
public class App extends ResourceConfig {
#Inject
public App(final ServiceLocator serviceLocator) {
// Packages to Scan for Jersey Resources
packages(true, "com.starbucks.api");
packages(true, "com.starbucks.exception.mapper");
// Jackson
register(ObjectMapperContextResolver.class);
register(JacksonFeature.class);
// HK2-Guice Bridge
Injector injector = createGuiceInjector();
initGuiceIntoHK2Bridge(serviceLocator, injector);
// Register Filters
// CORSFilter
register(SimpleCorsFilter.newBuilder()
.allowOriginDomain("localhost")
.allowCredentials()
.allowMethod(HttpMethod.GET)
.allowMethod(HttpMethod.OPTIONS)
.allowMethod(HttpMethod.POST)
.allowMethod(HttpMethod.PUT)
.allowHeader(HttpHeaders.CONTENT_TYPE)
.build());
// Jersey Event Listener
// Swagger
register(ApiListingResource.class);
register(SwaggerSerializers.class);
setUpSwagger();
//Tracing
property(ServerProperties.TRACING, "ON_DEMAND");
property(ServerProperties.TRACING_THRESHOLD, "VERBOSE");
//Jersey BeanValidation
property(ServerProperties.BV_SEND_ERROR_IN_RESPONSE, true);
}
private void initGuiceIntoHK2Bridge(final ServiceLocator serviceLocator, final Injector injector) {
GuiceBridge.getGuiceBridge().initializeGuiceBridge(serviceLocator);
GuiceIntoHK2Bridge guiceBridge = serviceLocator.getService(GuiceIntoHK2Bridge.class);
guiceBridge.bridgeGuiceInjector(injector);
}
private boolean isMac() {
return "mac os x".equalsIgnoreCase(System.getProperty("os.name"));
}
private Module[] getBaseModule() {
return new Module[]{
new ServletModule(),
new ApiBaseModule()
};
}
private Injector createGuiceInjector() {
if (isMac()) {
return Guice.createInjector(getBaseModule());
} else {
return Guice.createInjector(Stage.PRODUCTION, getBaseModule());
}
}
private BeanConfig setUpSwagger() {
BeanConfig beanConfig = new BeanConfig();
beanConfig.setVersion("1.0.2");
beanConfig.setSchemes(new String[]{"http"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/api");
beanConfig.setResourcePackage("com.starbucks.api");
beanConfig.setDescription("Provides the list of APIs for Starbucks backend");
beanConfig.setTitle("Starbucks Backend API");
beanConfig.setScan(true);
return beanConfig;
}
}
==================== Resource File ====================
package com.starbucks.api;
import com.starbucks.config.SharedConfig;
import com.starbucks.service.PingService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import javax.inject.Inject;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
#Api(value = "Health Check")
#Path("v1")
#Produces(MediaType.APPLICATION_JSON)
#Consumes(MediaType.APPLICATION_JSON)
public class PingApiResource {
private SharedConfig config;
private PingService pingService;
#Inject
public PingApiResource(final SharedConfig config, final PingService pingService) {
this.config = config;
this.pingService = pingService;
}
#GET
#Path("/ping")
#ApiOperation(value = "Ping API",
notes = "Simple Ping API for health check",
response = String.class)
#ApiResponses(value = {
#ApiResponse(code = 200, message = "OK"),
#ApiResponse(code = 404, message = "PING NOT FOUND"),
#ApiResponse(code = 500, message = "INTERNAL SERVER ERROR")
})
public Response ping() {
String res = pingService.getPingResponse();
System.out.println(config.getList("whiteListedDomains"));
return Response.ok().entity("{\"data\":\"" + res + " from " + config.appName("appName") + "\"}").build();
}
}
I would really appreciate the help. Thank you so much!!!
Related
Main Application Class: (It was going to be using JSP but realized the trouble with Spring Boot):
package com.MBS.Consulting.jsp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.context.annotation.Configuration;
#Configuration
#SpringBootApplication(scanBasePackages="com.MBS.Consulting.jsp")
public class SampleWebJspApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(SampleWebJspApplication.class);
}
public static void main(String[] args) throws Exception {
SpringApplication.run(SampleWebJspApplication.class, args);
}
}
WelcomeController - In sub folder of main class (this controller is accessible):
package com.MBS.Consulting.jsp.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class WelcomeController {
#GetMapping("/")
public String index() {
return "static/index";
}
#GetMapping("/Home")
public String welcome() {
return "Welcome/welcome";
}
#GetMapping("/ContactUs")
public String contactUs() {
return"Welcome/contact_Us";
}
#GetMapping("/AboutUs")
public String aboutUs() {
return "Welcome/about_us";
}
}
CustomerController - Does not even show that it is called with AOP. The package name is the same as the last controller. I do need to login using Spring Security to reach this page. It allows me to login and then gives me 404.
package com.MBS.Consulting.jsp.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import com.MBS.Consulting.jsp.entity.Customers;
import com.MBS.Consulting.jsp.entity.Users;
import com.MBS.Consulting.jsp.services.CustomersService;
#Controller
#RequestMapping("/Customer")
public class CustomerController {
#Autowired
private CustomersService customerService;
#GetMapping("/Home")
public String customerHome() {
return "Customer/Customer_Home";
}
}
Security config:
Not sure if I really need this or not but added it just to make sure that it couldn't be causing the problem.
package com.MBS.Consulting.jsp.config;
import java.util.HashMap;
import java.util.Map;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.crypto.password.Pbkdf2PasswordEncoder;
import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
#Configuration
#EnableWebSecurity
public class DemoSecurityConfig {
// add a reference to our security data source
#Autowired
#Qualifier("securityDataSource")
private DataSource securityDataSource;
#Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests((auth) -> {
try {
auth
.antMatchers("/Admin/**").hasRole("ADMIN")
.antMatchers("/Billing/**").hasAnyRole("ADMIN", "CUSTOMER", "EMPLOYEE")
.antMatchers("/Contacts/**").hasAnyRole("ADMIN", "EMPLOYEE")
.antMatchers("/Customer/**").hasAnyRole("ADMIN", "CUSTOMER")
.antMatchers("/Order/**").hasAnyRole("ADMIN", "CUSTOMER", "EMPLOYEE")
.antMatchers("/Plan/**").hasAnyRole("ADMIN", "CUSTOMER", "EMPLOYEE")
.antMatchers("/Services/**").hasAnyRole("ADMIN", "CUSTOMER", "EMPLOYEE")
.antMatchers("/Welcome", "/Login").permitAll()
.and()
.formLogin()
.and()
.logout()
.permitAll()
.and()
.exceptionHandling()
.accessDeniedPage("/access-denied");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
)
.httpBasic();
return http.build();
}
}
Project structure:
I hope the image shows up due just to show the project structure and that I believe the controllers are in the correct location to not be a problem for Spring Boot.
In the logs for console I get no information at all when visit CustomerController, but I do get a 404 Error. The web address I visit is http://localhost:8080/Customer/Home to try to call CustomerController. I am unsure what will cause this and if someone could explain what I did wrong.
I did search on it and I was going to try and configure the dispatcher servlet but it should of been auto configured. I believe if it reaching one it should be able to reach the other if it is the same folder. Also I understand the it needs to be in the sub folder of the main class. Finally I checked to see if it was the mapped right since I used folders in the template folder.
While mappings were correct and the project structure is correct it was unable to reach controllers due to spring security. The security FilterChain in the screen shot is missing two asterisks on the permit all controllers.
this:
.antMatchers("/","/Welcome", "/Login").permitAll()
should be:
.antMatchers("/**","/Welcome/**", "/Login/**").permitAll()
I have a spring boot application runs on jetty + swagger
and I don't see any end point specification when i go to http://localhost:8080/home/swagger-ui.html (see attachment) even do I wrote a controller and have an endpoint there.
my Application code is:
package com.MyService;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
#SpringBootApplication
#EnableSwagger2
public class MyServiceApplication {
public static void main(String[] args) {
SpringApplication.run(GcmAuthenticationServiceApplication.class, args);
}
}
in pom.xml I use:
<!-- Swagger 2.0 support -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
my controller:
package com.MyService.controller;
import com.MyService.model.RegistrationData;
import io.swagger.annotations.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.validation.Valid;
#Api(value = "register", description = "the registration API")
public interface RegistrationApi {
#ApiOperation(value = "Register user", nickname = "register", notes = "", authorizations = {
#Authorization(value = "petstore_auth", scopes = {
#AuthorizationScope(scope = "write:pets", description = "modify pets in your account"),
#AuthorizationScope(scope = "read:pets", description = "read your pets")
})
}, tags={ "register", })
#ApiResponses(value = {
#ApiResponse(code = 405, message = "Invalid input") })
#RequestMapping(value = "/register",
produces = { "application/json", "application/xml" },
consumes = { "application/json", "application/xml" },
method = RequestMethod.POST)
default ResponseEntity<Void> registerUser(#ApiParam(value = "Pet object that needs to be added to the store" ,required=true )
#Valid #RequestBody RegistrationData body) {
return new ResponseEntity<>(HttpStatus.NOT_IMPLEMENTED);
}
}
------
package com.MyService.controller;
import com.MyService.model.RegistrationData;
import com.MyService.service.RegistrationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/api/v1")
public class RegistrationController implements RegistrationApi{
private RegistrationService registrationService;
#Autowired
public void setProductService(RegistrationService registrationService) {
this.registrationService = registrationService;
}
#RequestMapping(value = "/register", method = RequestMethod.POST)
public ResponseEntity registerUser(#RequestBody RegistrationData registrationData){
//todo call service to rgeister
return new ResponseEntity("user register successfully", HttpStatus.OK);
}
}
my SwaggerConfig:
package com.MyService.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
import static springfox.documentation.builders.PathSelectors.regex;
#Configuration
#EnableSwagger2
public class Swagger2Config extends WebMvcConfigurationSupport {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select().apis(RequestHandlerSelectors.basePackage("guru.springframework.controllers"))
.paths(regex("/product.*")).build();
}
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("swagger-ui.html")
.addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}
my swagger documentation look as the following:
You can use the below with a change to your existing code. The base package must point to your controller base package and the URL context should be among the one's which you have added in the controller.
Modified base package to "com.MyService.controller" and added "/api/v1" & "/register" to the paths regex,
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select()
.apis(RequestHandlerSelectors.basePackage("com.MyService.controller"))
.paths(regex("(/api/v1.*)|(/register.*)")).build();
}
You are allowed to show /product.* URLs but In your endpoint, there don't have any URL match with /product.*. that's why it doesn't show any endpoint.
change your code like below
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select().apis(RequestHandlerSelectors.basePackage("guru.springframework.controllers"))
.paths(or(regex("/register.*"),regex("/api/v1.*"))).build();
}
you can allow all endpoints using regex("/.*").
I'm new to Spring Boot and currently stuck. I followed this (https://github.com/AppDirect/service-integration-sdk/wiki) Tutorial, as I want to implement an application that integrates itself into AppDirect. In the log I can see that the endpoints get created and mapped:
2018-10-29 16:32:48.898 INFO 8644 --- [ main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/api/v1/integration/processEvent],methods=[GET],produces=[application/json]}" onto public org.springframework.http.ResponseEntity<com.appdirect.sdk.appmarket.events.APIResult> com.appdirect.sdk.appmarket.events.AppmarketEventController.processEvent(javax.servlet.http.HttpServletRequest,java.lang.String)
But when I try to access the endpoint (http://localhost:8080/api/v1/integration/processEvent) with Browser or Http-Requester I get the following response:
{timestamp":"2018-10-29T08:50:13.252+0000","status":403,"error":"Forbidden","message":"Access Denied","path":"/api/v1/integration/processEvent"}
My application.yml looks like this:
connector.allowed.credentials: very-secure:password
server:
use-forward-headers: true
tomcat:
remote_ip_header: x-forwarded-for
endpoints:
enabled: true
info:
enabled: true
sensitive: false
health:
enabled: true
sensitive: false
time-to-live: 5000
info:
build:
name: #project.name#
description: #project.description#
version: #project.version#
This is my Application.java:
package de.....;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.List;
import org.springframework.boot.SpringApplication;
import org.springframework.http.MediaType;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
public class Application extends WebMvcConfigurerAdapter {
public static void main(String... args) {
SpringApplication.run(RootConfiguration.class, args);
}
/**
* Hack to make Spring Boot #Controller annotated classed to recognize the 'x-www-form-urlencoded' media type
*
* #param converters
*/
#Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FormHttpMessageConverter converter = new FormHttpMessageConverter();
MediaType mediaType = new MediaType("application", "x-www-form-urlencoded", Charset.forName("UTF-8"));
converter.setSupportedMediaTypes(Collections.singletonList(mediaType));
converters.add(converter);
super.configureMessageConverters(converters);
}
}
And this is the RootConfiguration.java:
package de.....;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import com.appdirect.sdk.ConnectorSdkConfiguration;
import com.appdirect.sdk.appmarket.DeveloperSpecificAppmarketCredentialsSupplier;
import com.appdirect.sdk.credentials.StringBackedCredentialsSupplier;
import de.....;
#Configuration
#Import({
ConnectorSdkConfiguration.class,
EventHandlersConfiguration.class
})
#EnableAutoConfiguration
public class RootConfiguration {
#Bean
public DeveloperSpecificAppmarketCredentialsSupplier environmentCredentialsSupplier(#Value("${connector.allowed.credentials}") String allowedCredentials) {
return new StringBackedCredentialsSupplier(allowedCredentials);
}
}
Any help is appreciated as intensive googleing didn't help.
Thanks in advance.
Adding the following class and registering it in Application.java solved my problem:
package de.......;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
#Configuration
#EnableWebSecurity
#Order(1)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests().antMatchers("/").permitAll();
}
}
I am looking for help on implementing swagger in my spring MVC rest api. I tried googling but so much confusion that I am not able to understand. I am not using spring boot.
Changes to Configuration class
package com.sample.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
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.view.InternalResourceViewResolver;
/**
* #author EOV537 -
* #since 1.0
*/
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = {"com.sample"})
public class ApplicationConfig extends WebMvcConfigurerAdapter {
private static final String VIEW_RESOLVER_PREFIX = "/WEB-INF/jsp/";
private static final String VIEW_RESOLVER_SUFFIX = ".jsp";
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations("/static/");
registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
// viewResolver.setViewClass(InternalResourceViewResolver.class); // NOSONAR
viewResolver.setPrefix(VIEW_RESOLVER_PREFIX);
viewResolver.setSuffix(VIEW_RESOLVER_SUFFIX);
return viewResolver;
}
}
WebApplint
package com.sample.config;
import javax.annotation.PreDestroy;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextCleanupListener;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
/**
* #author EOV537 -
* #since 1.0
*/
public class WebApplint implements WebApplicationInitializer {
/*
* (non-Javadoc)
*
* #see org.springframework.web.WebApplicationInitializer#onStartup(javax.servlet.ServletContext)
*/
private AnnotationConfigWebApplicationContext rootContext = null;
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
System.setProperty("spring.profiles.active", "web");
// Create the 'root' Spring application context
rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(ApplicationConfig.class, SwaggerConfig.class);
// Manages the lifecycle
servletContext.addListener(new ContextLoaderListener(rootContext));
servletContext.addListener(new ContextCleanupListener());
ServletRegistration.Dynamic springWebMvc = servletContext.addServlet("DispatcherServlet",
new DispatcherServlet(rootContext));
springWebMvc.setLoadOnStartup(1);
springWebMvc.addMapping("/");
springWebMvc.setAsyncSupported(true);
}
#PreDestroy
protected final void cleanup() {
if (rootContext != null) {
rootContext.close();
}
}
}
SwaggerConfig.java
package com.sample.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
/**
* #author EOV537 -
* #since 1.0
*/
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any()).build();
}
private ApiInfo apiInfo() {
ApiInfo apiInfo = new ApiInfo("My REST API", "Some custom description of API.", "API Blog web",
"Terms of service", "myeaddress#company.com", "License of API", "API license URL");
return apiInfo;
}
}
Add following 2 dependencies in pom.xml
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.3.0</version>
</dependency>
Access Swagger using
http://localhost:8082/rest-service/swagger-ui.html#/
I'm trying to run elementary spring-4 web-mvc application without xml configuration at all. I've looked spring documentation and examples, but it didn't work for me.
My controller:
package com.nikolay.exam.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class HomeController {
#RequestMapping(value = "/home", method = RequestMethod.GET)
#ResponseBody
public String home() {
return "Hello world!";
}
}
AppConfig:
package com.nikolay.exam.config;
import org.springframework.context.annotation.Configuration;
#Configuration
public class AppConfig {
}
WebConfig:
package com.nikolay.exam.config;
import com.nikolay.exam.controller.HomeController;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
#Configuration
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public HomeController homeController() {
return new HomeController();
}
}
And WebInitializer:
package com.nikolay.exam.config;
import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
public class WebInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext root = new AnnotationConfigWebApplicationContext();
root.setConfigLocation("com.nikolay.exam.config");
servletContext.addListener(new ContextLoaderListener(root));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(root));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/*");
}
}
But when I run my application on tomcat I receive an error:
14-Feb-2015 11:35:29.825 WARNING [http-nio-8080-exec-1] org.springframework.web.servlet.PageNotFound.noHandlerFound No mapping found for HTTP request with URI [/home/] in DispatcherServlet with name 'dispatcher'
14-Feb-2015 11:35:32.766 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deploying web application directory /home/nikolay/apache-tomcat-8.0.9/webapps/manager
14-Feb-2015 11:35:32.904 INFO [localhost-startStop-1] org.apache.catalina.startup.HostConfig.deployDirectory Deployment of web application directory /home/nikolay/apache-tomcat-8.0.9/webapps/manager has finished in 136 ms
14-Feb-2015 11:35:34.888 WARNING [http-nio-8080-exec-3] org.springframework.web.servlet.PageNotFound.noHandlerFound No mapping found for HTTP request with URI [/home/] in DispatcherServlet with name 'dispatcher'
I think it's the way you register your config class that is not correct.
Try using the AnnotationConfigWebApplicationContext#register instead.
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(WebConfig.class);
Probably you need to change
dispatcher.addMapping("/*");
to
dispatcher.addMapping("/");