0

So I try to inject an interface implemention through a field. But can't figure it out why it's null.

Package
   com.a
         Interfacex
   com.b
         Interfaceximpl

Interfacex.java

public interface Interfacex {
  void doA ();
}

Interfaceximpl.java

@Component
public class Interfaceximpl implements interfacex { 
@Override
void doA(){
// do something
}
}

Main.java

public class Main {
@Autowired
Interfacex interfacex;

public static void main (String args[]){ //....}

}

This interfacex seems to be null.

@Configuration
@ComponentScan("com")
public class AppConfig { // nothing here}

There is no such setter injection in my case. I just inject the interfacex with @Autowired. Why is it null?.

Federico klez Culloca
  • 26,308
  • 17
  • 56
  • 95
  • Also how exactly do you "plug in" spring here? Can you show relevant parts of code from the main method (an application context creation, etc.) Otheriwse please see my answer – Mark Bramnik Jul 14 '22 at 10:54
  • @MarkBramnik, my classes are that pretty simple. Throught that *AppConfig* I assumed that *Interfacex* will know who's the implementor. – Plain_Dude_Sleeping_Alone Jul 14 '22 at 10:56
  • I've added an actual answer :) – Mark Bramnik Jul 14 '22 at 10:57
  • _Why is it null?_ How do you verify it's `null`? Please provide a [mcve]. – Sotirios Delimanolis Jul 14 '22 at 12:08
  • There is far too little information here to answer it. – M. Deinum Jul 14 '22 at 12:58
  • @SotiriosDelimanolis. My scenario is that simple. Nothing more (more or less). That *Interfacex* in my case can't directly be injected with the *Interfaceximpl* and hence the question. However it's solved already using the intuition I found on Mark Bramnik's answer. – Plain_Dude_Sleeping_Alone Jul 14 '22 at 13:12
  • This is still unclear. Are you instantiating Main and trying to access the instance’s field ? – Sotirios Delimanolis Jul 14 '22 at 13:19
  • @SotiriosDelimanolis I did wiring directly in the main method. Not a web. I had done this for some quick instances access/modification purposes. To test them manually. And I came with this simple scenario. Yes it looks funny btw. – Plain_Dude_Sleeping_Alone Jul 14 '22 at 13:36
  • I’m asking where are you doing `xyz.interfacex` and seeing null. – Sotirios Delimanolis Jul 14 '22 at 13:43
  • @SotiriosDelimanolis. The Eclipse will directly tells/throws/slap the NPE on my face whenever I do *interfacex.someImplMethods()*. – Plain_Dude_Sleeping_Alone Jul 14 '22 at 13:49
  • 1
    That doesn't make sense. Throwing exception is a runtime behavior. If it's performing static analysis, it would warn you on an actual method invocation. If it's just saying that the `interfacex` field is `null`, then that is a whole other thing, unrelated to Spring. It's very unclear what you're seeing without an actual error/warning message and without a [mcve]. – Sotirios Delimanolis Jul 14 '22 at 13:51

2 Answers2

3

Are you really placing the @Autowired on the field of the main class or its just an illustration? If you do - it won't work because the class on which @Autowired can happen must be by itself managed by Spring. And in this case its obviously not, because its a special class - an entry point of the application...

I suggest to use something like this instead:

@Component 
public class EntryPoint {
 
   
    @Autowired
    Interfacex interfacex; 

    public void foo() {
      // interfacex shouldn't be null 
      // because everything is managed by spring now
      interfacex.doA();
    } 

}

public class Main {

    public static void main(..) {
        ApplicationContext ctx = ...
        EntryPoint ep = ctx.getBean(EntryPoint.class);
        ep.foo();
    }
}
Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
  • So it means that I still have to load the bean through the context? I mean I thought that *AppCofig* will do the rest... – Plain_Dude_Sleeping_Alone Jul 14 '22 at 10:58
  • No AppConfig (in general, class annotated with a `@Configuration` only helps to spring to understand where to find the beans. But the beans themselves are placed in the application context and should be accessed from there. Of course its only about the entry point from that "EntryPoint" all the beans will be managed by spring and autowiring will work as you expect- you just have to "start from somewhere" – Mark Bramnik Jul 14 '22 at 11:01
  • I see let me made an intermediary class somewhere and declare the *@Autowired* in it. – Plain_Dude_Sleeping_Alone Jul 14 '22 at 11:06
  • Btw what whould be the 'ctx' declared with?? Like *"ctx = new AnnotationConfigApplicationContext(AppConfig.class);"* ?? – Plain_Dude_Sleeping_Alone Jul 14 '22 at 11:14
  • That's what I've asked to clarify in the question actually :) In plain spring (not spring boot) you __have__ to define the ApplicationContext somehow - so yes, this snippet can work – Mark Bramnik Jul 14 '22 at 11:20
  • "*its a special class*" It's not really a special class. It can be instantiated just like any other, and there's nothing special about the instances. There could be multiple classes with main methods too. – Michael Jul 14 '22 at 12:57
1

@Autowired annotation will not be recognized and acted upon by spring unless the class is a bean.

In this case, the 'Main' class is not a bean. So, @Autowired will do nothing.

You need to make 'Main' a bean. One way to do that is to add @Component annotation to that class.

Also, this seems like just something you are trying out to understand the working. In that case, you can try my above suggestion.

If you are doing this for prod, then you should change the class structure, class and variable names and the way you are creating beans.

Amol Limaye
  • 108
  • 1
  • 4