SqlInvalidAuthorizationSpecException printed even when caught

36 views Asked by At

I have Spring Application which connects to a lot of DBs, at startup I m trying to check for valid credentials since they will be quite often changed in future I want the application to stop and display reasonable message in logs without spamming useless exception stack-trace. I m using multiple DataSources:

@Configuration
public class DBConfig {
 @Bean
  @ConfigurationProperties(prefix = "db.foo.datasource")
  public DataSource DB2Foo() {
    return DataSourceBuilder
        .create()
        .build();
  }

 @Bean
  public AbstractClientService fooDB(@Qualifier("DB2Foo") DataSource dataSource){
    return new AbstractClientService(dataSource, "DB2Foo");
  }

 @Bean
  @ConfigurationProperties(prefix = "db.bar.datasource")
  public DataSource DB2Bar() {
    return DataSourceBuilder
        .create()
        .build();
  }

@Bean
  public AbstractClientService barDB(@Qualifier("DB2Bar") DataSource dataSource){
    return new AbstractClientService(dataSource, "DB2Bar");
  }
}

Then in AbstractClientService I m trying to verify connection during initialization in constructor since it seems to be the easiest option in my case and does not require adding more logic after startup.

@Service
public class AbstractClientService implements ApplicationContextAware {

  private ApplicationContext context;
  private static final Logger LOGGER = LogManager.getLogger(AbstractClientService.class);
  private final JdbcTemplate jdbcTemplate;

  public AbstractClientService(DataSource dataSource, String... name) {
    try {
      dataSource.getConnection();
    }catch (SqlInvalidAuthorizationSpecException e){
      LOGGER.error("Invalid credentials for DB:" + Arrays.toString(name));
      System.exit(1);
    }catch (SQLException e) {
      LOGGER.error("Exception occurred during :" + Arrays.toString(name) + " initialization");
      System.exit(1);
    }
    this.jdbcTemplate = new JdbcTemplate(dataSource);
  }

Based on the domain it does not make sense to continue even if 1 DB has invalid creds. So after that I want to terminate the APP. I tried using ApplicationContext but it was always null when trying with @Autowired, and dependency injection would add more ugly code since I would need to add it everywhere in DBConfig. So I used System.exit with spring.main.register-shutdown-hook:false

This solution look good to me but even though SqlInvalidAuthorizationSpecException is caught its still dumps the stack-trace in logs.

Is it possible to somehow globally catch that exception and remove stack-trace ? or prevent Spring from Logging it ? Maybe turn off logging before and turn it back on after ? Thanks

Logs until line with my class:

com.ibm.db2.jcc.am.SqlInvalidAuthorizationSpecException: [jcc][t4][2013][11249][4.32.28] Connection authorization failure occurred.  Reason: User ID or Password invalid. ERRORCODE=-4214, SQLSTATE=28000
    at com.ibm.db2.jcc.am.b7.a(b7.java:808) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.am.b7.a(b7.java:66) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.am.b7.a(b7.java:133) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.f(b.java:2683) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.b(b.java:2011) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.z.r(z.java:961) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.z.k(z.java:494) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.z.c(z.java:144) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.k(b.java:1520) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.b(b.java:1433) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.a(b.java:6862) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.b(b.java:949) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.a(b.java:862) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.a(b.java:457) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.a(b.java:430) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.t4.b.<init>(b.java:368) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.DB2SimpleDataSource.getConnection(DB2SimpleDataSource.java:243) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.DB2SimpleDataSource.getConnection(DB2SimpleDataSource.java:200) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.DB2Driver.connect(DB2Driver.java:491) ~[jcc-11.5.8.0.jar:na]
    at com.ibm.db2.jcc.DB2Driver.connect(DB2Driver.java:117) ~[jcc-11.5.8.0.jar:na]
    at com.zaxxer.hikari.util.DriverDataSource.getConnection(DriverDataSource.java:138) ~[HikariCP-5.0.1.jar:na]
    at com.zaxxer.hikari.pool.PoolBase.newConnection(PoolBase.java:359) ~[HikariCP-5.0.1.jar:na]
    at com.zaxxer.hikari.pool.PoolBase.newPoolEntry(PoolBase.java:201) ~[HikariCP-5.0.1.jar:na]
    at com.zaxxer.hikari.pool.HikariPool.createPoolEntry(HikariPool.java:470) ~[HikariCP-5.0.1.jar:na]
    at com.zaxxer.hikari.pool.HikariPool.checkFailFast(HikariPool.java:561) ~[HikariCP-5.0.1.jar:na]
    at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:100) ~[HikariCP-5.0.1.jar:na]
    at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:112) ~[HikariCP-5.0.1.jar:na]
    at foo.AbstractClientService.<init>(AbstractClientService.java:33) ~[classes/:na]

I searched all web for 3-4 hours, this is first time I had to result into asking Q here.

0

There are 0 answers