Home > OS >  FileNotFoundException while dockerized application start
FileNotFoundException while dockerized application start

Time:11-18

I have a problem with dockerized Spring Boot application, namely, while start-up of the application I am receiving:

api-gateway_1  | Caused by: org.springframework.boot.web.server.WebServerException: Unable to start embedded Tomcat
api-gateway_1  |        at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:142) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.<init>(TomcatWebServer.java:104) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getTomcatWebServer(TomcatServletWebServerFactory.java:450) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory.getWebServer(TomcatServletWebServerFactory.java:199) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.createWebServer(ServletWebServerApplicationContext.java:182) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.onRefresh(ServletWebServerApplicationContext.java:160) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        ... 16 common frames omitted
api-gateway_1  | Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'whitelistingFilter' defined in URL [jar:file:/app.jar!/BOOT-INF/classes!/com/fitnessgo/apigateway/intrastructure/security/cognito/security/filter/WhitelistingFilter.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisConfiguration' defined in URL [jar:file:/app.jar!/BOOT-INF/classes!/com/fitnessgo/apigateway/intrastructure/cache/RedisConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.fitnessgo.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$dc73223a]: Constructor threw exception; nested exception is java.io.FileNotFoundException
api-gateway_1  |        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:800) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:229) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1354) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1204) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:213) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.getOrderedBeansOfType(ServletContextInitializerBeans.java:212) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:175) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAsRegistrationBean(ServletContextInitializerBeans.java:170) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.addAdaptableBeans(ServletContextInitializerBeans.java:155) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.servlet.ServletContextInitializerBeans.<init>(ServletContextInitializerBeans.java:87) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.getServletContextInitializerBeans(ServletWebServerApplicationContext.java:260) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.selfInitialize(ServletWebServerApplicationContext.java:234) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.springframework.boot.web.embedded.tomcat.TomcatStarter.onStartup(TomcatStarter.java:53) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5219) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
api-gateway_1  |        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140) ~[na:na]
api-gateway_1  |        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:919) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.core.StandardHost.startInternal(StandardHost.java:835) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1396) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1386) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
api-gateway_1  |        at org.apache.tomcat.util.threads.InlineExecutorService.execute(InlineExecutorService.java:75) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at java.base/java.util.concurrent.AbstractExecutorService.submit(AbstractExecutorService.java:140) ~[na:na]
api-gateway_1  |        at org.apache.catalina.core.ContainerBase.startInternal(ContainerBase.java:919) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.core.StandardEngine.startInternal(StandardEngine.java:263) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.core.StandardService.startInternal(StandardService.java:432) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:927) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.apache.catalina.startup.Tomcat.start(Tomcat.java:486) ~[tomcat-embed-core-9.0.52.jar!/:na]
api-gateway_1  |        at org.springframework.boot.web.embedded.tomcat.TomcatWebServer.initialize(TomcatWebServer.java:123) ~[spring-boot-2.5.4.jar!/:2.5.4]
api-gateway_1  |        ... 21 common frames omitted
api-gateway_1  | Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'redisConfiguration' defined in URL [jar:file:/app.jar!/BOOT-INF/classes!/com/fitnessgo/apigateway/intrastructure/cache/RedisConfiguration.class]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.fitnessgo.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$dc73223a]: Constructor threw exception; nested exception is java.io.FileNotFoundException
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1316) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:410) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1334) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1177) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:564) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:524) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1380) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1300) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:887) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:791) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        ... 62 common frames omitted
api-gateway_1  | Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.fitnessgo.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$dc73223a]: Constructor threw exception; nested exception is java.io.FileNotFoundException
api-gateway_1  |        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:221) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1308) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        ... 83 common frames omitted
api-gateway_1  | Caused by: java.io.FileNotFoundException: null
api-gateway_1  |        at com.fitnessgo.apigateway.intrastructure.security.cognito.ConfigurationReader.readConfigurationFile(ConfigurationReader.java:33) ~[classes!/:0.0.1-SNAPSHOT]
api-gateway_1  |        at com.fitnessgo.apigateway.intrastructure.cache.RedisConfiguration.<init>(RedisConfiguration.java:28) ~[classes!/:0.0.1-SNAPSHOT]
api-gateway_1  |        at com.fitnessgo.apigateway.intrastructure.cache.RedisConfiguration$$EnhancerBySpringCGLIB$$dc73223a.<init>(<generated>) ~[classes!/:0.0.1-SNAPSHOT]
api-gateway_1  |        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:na]
api-gateway_1  |        at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:64) ~[na:na]
api-gateway_1  |        at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:na]
api-gateway_1  |        at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500) ~[na:na]
api-gateway_1  |        at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481) ~[na:na]
api-gateway_1  |        at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:208) ~[spring-beans-5.3.9.jar!/:5.3.9]
api-gateway_1  |        ... 85 common frames omitted

My docker file looks like:

FROM openjdk:15

EXPOSE 8080

ADD ./target/app.jar app.jar

ENTRYPOINT ["java", "-jar", "app.jar"]

docker-compose.yml looks like:

