1

I have a spring boot application which runs fine via Maven's mvn spring-boot:run command. However, when I try to run it through the IDE, which is Intellij IDEA 2017.2.1 in my case, it fails because it could not @Autowire a data source.

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.myApp.Application required a bean of type 'javax.sql.DataSource' that could not be found.


Action:

Consider defining a bean of type 'javax.sql.DataSource' in your configuration.

The original authors of this code base have the main class, which starts the application, accepting constructor arguments for the data source, an approach I am unfamiliar with as I am used to just doing it through the application.properties file and letting Spring Boot wire up it's own DataSource.

@EnableTransactionManagement
@SpringBootApplication
@EnableCaching
public class Application extends JpaBaseConfiguration {


    protected Application(DataSource dataSource, JpaProperties properties,
            ObjectProvider<JtaTransactionManager> jtaTransactionManagerProvider,
            ObjectProvider<TransactionManagerCustomizers> transactionManagerCustomizers) {
        super(dataSource, properties, jtaTransactionManagerProvider, transactionManagerCustomizers);
    }

In IDEA, I've noticed that the datasource and the properties arguments to this constructor are underlined in red. For datasource the IDE is complaining that two beans exist and it doesn't know which to autowire between XADataSourceAutoConfiguration.class and DataSourceConfiguration.class. As for the other argument to the construction which is underlined in red, properties, it can't find any beans, the IDE complains that no bean of type JpaProperties is found. Here are some other methods which are overridden in the main application starter class,

        @Override
        protected AbstractJpaVendorAdapter createJpaVendorAdapter() {
            return new HibernateJpaVendorAdapter();
        }


        @Override
        protected Map<String, Object> getVendorProperties() {
            Map<String, Object> vendorProperties = new LinkedHashMap<>();
            vendorProperties.putAll(getProperties().getHibernateProperties(getDataSource()));
            return vendorProperties;
        }


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


}

Unfortunately, because I am not familiar with this approach of using the constructor to configure/auto-configure the application in Spring Boot, I am unsure of a few things, but my exact question is why does the application run fine with Maven but not in Intellij IDEA? Moreover, since I don't have access to the original authors to this proprietary code base, I'd love to know why, if anyone can even give me a hint, they have configured the constructor as such as opposed to default autoconfiguration. I also have an integration test which I wrote that I am trying to run but this test, whether run through the IDE or via Maven's failsafe plugin also results in the same error with the DataSource not being @Autowired. So this is another question as to why this test won't run through Maven when the main application will. Here's my integration test,

@RunWith(SpringJUnit4ClassRunner.class)
@WebMvcTest(value = TransactionController.class, secure = false)
public class TransactionControllerIT {

    @Autowired
    MockMvc mockMvc;

    @Test
    public void shouldInitiateTransfer() {

        String transferTransaction =
              "some json string I can't show here on stack overflow";

        RequestBuilder requestBuilder = MockMvcRequestBuilders
                .post("/begin-transfer")
                .accept(MediaType.APPLICATION_JSON).content(transferTransaction)
                .contentType(MediaType.APPLICATION_JSON);

        MvcResult result = null;

        try {
            result = mockMvc.perform(requestBuilder).andReturn();
        } catch (Exception e) {
            fail("Exception in integration test!");
        }

        MockHttpServletResponse response = result.getResponse();

        assertEquals(HttpStatus.CREATED.value(), response.getStatus());

    }
}

Thank you for reading my question.

Anonymous Human
  • 1,858
  • 1
  • 21
  • 47

2 Answers2

6

You can easily run any Spring Boot app from IDEA doing the following:

enter image description here

In Maven panel, go to Plugins, unfold spring-boot and right-click on "spring-boot:run". Then click on "Create your-project..." as shown in the image.

This way you can just start the application in a comfortable way from IDEA from the main toolbar:

enter image description here

This way you are still using the maven way, but integrated in IDEA. I don't really know why are you having those problems. I also experience some problems when trying to execute the spring boot app directly.

spekdrum
  • 1,559
  • 2
  • 11
  • 15
  • 2
    I have actually resorted to doing just that, I've created a Maven run configuration in IDEA because IDEA wouldn't run the application natively. I'd still love to know why it won't run in IDEA though. – Anonymous Human Aug 17 '17 at 14:38
1

Your test is failing because it's using a slice test, @WebMvcTest these tests (@DataJpaTest, JsonTest) only loads a small part of the overall application context rather than everything that the application does on startup or a (@SpringBootTest) would.

When using a slice test it will use any annotations, and require any beans, defined within the @SpringBootApplication class.

E.g. because you have autowired beans defined and and two additional annotations for any slice test caching and transaction management will be enabled and it will always require these dependencies passed.

I would not make your main application class extend a configuration class in this way, it's overly complex and smells like XY problem. You should externalize configurations (and Enable annotations) to their own @Configuration class and leave the @SpringBootApplication as vanilla a possible to avoid these sort of errors.

Darren Forsythe
  • 10,712
  • 4
  • 43
  • 54
  • Thanks for the informative response. Would you be able to show me what annotations would make my integration test work? I tried SpringBootTest but now the autowired MockMvc is null. Also, given the current configuration, can you advise as to what I could do to get the project to run in the IDE? – Anonymous Human Aug 17 '17 at 16:14
  • Unsure about the IDE issue. You should be able to use a combination of `@SpringBootTest(webEnvironment=MOCK)` and `@AutoConfigureMockMvc`. There is also a fallback that you could use and use a `MockMvcBuilder` and create it yourself via passing controllers or the web application context. https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/web/servlet/setup/MockMvcBuilders.html – Darren Forsythe Aug 17 '17 at 16:45