pak1989
pak1989

Reputation: 21

Converting xml beans to java config issue

I have a bean in xml:

<bean id="fooBean" class="org.model.Foo" scope="prototype">
    <property name="propOne" ref="fooBarOne"/>
    <property name="propTwo" ref="fooBarTwo"/>
    <property name="propThree" ref="fooBarThree"/>
</bean>

I converted it in java like this:

@Bean
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public Foo fooBean(
    FooBarOneImpl fooBarOne,
    FooBarTwoImpl fooBarTwo,
    FooBarThreeImpl fooBarThree
) {
    Foo foo = new Foo();
    foo.setPropOne(fooBarOne);
    foo.setPropTwo(fooBarTwo);
    foo.setPropThree(fooBarThree);
    return foo;
}

When I execute:

(IFoo) applicationContext.getBean("fooBean", pizza, patatine, cocaCola);

with the xml config it works correctly, with Java config it gives I get an Exception.
The exception is the following:

org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.model.Foo]: Illegal arguments to factory method 'fooBean'; args: "ciao","11","abc"; nested exception is java.lang.IllegalArgumentException: argument type mismatch  

The class Foo has the constructor defined Foo(String pizza, String patatine, String cocaCola){...}.

Why when the bean is defined in the xml it finds the right constructor?

I tried to change the java conversion

Upvotes: 0

Views: 59

Answers (1)

Numichi
Numichi

Reputation: 1092

@Bean
public FooBarOne propOne() { // Bean name will be set by method name
    return new FooBarOne(); // if FooBarOne is an interface, use here any implementation
}

@Bean
public FooBarTwo propTwo() { // Bean name will be set by method name
    return new FooBarTwo(); // if FooBarTwo is an interface, use here any implementation
}

@Bean 
public FooBarThree propThree() { // Bean name will be set by method name
    return new FooBarThree(); // if FooBarThree is an interface, use here any implementation
}

@Bean
@Scope("prototype")
public Foo fooBean(FooBarOne a, FooBarTwo b, FooBarThree c) {
    // Here, I linked by type name and not bean name. The name of the parameter is optional, it can be anything you like.
    // If you want to link by bean name, use @Qualified annotation.
    // This annotation is needed if the bean injection is not trivial.
    return new Foo(a, b, c)
}

Another critical topic: If you defined a CLASS return type, we can't be referencing the instance's interface.

interface I {}
class A implemented I {}

// ------------------------------------------------------

@Bean
public A a() { return new A() }

@Bean
public A a(I instance) { ... } // ERROR
@Bean
public A a(A instance) { ... } // OK

// ------------------------------------------------------

@Bean
public I a() { return new A() }

@Bean
public A a(I instance) { ... } // OK
@Bean
public A a(A instance) { ... } // ERROR

If you use @Service/@Repository/@Component on your class, you can do ref because Spring will scan your project. Spring won't do it via @Bean because @Bean is the direct definition.

Upvotes: 0

Related Questions