override spring bean in a jar file - spring

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.

Related

Delay spring xml imports

I have an application where I have to read all application properties from properties files. Then override them from a external cache framework. Then initialize spring beans.
I am using Java Config of spring to read properties and override them. And using #import to load xml files. But xml files import as soon as context starts loading, resulting all the xml beans being initialized.
So is there a way I can delay xml files import until I load all the properties first?
You can use the following code.
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>
or individually add lazy-init on beans which you don't want to load.
Or
There are lot of ways you can achieve your requirement One of which can be use of depends-on or #DependsOn if you are looking for annotation based configuration,
You can read property file after that you can create a cache bean and use
depends-on to let the container know you bean is depending on some other bean you can initialise a cache bean and use the same as you see fit.
See this example for better clearity.
<bean id="primaryBean" depends-on="cacheBean"></bean>
Now IoC guarantees that depending bean will be created before the bean which depends on this bean, So you will have an instance of this bean, and can use it.
Other than this you can implement LifeCycle interface
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
For more references you can refer spring docs.

Annotating Groovy beans to load within Spring

Our application uses #Bean to define create beans and load them into the Spring context.
We now need to externalize these, so as to enable the application to be configured without touching the java source code.
We wish to replace the #Bean's with Groovy classes.
Is there a way to annotate a Groovy bean so that it will be picked up by Spring?
Note that we cannot simply reference each Groovy bean in the Spring XML, as we need to add and modify beans without touching the Spring code.
Thanks very much.
Use Spring config inheritance.
Move all shared code in a common "base" project that each individual / specific project depends on. Use Maven for this.
Create a common / base Spring config and put that into the "base" project. This config doesn't contain a definition for ProcessDefinition
In the specific project, create one bean which inherits from ProcessDefinition. Create a Spring config which imports the base config and define the single specific bean in it.

#Autowired in bean not in spring context

I am new to springs. Is there an alternative for autowired to be used in a ordinary java bean which is not present in spring context.
You can do so by using Spring #Configurable with some AspectJ magic.
If you need a detailed explanation, here is the link.
And here is a brief overview of how it can be achieved.
First you have some bean that you want injected somewhere:
#Component
public class InjectedClass {
// ...
}
Then, you have a class that is not spring-container managed, that you want to instantiate. You want autowiring to work with this class. You mark it as a #Configurable.
#Configurable
public class NonContainerManagedClass {
#Autowired
private InjectedClass injected;
// ...
}
Now you need to tell spring that you want this non-container managed autowiring to work. So you put the following in your spring configuration.
<context:load-time-weaver />
<context:spring-configured />
Now, since this kind of thing requires modification of the bytecodes of your #Configurable class. So you tell Tomcat to use a different classloader. You can do so by creating a context.xml in your application's META-INF diretory and putting the following in there.
<Context path="/youWebAppName">
<Loader loaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
useSystemClassLoaderAsParent="false"/>
</Context>
Now, Tomcat needs to find that classloader. You can ensure that by putting Spring's spring-tomcat-weaver.jar (probably named org.springframework.instrument.tomcat-<version>.jar) in your tomcat installation's lib directory, and voila, the aspectj magic starts working. For classes that are annotated with #Configurable annotation, the #Autowired dependencies are resolved automatically; even if the instances are created outside of the spring-container.
This is probably the only way to make that work with Spring, in a clean manner. Make sure that you have appropriate dependencies in your classpath.
Another way would be to use the full AspectJ functionality and providing custom aspects around all your constructors and handling the dependency-injection yourself.

Spring Dynamic service provider injection based on configuration in properties file

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.

Spring custom annotation - how to make it part of a library?

I've created a custom annotation (in Spring 3.05) that works great. I'd like to take that code and make it part of a library, packaged in a jar file, so I don't have to include my custom annotation code in each web app I write.
I'm unable to get Spring to act on the annotation, however. My library jar is in my web app's classpath and I tried scanning for it in applicationContext.xml:
<context:component-scan base-package="my.annotation.pkg" />
The field annotated with my custom annotation continues to be null.
Ideally I'd like to this to just work with a minimum of fuss and configuration, but so far I haven't had any success.
What part of Spring's wiring am I missing to get my custom annotation recognized when it's part of an external library?
Update
Here is how I "solved" it...just had to read a little more closely. In each context file (i.e. applicationContext.xml, dispatch-servlet.xml) I added the line:
<bean class="my.annotation.CustomInjector" />
...where my CustomInjector implements BeanPostProcessor. I based this on the code at this blog post: Implementing Seam style #Logger injection with Spring.
The author says I needed to do exactly what I did, so bad on me for not reading thoroughly. Why, though, is adding that bean definition required? Maybe Spring annotations are configured similarly under the hood - I just don't get why having the jar file on the classpath isn't enough.
Is your custom annotation annotated with the #Component annotation? From the Spring reference manual:
By default, classes annotated with #Component, #Repository, #Service, #Controller, or a custom annotation that itself is annotated with #Component are the only detected candidate components.
Alternatively, you could add a custom include-filter to the component-scan element in your XML configuration.

Resources