version: '3.7'
services:

  api-gateway:
    image: 'api-gateway:1.0'
    build:
      context: ./api-gateway
      dockerfile: Dockerfile
    restart: always
    ports:
      - '8080:8080'
    networks:
      - app-network
      
networks:
  app-network: null
volumes:
  app-volume: {}

problematic RedisConfiguration and Whitelisting classes look like:

import java.time.Duration;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.jedis.JedisClientConfiguration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
@PropertySource("classpath:redis.properties")
@Slf4j
public class RedisConfiguration {

  private static final String REDIS_PROPERTIES = "redis.properties";
  private final Properties redisProperties = readConfigurationFile(REDIS_PROPERTIES);

  @Value("${redis.host}")
  private String host;

  @Value("${redis.port}")
  private int port;

  @Value("${redis.password}")
  private String password;

  @Value("${redis.timeout}")
  private String timeout;

  @Bean(name = "jedisConnectionFactory")
  JedisConnectionFactory jedisConnectionFactory() {
    return new JedisConnectionFactory();
  }

  @Bean(name = "redisTemplate")
  public RedisTemplate<String, Object> redisTemplate(
      @Qualifier(value = "jedisConnectionFactory") RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(stringRedisSerializer());
    template.setValueSerializer(stringRedisSerializer());
    return template;
  }

  @Bean(name = "redisUserConnectionFactory")
  public JedisConnectionFactory redisUserConnectionFactory() {
    RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();
    String userDb = getProperty(redisProperties, RedisDb.USER_DB);

    setRedisProperties(redisConfiguration, userDb);

    JedisClientConfiguration jedisClientConfiguration =
        JedisClientConfiguration.builder()
            .connectTimeout(Duration.ofMillis(Long.parseLong(timeout)))
            .build();
    logRedisConnectionDetails(redisConfiguration);

    return new JedisConnectionFactory(redisConfiguration, jedisClientConfiguration);
  }

  @Bean(name = "userRedisTemplate")
  public RedisTemplate<String, Object> userRedisTemplate(
      @Qualifier(value = "redisUserConnectionFactory")
          RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(stringRedisSerializer());
    template.setValueSerializer(stringRedisSerializer());
    return template;
  }

  @Bean(name = "redisRegistrationTokenConnectionFactory")
  public JedisConnectionFactory redisRegistrationTokenConnectionFactory() {
    RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();

    String registrationTokenDb = getProperty(redisProperties, RedisDb.REGISTRATION_TOKEN_DB);
    setRedisProperties(redisConfiguration, registrationTokenDb);

    JedisClientConfiguration jedisClientConfiguration =
        JedisClientConfiguration.builder()
            .connectTimeout(Duration.ofMillis(Long.parseLong(timeout)))
            .build();
    logRedisConnectionDetails(redisConfiguration);

    return new JedisConnectionFactory(redisConfiguration, jedisClientConfiguration);
  }

  @Bean(name = "registrationTokenRedisTemplate")
  public RedisTemplate<String, Object> registrationTokenRedisTemplate(
      @Qualifier(value = "redisRegistrationTokenConnectionFactory")
          RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(stringRedisSerializer());
    template.setValueSerializer(stringRedisSerializer());
    return template;
  }

  @Bean(name = "redisWhitelistingConnectionFactory")
  public JedisConnectionFactory redisWhitelistingConnectionFactory() {
    RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration();

    String whitelistingDb = getProperty(redisProperties, RedisDb.WHITELISTING_DB);
    setRedisProperties(redisConfiguration, whitelistingDb);

    JedisClientConfiguration jedisClientConfiguration =
        JedisClientConfiguration.builder()
            .connectTimeout(Duration.ofMillis(Long.parseLong(timeout)))
            .build();
    logRedisConnectionDetails(redisConfiguration);

    return new JedisConnectionFactory(redisConfiguration, jedisClientConfiguration);
  }

  @Bean(name = "whitelistingRedisTemplate")
  public RedisTemplate<String, Object> whitelistingRedisTemplate(
      @Qualifier(value = "redisWhitelistingConnectionFactory")
          RedisConnectionFactory redisConnectionFactory) {
    RedisTemplate<String, Object> template = new RedisTemplate<>();
    template.setConnectionFactory(redisConnectionFactory);
    template.setKeySerializer(stringRedisSerializer());
    template.setValueSerializer(stringRedisSerializer());
    return template;
  }

  @Bean(name = "stringRedisSerializer")
  public StringRedisSerializer stringRedisSerializer() {
    return new StringRedisSerializer();
  }

  private void setRedisProperties(RedisStandaloneConfiguration redisConfiguration, String redisDb) {
    redisConfiguration.setHostName(host);
    redisConfiguration.setPort(port);
    redisConfiguration.setDatabase(Integer.parseInt(redisDb));
    redisConfiguration.setPassword(RedisPassword.of(password));
  }

