Injecting Mockito mocks into a Spring bean - spring

I would like to inject a Mockito mock object into a Spring (3+) bean for the purposes of unit testing with JUnit. My bean dependencies are currently injected by using the #Autowired annotation on private member fields.
I have considered using ReflectionTestUtils.setField but the bean instance that I wish to inject is actually a proxy and hence does not declare the private member fields of the target class. I do not wish to create a public setter to the dependency as I will then be modifying my interface purely for the purposes of testing.
I have followed some advice given by the Spring community but the mock does not get created and the auto-wiring fails:
<bean id="dao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.package.Dao" />
</bean>
The error I currently encounter is as follows:
...
Caused by: org...NoSuchBeanDefinitionException:
No matching bean of type [com.package.Dao] found for dependency:
expected at least 1 bean which qualifies as autowire candidate for this dependency.
Dependency annotations: {
#org...Autowired(required=true),
#org...Qualifier(value=dao)
}
at org...DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(D...y.java:901)
at org...DefaultListableBeanFactory.doResolveDependency(D...y.java:770)
If I set the constructor-arg value to something invalid no error occurs when starting the application context.

The best way is:
<bean id="dao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.package.Dao" />
</bean>
Update
In the context file this mock must be listed before any autowired field depending on it is declared.

#InjectMocks
private MyTestObject testObject;
#Mock
private MyDependentObject mockedObject;
#Before
public void setup() {
MockitoAnnotations.initMocks(this);
}
This will inject any mocked objects into the test class. In this case it will inject mockedObject into the testObject. This was mentioned above but here is the code.

I have a very simple solution using Spring Java Config and Mockito:
#Configuration
public class TestConfig {
#Mock BeanA beanA;
#Mock BeanB beanB;
public TestConfig() {
MockitoAnnotations.initMocks(this); //This is a key
}
//You basically generate getters and add #Bean annotation everywhere
#Bean
public BeanA getBeanA() {
return beanA;
}
#Bean
public BeanB getBeanB() {
return beanB;
}
}

Given:
#Service
public class MyService {
#Autowired
private MyDAO myDAO;
// etc
}
You can have the class that is being tested loaded via autowiring, mock the dependency with Mockito, and then use Spring's ReflectionTestUtils to inject the mock into the class being tested.
#ContextConfiguration(classes = { MvcConfiguration.class })
#RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {
#Autowired
private MyService myService;
private MyDAO myDAOMock;
#Before
public void before() {
myDAOMock = Mockito.mock(MyDAO.class);
ReflectionTestUtils.setField(myService, "myDAO", myDAOMock);
}
// etc
}
Please note that before Spring 4.3.1, this method won't work with services behind a proxy (annotated with #Transactional, or Cacheable, for example). This has been fixed by SPR-14050.
For earlier versions, a solution is to unwrap the proxy, as described there: Transactional annotation avoids services being mocked (which is what ReflectionTestUtils.setField does by default now)

If you're using Spring Boot 1.4, it has an awesome way of doing this. Just use new brand #SpringBootTest on your class and #MockBean on the field and Spring Boot will create a mock of this type and it will inject it into the context (instead of injecting the original one):
#RunWith(SpringRunner.class)
#SpringBootTest
public class MyTests {
#MockBean
private RemoteService remoteService;
#Autowired
private Reverser reverser;
#Test
public void exampleTest() {
// RemoteService has been injected into the reverser bean
given(this.remoteService.someCall()).willReturn("mock");
String reverse = reverser.reverseSomeCall();
assertThat(reverse).isEqualTo("kcom");
}
}
On the other hand, if you're not using Spring Boot or are you using a previous version, you'll have to do a bit more work:
Create a #Configuration bean that injects your mocks into Spring context:
#Configuration
#Profile("useMocks")
public class MockConfigurer {
#Bean
#Primary
public MyBean myBeanSpy() {
return mock(MyBean.class);
}
}
Using #Primary annotation you're telling spring that this bean has priority if no qualifier are specified.
Make sure you annotate the class with #Profile("useMocks") in order to control which classes will use the mock and which ones will use the real bean.
Finally, in your test, activate userMocks profile:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {Application.class})
#WebIntegrationTest
#ActiveProfiles(profiles={"useMocks"})
public class YourIntegrationTestIT {
#Inject
private MyBean myBean; //It will be the mock!
#Test
public void test() {
....
}
}
If you don't want to use the mock but the real bean, just don't activate useMocks profile:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = {Application.class})
#WebIntegrationTest
public class AnotherIntegrationTestIT {
#Inject
private MyBean myBean; //It will be the real implementation!
#Test
public void test() {
....
}
}

