dependency-check in Spring3.x - java

Spring2.5 had a feature called dependency-check which can be given for a bean tag and default-dependency-check which can be given at the parent level <beans> tag.
Eg: <bean id="soandSo" class="..." dependecy-check=""/>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
default-dependency-check="all">
however in Spring3.x these attributes are deprecated, is there any alternate way of setting dependency-check apart from using #Required attribute and any equivalent to default-dependency-check in Spring3.x??

This feature is no loger supported since Spring 3.x. You can achieve similar result by telling Spring to respect #Required and #Autowired annotations. It can be done using any of the following configuration options within XML context file:
<context:annotation-config/>
<context:component-scan base-package="*"/>
You can skip those options by registering appropriate BeanPostProcessors such as AutowiredAnnotationBeanPostProcessor and RequiredAnnotationBeanPostProcessor.

I think no, because In Spring 2.5 annotations were fully embraced and as the framework evolves through these types of changes, its evident that annotations will continue to be a strong driver in keeping the framework as clear and straightforward as possible.
Spring team now encourages developers to use the following alternatives going forward (with Spring 3 and beyond).
Use constructors (constructor injection instead of setter injection)
exclusively to ensure the right properties are set. Create setters
with a dedicated init method implemented.
Create setters with #Required annotation when the property is required.
Use #Autowired-driven injection which also implies a required property by
default.

Related

Overriding Spring bean

I have the following scenario:
Spring project A with multiple bean configurations, including a bean named "searchHelper":
<bean name="searchHelper" class="com.test.SearchHelperImpl"/>
where SearchHelperImpl implements "SearchHelper" interface
Spring project B depends on A with a custom SearchHelperBImpl
What I was thinking of making is just copying the whole configuration into the new project and changing what needs to be changed, but that's not convenient and there must be an easier way of doing this.
My question is, how do I override the definition of the "searchHelper" bean to use SearchHelperBImpl instead of SearchHelperImpl? I want to use the same bean name in order for everything that uses this name to use the new implementation. I am using Spring 3.2.2
Thanks
You should be able to utilize the primary xml attribute on your bean element.
<bean name="searchHelper" primary="true" class="com.test.SearchHelperBImpl"/>
Alternatively, if you are using JavaConfig, you can utilize the #Primary annotation.
#Primary
#Bean
public SearchHelper searchHelper() {
return new SearchHelperBImpl();
}
One interesting "feature" (some consider it a bug) of Spring is that a bean with the same name declared later in configuration will override a bean declared earlier in configuration. So if your project B depends on A, and the configuration in A is included in B, and B defines a bean by the same name after the A configuration then the B instance will "win" and that's the instance you will get.
I would not recommend depending on this behavior, but would go with the answer regarding the Primary annotation. I just thought I would bring this up so you would be aware that even without the primary, or in case the one in project A is also primary you would know that the latest definition wins.
NOTE
This answer relates to how to avoid duplicate bean definitions. For overriding see the answer by nicholas.hauschild.
More effective solution to avoid copying is to place all the beans that are common for both projects in a separate XML configuration file, say "common-beans.xml". And in the configuration XML file for the project B (and any other project that needs those beans) you import that file like this:
<import resource="common-beans.xml" />
Simple example
example-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"
<!--
Assuming common-beans.xml is a Spring config file
that contains the definitions you need to use
in the current project.
-->
<import resource="common-beans.xml" />
<!-- Defining a bean with the implementaion you need -->
<bean name="searchHelper" class="com.test.SearchHelperBImpl"/>
<!-- Some other configurations if needed -->
</beans>
Useful reading:
Composing XML-based configuration
metadata

Override default-lazy-init=true for Spring bean definitions

