0

I'm currently using JDBC Templates to fetch data from a database. For this, I've created a "static" Repository class (i.e. a class marked "final" and with a single private constructor). In it, I'm trying to set the values of two private static PlatformTransactionManager class variables.

However, my IntelliJ tells me that the value of the class variables are always null and I have no idea how to solve this issue.

I was hoping on just using them as local variables in the static constructor, since what I really want are the JdbcTemplate constants that I'll prepare using the PTMs. Since, I don't know how to do that, I tried making them into private static final fields. But IntelliJ didn't allow that either.

To try to solve this, I have looked at these threads:

. . . as well as this note on Qualifiers:

Important Notes:

  • The project I'm working on does not have XML configuration files. There are [*]Config files in the project that handle the configurations.
  • One more thing to note is that I don't quite understand annotations in general (be they in Java, C#, etc.). That is, I know the basic idea behind them, but I have no idea how they really work . . . and I don't remember much of the Spring framework anymore (since I've been working on Core Java and C#.NET for quite some time now). So . . . I'd appreciate any help to solve this issue.

The following is a sample of what my source code looks like:

private final class Repository {

  private Repository() {}

  private static final JdbcTemplate TEMPLATE1;
  private static final JdbcTemplate TEMPLATE2;

  @Qualifier( "transactionManager1" )
  private static PlatformTransactionManager manager1;

  @Qualifier( "transactionManager2" )
  private static PlatformTransactionManager manager2;

  static {
    // NOTE: For this one, IntelliJ shows me an error stating, "Value 'manager1'
    // is always 'null'."
    DataSource source =
      ( ( JpaTransactionManager ) manager1 ).getDataSource();

    TEMPLATE1 = new JdbcTemplate( source );

    // NOTE: Here, there is no error ... at least, IntelliJ isn't showing any.
    source = ( ( JpaTransactionManager ) manager2 ).getDataSource();

    TEMPLATE2 = new JdbcTemplate( source );
  }

  public Map<String, Object> fetchData() {
    return TEMPLATE1.queryForList( "..." ); // TODO: something
  }

}
  • You have to use `@Autowired` to inject `PlatformTransactionManager` ,but it does not work on the static fields . So do your requirement is that you must use static field for the `PlatformTransactionManager`? If not , I suggest you to consider changing it to use non-static field for the dependencies which normally are regards as a much better practise than using static field ...... – Ken Chan Jan 01 '19 at 15:20

1 Answers1

0

You can implement ApplicationContextAware interface to get context object and using this context object you can get the bean even in static context.

public class ApplicationBeansProvider implments ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext)
            throws BeansException {
        this.applicationContext = applicationContext;
    }

    public static Object getBean(String beanName) {
        return applicationContext.getBean(beanName);
    }
}

and then in your code you can do something like

private final class Repository {

  private Repository() {}

  private static final JdbcTemplate TEMPLATE;

  private static PlatformTransactionManager manager = ApplicationBeansProvider.getBean("transactionManager");


  static {
    DataSource source =
      ( ( JpaTransactionManager ) manager ).getDataSource();

    TEMPLATE = new JdbcTemplate( source );

  }

  public Map<String, Object> fetchData() {
    return TEMPLATE1.queryForList( "..." ); // TODO: something
  }

}
Yogesh Badke
  • 4,249
  • 2
  • 15
  • 23