Since 1.8.3 Mockito has #InjectMocks - this is incredibly useful. My JUnit tests are #RunWith the MockitoJUnitRunner and I build #Mock objects that satisfy all the dependencies for the class being tested, which are all injected when the private member is annotated with #InjectMocks.
I #RunWith the SpringJUnit4Runner for integration tests only now.
I will note that it does not seem to be able to inject List<T> in the same manner as Spring. It looks only for a Mock object that satisfies the List, and will not inject a list of Mock objects. The workaround for me was to use a #Spy against a manually instantiated list, and manually .add the mock object(s) to that list for unit testing. Maybe that was intentional, because it certainly forced me to pay close attention to what was being mocked together.

Update: There are now better, cleaner solutions to this problem. Please consider the other answers first.
I eventually found an answer to this by ronen on his blog. The problem I was having is due to the method Mockito.mock(Class c) declaring a return type of Object. Consequently Spring is unable to infer the bean type from the factory method return type.
Ronen's solution is to create a FactoryBean implementation that returns mocks. The FactoryBean interface allows Spring to query the type of objects created by the factory bean.
My mocked bean definition now looks like:
<bean id="mockDaoFactory" name="dao" class="com.package.test.MocksFactory">
<property name="type" value="com.package.Dao" />
</bean>

As of Spring 3.2, this is no longer an issue. Spring now supports Autowiring of the results of generic factory methods. See the section entitled "Generic Factory Methods" in this blog post: http://spring.io/blog/2012/11/07/spring-framework-3-2-rc1-new-testing-features/.
The key point is:
In Spring 3.2, generic return types for factory methods are now
properly inferred, and autowiring by type for mocks should work as
expected. As a result, custom work-arounds such as a
MockitoFactoryBean, EasyMockFactoryBean, or Springockito are likely no
longer necessary.
Which means this should work out of the box:
<bean id="dao" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.package.Dao" />
</bean>

If you're using spring >= 3.0, try using Springs #Configuration annotation to define part of the application context
#Configuration
#ImportResource("com/blah/blurk/rest-of-config.xml")
public class DaoTestConfiguration {
#Bean
public ApplicationService applicationService() {
return mock(ApplicationService.class);
}
}
If you don't want to use the #ImportResource, it can be done the other way around too:
<beans>
<!-- rest of your config -->
<!-- the container recognize this as a Configuration and adds it's beans
to the container -->
<bean class="com.package.DaoTestConfiguration"/>
</beans>
For more information, have a look at spring-framework-reference : Java-based container configuration

Below code works with autowiring - it is not the shortest version but useful when it should work only with standard spring/mockito jars.
<bean id="dao" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target"> <bean class="org.mockito.Mockito" factory-method="mock"> <constructor-arg value="com.package.Dao" /> </bean> </property>
<property name="proxyInterfaces"> <value>com.package.Dao</value> </property>
</bean>

Perhaps not the perfect solution, but I tend not to use spring to do DI for unit tests. the dependencies for a single bean (the class under test) usually aren't overly complex so I just do the injection directly in the test code.

I can do the following using Mockito:
<bean id="stateMachine" class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="com.abcd.StateMachine"/>
</bean>

