Metrics are not supported for Spring Boot 1.x applications - spring-boot

I am using Spring Boot 2.x but in Spring Boot Admin-> Wallboard -> Metrics I am getting "Metrics are not supported for Spring Boot 1.x applications".

I had the same issue and the reason was, that my application always sent a fixed content-type in the response header.
Spring Boot Admin checks for the content-type application/vnd.spring-boot.actuator.v2. If this content-type is absent, your application is considered to be a Spring Boot 1 application.
In my case, the reason was a WebMvcConfigurer which hard-coded the defaultContentType to application/json. I had something like the following in my configurer:
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.APPLICATION_JSON)
.favorPathExtension(false).favorParameter(true).ignoreAcceptHeader(true).useRegisteredExtensionsOnly(true);
}
After changing it to
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.defaultContentType(MediaType.valueOf("application/vnd.spring-boot.actuator.v2+json"), MediaType.APPLICATION_JSON)
.favorPathExtension(false).favorParameter(true).ignoreAcceptHeader(true).useRegisteredExtensionsOnly(true);
}
, Spring Boot Admin showed me the metrics as it was supposed to.

Related

CORS spring security filter vs WebMvcConfigurer.addCorsMappings

What the difference of cors() filter in configure method of WebSecurityConfigurerAdapter class and create bean of WebMvcConfigurer and override addCorsMappings method? when we use of which? can anyone explain it?
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurer() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:3000");
}
};
}
vs
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and()
.csrf().disable()
.authorizeRequests()
.mvcMatchers("/rest/**").authenticated()
.anyRequest().permitAll()
.and()
.oauth2ResourceServer().jwt().jwtAuthenticationConverter(this.jwtAuthenticationConverter())
;
}
}
Spring Web MVC
WebMvcConfigurer is part of the Spring Web MVC library. Configuring CORS with addCorsMappings adds CORS to all URLs which are handled by Spring Web MVC, see 1.7.2. Processing:
Spring MVC HandlerMapping implementations provide built-in support for CORS. After successfully mapping a request to a handler, HandlerMapping implementations check the CORS configuration for the given request and handler and take further actions.
You have to use it, if no Spring Security is used (non secured applications) or not all Spring Web MVC URLs are handled by Spring Security (some ULRs are unsecured).
You can't use it for non Spring Web MVC URLs like JSF, Servlet, JAX-WS, JAX-RS, ...
Spring Security
WebSecurityConfigurerAdapter is part of the Spring Security library. Configuring CORS with cors() adds CORS to all URLs which are handled by Spring Security, see 15.8. CORS:
Spring Framework provides first class support for CORS. CORS must be processed before Spring Security because the pre-flight request will not contain any cookies (i.e. the JSESSIONID). If the request does not contain any cookies and Spring Security is first, the request will determine the user is not authenticated (since there are no cookies in the request) and reject it.
The easiest way to ensure that CORS is handled first is to use the CorsFilter.
You have to use it, if you use Spring Security.
If you are using Spring Web MVC and Spring Security together you can share the configuration, see 15.8. CORS:
If you are using Spring MVC’s CORS support, you can omit specifying the CorsConfigurationSource and Spring Security will leverage the CORS configuration provided to Spring MVC.

What Is the Correct Way To Use AbstractReactiveWebInitializer

I've got a Spring WebFlux application running successfully as a standalone spring boot application.
I am attempting to run the same application in a Tomcat container, and following the documentation, I've created a class that extends AbstractReactiveWebInitializer. The class requires that I implement a method getConfigClasses that would return classes normally annotated with #Configuration. If the working spring boot app started with a class called ApplicationInitializer, then the resulting implementations would look like this:
#SpringBootApplication(scanBasePackages = "my.pkg")
#EnableDiscoveryClient
#EnableCaching
public class ApplicationInitializer {
public static void main(String... args) {
SpringApplication.run(ApplicationInitializer.class, args);
}
}
and
public class ServletInitializer extends AbstractReactiveWebInitializer {
#Override
protected Class<?>[] getConfigClasses() {
return new Class[] {ApplicationInitializer.class};
}
}
When deployed, the only thing that starts is ApplicationInitializer, none of the autoconfigured Spring Boot classes (Cloud Config, DataSource, etc) ever kick off.
The documenation states this is the class I need to implement, I just expected the remainder of the spring environment to "just work".
How should I be using this class to deploy a Reactive WebFlux Spring Boot application to a Tomcat container ?
Edit:
After some additional research, I've narrowed it down to likely just Cloud Config. During bean post processing on startup, the ConfigurationPropertiesBindingPostProcessor should be enriched with additional property sources (from cloud config), but it appears to be the default Spring properties instead, with no additional sources.
The misisng properties is causing downstream beans to fail.
Spring Boot does not support WAR packaging for Spring WebFlux applications.
The documentation you're referring to is the Spring Framework doc; Spring Framework does support that use case, but without Spring Boot.
you can extend SpringBootServletInitializer, add add reactive servlet on onStartup method

