-1

I searched for this in a lot of ways already but couldn't find anything related to it. I'm having an issue where no spring bean inside another bean (that is extended) is being autowired.

What I have is this:

interface A {
}

@Service
class B implements A {
    @Autowired
    private RandomSpringBean randomSpringBean;
}

@Primary
@Service
class C extends B {
    
}

And what is happening is that RandomSpringBean inside B isn't being autowired when it's being called by another class that autowires B, but only by classes that autowire C, like this:

class D {
    @Autowired
    private B b;//beans inside B are null
}

class E {
    @Autowired
    private C c;//beans inside B (C subclass) are not null
}

Both D and E are being autowired inside other classes. If I comment out/remove C, B goes back to working properly.

I hope that wasn't too confusing.

Ps: I didn't do it like this, it was someone else. I'm just having this issue and want to know a way to fix it, maybe without making C stop extending B.

Cam Moreira
  • 352
  • 1
  • 4
  • 13
  • Your issue isn't that setup, your issue is most likely how you create D and E instances. – Tom Mar 17 '21 at 14:42
  • can you provide packages structure and bean config classes/xmls? – Krzysztof K Mar 17 '21 at 14:42
  • I assume the OP is saying that D and E are created in the same way. Also, if they are both being autowired (neither `b` or `c` are `null`), then I don't see how they can be being created incorrectly. - But it certainly can't hurt to have more information. – CryptoFool Mar 17 '21 at 14:56
  • @Tom both D and E instances are also autowired inside other classes – Cam Moreira Mar 17 '21 at 15:07
  • @CryptoFool you assumed correctly, they are both being autowired. And as I added now, if I remove class C, then it works properly. – Cam Moreira Mar 17 '21 at 15:10
  • Please provide a [mcve]. – Sotirios Delimanolis Mar 17 '21 at 15:12
  • @KrzysztofK sorry, I don't know how to provide that without having to post the actual file, which I don't want to do since it's not a personal project. But like CryptoFool said, they are both being autowired. Also, if I remove C, it works properly. – Cam Moreira Mar 17 '21 at 15:13
  • This is a duplicate of https://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-field-null(which already contains information on why a field cannot be null). For a dedicated blog post see https://deinum.biz/2020-07-03-Autowired-Field-Null/. As a rule of thumb an `@Autowired` field cannot be `null` (spring will stop starting the application if it cannot fulfil the dependencies). – M. Deinum Mar 17 '21 at 18:54
  • @M.Deinum it's not the same problem, I'm not creating any instance with a {{new}}. It's everything being autowired – Cam Moreira Mar 17 '21 at 19:31
  • Please read the answers to that question amps well the linked blog post. The latter has all the issues listed for an @autowired field appearing to be null. Again as mentioned an autowired field cannot be null else your application wouldn’t start. – M. Deinum Mar 17 '21 at 19:33
  • Let me rephrase my question/statement do you get a nullpointerexception during running the application or does it appear to have null fields in the debugger? – M. Deinum Mar 17 '21 at 19:37
  • @M.Deinum Both. I get a NPE and then when I was debugging, all the other beans were also null. – Cam Moreira Mar 17 '21 at 19:42
  • They appear to be null because you are probably looking at the proxy instead of the actual bean. If you get a NPE please include that in your question. And as mentioned please read the blog post I linked I suspect you are invoking a final method or non public method on a proxy – M. Deinum Mar 17 '21 at 19:44
  • @M.Deinum it was because I was invoking a package-private method. Well, thanks. – Cam Moreira Mar 17 '21 at 19:55

1 Answers1

-1

This part of the code should cause you problems if you are not using @Qualifier / @Primary or similar structure:

class D {
     @Autowired
     private B b;
}

Exception would be something like:

Field b in my.boring.package.beandemo.D required a single bean, but 2 were found:

Here is a working demo:

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
public class MyBeans {
    
    @Component
    public static class RandomBean {}
    
    public static interface A {}
    
    @Component("B")
    public static class B implements A {
        
        @Autowired
        RandomBean randomBean;
    }
    
    @Component
    public static class C extends B {}
    
    @Component
    public static class D {
        
        @Autowired
        @Qualifier("B")
        private B b;
        
        @PostConstruct
        public void checkRandomBean() {
            if (b.randomBean != null) {
                System.out.println("B has randomBean");
            }
        }
    }
    
    @Component
    public static class E {
        
        @Autowired
        private C c;
        
        @PostConstruct
        public void checkRandomBean() {
            if (c.randomBean != null) {
                System.out.println("C has randomBean");
            }
        }
    }
}

Edit:

Please check runtime class of B inside D.

Since C is annotated with @Primary, an instance of C should be injected to D.

Also C will not have access to private fields of B.

Ghokun
  • 3,345
  • 3
  • 26
  • 30