Reference an Annotated Spring Component in an XML Bean Definition - spring

I am using an external library that requires that I configure it using an XML Bean definition; in the Bean definition I need to provide an external class with a Bean from my project. I am using spring annotations with component scanning.
How do I reference my annotated Bean within the XML Bean Definition?
Are there any alternatives to creating an XML Bean Definition?
Details: Spring 3.0.7

No matter how it got created (based on XML- or annotation- metadata), every bean ends up in the application context under a unique name.
If you've just annotated your class with #Component or derivatives, without stating any name, the default naming scheme will be applied and the bean name will be your class name with the first character lowercased: ClassName => "className".
With that in mind, if you need to inject that bean in an XML bean definition, you do it like with any other bean in your context:
<bean id="someBean" class="SomeClass">
<property name="someProp" ref="className"/><!-- to stick to the above example -->
</bean>
Since you're mixing annotations with XML, the application context will be able to locate the "className" bean properly.

The #Service annotation takes an optional String value which can be used to give the bean a name of your choosing. For example, if your custom bean looks like:
#Service("mySpecialName")
public class MyClass { ... }
Then your xml could have:
<bean class="com.someone.else.library.SomeClass">
<property name="someProp" ref="mySpecialName"/>
</bean>

Make sure add below code in your xml file
<context:component-scan base-package="" />
<context:annotation-config />

Related

Spring inject bean is always singleton

We are using spring 3.2.
We defined a bean myAccountVO in spring.xml files and set the scope to prototype, but the spring creates this bean as singleton bean.
Here is the spring xml:
<bean name="myAccountVO1"
class="valueobject.AccountVO"
scope="prototype" >
<property name="accountNo" value="0105069413007" />
<property name="accountType" value="01" />
</bean>
The service class is:
#Service //I've tested the #Scope("prototype") but no luck
public class AccountSummary {
#Autowired //I also tested #Resource but same result
private AccountSummaryVO myAccountSummaryVO1;
AccountSummaryVO getAccount(){
return myAccountSummaryVO1
}
}
Later we use this service as:
#Autowired
AccountSummary accountSummary;
............
accountSummary.getAccount()
As far as I get the AccountSummary class, itself, is a singleton and will not be instantiated every time.
It seems are very basic usecase, but I don't know what am I missing.
I don't see where you are injecting myAccountVO1.
But I guess when you reveal the injected place that it's probably a member of a bean which itself is not in the scope prototype, e.g. #Service or #Controller. The service bean will be instantiated with a newly created myAccountVO1, but this instance stays there forever.
Change the scope of the containing bean. See 4.5.3 Singleton beans with prototype-bean dependencies.
This applies as well to the beans which have the service beans injected.

spring: need for an example of using prototype bean in a web environment

I wonder how can I properly inject a prototype bean to a singleton one in a web app. Consider this example:
<bean id="order" class="com.foo.Order" scope="prototype"/>
<bean id="orderService" class="com.foo.OrderService">
<property name="userPreferences" ref="userPreferences"/>
</bean>
I thought of using getBean() but isn't that a way to make my code dependent to spring itself?
I need a short java code example to demonstrate how to inject an order bean in my OrderService singleton.
Thanks
You can use jsr-330 Providers, just put:
#Autowired
Provider<Order> orderProvider;
in your singleton bean, and then use the provider:
public Whatever yourMethod() {
Order order = orderProvider.get();
}

How to import Java-config class into XML-config so that both contexts have beans?