Posting a few examples based on the above approaches
With Spring:
#ContextConfiguration(locations = { "classpath:context.xml" })
#RunWith(SpringJUnit4ClassRunner.class)
public class TestServiceTest {
#InjectMocks
private TestService testService;
#Mock
private TestService2 testService2;
}
Without Spring:
#RunWith(MockitoJUnitRunner.class)
public class TestServiceTest {
#InjectMocks
private TestService testService = new TestServiceImpl();
#Mock
private TestService2 testService2;
}

Update - new answer here: https://stackoverflow.com/a/19454282/411229. This answer only applies to those on Spring versions before 3.2.
I've looked for a while for a more definitive solution to this. This blog post seems to cover all my needs and doesn't rely on ordering of bean declarations. All credit to Mattias Severson. http://www.jayway.com/2011/11/30/spring-integration-tests-part-i-creating-mock-objects/
Basically, implement a FactoryBean
package com.jayway.springmock;
import org.mockito.Mockito;
import org.springframework.beans.factory.FactoryBean;
/**
* A {#link FactoryBean} for creating mocked beans based on Mockito so that they
* can be {#link #Autowired} into Spring test configurations.
*
* #author Mattias Severson, Jayway
*
* #see FactoryBean
* #see org.mockito.Mockito
*/
public class MockitoFactoryBean<T> implements FactoryBean<T> {
private Class<T> classToBeMocked;
/**
* Creates a Mockito mock instance of the provided class.
* #param classToBeMocked The class to be mocked.
*/
public MockitoFactoryBean(Class<T> classToBeMocked) {
this.classToBeMocked = classToBeMocked;
}
#Override
public T getObject() throws Exception {
return Mockito.mock(classToBeMocked);
}
#Override
public Class<?> getObjectType() {
return classToBeMocked;
}
#Override
public boolean isSingleton() {
return true;
}
}
Next update your spring config with the following:
<beans...>
<context:component-scan base-package="com.jayway.example"/>
<bean id="someDependencyMock" class="com.jayway.springmock.MockitoFactoryBean">
<constructor-arg name="classToBeMocked" value="com.jayway.example.SomeDependency" />
</bean>
</beans>

