0

I am using latest version of IntelliJIDEA CE edition (11.0.4). There is one thing that I could not find anywhere, and it is a blocker for my further improvements with Java/Spring.

Controller:

import com.example.demo.classes.SaveToFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class MainController {
    @Autowired protected SaveToFile saveToFile;
    //@Autowired SaveToDb saveToDb;

    @RequestMapping("/start")
    public String whatever(@RequestParam(value="name", defaultValue="World") String name) {
         saveToFile.save(name);
         return "something";
        //return new SaveToFile(name);
    }
}

Class: import com.example.demo.interfaces.ISave;

public class SaveToFile implements ISave {

    private String filename = "Vlad";   

    @Override
    public void save(String name) {
        System.out.println("Saving " + name + " to file.");
    }

    public String getFilename(){
        return filename;
    }
}

Class Interface:

public interface ISave {
    void save(String name);
}

Nothing fancy, just to get a grasp of Spring and Java.

Inside my Controller, when I try to use

@Autowired protected SaveToFile saveToFile;

I get an error that prevents app from starting. Here is the error:

Execution failed for task ':DemoApplication.main()'.

Process 'command '/Library/Java/JavaVirtualMachines/openjdk-11.0.2.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1

If I comment that out, I can instantiate my class with "new", but thats not the point.

I have tried changing SDK's in the Project Structure menu option. but to no avail. Maybe worth to point out, that similar project I also work on in Kotlin, has no issues at all. I tried to Mimick the "Kotlin" settings, but nothing.

Does anyone have any clue as to what is going on in here?

Amiga500
  • 5,874
  • 10
  • 64
  • 117
  • Do you declare `SaveToFile` as a bean somewhere? Otherwise it won't be picked up by Spring. – Michael Nov 29 '19 at 14:44
  • 1
    Your SaveToFile is not spring managed bean. It should be annotated as `@Component` or `@Service`. Or instantiated another way: Java DSL bean definition, xml configuration etc. And second: you are injecting an exact implementation rather than abstract contract, defined in `ISave`. You should inject/autowire an instance of `ISave` bean. – Ilya Dyoshin Nov 29 '19 at 14:44

3 Answers3

2

You should either annotate the SaveToFile class with @Component, or create a bean of that type (annotated @Bean) in any config class for the @Autowired to work.

Stan Ostrovskii
  • 528
  • 5
  • 19
1

First, make SaveToFile a Spring-managed bean:

@Component
public class SaveToFile implements ISave {
   // [...]    
}

Second, autowire the bean:

@RestController
public class MainController {

   @Autowired protected ISave saveToFile;

   // [...]
}
Michael
  • 1,044
  • 5
  • 9
  • In my question I have saveToDB, which also implements ISave. How can I distinguish them inside the controller? If I autowire via ISave, then how can I select what bean? – Amiga500 Nov 29 '19 at 14:56
  • 1
    @VedranMaricevic. In that case you can simply use the specific type instead of the generic one. Like `@Autowired protected SaveToFile saveToFile`. :) – Michael Nov 29 '19 at 14:58
1

Spring needs to pick that one up as a component, otherwise it doesn't really know where to Autowire it from.

Try annotating it with a @Service and make the class itself is within Component Scanner's reach.