  private void logRedisConnectionDetails(RedisStandaloneConfiguration redisConfiguration) {
    log.info(
        "Connected to Redis host: {}, port: {}, database: {}",
        redisConfiguration.getHostName(),
        redisConfiguration.getPort(),
        redisConfiguration.getDatabase());
  }
}
import java.util.Optional;
import java.util.Properties;
import java.util.stream.Stream;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.filter.OncePerRequestFilter;

@Component
@Slf4j
public class WhitelistingFilter extends OncePerRequestFilter {

  private static final String SECURITY_PROPERTIES = "security.properties";
  private final Properties securityProperties = readConfigurationFile(SECURITY_PROPERTIES);
  private final String whitelistingEnabled = securityProperties.getProperty("whitelisting.enabled", FALSE.toString());

  private final RedisTemplate<String, Object> whitelistingRedisTemplate;
  private final AwsCognitoIdTokenProcessor awsCognitoIdTokenProcessor;

  public WhitelistingFilter(
      @Qualifier("whitelistingRedisTemplate")
          RedisTemplate<String, Object> whitelistingRedisTemplate,
      AwsCognitoIdTokenProcessor awsCognitoIdTokenProcessor) {
    this.whitelistingRedisTemplate = whitelistingRedisTemplate;
    this.awsCognitoIdTokenProcessor = awsCognitoIdTokenProcessor;
  }

  @Override
  protected boolean shouldNotFilter(@NonNull HttpServletRequest request) {
    AntPathMatcher pathMatcher = new AntPathMatcher();
    return Stream.of(USER_LOGIN_URL, ADMIN_LOGIN_URL, SIGNUP_BY_ADMIN_URL, SIGNUP_URL, LOGOUT_URL)
            .anyMatch(p -> pathMatcher.match(p, request.getServletPath())) || whitelistingDisabled();
  }

  private boolean whitelistingDisabled() {
    return FALSE.toString().equalsIgnoreCase(whitelistingEnabled);
  }

  @Override
  protected void doFilterInternal(@NonNull HttpServletRequest httpServletRequest, @NonNull HttpServletResponse httpServletResponse, @NonNull FilterChain filterChain) {
    try {
      Authentication authentication = awsCognitoIdTokenProcessor.getAuthentication(httpServletRequest);
      Optional<String> username = Optional.ofNullable(authentication.getName());
      if (username.isPresent() && usernameWhitelisted(username.get())) {
        log.info("User with username: {} is present in whitelisting", username.get());
        filterChain.doFilter(httpServletRequest, httpServletResponse);
      } else {
        httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        log.error("Username: {} not whitelisted or empty", username.orElse(""));
      }

    } catch (Exception e) {
      logger.error("Error occurred while checking user in redis whitelisting", e);
      SecurityContextHolder.clearContext();
    }
  }

  private boolean usernameWhitelisted(String username) {
    return Boolean.TRUE.equals(whitelistingRedisTemplate.hasKey(WHITELISTING_PREFIX   username));
  }
}

Below resources structure:

resources

From my point of view, it seems that the docker image doesn't contain mandatory properties files from the resource folder. Additionally, locally application starts without any effort. I will be grateful for suggestions on what I am doing wrong while dockerization of the Spring Boot application or how I can add entire resources file to the container.

EDIT:

ConfigurationReader class:

@Slf4j
public class ConfigurationReader {

  private ConfigurationReader() {}

  private static final String DEFAULT_PROPERTY_VALUE = "";

  @SneakyThrows
  public static Properties readConfigurationFile(String... relativeConfigurationFile) {
    String path = resolveToAbsolutePath(relativeConfigurationFile);
    Path resources = Paths.get(".", "src", "main", "resources", path).normalize().toAbsolutePath();
    try (InputStream fileAsStream = getConfigurationFileAsStream(resources.toString())) {
      Properties properties = new Properties();
      properties.load(fileAsStream);
      return properties;
    } catch (Exception e) {
      log.error("[configurationReader] Cannot read configuration file {}", path);
      throw new FileNotFoundException();
    }
  }

  public static String getProperty(Properties propertyFile, String propertyName) {
    return propertyFile.getProperty(propertyName, DEFAULT_PROPERTY_VALUE);
  }

  private static InputStream getConfigurationFileAsStream(String path) throws IOException {
    Path configurationFilePath = FileSystems.getDefault().getPath(path);
    return Files.newInputStream(configurationFilePath, StandardOpenOption.READ);
  }

  private static String resolveToAbsolutePath(String... relativeConfigurationPath) {
    return String.join(FileSystems.getDefault().getSeparator(), relativeConfigurationPath);
  }
}

CodePudding user response:

You are trying to load the file src/main/resources/redis.properties. This file only exists when you application's source code is available and the working directory is the root of the source tree. You'll see the same failure outside of Docker if you run the jar file without the source available.

Rather than loading the file from the file system, you should load it from the classpath. Any file in src/main/resources will be available from the root of the classpath. You could load redis.properties using the InputStream returned from ConfigurationReader.class.getClassLoader().getResourceAsStream("redis.properties"). Alternatively, as you're using Spring Boot, you might want to use Spring Framework's ClasspathResource instead.

  • Related