0

In my Spring Boot Application, I implemented the following class with a method to call a stored procedure.

@Component
@ConfigurationProperties(prefix = "spring")
public class FmTrfUtil {
    static int returnVal;
    @Value("${spring.datasource.url}")
    static String url;

    public static int insertFmTrfs(List<String> trfs, String source) {
        System.out.println(url);
        EntityManager em = Persistence.createEntityManagerFactory("RIStore_FM").createEntityManager();
        Session session = em.unwrap( Session.class );
        final String[] trfArray = trfs.toArray(new String[trfs.size()]);
        final String src = source;

        session.doWork( new Work(){
            public void execute(Connection conn) throws SQLException {
                CallableStatement stmt = null;               
                OracleConnection oraCon = conn.unwrap(OracleConnection.class);
                Array array = oraCon.createARRAY("VARCHAR2_TAB_T", trfArray);
                stmt = conn.prepareCall("{? = call FM_TRF_UTIL.process_fm_trf(?,?)}");
                stmt.registerOutParameter(1, Types.INTEGER);
                stmt.setArray(2, array);
                stmt.setString(3, src);
                stmt.execute();
                returnVal = stmt.getInt(1);
            }
        });
        return returnVal;
    }
}

Since calling stored procedure requires database connection, I need to load the these corresponding property values from application.properties:

spring.profiles.active=dev
spring.datasource.url=jdbc:oracle:thin:@ldap://xxx:389/risdev3, cn=OracleContext,dc=x,dc=net
spring.datasource.username=owner
spring.datasource.password=owner987

Based on the following articles about similar issue, Spring boot - custom variables in Application.properties and Using Spring-Boot configuration properties in your own classes and Spring Boot @ConfigurationProperties example, I added this annotation for my class @ConfigurationProperties(prefix = "spring") (properties for db connection all have "spring" as prefix). However when I run it with a test class as follows, I got error "the application must supply JDBC connection" which means properties in application.properties are not picked up.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = RistoreWebApplication.class, initializers = ConfigFileApplicationContextInitializer.class)
public class FmTrfUtilTest {
    @Test
    public void test() {
        List<String> trfs = new ArrayList<String>();
        trfs.add("TRF000001");
        trfs.add("TRF000002");
        int ret = FmTrfUtil.insertFmTrfs(trfs, "SARC");
        assertTrue(ret > 0);
    }
}

In order for @ConfigurationProperties to work, I added maven dependency spring-boot-configuration-processor too. Why is it still not working? What did I miss?

Community
  • 1
  • 1
ddd
  • 4,665
  • 14
  • 69
  • 125

1 Answers1

1

There are few things wrong here:

  • @Value does not work on static fields
  • @ConfigurationProperties are used to bind fields from application.properties or application.yml to Java object. Look at any @ConfigurationProperties annotated class from Spring Boot itself to easily understand how it should be used.
  • you should not use your own @ConfigurationProperties with prefix spring since it's already used by Spring Boot itself
  • spring-boot-configuration-processor is used only for nicer code completion in your IDE. You do not need this.

If you want to utilize Spring Boot configuration properties for database connection, instead of creating EntityManager like you do:

EntityManager em = Persistence.createEntityManagerFactory("RIStore_FM").createEntityManager();

You should just inject it assuming you have Spring Data JPA Starter in your dependency list.

I see you use lots of static methods and fields. That's not going to work with Spring. Use dependency injection instead and autowire what you need.

Maciej Walkowiak
  • 12,372
  • 59
  • 63
  • How exactly should I inject em? I tried to inject `EntityManager` with `@PersistenceContext(unitName = "RIStore_FM")` `static EntityManager em;` just above the method, but got `Persistence annotations are not supported on static fields` error. If I take out the `static`, it will not compile saying em in the method must be declared static – ddd Nov 04 '16 at 21:15
  • Neither method nor field should be static. Look at Spring Data sample projects and reference. Using JPA with Spring is really simple if you do it Spring way. – Maciej Walkowiak Nov 04 '16 at 21:16