0

I have a spring boot REST service with the following structure:

├── src
│   ├── main
│   │   ├── java
│   │   │   ├── daos
│   │   │   ├── db
│   │   │   │   └── DBConnector.java
│   │   │   ├── serviceComponents
│   │   │   │   └── serviceResources
│   │   │   │       ├── Application.java
│   │   │   │       ├── UserController.java
│   │   │   │       └── UserDAO.java
│   │   │   └── serviceRepresentations
│   │   │       └── User.java
│   │   └── resources
│   │       └── application.properties

The main files related to this question are:

Application.java:

package serviceComponents.serviceResources;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.ErrorMvcAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;

@SpringBootApplication(exclude = {ErrorMvcAutoConfiguration.class})
@ComponentScan
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

DBConnector.java:

package db;

import java.sql.Connection;
import java.sql.SQLException;

import oracle.jdbc.pool.OracleDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;


@Component
public class DBConnector {
    @Value("${current.app.url}")
    String dbUrl;

    @Value("${current.app.sid}")
    String dbSid;

    @Value("${current.app.port}")
    String dbPort;

    @Value("${current.app.user}")
    String dbUser;

    @Value("${current.app.password}")
    String dbPassword;

    String jdbcUrl = String.format("jdbc:oracle:thin:@%s:%s:%s", dbUrl, dbPort, dbSid);
    Connection conn;

    int count = 0;

    public DBConnector() {}

    @PostConstruct
    private void init() {

        try {
            Class.forName("oracle.jdbc.OracleDriver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        OracleDataSource ds = null;

        try {
            ds = new OracleDataSource();
        } catch (SQLException e) {
            e.printStackTrace();
        }

        ds.setURL(jdbcUrl);

        try {
            conn = ds.getConnection(dbUser, dbPassword);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public Connection getDBConnection() throws SQLException {
        if (count == 0) {
            init();
            count++;
        }

        return conn;
    }
}

And the properties file:

server.port = 8089

test.app.url = 127.0.0.1
test.app.sid = XE
test.app.port = 1521
test.app.user = foouser
test.app.password = barbazpass

current.app.url = test.app.url
current.app.sid = test.app.sid
current.app.port = test.app.port
current.app.user = test.app.user
current.app.password = test.app.password

And there is the relevant piece of code from the controller:

@RestController
@RequestMapping("/v1/user/")
public class UserController {

    DBConnector dbConnector = new DBConnector();
    UserDAO userDAO = new UserDAO(dbConnector);

However when I run the application, the fields from DBConnector.java annotated with @Value are not populated with the expected values from the configuration file. I know that spring boot detects application.properties as the default configuration file for a project. What am I doing wrong?

cristid9
  • 1,070
  • 1
  • 17
  • 37
  • How are you getting an instance of `DBConnector`? Given that its package is `db` and you're component scanning in `serviceComponents.serviceResources`, Spring won't know about it at all. – Andy Wilkinson May 26 '17 at 19:22
  • I have updated the question with a snippet from the controller. Basically I create an instance of the `DBConnector` in the controller. – cristid9 May 26 '17 at 19:22

1 Answers1

1

Perhaps try it with @Autowired:

@Autowired DBConnector dbConnector = new DBConnector();

I've tried replacing parts of my current Spring app with some of your annotations where we differ, but the only thing that caused a problem that I've yet found (a NullPointerException, though, so perhaps not the same issue as you are experiencing) was when I removed the @Autowired annotation in my controller.

EDIT: I didn't notice at first, but my NPE is obviously caused because I'm just autowiring a reference, not instantiating. For you, the equivalent would be:

@Autowired DBConnector dbConnector;

EDIT 2: My application isn't instantiating exactly like yours, so this may not work, but I have a class like this:

@SpringBootApplication
public class ParameterClassConfigurator
{
    @Value("${my.first.property}") String property1;
    @Value("${my.second.property}") String property2;

    @Bean
    public ParameterClass parameterClass()
    {
        ParameterClass params = new ParameterClass(property1, property2);
        return params;
    }
}

The key seems to be that @Bean annotation. Without it, my Spring boot app will not start, throwing org.springframework.beans.factory.UnsatisfiedDependencyException.

Dan N
  • 98
  • 1
  • 1
  • 6
  • It tells me: "Could not autowire. No beans of 'DBConnector' type found." – cristid9 May 26 '17 at 19:38
  • @cristid9 Edited my answer with "edit 2". Does this work for you? – Dan N May 26 '17 at 20:12
  • So `ParameterClass` is a container for the fields in `application.properties`? – cristid9 May 26 '17 at 20:14
  • That was just an ad-hoc example which may not be helpful. I think you can leave your DBConnector as it is, and just instantiate it in a configurator as my example without reading any properties. But based on this (https://stackoverflow.com/a/40861225/3850440), @Bean is more for when you can't annotate a third-party library, which is my situation, so it may not be useful in your situation. – Dan N May 26 '17 at 20:23