I use a combination of the approach used in answer by Markus T and a simple helper implementation of ImportBeanDefinitionRegistrar that looks for a custom annotation (#MockedBeans) in which one can specify which classes are to be mocked. I believe that this approach results in a concise unit test with some of the boilerplate code related to mocking removed.
Here's how a sample unit test looks with that approach:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(loader=AnnotationConfigContextLoader.class)
public class ExampleServiceIntegrationTest {
//our service under test, with mocked dependencies injected
#Autowired
ExampleService exampleService;
//we can autowire mocked beans if we need to used them in tests
#Autowired
DependencyBeanA dependencyBeanA;
#Test
public void testSomeMethod() {
...
exampleService.someMethod();
...
verify(dependencyBeanA, times(1)).someDependencyMethod();
}
/**
* Inner class configuration object for this test. Spring will read it thanks to
* #ContextConfiguration(loader=AnnotationConfigContextLoader.class) annotation on the test class.
*/
#Configuration
#Import(TestAppConfig.class) //TestAppConfig may contain some common integration testing configuration
#MockedBeans({DependencyBeanA.class, DependencyBeanB.class, AnotherDependency.class}) //Beans to be mocked
static class ContextConfiguration {
#Bean
public ExampleService exampleService() {
return new ExampleService(); //our service under test
}
}
}
To make this happen you need to define two simple helper classes - custom annotation (#MockedBeans) and a custom
ImportBeanDefinitionRegistrar implementation. #MockedBeans annotation definition needs to be annotated with #Import(CustomImportBeanDefinitionRegistrar.class) and the ImportBeanDefinitionRgistrar needs to add mocked beans definitions to the configuration in it's registerBeanDefinitions method.
If you like the approach you can find sample implementations on my blogpost.

Looking at Springockito pace of development and number of open issues, I would be little bit worried to introduce it into my test suite stack nowadays. Fact that last release was done before Spring 4 release brings up questions like "Is it possible to easily integrate it with Spring 4?". I don't know, because I didn't try it. I prefer pure Spring approach if I need to mock Spring bean in integration test.
There is an option to fake Spring bean with just plain Spring features. You need to use #Primary, #Profile and #ActiveProfiles annotations for it. I wrote a blog post on the topic.

I found a similar answer as teabot to create a MockFactory that provides the mocks. I used the following example to create the mock factory (since the link to narkisr are dead):
http://hg.randompage.org/java/src/407e78aa08a0/projects/bookmarking/backend/spring/src/test/java/org/randompage/bookmarking/backend/testUtils/MocksFactory.java
<bean id="someFacade" class="nl.package.test.MockFactory">
<property name="type" value="nl.package.someFacade"/>
</bean>
This also helps to prevent that Spring wants to resolve the injections from the mocked bean.

<bean id="mockDaoFactory" name="dao" class="com.package.test.MocksFactory">
<property name="type" value="com.package.Dao" />
</bean>
this ^ works perfectly well if declared first/early in the XML file. Mockito 1.9.0/Spring 3.0.5

I developed a solution based on the proposal of Kresimir Nesek. I added a new annotation #EnableMockedBean in order to make the code a bit cleaner and modular.
#EnableMockedBean
#SpringBootApplication
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes=MockedBeanTest.class)
public class MockedBeanTest {
#MockedBean
private HelloWorldService helloWorldService;
#Autowired
private MiddleComponent middleComponent;
#Test
public void helloWorldIsCalledOnlyOnce() {
middleComponent.getHelloMessage();
// THEN HelloWorldService is called only once
verify(helloWorldService, times(1)).getHelloMessage();
}
}
I have written a post explaining it.

I would suggest to migrate your project to Spring Boot 1.4. After that you can use new annotation #MockBean to fake your com.package.Dao

Today I found out that a spring context where I declared a before the Mockito beans, was failing to load.
After moving the AFTER the mocks, the app context was loaded successfully.
Take care :)

For the record, all my tests correctly work by just making the fixture lazy-initialized, e.g.:
<bean id="fixture"
class="it.tidalwave.northernwind.rca.embeddedserver.impl.DefaultEmbeddedServer"
lazy-init="true" /> <!-- To solve Mockito + Spring problems -->
<bean class="it.tidalwave.messagebus.aspect.spring.MessageBusAdapterFactory" />
<bean id="applicationMessageBus"
class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="it.tidalwave.messagebus.MessageBus" />
</bean>
<bean class="org.mockito.Mockito" factory-method="mock">
<constructor-arg value="javax.servlet.ServletContext" />
</bean>
I suppose the rationale is the one Mattias explains here (at the bottom of the post), that a workaround is changing the order the beans are declared - lazy initialization is "sort of" having the fixture declared at the end.

If you're using spring boot 2.2+, you can use #MockInBean as an alternative to #MockBean and keep your Spring context clean:
#SpringBootTest
public class MyServiceTest {
#MockInBean(MyService.class)
  private ServiceToMock serviceToMock;
    #Autowired
    private MyService myService;
    #Test
    public void test() {
        Mockito.when(serviceToMock.returnSomething()).thenReturn(new Object());
        myService.doSomething();
    }
}
disclaimer: I created this library to avoid Spring Context re-creation caused by #MockBean/#SpringBean that leads to slow build test phases (see Using #MockBean in tests forces reloading of Application Context or the problem with #MockBean)

Related

Wiring multiple beans with the same dependency via Spring Boot #Configuration

