My backend microservice fall down with OutOfMemory exception in production environment. ////////////////////////////////
UPDATE: look like problem come from embedded tomcat, I found this
It store sessions for each requests. Currently Have no idea how to clean it. I have this config:
server:
port: 38083
compression:
enabled: true
mime-types: text/html, text/xml, text/plain, text/css, application/javascript, application/json
min-response-size: 1024
spring:
session:
store-type: none
timeout: 1
////////////////////////
I'm still not sure, but look like problem come from
org.keycloak.representations.AccessToken.roles hash map. Currently I reduce microservice to simpliest as it possible, I have only this controller:
@RestController
@RequestMapping("/nurse")
public class NurseController {
List<NurseDto> cache = null;
public NurseController() {
cache = new ArrayList<>();
int i = 5000;
while (i-- > 0) {
NurseDto n = new NurseDto();
n.setId("123");
n.setInternalId("234234");
n.setName("asdfasfasoinasdf");
n.setType("NURSE");
cache.add(n);
}
}
@GetMapping
public ResponseEntity<List<NurseDto>> findAllNurses() {
return ResponseEntity.ok(cache);
}
}
and I call this controller from 20 threads without any pause. After couple minutes application fail with memory leak exception. In same time, I have this information from heap dump:
with this amount of objects:

Where 99% of hash map nodes refer to org.keycloak.representations.AccessToken.roles and 99% of string refer to privileges from access token. Previously, application work with
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>6.0.1</version>
</dependency>
but after I update it to 11.0.2 issue remain
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
<version>11.0.2</version>
</dependency>
Any thoughts why it happen? Is it desired behavior, and I should set something like a "cache" limit?
Here is my security config, may be it can help:
@KeycloakConfiguration
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Profile("!test")
public class WebSecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configure(AuthenticationManagerBuilder auth) {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
@Bean
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
return new KeycloakSpringBootConfigResolver();
}
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new NullAuthenticatedSessionStrategy();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
super.configure(http);
http.authorizeRequests().anyRequest().permitAll().and().cors().and().csrf().disable();
}
@Bean
public CorsFilter corsFilter() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.setAllowedOrigins(Collections.singletonList("*"));
config.setAllowedHeaders(Collections.singletonList("*"));
config.setAllowedMethods(
Arrays.stream(HttpMethod.values()).map(HttpMethod::name).collect(Collectors.toList()));
source.registerCorsConfiguration("/**", config);
return new CorsFilter(source);
}
}