I am maintaining a large Java EE system. Most of the business logic is converted from EJB:s into POJO:s configured in several spring context configuration files. EJB:s are mostly used as Facades, that looks up the business logic spring beans from a context composed of all spring context configuration files mentioned earlier. For this we use the AbstractStatelessSessionBean provided with the spring framework.
All these configuration files have the default-lazy-init=true directive, which means that the business logic beans are not created until they are actually used by the system. This is preferable most of the time since republishing in developer mode becomes faster.
But when large merges are made, we are having problems finding all the configuration errors, such as missing dependencies.
My idea is to write some form of integration test, with the purpose of finding those errors. This means, i think, that I need to find a way to override all default-lazy-init=true declarations when creating the application context.
Is there any way of doing this programmatically, or perhaps with some test-only context file that includes all the actual context files?
Let's say currently you have a single applicationContext.xml file containing all bean definitions:
<beans default-lazy-init="true">
<!-- all your beans -->
</beans>
Rename it to applicationContext-main.xml or something and remove default-lazy-init="true" attribute. Now create two applicationContext.xml files:
<beans default-lazy-init="true">
<import resource="applicationContext-core.xml"/>
</beans>
and:
<beans default-lazy-init="false">
<import resource="applicationContext-core.xml"/>
</beans>
As you can see the only difference is the value of default-lazy-init. During development your team can use the former version of applicationContext.xml that includes all the beans with lazy-init. On staging and testing environments switch it to the latter so that all beans included in applicationContext-core.xml are created eagerly.
I believe that the best way is to control lazy init of beans is to leave the default-lazy-init out of all config files except the topmost as Tomasz Nurkiewicz suggests. I did however in this case need a quick and dirty fix to verify all bean definitions. (It is a bit of a process to change the lazy init policy.)
I came up with a simple BeanFactoryPostProcessor which seems to do the job:
public class NonLazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
for (String beanName : beanFactory.getBeanDefinitionNames()) {
beanFactory.getBeanDefinition(beanName).setLazyInit(false);
}
}
}
If included in a context file, it will override the lazy init flag set by any included context files.
<beans default-lazy-init="false">
<bean class="example.NonLazyInitBeanFactoryPostProcessor" />
<import resource="applicationContext-core.xml"/>
</beans>
If I try to create a context from the above xml, configuration errors previously hidden by lazy initialization will show up immediately as exceptions.
There is one 'but' in this PostProcessor
for (String beanName : beanFactory.getBeanDefinitionNames()) {
beanFactory.getBeanDefinition(beanName).setLazyInit(false);
}
This for loop will iterate only over top most beans not including e.g internal(local) bean defintions ...
You can't access the scanner from the context - it's completely private, but since you can step into the source code, you can see what's required to set up your own. I used Spring's own ReflectionTestUtils to set my own configured scanner in the context:
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(context);
BeanDefinitionDefaults defaults = new BeanDefinitionDefaults();
defaults.setLazyInit(true);
scanner.setBeanDefinitionDefaults(defaults);
ReflectionTestUtils.setField(context, "scanner", scanner);
context.scan("com.some.path");
You can do this anywhere you have access to the Application Context before the component scan takes place.

Can I wire in a spring #stereotype bean using xml

If I create a bean as follows:
#Repository("myRepository")
public class MyRepository {
...
}
In XML should I be able to wire it in as follows:
<bean id="xmlBean" class="uk.co.foo.myBean">
<constructor-arg ref="myRepository"/>
</bean>
Or is mixing like this not allowed?
The reason is for some things, generally business logic, it make sense for me to configure and wire various beans in XML as I may have multiple instances of the same interfaces, be likely to swap stuff round and it lets me to see my project configuration clearly from XML. However for repositorys it's very unlikely I am going to need to do or see any of those things and it's much more convenient just to use annotations.
It should work fine dont forget to enable context scanning in your xml configuration for Spring to find the bean it needs to AutoWire. You enable scanning by
<context:component-scan base-package="your package to scan" />

How to enable #Required?