In older Spring MVC apps, where you'd specify application.xml and declare your app's beans so that Spring DI could instantiate them and wire them together, you might have something like this:
<bean id="chargeFactory" class="com.example.myapp.ChargeFactory" />
<bean id="paymentService" class="com.example.myapp.DefaultPaymentService">
<ref id="chargeFactory"/>
</bean>
<bean id="chargeAuditor" class="com.example.myapp.ChargeAuditor">
<ref id="chargeFactory"/>
</bean>
Which might help wire up the following code:
public interface PaymentService {
public void makePayment(Payment payment);
}
public class DefaultPaymentService implements PaymentService {
#Autowired
private ChargeFactory chargeFactory;
#Override
public void makePayment(Payment payment, String key) {
Charge charge = chargeFactory.createCharge(key);
charge.doCharge(payment);
}
}
public class ChargeAuditor {
#Autowired
private ChargeFactory chargeFactory;
public void auditAllCharges(String key) {
List<Charge> charges = chargeFactory.getAllCharges(key);
// blah whatever
}
}
How do you accomplish the same bean wiring in Spring Boot with the #Configuration class? For example:
#Configuration
public class MyAppInjector {
#Bean
public ChargeFactory chargeFactory() {
return new ChargeFactory();
}
#Bean
public PaymentService paymentService() {
return new DefaultPaymentService(chargeFactory());
}
#Bean
public ChargeAuditor chargeAuditor() {
return new ChargeAuditor(chargeFactory());
}
}
This might work but introduces some issues:
It would force me to have to write value constructors for all my classes, which goes against everything I see in literally every tutorial/article I've come across. Plus, if I had to do that, then there's no real value to #Autowired anyways...
At this point I'm essentially doing "DIY DI", which is OK, except I'm trying to deliberately use Spring DI :-)
Every time I call chargeFactory() I'm getting a new (prototype-style) ChargeFactory instance. Maybe I want a singleton. Using this approach I have to hand-roll my own singleton implementation.
Sure, I can do all of this, but I feel like I'm flagrantly misusing/misunderstanding how #Configuration is supposed to be used, because it seems like I'm introducing a whole lot of DIY/homegrown code to solve something Spring DI should be able to do for me.
How would I reference the chargeFactory bean and wire it into both the "provider methods" for the paymentService and chargeAuditor beans? Again, looking for the Java-based #Configuration solution instead of writing an XML document to define the wirings.
I found this article which seems to be the only tutorial/documentation (surprisingly) on wiring Spring Boot apps via #Configuration (which leads me to believe there might be other/better methods...), but it does not address:
How to specify singleton vs prototype bean instantiation patterns
If multiple instances of a bean-class exist, how do I specify which instance gets wired into which dependency?
How do I get around not defining value constructors for all my classes, and just let Spring/#Autowired inject fields automagically?
When you call chargeFactory() , spring won't create new instance everytime. Give it a try and see. Same object will be returned. Anyways
You can do something like this.
#Bean
public PaymentService paymentService(ChargeFactory chargeFactory) { return new DefaultPaymentService(chargeFactory); }

#Inject , #AutoWired, #Resource & #ManagedProperty : which one should I use ,where and when?

