I know there are threads similar to this issue. Below is my class and I am configuring it in spring.xml file. Actually HumanResourceService is an interface having only one method.
#Endpoint
public class HolidayEndpoint {
#Autowired
private HumanResourceService humanResourceService;
#Autowired
public HolidayEndpoint(HumanResourceService humanResourceService) throws JDOMException {
this.humanResourceService = humanResourceService;
}
}
My problem is that in my spring.xml file, when I define HumanResourceService as bean, it cannot be instantiated as this is an interface. How can I mention an interface in spring configuration file. My spring.xml file is below
<bean id="holidayEndpoint" class="com.mycompany.hr.ws.HolidayEndpoint" autowire="constructor" >
<property name="humanResourceService" ref="humanResourceService" />
</bean>
<bean id="humanResourceService" class="com.mycompany.hr.service.HumanResourceService" />
You can't, Spring needs something it can make an instance from, the interface isn't enough.
In your spring.xml, the value of the class attribute for your bean with id="humanResourceService" should be the name of your implementation class, not the interface. Spring needs you to tell it what implementation class you want it to use for this.
This following does not behave like I expect, using Spring 3.2.1.RELEASE, groovy 1.8.8. I've elided quite a bit of code. If this isn't sufficient, I'll put together a (not) working full example.
groovy bean:
package foo
import javax.annotation.Resource
class SomeBean {
#Resource
String someProp
}
spring xml:
<context:annotation-config />
<context:component-scan base-package="other.packages.not.foo" />
<bean id="someBean" class="foo.SomeBean">
<property name="someProp" value="bar" />
</bean>
This fails with an error about not being able to find a bean to satisfy the String property. To work around this, I ended up doing this:
groovy bean:
#Resource( name = 'someProp' )
String someProp
spring xml:
<bean id="someProp" class="java.lang.String">
<constructor-arg value="bar" />
</bean>
<bean id="someBean" class="foo.SomeBean" />
I don't like this solution, because it couples the bean source code to the spring config, and that's coupling in the wrong direction. And it creates an unnecessary bean for a simple String. Am I missing an obvious solution?
#Resource is not meant for property injection.
For this to work:
<bean id="someBean" class="foo.SomeBean">
<property name="someProp" value="bar" />
</bean>
you need to implement a setter method
public void setSomeBean(String value) {
someValue = value;
}
#Resource could be used if you want to inject a different bean from your context.
#Resource(name="someBean")
SomeBean someBean
I'm trying to inject (autowire) a spring bean to an abstract class but it doesn't seem to work.
public abstract class BaseEntity {
#Autowired(required = true)
protected SecurityProvider securityService;
public BaseEntity() {
}
}
And the injected class:
#Component
public class SecurityService extends SecurityProviderImpl implements SecurityProvider {
#Autowired
public SecurityService(ICipherDescriptor cipherDescriptor) {
super(cipherDescriptor);
}
}
The SecurityService gets initialized just fine (I can see it while debugging) but the class that inherit from BaseEntity cannot use the injected SecurityService since it is null (doesn't get injected for some reason).
I tried doing it via XML as well, defining the BaseEntity as abstract:
<bean id="baseEntity" abstract="true" class="com.bs.dal.domain.BaseEntity">
<property name="securityService" ref="securityService"/>
</bean>
<bean id="securityService" class="com.bs.dal.secure.SecurityService">
<constructor-arg ref="cipherDescriptor" />
</bean>
but still with no success.
Where am I going wrong?
I think I know what's wrong here. I'm trying to inject a spring bean to an entity - which is impossible (unless you use aspectJ weaving) since the entities are not instantiated/managed by Spring. Make sense, isn't it?
If your BaseEntity is also instantiated by spring, you just need to add a parent attribute to the bean definition to link it to your BaseEntity definition like so:
<bean id="baseEntity" abstract="true" class="com.bs.dal.domain.BaseEntity">
<property name="securityService" ref="securityService"/>
</bean>
<bean id="derivedEntity" parent="baseEntity" class="com.bs.dal.domain.DerivedEntity"/>
<bean id="securityService" class="com.bs.dal.secure.SecurityService">
<constructor-arg ref="cipherDescriptor" />
</bean>
In short, the two key parts to such a definition are the abstract attribute on the parent class and the parent attribute on the subclass.
let's say I have a factory bean:
<bean id="myFactory" class="com.company.MyFactory" lazy-init="true">
<property name="myProperty" ref="propA">
</bean>
Let's say propA is a bean injected by IOC used in the factory method. And I have 2 beans generated from this factory:
<bean id="bean1" factory-bean="myFactory" factory-method="instance"/>
<bean id="bean2" factory-bean="myFactory" factory-method="instance"/>
How can I make bean2 to use a different myProperty than bean1 without using a different factory method? Or, how can I pass propA as a parameter to the factory-method from the bean1 or bean2 configuration?
This can be achieved in a slightly different way:
class MyFactory {
public Bean instance(MyProperty myProperty) {
return //...
}
}
Now you can use counterintuitive syntax like following:
<bean id="bean1" factory-bean="myFactory" factory-method="instance">
<constructor-arg ref="propA"/>
</bean>
<bean id="bean2" factory-bean="myFactory" factory-method="instance">
<constructor-arg ref="propB"/>
</bean>
Believe it or not but propA and propB will be used as instance() method arguments.
Can we have duplicate names for the same bean id that is mentioned in the XML?
If not, then how do we override the bean in Spring?
Any given Spring context can only have one bean for any given id or name. In the case of the XML id attribute, this is enforced by the schema validation. In the case of the name attribute, this is enforced by Spring's logic.
However, if a context is constructed from two different XML descriptor files, and an id is used by both files, then one will "override" the other. The exact behaviour depends on the ordering of the files when they get loaded by the context.
So while it's possible, it's not recommended. It's error-prone and fragile, and you'll get no help from Spring if you change the ID of one but not the other.
I will add that if your need is just to override a property used by your bean, the id approach works too like skaffman explained :
In your first called XML configuration file :
<bean id="myBeanId" class="com.blabla">
<property name="myList" ref="myList"/>
</bean>
<util:list id="myList">
<value>3</value>
<value>4</value>
</util:list>
In your second called XML configuration file :
<util:list id="myList">
<value>6</value>
</util:list>
Then your bean "myBeanId" will be instantiated with a "myList" property of one element which is 6.
Not sure if that's exactly what you need, but we are using profiles to define the environment we are running at and specific bean for each environment, so it's something like that:
<bean name="myBean" class="myClass">
<constructor-arg name="name" value="originalValue" />
</bean>
<beans profile="DEV, default">
<!-- Specific DEV configurations, also default if no profile defined -->
<bean name="myBean" class="myClass">
<constructor-arg name="name" value="overrideValue" />
</bean>
</beans>
<beans profile="CI, UAT">
<!-- Specific CI / UAT configurations -->
</beans>
<beans profile="PROD">
<!-- Specific PROD configurations -->
</beans>
So in this case, if I don't define a profile or if I define it as "DEV" myBean will get "overrideValue" for it's name argument. But if I set the profile to "CI", "UAT" or "PROD" it will get "originalValue" as the value.
An example from official spring manual:
<bean id="inheritedTestBean" abstract="true"
class="org.springframework.beans.TestBean">
<property name="name" value="parent"/>
<property name="age" value="1"/>
</bean>
<bean id="inheritsWithDifferentClass"
class="org.springframework.beans.DerivedTestBean"
parent="inheritedTestBean" init-method="initialize">
<property name="name" value="override"/>
<!-- the age property value of 1 will be inherited from parent -->
</bean>
Is that what you was looking for?
Updated link
Since Spring 3.0 you can use #Primary annotation. As per documentation:
Indicates that a bean should be given preference when multiple
candidates are qualified to autowire a single-valued dependency. If
exactly one 'primary' bean exists among the candidates, it will be the
autowired value. This annotation is semantically equivalent to the
element's primary attribute in Spring XML.
You should use it on Bean definition like this:
#Bean
#Primary
public ExampleBean exampleBean(#Autowired EntityManager em) {
return new ExampleBeanImpl(em);
}
or like this:
#Primary
#Service
public class ExampleService implements BaseServive {
}
Another good approach not mentioned in other posts is to use PropertyOverrideConfigurer in case you just want to override properties of some beans.
For example if you want to override the datasource for testing (i.e. use an in-memory database) in another xml config, you just need to use <context:property-override ..."/> in new config and a .properties file containing key-values taking the format beanName.property=newvalue overriding the main props.
application-mainConfig.xml:
<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource"
p:driverClassName="org.postgresql.Driver"
p:url="jdbc:postgresql://localhost:5432/MyAppDB"
p:username="myusername"
p:password="mypassword"
destroy-method="close" />
application-testConfig.xml:
<import resource="classpath:path/to/file/application-mainConfig.xml"/>
<!-- override bean props -->
<context:property-override location="classpath:path/to/file/beanOverride.properties"/>
beanOverride.properties:
dataSource.driverClassName=org.h2.Driver
dataSource.url=jdbc:h2:mem:MyTestDB
Whether can we declare the same bean id in other xml for other reference e.x.
Servlet-Initialize.xml
<bean id="inheritedTestBean" class="org.springframework.beans.TestBean">
<property name="name" value="parent"/>
<property name="age" value="1"/>
</bean>
Other xml (Document.xml)
<bean id="inheritedTestBean" class="org.springframework.beans.Document">
<property name="name" value="document"/>
<property name="age" value="1"/>
</bean>
Question was more about XML but as annotation are more popular nowadays and it works similarly I'll show by example.
Let's create class Foo:
public class Foo {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
and two Configuration files (you can't create one):
#Configuration
public class Configuration1 {
#Bean
public Foo foo() {
Foo foo = new Foo();
foo.setName("configuration1");
return foo;
}
}
and
#Configuration
public class Configuration2 {
#Bean
public Foo foo() {
Foo foo = new Foo();
foo.setName("configuration2");
return foo;
}
}
and let's see what happens when calling foo.getName():
#SpringBootApplication
public class OverridingBeanDefinitionsApplication {
public static void main(String[] args) {
SpringApplication.run(OverridingBeanDefinitionsApplication.class, args);
AnnotationConfigApplicationContext applicationContext =
new AnnotationConfigApplicationContext(
Configuration1.class, Configuration2.class);
Foo foo = applicationContext.getBean(Foo.class);
System.out.println(foo.getName());
}
}
in this example result is: configuration2.
The Spring Container gets all configuration metadata sources and merges bean definitions in those sources. In this example there are two #Beans. Order in which they are fed into ApplicationContext decide. You can flip new AnnotationConfigApplicationContext(Configuration2.class, Configuration1.class); and result will be configuration1.