How to enable the #Required annotation in Java (Spring 3.1) ? Not in a xml, but in through Java. Also under which annotation I put this enabling? Under #Feature (in #FutureConfiguration or #Bean (in #Configuration) ?
Edit:
#Feature
public MvcAnnotationDriven annotationDriven(ConversionService conversionService) {
return new MvcAnnotationDriven().conversionService(conversionService)
.argumentResolvers(new CustomArgumentResolver());
}
Does this enables all annotations?
#anubhava's answer works, but he's referenced the Spring 2.0 manual, which is 5 years old.
In XML config, Spring 3.x has a more elegant approach: <context:annotation-config/>. This also enabled a whole other bunch of features that you'll probably want, whereas RequiredAnnotationBeanPostProcessor only enables a few.
See Spring 3.x manual.
If you're using #Bean-style config, then annotations like #Required should already be enabled, since that's how #Bean works. However, it's possible that this is a bug - Spring 3.1 is still in early beta, and big chunks of it are likely to be broken.
Unless you really know what you're doing, I strongly recommend sticking to 3.0.x.
From the Spring manual:
There is one last little (small, tiny)
piece of Spring configuration that is
required to actually 'switch on' this
behavior. Simply annotating the
'setter' properties of your classes is
not enough to get this behavior. You
need to enable a component that is
aware of the #Required annotation and
that can process it appropriately.
This component is the
RequiredAnnotationBeanPostProcessor
class. This is a special
BeanPostProcessor implementation that
is #Required-aware and actually
provides the 'blow up if this required
property has not been set' logic. It
is very easy to configure; simply drop
the following bean definition into
your Spring XML configuration.
<bean class=
"org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
Please check: http://static.springsource.org/spring/docs/2.0.x/reference/metadata.html
Use AnnotationConfigApplicationContext if you don't want to use XML:
Standalone application context,
accepting annotated classes as input -
in particular #Configuration-annotated
classes, but also plain #Components
and JSR-330 compliant classes using
javax.inject annotations. Allows for
registering classes one by one
(register(java.lang.Class...)) as well
as for classpath scanning
(scan(java.lang.String...)).
In case of multiple Configuration
classes, Bean methods defined in later
classes will override those defined in
earlier classes. This can be leveraged
to deliberately override certain bean
definitions via an extra Configuration
class.
Sample Code:
ConfigurableApplicationContext applicationContext =
new AnnotationConfigApplicationContext(
"com.mycompany.package1",
"com.mycompany.package2",
"com.mycompany.package3"
// etc.
);
applicationContext.refresh();

Can I inject a Java object using Spring without any xml configuration files?

I want to inject a plain java object using Spring programmatically without using any xml configuration. Want to inject fields/methods annotated with tags Like #EJB, #PostConstruct etc. Is that possible? Thanks!
Creating an ApplicationContext without XML (using AnnotationConfigApplicationContext)
With AnnotationConfigApplicationContext, you don't need any XML at all. You create the Application context programatically and either
a) manually register annotated classes
appContext.register( MyTypeA.class,
MyTypeB.class,
MyTypeC.class );
b) or scan the classpath for annotated classes
appContext.scan(
"com.mycompany.myproject.mypackagea",
"com.mycompany.myproject.mypackageb"
)
If you use one of the convenience constructors
AnnotationConfigApplicationContext(Class<?> ... annotatedClasses)
or
AnnotationConfigApplicationContext(String ... basePackages)
the context is created and refreshed automatically, otherwise you need to call the refresh() method manually after adding the classes or packages.
Autowiring existing non-Spring beans (using AutowireCapableBeanFactory)
For autowiring an existing bean I think the preferred idiom is to use
appContext.getAutowireCapableBeanFactory().autowireBean(existingBean)
Or, if you want more control, use
appContext.getAutowireCapableBeanFactory()
.autowireBeanProperties(
existingBean,
autowireMode,
// e.g. AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE
dependencyCheck
)
For further reference, see
ApplicationContext.getAutowireCapeableBeanFactory()
AutowireCapeableBeanFactory.autowireBean(Object existingBean)
AutowireCapeableBeanFactory.autowireBeanProperties(Object
existingBean, int autowireMode,
boolean dependencyCheck)
Yes, you can annotate any POJO with #Component, #Service, #Controller, or #Respository (depending on its responsibilities), and it becomes a spring bean. You just have to put this line into the applicationContext.xml:
<context:component-scan base-package="org.yourbasepackage" />
You can also use #PostConstruct and #PreDestroy instead of the xml init-method and destroy-method.
Update: There is a project called spring-javaconfig. Parts of it have become part of the core spring and you can see more details here. In short, it allows you to use java classes instead of xml for configuring your beans.
The documentation around annotation-based Spring configuration can be found here. You will need a minimal amount of XML, so that Spring knows to look for annotation-based configuration:
<context:component-scan base-package=".." />
Once that is done, you can use the #Autowired annotation to set up your beans.

Categories

Resources