Spring Boot 2 http.httpBasic().disable(); not working

I recently upgraded from Spring Boot 1.x to Spring Boot 2.0.3 and I am trying to disable basic auth with no success.
#Configuration
#EnableWebSecurity(debug=true)
#EnableGlobalMethodSecurity(securedEnabled = true)
public class CustomSecurity extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.httpBasic().disable();
// the rest of my config
}
}
What hidden gem am I missing to just simply turn off basic auth?
Why does turning things off in Spring need to be so difficult now?
I was reading this:
https://github.com/spring-projects/spring-boot/issues/10306
and I have to agree that it should be much easier and a clearer explanation should be provided on how to turn this off.
EDIT
This link https://spring.io/blog/2017/09/15/security-changes-in-spring-boot-2-0-m4 talks about how the property was removed but doesn't say anything about how to continue to use the configuration as it exists in current application that utilize it.

Spring Boot Actuator requires #EnableWebMvc but that turns off other features

I got confused trying to integrate Actuator to a project using Spring Boot 1.5.11's static resource serving feature:
Spring Boot Actuator does not work without #EnableWebMvc, HTTP 406 is returned because the right Http media converter is not installed.
But if I add #EnableWebMvc, it turns off serving resources from the static folder and other Spring Boot features.
Is there a way to initialize Actuator without losing Boot features?
Found a bug in Spring Boot 2.0, it seems it was there in Boot 1.5 as well. Workaround: setting favorPathExtension to false turns off buggy code in ServletPathExtensionContentNegotiationStrategy and Actuator endpoints start working.
#Configuration
public class WebConfig implements WebMvcConfigurer {
#Override
public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
configurer.favorPathExtension(false);
}
}

Spring Boot Jersey and Monitoring URL's

We have a simple Spring Boot application with Jersey.
Spring Boot provides default monitoring end points
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#production-ready-monitoring
Example:
#Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
// registering resources from rest package
packages("com.xyx.abc.rest");
}
}
The REST end points that are provided by Spring Boot are not available in the context of a Spring Boot Jersey Application.
The Spring Boot dependency includes Jersey, starter-actuator, starter-tomcat.
Our REST resources show up fine, but the ones provided by Spring Boot for monitoring dont show up.
E.g http://abc.xyx.com:8080/health returns a 404
If you are using it as a Filter you need to tell Jersey not to handle those requests. E.g. by putting the Jersey resources under a separate path, like "/api/*" or something:
#Bean
public FilterRegistrationBean jersey() {
FilterRegistrationBean bean = new FilterRegistrationBean();
...
bean.setUrlPatterns(Lists.newArrayList("/api/*"));
return bean;
}
(from here).
Or by declaring that your admin endpoints are "static" (via another init parameter "com.sun.jersey.config.property.WebPageContentRegex"):
#Bean
public FilterRegistrationBean jersey() {
FilterRegistrationBean bean = new FilterRegistrationBean();
...
bean.addInitParameter("com.sun.jersey.config.property.WebPageContentRegex",
"/admin/.*");
return bean;
}
where we have set management.contextPath=/admin in the Spring Boot external configuration (otherwise you'd have to enumerate all the endpoints in the regex).
You can also tell Jersey to ignore unresolved requests (instead of sending a 404). That would also achieve your goal, but might affect your client apps (if they rely on a 404 for their behaviour).

Resources