Spring Dynamic service provider injection based on configuration in properties file - spring

I have multiple mutually exclusive data sources and I want to configure which implementation to inject/autowire into Controller based on a property defined in a configuration file.
I'm thinking of something along the lines #Qualifier but I'm no spring expert so can't figure the mechanics.
The aim is to avoid the convoluted if/else that will result.
Any ideas?

You can do the trick with context:property-placeholder and #Qualifier.
It will look like the following:
app.properties
some.implementation=com.example.MyServiceImpl
spring context file
<context:property-placeholder
location="classpath:/app.properties"/>
<bean id="myService" class="${some.implementation}" />
Controller
#Autowired
#Qualifier("myService")
private MyService myService;
As the opposite solution: you can save in properties file bean ID, and use it within #Qualifier
#Qualifier("${some.implementation.bean.id}")
But if you are using Spring 3.1+, then you probably need to look at Profiles mechanism.

Related

Types of Spring configuration in theory

I would like to ask for explanation of Spring configuration types?
Here is what I know but I am confused by what I have found here on stack and other places.
XML based configuration
Java based configuration
Annotation based configuration (this is what I am interested about)
I have read a lot of articles or opinions that there are basically only two configuration options (XML and Java). So what is wrong when I consider Annotation based config as a third option? I asssume that this option is available only when I use XML based configuration using:
<context:annotation-config/>
So is that why some people does not consider Annotation based config as a third options because it is dependent on XML (or Java) config?
I have one more questions:
Can I use Annotation approach by using Java based configuration? I was not able to find how to enable it using Java. (maybe using #EnableAutoConfiguration??)
I consider this scenario using Spring Core. When we are talking about SpringBoot I assume there is Annotation config enabled by default in #SpringBootApplication annotation?
Thank you!
You are right in the general sense, I refer you to this small section in the official docs for spring [https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html]
Here you will see an example of using XML configurations using the
<beans>
<context:annotation-config/>
<bean class="com.acme.AppConfig"/>
</beans>
and JAVA spring component scanning
#Configuration
public class AppConfig {
private final SomeBean someBean;
public AppConfig(SomeBean someBean) {
this.someBean = someBean;
}
// #Bean definition using "SomeBean"
}
You are also right about springboot #SpringBootApplication I contains #Configuration, #ComponentScan and #EnableAutoConfiguration to scan and configure your beans

Is there an annotation equivalent to the Spring AOP aop:include configuration for autoproxies

When specifying the XML configuration below:
<aop:aspectj-autoproxy>
<aop:include name="myBean" />
</aop:aspectj-autoproxy>
We all know that the #EnableAspectJAutoProxy annotation is the equivalent to the aspectj-autoproxy XML configuration but is there a java-based annotation equivalent for the aop:include XML configuration? I searched extensively and could not find.
Normally you tell Spring that you are using a particular feature, like Transaction management and it will create the proxies needed.
For instance #EnableTransactionManagement will cause Spring to create proxies for Components (services, controllers and repositories) which use #Transactional, you don't need to declare this, Spring automatically finds the beans that need to be proxied.
It works the same way with #EnableScheduling causing Spring to detect #Scheduled methods, and #EnableCaching to detect #Cached method.

override spring bean in a jar file

I have a dao jar file that contains all the domain objects and service classes. it has a config file dao-resource.xml with id=datasource.
I am using this jar file in another project which has its own app-context.xml, but i want to override the bean with id="datasource" in the jar file
how do i do this. I tried to add a bean with same id in app-context.xml and added both files to classpathxmlapplicat.... first dao-resource.xml then app-context.xml
but that did not seem to work.
how else can i override a bean
Having spring config files in jars makes things a bit harder to manage. If you have annotated your classes it would be easier.
But anyway, I'd suggest splitting the dao xml in two parts - your beans, and infrastructure-related beans (like the datasource). Then you can include only the ones you need in your app-context.xml.
Another way would be to use primary="true" on your overriding bean. This would mean all injection points that need a bean of type DataSource, would pick your primary bean. But that won't work if you refer to your datasource in your dao xml.
So in short - you can't override a bean, so split your xml file and include only the parts you need.

Using EasyMock 3 IMockBuilder with Spring

I've been looking into using EasyMock 3's IMockBuilder as a means of generating partial mocks (I know partial mocking may suggest a design flaw, but I'm writing tests for old code). Presumably I can use the deprecated static EasyMock.createMock() methods to create beans in my Spring config, like this:
<bean id="myBean" class="org.easymock.EasyMock" factory-method="createMock">
<constructor-arg value="org.mypackage.MyClass.class" />
</bean>
When creating a partial mock using an IMockBuilder, I need to make several calls to addMockedMethod() in order to define the methods I want mocked. Is there a way I can do this in a Spring XML configuration file? Ideally I'd like all the dependencies of all my beans set by Spring, and don't want to have to override them in my test cases in order to pass in mock objects created in this way.
Thanks
No, XML config isn't capable of that sort of flexibility.
You have two options:
Write an implementation of FactoryBean which creates the mock, configures it, and returns the mock to Spring. See Customizing instantiation logic with the FactoryBean Interface.
Use #Configuration-style configuration in Java, instead of XML style configuration. This is the most flexible approach, and is generally better than XML config. See Java-based container configuration

Referencing beans in xml config created via Annotations

This must be possible but I can't work out how or see it in the docs.
I need to reference a bean which has been created via an annotation #Service and context:component-scan, within a spring xml config file.
How is this achieved?
Cheers
use #Service("myService")
in the xml, use <property name="myProperty" ref="myService"/>

Resources