I'm using Hibernate, Spring & JSF for an application.
I'm actually evolving the application with a Restfull WebService with Jersey(JAX-RS). For that need i annotated my class with #Component. Inside this class, i need to call a service to grap some stuffs from the database.
#Component
#Path("/Graphic")
public class GraphicService {
//#Autowired //#Inject
//ParticipantBo participantBo;
or
//#ManagedProperty("#{participantBo}")
//private ParticipantBo participantBo;
I meet some annotations in tutorials that i don't know/understand well the meaning.
So i'd like to make a check-up to see if my configuration for the whole application is ok or if i could clean up some stuffs.
Most of the time, i'm using #ManagedProperty Annotation to include a dependency (a ServiceBO which one call then a Dao) inside my class annotated with #ManagedBean.
#ManagedBean(name="participantController")
#ViewScoped
public class AddParticipantBean implements Serializable{
private static final long serialVersionUID = -6952203235934881190L;
#ManagedProperty(value="#{participantBo}")
ParticipantBo participantBo;
}
I have an applicationContext.xml file where i declare all my classes this way :
<!-- Participant Data Access Object -->
<bean id="participantDao" class="X.X.X.dao.participant.ParticipantDaoImpl" >
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- Participant Business Object -->
<bean id="participantBo" class="X.X.X.bo.participant.ParticipantBoImpl" >
<property name="participantDao" ref="participantDao" />
</bean>
Is my configuration well done ? Could i configure the application differently ? , maybe without xml declaration ? using #Inject or #AutoWired maybe ? But what are the use cases for them ?
I prefere to use the standards that Java EE provides. And also I prefere to annotate the setters instead the property directly. With this way is more easy to start doing unit testing (and mocking these objects). Check also my answer here
For example your class GraphicService will be like this:
#Component
#Path("/Graphic")
public class GraphicService {
ParticipantBo participantBo;
#Resource
public void setParticipantBo(ParticipantBo participantBo){
this.participantBo = participantBo;
}
More info about #Resource
Hope it helps.

Spring #Autowiring with generic factory-built beans

I have a set of classes with a complex initialization scheme. Basically, I start with the interface I need to get a hold of, and then make a bunch of calls, and I end up with an object that implements that interface.
In order to handle this, I made a factory class that can, given an interface, produce the final object. I made this factory into a bean, and in XML I specified my various service beans as being instantiated via this factory object with a parameter of the interface that they will implement.
This works great, and I totally get exactly the beans I need. Unfortunately, I would like to access them from my controller classes, which are discovered via component scanning. I use #Autowired here, and it appears that Spring has no idea what type of object these are, and since #Autowired works by type, I'm SOL.
Using #Resource(name="beanName") here would work perfectly, however it seems odd to use #Resource for some beans and #Autowired for others.
Is there a way to get Spring to know what interface the factory will be creating for each of these beans without having a different factory method for each type?
I'm using Spring 2.5.6, by the way, otherwise I'd just JavaConfig the whole thing and forget about it.
Factory class:
<T extends Client> T buildService(Class<T> clientClass) {
//Do lots of stuff with client class and return an object of clientClass.
}
app context:
<bean id="serviceFactoryBean" class="com.captainAwesomePants.FancyFactory" />
<bean id="userService" factory-bean="serviceFactoryBean" factory-method="buildService">
<constructor-arg value="com.captain.services.UserServiceInterface" />
</bean>
<bean id="scoreService" factory-bean="serviceFactoryBean" factory-method="buildService">
<constructor-arg value="com.captain.services.ScoreServiceInterface" />
</bean>
my controller:
public class HomepageController {
//This doesn't work
#Autowired #Qualifier("userService") UserServiceInterface userService;
//This does
#Resource(name="scoreService") ScoreServiceInterface scoreService;
}
I suggest you take the factory pattern one step further and implement your factories as Spring FactoryBean classes. The FactoryBean interface has a getObjectType() method which the contain calls to discover what type the factory will return. This gives your autowiring something to get its teeth into, as long as your factory returns a sensible value.
I had a similar problem, but for me I wanted to use a single factory for creating mocked-out implementations of my auto-wired dependencies using JMockit (the testing framework that I am required to use).
After finding no satisfactory solution on the interwebs, I threw together a simple solution that is working really well for me.
My solution uses a Spring FactoryBean as well, but it only uses a single factory bean for creating all my beans (which the original asker seems to have wished to do).
My solution was to implement a factory-of-factories meta-factory that serves-up FactoryBean wrappers around the real, single factory.
Here is the Java for my JMockit mock bean factory:
public class MockBeanFactory<C> implements FactoryBean<C> {
private Class<C> mockBeanType;
protected MockBeanFactory(){}
protected <C> C create(Class<C> mockClass) {
return Mockit.newEmptyProxy(mockClass);
}
#Override
public C getObject() throws Exception {
return create(mockBeanType);
}
#Override
public Class<C> getObjectType() {
return mockBeanType;
}
#Override
public boolean isSingleton() {
return true;
}
public static class MetaFactory {
public <C> MockBeanFactory<C> createFactory(Class<C> mockBeanType) {
MockBeanFactory<C> factory = new MockBeanFactory<C>();
factory.mockBeanType = mockBeanType;
return factory;
}
}
}
And then in the Spring context XML file, you just can simply create the meta factory that creates the specific bean-type factories:
<bean id="metaFactory" class="com.stackoverflow.MockBeanFactory$MetaFactory"/>
<bean factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="mockBeanType" value="com.stackoverflow.YourService"/>
</bean>
To make this work for the original asker's situation, it could be tweaked to make the FactoryBeans into wrappers/adapter for the serviceFactoryBean:
public class FancyFactoryAdapter<C> implements FactoryBean<C> {
private Class<C> clientClass;
private FancyFactory serviceFactoryBean;
protected FancyFactoryAdapter(){}
#Override
public C getObject() throws Exception {
return serviceFactoryBean.buildService(clientClass);
}
#Override
public Class<C> getObjectType() {
return clientClass;
}
#Override
public boolean isSingleton() {
return true;
}
public static class MetaFactory {
#Autowired FancyFactory serviceFactoryBean;
public <C> FancyFactoryAdapter<C> createFactory(Class<C> clientClass) {
FancyFactoryAdapter<C> factory = new FancyFactoryAdapter<C>();
factory.clientClass = clientClass;
factory.serviceFactoryBean = serviceFactoryBean;
return factory;
}
}
}
Then in the XML (notice the userServiceFactory id and the userService bean id are necessary only to work with the #Qualifier annotation):
<bean id="metaFactory" class="com.stackoverflow.FancyFactoryAdapter$MetaFactory"/>
<bean id="userServiceFactory" factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="clientClass" value="com.captain.services.UserServiceInterface"/>
</bean>
<bean id="userService" factory-bean="userServiceFactory"/>
<bean id="scoreServiceFactory" factory-bean="metaFactory" factory-method="createFactory">
<constructor-arg name="clientClass" value="com.captain.services.ScoreServiceInterface"/>
</bean>
<bean id="scoreService" factory-bean="scoreServiceFactory"/>
And that's it, just one little Java class and a smidge of boiler-plate configuration and your custom bean factory can create all of your beans and have Spring resolve them successfully.
You should be able to achieve this using:
<bean id="myCreatedObjectBean" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass">
<value>com.mycompany.MyFactoryClass</value>
</property>
<property name="targetMethod">
<value>myFactoryMethod</value>
</property>
</bean>
Then you can use either #Resource or #Autowired + #Qualifier to inject into your object directly.

How to do Spring Lookup Method Injection with Annotations?

Is there any way to use Lookup Method Injection using annotations?
Given the following class:
#Service
public abstract class A {
protected abstract createB();
}
In order to get it to work I have to declare in spring applicationContext.xml the following:
<bean id="b" class="com.xyz.B">
</bean>
<bean id="a" class="com.xyz.A">
<lookup-method name="createB" bean="b"/>
</bean>
Even though I am using <context:component-scan base> I have to declare it also in the XML. Not a good approach I think.
How to do it with annotations?
It is possible to use javax.inject.Provider. All thanks go to Phil Webb.
public class MySingleton {
#Autowired
private Provider<MyPrototype> myPrototype;
public void operation() {
MyPrototype instance = myPrototype.get();
// do something with the instance
}
}
It is also possible with org.springframework.beans.factory.ObjectFactory if you want to keep up with Spring API
public class MySingleton {
#Autowired
private ObjectFactory<MyPrototype> myPrototypeFactory;
public void operation() {
MyPrototype instance = myPrototypeFactory.getObject();
// do something with the instance
}
}
you can read more in the documentation.
It is implemented only with Spring >= 4.1 See the ticket.
Finally introduced as #Lookup annotation. Here is discussion on how to use it.

Spring 3 DI using generic DAO interface

I'm trying to use #Autowired annotation with my generic Dao interface like this:
public interface DaoContainer<E extends DomainObject> {
public int numberOfItems();
// Other methods omitted for brevity
}
I use this interface in my Controller in following fashion:
#Configurable
public class HelloWorld {
#Autowired
private DaoContainer<Notification> notificationContainer;
#Autowired
private DaoContainer<User> userContainer;
// Implementation omitted for brevity
}
I've configured my application context with following configuration
<context:spring-configured />
<context:component-scan base-package="com.organization.sample">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
type="annotation" />
</context:component-scan>
<tx:annotation-driven />
This works only partially, since Spring creates and injects only one instance of my DaoContainer, namely DaoContainer. In other words, if I ask userContainer.numberOfItems(); I get the number of notificationContainer.numberOfItems()
I've tried to use strongly typed interfaces to mark the correct implementation like this:
public interface NotificationContainer extends DaoContainer<Notification> { }
public interface UserContainer extends DaoContainer<User> { }
And then used these interfaces like this:
#Configurable
public class HelloWorld {
#Autowired
private NotificationContainer notificationContainer;
#Autowired
private UserContainer userContainer;
// Implementation omitted...
}
Sadly this fails to BeanCreationException:
org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.organization.sample.dao.NotificationContainer com.organization.sample.HelloWorld.notificationContainer; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [com.organization.sample.NotificationContainer] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
Now, I'm a little confused how should I proceed or is using multiple Dao's even possible. Any help would be greatly appreciated :)
Ok, I think I've found a fairly reasonable solution for this puzzle. One way of dealing with this would be creating interface and implementations for each and every entity in my domain model (as Espen pointed out in his answer earlier). Now, consider having hundreds of entities and respectively hundreds of implementations. That wouldn't feel right, would it?
I've discarded strongly typed sub-interfaces and I'm using generic interface instead:
#Service // Using #Service annotation instead #Configurable as Espen pointed out
public class HelloWorld {
#Autowired
private DaoContainer<Notification> notificationContainer;
#Autowired
private DaoContainer<User> userContainer;
// Implementation omitted
}
Implementation for my DaoContainer interface would look something like this:
#Repository
public class DaoContainerImpl<E extends DomainObject> implements DaoContainer<E> {
// This is something I need in my application logic
protected Class<E> type;
public int getNumberOfItems() {
// implementation omitted
}
// getters and setters for fields omitted
}
And finally application context:
<context:spring-configured />
<context:component-scan base-package="com.organization.sample">
<context:exclude-filter expression="org.springframework.stereotype.Controller"
type="annotation" />
</context:component-scan>
<bean class="com.organization.sample.dao.DaoContainerImpl" id="userContainer">
<property name="type" value="com.organization.sample.domain.DiaryUser" />
</bean>
<bean class="com.organization.sample.dao.DaoContainerImpl" id="notificationContainer">
<property name="type" value="com.organization.sample.domain.DiaryNotification" />
</bean>
So basically I couldn't get pure generic autowiring to work, but this solution works for me (at least for now) :)
It's possible to autowire as many bean as you like.
But when you're using autowiring by type, it can be only one of bean of each interface. Your error message says you have none bean available in the Spring container of given interface.
A solution:
Your missing DAO implementations:
#Repository
public class NotificationContainerImpl implements NotificationContainer {}
#Repository
public class UserContainerImpl implements UserContainer {}
Your service class:
#Service
public class HelloWorld {
#Autowired
private NotificationContainer notificationContainer;
#Autowired
private UserContainer userContainer;
// Implementation omitted...
}
I replaced the #Configurable annotation with #Service. #Configurable is used together with AspectJ and is not what you want here. You must use #Component or a specialization of it like #Service.
Also remember to have all your Spring components inside your com.organization.sample package to enable the Spring container to find them.
I hope this helps!

Resources