Hide/remove Spring MVC endpoint in Swagger2 - spring-mvc

I'm using Swagger 2 for API UI. So, my gradle.build has:
compile "io.springfox:springfox-swagger2:${swaggerVersion}"
compile "io.springfox:springfox-swagger-ui:${swaggerVersion}"
I've configured Swagger as below:
#Configuration
#Profile("!production")
#EnableSwagger2
#ComponentScan(basePackageClasses = com.company.controllers.ContentController.class)
public class SwaggerConfiguration {
#Autowired
private BuildInfo buildInfo;
#Bean
public Docket awesomeApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(this.awesomeApiInfo())
.select()
.apis(Predicates.not(RequestHandlerSelectors.basePackage("org.springframework.boot")))
.build();
}
private ApiInfo awesomeApiInfo() {
return new ApiInfoBuilder()
.title("Awesome API - build #" + this.buildInfo.getVersion())
.description("Enter the IDs in order to look for the content")
.version("0.1")
.build();
}
}
I'm getting the api endpoint that I have defined, but also getting the Spring MVC endpoints as below:
Now, I need to get rid of these mvc endpoints.
Any help is highly appreciated!!

Ohhh... actually it was my silly mistake. I changed RequestHandlerSelectors to select only endpoints from my own controller package as follow:
#Bean
public Docket awesomeApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(this.awesomeApiInfo())
.select()
.paths(PathSelectors.any())
.apis(RequestHandlerSelectors.basePackage("com.company.awesome.controllers"))
.build();
}
And this shows only the endpoints mapped within the classes in controller package.

The best approach you can follow is to restrict visibility and access to ServiceStack. So you can hide it from being visible externally with:
[Restrict(VisibleInternalOnly = true)]
public class InternalAdmin { }
you can read more about it here

An alternative to specifying base package is to create a class annotation like this:
#Target({ElementType.TYPE})
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Component
public #interface SwaggerDocumentation {
}
and then once defined use it on your Controller as desired:
#RestController
#SwaggerDocumentation
public class EntityRestController {
EntityService entityService;
#Autowired
public EntityRestController(final EntityService entityService) {
this.entityService = entityService;
}
#GetMapping("/status")
String getTest() {
return "Ready";
}
#GetMapping("/api/entities")
Collection<Entity> getEntities() {
return entityService.findSome();
}
}
and then finally in the SwaggerConfig class
#Configuration
#EnableSwagger2
public class SwaggerConfig {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.withClassAnnotation(SwaggerDocumentation.class))
.build();
}
}

Related

Camel Rest and RestController in the same project

I have a camel rest in my project and a servlet is configured for it. At the moment I'm trying to add a regular RestController without camel. Can two types of rest be in the same project?
For example
#Override
public void configure() throws Exception {
rest("/dictionary/get-dictionary")
.get()
.param().name("dictionary").required(true).type(RestParamType.query).endParam()
.param().name("name").required(true).type(RestParamType.query).endParam()
.....
.endRest();
CamelServlet implemented for camel
#RestController
#RequestMapping("/createOrder")
#RequiredArgsConstructor
public class OrderController {
private final OrderService OrderService;
#PostMapping
public void createForm(#RequestBody App app) {
orderService.createFullOrder(app);
}
}
When I request createOrder, I always get 404. How can I make both types of controllers work?
Thank in advice
Solution
#Configuration
public class AppConfig {
#Bean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
#SuppressWarnings("rawtypes")
#Bean
public ServletRegistrationBean axisServletRegistrationBean() {
#SuppressWarnings("unchecked")
ServletRegistrationBean registration = new ServletRegistrationBean(dispatcherServlet(), "/createOrder");
registration.addUrlMappings("/createOrder");
return registration;
}
}
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.package.package")
public class WebConfig {
}

how upgrade swagger2 to swagger3 in plain spring project

In our spring-webmvc project we are using the following code to configure swagger2, now we want to upgrade to swagger3, so we added springdoc-openapi-ui in pom file, what changes we need to make in our swagger-configuration file
#Configuration
#EnableSwagger2
public class SwaggerConfiguration {
#Bean
public Docket api() {
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.basePackage("com.hjk.controller"))
.paths(PathSelectors.any())
.build()
.apiInfo(getApiInfo());
}
private ApiInfo getApiInfo() {
return new ApiInfo(title, description, version, termsOfServiceUrl, contact, license, licenseUrl);
}
}
You have to remove #EnableSwagger2
and change your Docket api() like this.
#Bean
public OpenAPI customOpenAPI() {
return new OpenAPI().info(new Info().title("SpringShop API"));}
For more details Please refer to this docs https://springdoc.org/#migrating-from-springfox.

RedisSentinelConfiguration using spring.redis.sentinel.nodes with spring boot

