#Could not autowire. No beans of 'SmsService' type found.

130 messages · Page 1 of 1 (latest)

honest swan
#

As you can see in this example:

@SpringBootApplication
public class  KafkaTestApplication {

    public static void main(String[] args) {
        SpringApplication.run(KafkaTestApplication.class, args);
    }
    @Configuration
    public static class ProjectConfig {

        @Bean
        public MessageService smsService() {
            System.out.println("SMS service");
            return new SmsService();
        }

        @Bean
        public String something(SmsService smsService) {
            System.out.println("Something");
            return smsService.toString();
        }

        public static class SmsService implements MessageService {
            public SmsService() {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        }

        public interface MessageService {}
    }
}

Spring is somehow resolving SmsService even though it doesn't have a bean of type SmsService what it dos have is MessageService. I tried delaying the construction of something bean with that thread sleep method, but every time smsService bean is constructed first. Also intellij gives a warning in there Could not autowire. No beans of 'SmsService' type found. which makes sense but the whole thing just compiles fine.

Is this behavior guaranteed to always work like that? Can one rely on returning object in it's parent form and expect spring to inject it as a child form? Very strange.

pine rivetBOT
#

<@&1004656351647117403> please have a look, thanks.

honest swan
#

WARNING: use your sunglasses while opening an image guys.
Here is the image:

honest swan
#

Now I have reordered the bean declarations and as crazy it might sound app crashes every time:


Error starting ApplicationContext. To display the condition evaluation report re-run your application with 'debug' enabled.
2026-08-17T11:49:41.426+04:00 ERROR 819090 --- [kafka-test] [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

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

Description:

Parameter 0 of method applicationRunner in com.github.konstantinevashalomidze.kafkatest.KafkaTestApplication$ProjectConfig required a single bean, but 2 were found:
    - kafkaTestApplication.ProjectConfig.EmailService: defined in file [/home/kosta/github-projects/kafka-test/target/classes/com/github/konstantinevashalomidze/kafkatest/KafkaTestApplication$ProjectConfig$EmailService.class]
    - kafkaTestApplication.ProjectConfig.SmsService: defined in file [/home/kosta/github-projects/kafka-test/target/classes/com/github/konstantinevashalomidze/kafkatest/KafkaTestApplication$ProjectConfig$SmsService.class]

This may be due to missing parameter name information

Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

Ensure that your compiler is configured to use the '-parameters' flag.
You may need to update both your build tool settings as well as your IDE.
(See https://github.com/spring-projects/spring-framework/wiki/Spring-Framework-6.1-Release-Notes#parameter-name-retention)

#

So does that mean that order matters in configuration ? of which we define beans?

#

Crazy man crazy

pulsar vault
#

what do you mean it has MessageService

#

oh

#

so you actually return SmsService even though you didnt say that in method declaration

#

spring boot still has the instance of SmsService though

pulsar vault
#

should not

#

because spring boot should take all of them and then decide which one to craete first

#

or i think it can even do circular dependency things in some cases but idk about that, probably only for fields not method arguments

honest swan
#

Formally I have never created SmsService bean on a first place.

pulsar vault
#

but why is it red?

honest swan
#

It is red because I have nevere created SmsService bean

#

I think only reasonable answer would be that spring determines types of objects at runtime calling .getClass directly on object

pulsar vault
#

i mean you did create a SmsService, and only said that you'll return MessageService, but i think spring boot might not care what you declared to return, it probably takes the actual SmsService, and does .getClass() on it. for testing you can try saying public Object smsService() and return the sms service as "object"

honest swan
#

that would explain how he supplies

#

SmsService there

#

But I don't know why would they do that

pulsar vault
#

yea it does

#

i mean im not sure but its still stores the actual object

honest swan
#

But take a look at my another example

#

When I reordered methods

#

Then app crashes

#

so it means that reordering has an effect as well

#

for some reason

#

Which is very error prone for the thing called "configuration"

#

I am genuinely interested why don't they just restrict the creation of and object of type "A" if type "A" is not defined as a Bean in some way

#

this would be easy to do

pulsar vault
#

okay i think it actually does decide by the declared class not by the .getClass i tested that

honest swan
#

I guess there is some reason which I absolutely have no idea

pulsar vault
#

did you actually get the bean injected even though the declaration is broader than the accepted bean?

#

okay wait a moment

honest swan
#

Yes of course that's why I am calling toString() on something() method

#

It means SmsService was injected

pulsar vault
#

okay no sorry i confused

#

it does inject

#

so about the order

honest swan
#

It can't tell if something has dependency on smsService

#

before injection

#

I can tell so since reordering breaks

#

the code

pulsar vault
#

oh wow

#

so the spring boot manages to inject it no matter of the order when i declare to return the Child

#

but when i declare to return the Parent it does not

#

you can try for a moment change the method signature to return actually what you return

#

and see if the order still matters

honest swan
honest swan
pulsar vault
#

weird thing, i guess ill wait for someone else that knows better why that happens

honest swan
#

Yeah me too

pulsar vault
#

but actually why do you declare the super type

#

you can declare the sub type

honest swan
#

I mean it makes more sense to return super type isn't it?

#

because

#

I might want to have 2 implementations

#

And I will have superclass defined

#

in dependant classes

#

and use interface instead

#

so in future if I want to replace one of them with other

#

I will do so

#

In the meantime I might want a concrete class

pulsar vault
#

i mean then i think you just return the specific class, but expect the parent

honest swan
#

Yes but let's say that in a bean

#

I have a some mechanism that pings

#

one provider

#

if it's dead

#

I will need another provider

#

they both are different classes

#

I can't return them both

pulsar vault
#

okay so what happens probably is that spring boot actually has to check anyway which components (beans) will have to be injected into what bean declarations, it has to order them in sequence before it calls any method, so before it calls your messagemanager it will not know what it returns exacly

#

and i think that is the reason you say SmsManager not MessageManager

#

service*

#

so spring knows for sure what it will get

pulsar vault
#

but not know which one

honest swan
#

Yes

#

for example

pulsar vault
#

i mean, then you can return the parent, but you also will accept the parent probably

#

because you dont even know what will be returned so you say you want any

honest swan
#

What if I do instance of

pulsar vault
#

yes

honest swan
#

and want to get the child itself

#

out of it

#

yeah that would work too

pulsar vault
#

so you know youll get parent but dont know if you get childA or childB

honest swan
#

since it is already ijected

pulsar vault
#

you can use restricted subclasses for that

honest swan
#

I mean I will probably never need to do something like that but it is indeed error prone

#

Configs get messy over time

#

if someone does something like that

#

injects child

#

and it somehow works

#

and then later in future Ai slop will reorder things will break

pulsar vault
#

ive made an Either class, but that only allows you to do 2

honest swan
#

Thankfully I have intellij and it screams

#

about this

pulsar vault
#

and is only usable for special cases

honest swan
#

and I will not do that

#

but I am not sure eclipse or netbeans will detect this

pulsar vault
#

return A or B and declare you return parent?

honest swan
#

Inject class when I don't have a exact bean defined

#

of type

pulsar vault
#

i dont know, you can instanceof

#

if so

#

it will be safe too if you use the sealed classes

honest swan
#

I think out conversation diverged a little bit. But hope there is reasonable answer why does this work like this. Even though I have no justifiable answer why would someone have to do such thing.

#

And why intellij catches this and spring allows such thing to happen.

pulsar vault
#

what questions do you still have?

#

i mean i already said why the order did matter

#

    @Bean
    public Super beanSuper() {
        return new Sub();
    }

    @Bean
    public String beanString(Sub sub) {
        System.out.println("ok, " + sub);
        return "hi";
    }
pine rivetBOT
pulsar vault
#

this should not work either

#

APPLICATION FAILED TO START


#

APPLICATION FAILED TO START

#

but it does.

#

i guess that is the question left

honest swan
#

Yeah that's the question

#

And another question why is it like that and not restricted

#

to start with

zinc coral
# honest swan I think out conversation diverged a little bit. But hope there is reasonable ans...

Spring flow for beans goes something like this

  1. Spring will register the bean definitions (both smsService and something)
  2. Spring will execute the method to obtain the object, in the order they were registered unless the bean method requires another object (like something which requires a SmsService object); in those cases, spring will first look for the object or the bean that gives that object and call it first
  3. Save all instances in the context

Now, why does your something method is autowiring with your smsService bean, even if the type is different? Well, that has to do with 2 things:

  1. Since smsService is called first, an instance of SmsService already exists (even with the type being MessageService)
  2. When spring checks if an object of SmsService already exists, Spring checks the runtime class of objects inside the Spring Context, and since the smsService bean matches SmsService, MessageService and Object (plus any other interface it might implement), it will use that object for the second bean.

And there is a test you can do that actually makes you understand the importance on the order: Switch the method definitions. This will throw an exception since spring can only check the runtime class of something that exists, if there is no object in the spring context that matches the required SmsContext and there is no Bean definition that provides that signature (return type SmsContext), it will throw UnsatisfiedDependencyException

#

If you want to "fix it", you can either define from which bean should the smsService be, use the @Qualifier("beanIdentifier") inside the mehtod parameters so you only accept that Bean as your dependency. As well you can switch from @Bean to @Configuration class, there you have more control with startup, then you can use @AutoConfigureAfter/@DependsOn to have control over the Bean sequence

zinc coral
#

Adding a lil bit more, this is not an issue with Spring itself but on how Java Objects works and as well how Spring Beans lifecycle is. If you add a lil bit of prints into the method definition, you can see that at runtime, your object is a SmsService object, even if the method signature says it will return a MessageService object. What springs see when checking if the object exists, is the object definition, not the method definition from where it comes from.

honest swan
zinc coral
#

Well, spring can not restrict it without affecting the Bean identification. Remember that Spring looks for the runtime class of the Bean to look for dependency candidates, if more identification (like check the method signature or something like that) is added in by default, it will make the bean look up slower. At the end you can avoid this by configuring your beans with specific dependency and configuration when there is aggregation in the desired bean