I have a project where I need to bootstrap #Configuration java-config classes into the XML configuration.
To do that, I'm reading that I also need to include the following bean definition (along with the bean definitions of the classes annotated with #Configuration).
<bean class="org.springframework.config.java.process.ConfigurationPostProcessor" />
But, I end up receiving the following error:
Caused by: java.lang.ClassNotFoundException: org.springframework.config.java.process.ConfigurationPostProcessor
I have to assume I'm missing a jar somewhere, but my various web searches hasn't resulted in an answer yet. Any help would be greatly appreciated. Thanks.
EDIT: Evidently, I was reading old documentation, which is no longer current. Let me back up. My project contains older XML-based configuration. The newer code is all using 'Java-config'. With that said, the contexts are apparently completely separate. I'd like to 'import' a java-config class into the XML configuration, so that both contexts have those particular beans. Does anyone know how I can do that?
This actually ended up being fairly simple. To get a Java-config bean definition into the xml-config, simply define the Java-config class as a bean within the XML-config. There are no extra jars necessary.
#Configuration
public class SomeJavaConfig {
#bean
... [bean definition]
}
inside the XML-config, you define this class as a bean.
<!-- needed to pick up the annotated java-config -->
<context:annotation-config />
<!-- Importing java-config class, which are annotated with #Configuration -->
<bean name="SomeJavaConfig" class="[fully qualified path].SomeJavaConfig" />
The XML-config, which may be part of a different context, now has all the bean definitions defined within the JavaConfig class.
UPDATED - to included Alan Franzoni's comment below in the answer.
Alternatively to annotation-config you can use component-scan. Then you do not have to include the Configuration Bean in XML:
<context:component-scan base-package="[fully qualified package path]" />
See Difference between <context:annotation-config> vs <context:component-scan> for more details.
Should be in:
spring-javaconfig-<version>.jar

Replace spring bean in one context with mock version from another context

I'm writing an integration test where an application context xml is initialized during startup. There are several test methods in the test class which make use of a specific bean 'X'(already defined in the xml). My actual requirement is to mock bean X only for one of the test methods.
Inside a test method: I tried creating a separate application context using ClassPathXMLApplicationContext with only the mock bean 'M'.
Now I have two Application Contexts (AC):
1. One created during test case startup (which contains the actual bean X) and
2. One created using ClassPathXMLApplicationContext within the test method (which has the mock bean M).
I want to replaced the actual bean definition 'X' within AC:1, using the mock bean definition 'M' from AC:2.
Can somebody throw some light on this please?
You can :
use the Profile annotation if you have spring 3.1.
use the Primary annotation
use qualifiers
wire the bean yourself in the spring context
and i'm sure there are even more options.
There is not a clear way to replace a a bean in a refreshed ApplicationContext unless you close it and refresh it again.
To emulate it, the common approach is to use a Proxy of the bean that you want to replace and change the target at runtime.
You can do it easily using the framework aop support classes:
<bean id="realBean" class="RealClass" />
<bean id="mockBean" class="MockClass" />
<bean id="targetSource" class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-arg ref="realBean" />
</bean>
<bean id="bean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="targetSource" ref="targetSource" />
</bean>
#Test
public void testWithMockBean() {
Object real = targetSource.swap(mock);
....
// do your test work
...
targetSource.swap(real);
}
Create a testApplicationContext with
<beans>
<import resource="classpath*:appContext.xml" />
<bean id="mockbeanOfX" class=....../>
</beans>
and then load this test application context in your testcase. Now you can get the mock bean from the application context and pass it whereever needed.

Spring injection bind toInstance

Is there a way to bind an injected object to a specific instance using Spring DI similar to Google Guice's
bind(MyClass.class).toInstance(myclassobject);
If the constructor or member variable is annotated with #Autowired, Spring will try to find a bean that matches the type of the Object. You can get similar functionality to the annotation using #Qualifier, for example:
bind(MyClass.class).annotatedWith(Names.named("main")).toInstance(myclassobject);
would become in Spring:
#Autowired #Qualifier("main") private MyClass myClassObject;
<bean name="myClassObject" class="example.MyClassImpl">
<qualifier value="main"/>
</bean>
See http://static.springsource.org/spring/docs/2.5.x/reference/beans.html#beans-autowired-annotation for more.

Resources