Trying to configure spring boot application with spring-session and redis but having below issue. Not able to resolve it.
Constructor threw exception; nested exception is java.lang.IllegalStateException: BeanFactory has not been injected into #Configuration class
This code works fine for me
#Configuration
#EnableRedisHttpSession
public class HttpSessionConfig {
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(SLAVE_PREFERRED)
.build();
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration()
.master("mymaster")
.sentinel("192.168.56.50", 26379)
.sentinel("192.168.56.50", 26380)
.sentinel("192.168.56.50", 26381);
#Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory(sentinelConfig, clientConfig);
}
}
but not this code using PropertySource.
Spring document says:-
**RedisSentinelConfiguration can also be defined with a PropertySource, which lets you set the following properties:
Configuration Properties
spring.redis.sentinel.master: name of the master node.
spring.redis.sentinel.nodes: Comma delimited list of host:port pairs.**
#Configuration
#EnableRedisHttpSession
#PropertySource(name="application", value="classpath:application.properties")
public class HttpSessionConfig {
#Resource
ConfigurableEnvironment environment;
#Bean
public PropertiesPropertySource propertySource() {
return (PropertiesPropertySource) environment.getPropertySources().get("defaultProperties");
}
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(SLAVE_PREFERRED)
.build();
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration(propertySource());
#Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory(sentinelConfig, clientConfig);
}
}
application.properties
server.port=8090
spring.security.user.name=admin
spring.security.user.password=admin
spring.redis.sentinel.master=mymaster
spring.redis.sentinel.nodes=192.168.56.50:26379,192.168.56.50:26380,192.168.56.50:26381
spring.application.name=spring-session-demo
The format of sentinel nodes property is comma separated key:value pairs. So you can extract host and port by java split() function.
#Autowired
private Environment env;
#Bean
public LettuceConnectionFactory connectionFactory() {
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration();
String master = env.getProperty("spring.redis.sentinel.master");
String nodes = env.getProperty("spring.redis.sentinel.nodes");
sentinelConfig.master(master);
for (String node : nodes.split(",")) {
String split[] = node.split(":");
sentinelConfig.sentinel(split[0], Integer.parseInt(split[1]));
}
...
}

How do I using RedisMessageListenerContainer in configuration class

I am using spring-MVC and spring-data-redis to control Redis-cluster pool.
When I using jedisCluster.subscribe(new JedisPubSubListener(), "bb");
my application will stock in this code(I try to use thread but the other one can't get the instance in #autowerid).
I google a lot of way point me to using spring-boot .
but I can change the structure in our project.
So I think when spring init I can register a listener to use.
But I can run sauce in my original code.
Can someone make an example for me if I using this following code :
#Configuration
public class RedisClusterConfig {
private List<String> redisNodes(){
return Arrays.asList(redisNode.split(","));
}
#Bean
JedisPoolConfig jedisPoolConfig(){
JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
jedisPoolConfig.setMaxTotal(maxTotal);
jedisPoolConfig.setMaxIdle(maxIdle);
jedisPoolConfig.setMinIdle(minIdle);
jedisPoolConfig.setMaxWaitMillis(maxWaitMillis);
jedisPoolConfig.setTestOnBorrow(testOnBorrow);
jedisPoolConfig.setTestOnReturn(testOnReturn);
jedisPoolConfig.setTestWhileIdle(testWhileIdle);
return jedisPoolConfig;
}
#Bean
RedisConnectionFactory redisClusterConnectionFactory(JedisPoolConfig
jedisPoolConfig){
JedisConnectionFactory redisConnectionFactory = new
JedisConnectionFactory(new RedisClusterConfiguration(redisNodes()));
redisConnectionFactory.setPoolConfig(jedisPoolConfig);
return redisConnectionFactory;
}
}
this is how I setting in my configuration.
#Bean
public RedisMessageListenerContainer redisMessageListenerContainer() {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(redisConnectionFactory);
container.addMessageListener(consumerRedis(),topic());
return container;
}
#Bean
public ConsumerRedisListener consumerRedis() {
return new ConsumerRedisListener();//this class implements MessageListener
}
#Bean
public ChannelTopic topic() {
return new ChannelTopic("channel");
}

SpringBoot - UTF8 & Controller

I am using SpringBoot and Spring MVC for my Web Application and when I submit any form my controller gets the information encoded with ISO-8859-1 instead of UTF-8.
My application.properties
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:mysql://localhost/pfg
spring.datasource.username=
spring.datasource.password=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.sqlScriptEncoding=UTF-8
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.jadira.usertype.autoRegisterUserTypes=true
spring.messages.encoding=UTF-8
server.tomcat.uri-encoding=UTF-8
spring.http.encoding.charset=UTF-8
spring.thymeleaf.mode=HTML5
spring.thymeleaf.encoding=UTF-8
I also have this ServerInitializer class:
#Configuration
public class ServletInitializer extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(PfgApplication.class);
}
#Bean
#Order(Ordered.HIGHEST_PRECEDENCE)
CharacterEncodingFilter characterEncodingFilter() {
CharacterEncodingFilter filter = new CharacterEncodingFilter();
filter.setEncoding("UTF-8");
filter.setForceEncoding(true);
return filter;
}
}
Thanks for the help.
Are you using 1.3.0.M5 by chance? In that case there's a bug and you might want to consider using the workaround:
https://github.com/spring-projects/spring-boot/issues/3912
#Autowired
private HttpEncodingProperties httpEncodingProperties;
#Bean
public OrderedCharacterEncodingFilter characterEncodingFilter() {
OrderedCharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
filter.setEncoding(this.httpEncodingProperties.getCharset().name());
filter.setForceEncoding(this.httpEncodingProperties.isForce());
filter.setOrder(Ordered.HIGHEST_PRECEDENCE);
return filter;
}
for Example
#RequestMapping(value="/user", **produces="text/html;charset=UTF-8"**)
public class UserController{
}
add blackbody part is ok!

Resources