I have a lot of repeating beans in my context definition files where only the names are different.
So when I want definition for the beans a, b and c I have to add:
<bean id="a" class="org.project.A" />
<bean id="b" class="org.project.B" />
<bean id="c" class="org.project.C" />
<bean id="aDao" class="org.project.ADAO" />
<bean id="bDao" class="org.project.BDAO" />
<bean id="cDao" class="org.project.CDAO" />
As there are many more than 3 beans, I want something like:
bean: a,b,c
templates:
- <bean id=":bean:" class="org.project.:bean:upper:" />
- <bean id=":bean:Dao" class="org.project.:bean:upper:DAO" />
Is there already a way to do this in Spring?
And if I have to implement my own solution, how can I make Spring call this function before trying to import the generated files?
There is no such functionality in Spring. You can write a maven plugin or some other pre-processing tool that searches for beans and generates the XML file.
Or you can let the Spring do this and drop the XML definitions altogether by annotating your beans with #Service, #Repository and friends.
If you use annotation based container configuration you don't need to generate the bean definition xml elements.
In one of my projects I used Apache Velocity to generate config for an IoC framework using a template file. The template language is simple yet powerful.
You may implement it as a Java app, call it from Ant, etc.
http://velocity.apache.org/
The last time I checked (several years ago), Spring used the following (simplified) algorithm to create beans:
Read XML files to get bean definition. The beans are not created immediately. Instead, their definitions are held in some data structures that later (in step 4) will be queried to create the beans.
Spring iterates over each bean definition, and uses reflection to check if a bean's class implements the BeanFactoryPostProcessor interface.
If so, that bean is created and its postProcessBeanFactory() operation is invoked. That method is typically coded to iterate over all the bean definitions and modify some of them, for example, to replace "${property.value}" with the value of a property read from a Java properties file.
Afterwards, the remaining ("normal") beans are created according to the (possibly modified) bean definitions.
It's been several years since I last looked at Spring, but if it still operates in the same way, then it might be possible to implement a class that implements the BeanFactoryPostProcessor interface and codes postProcessBeanFactory() to append a bean's id property onto its class property.
Related
In my Java/spring project there are lots of beans configured in an xml like,
<beans>..
<bean id="beanOne" class=...>
<property name="x" value="1"/>
<property name="y" value="something"/>
<property name="z" value="something else"/>
</bean>
</beans>
"beanOne"'s properties(x,y,z) values keep changing for different needs/machines. I can create different xml files having different values, one for each need/machine. But I want to write some custom bean creation logic so that I can define different properties in a single properties (or) json file and the custom class takes care of creating the beans with appropriate values from that single properties (or) json file for all needs/machines.
So how to can I do that in spring? - Extend AbstractFactoryBean, implement FactoryBean, implement BeanFactory, or something else? I just need the logic/skeleton of how to do that using spring.
Follow these steps to do the same,
create the object for your required bean.
Set the required properties for that object, you can fetch it from anywhere you want.
Register that object in beanFactory as a bean.
Reference : https://wordpress.com/post/anilagrawal038.wordpress.com/3
I'm trying to get a better understanding of the #Autowired annotations component scanning, but all the examples I found so far use context.getBean(..) at some point to get at least one Bean to start with.
I also read that doing that is considered bad practice , but I can't seem to find any information on how to do it without context.getBean(..)
Could somebody please enlighten me with an example and information on how to do this ?
Define your bean in xml and use
<context:component-scan base-package="com" />
<mvc:annotation-driven />
Bean def
<bean id="processEngine" class="com.processEngine">
<property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
now you can get bean as following
#Autowired
private ProcessEngine processEngine;
how it works
spring scans the bean's recipes either from xml or java configuration. then spring creates a beanDefinitions which are 'loaded' into BeanFactory. BeanFactory triggers a set of BeanPostProcessors (BPP) which are scanning classes for particular annotations like Autowired/Resource/PostProcessor and etc. and do appropriate actions. in case when your class contains #Autowired annotation, AutowiredAnnotationBeanPostProcessor would auto wire required field (dependencies), and when creation of an object is done and all BPP worked out, object is ready to be used by the app, from this point your code can get 'ready' objects from container.
there are some cases when you would need to access this beans from the code which is out of spring's control and not managed by container. in order to do so, you would need to get the ApplicationContext (container) and call #getBean specifying either name or type. using applicationContext directly is not a good practice because there are some problems that you can come to, f.ex. id of a bean might be changed and if you refer to bean by id then NPE would be thrown.
configuration
there are several approaches to configure spring to scan the classes for finding bean recipes. one would be defining component-scan, in this case classes which are located in the path that you've set and having any of valid spring annotations like #Component, #Service, #Repository, #Controller (for web container) would be considered. another way would be specifying each bean separately using <bean> or #Bean.
examples.
if you want to create a web app then you should see DispatcherServlet with ContextLoaderListener classes. this classes would boot your app and load everything according to configuration. f.ex. here,
but if you want to create a desktop app, then you would end up with something like this
From time to time (usually when not using Spring Boot), I use something along the lines of the following code:
public static <T> T autowire(ApplicationContext ctx, T bean) {
ctx.getAutowireCapableBeanFactory().autowireBean(bean);
return bean;
}
In my main, I create an instance of the main application class that contains a few #Autowired annotations for the main services / entry points to my Spring application.
With Spring it is possible to inject a list of beans by the interface class like:
#Component
public class Service {
#Autowire
private List<InterfaceType> implementingBeans;
...
}
All defined beans that implement this interface will be present in this List.
The annotation based approach is not possible for me, as the Service class is in a module that must not have spring dependencies.
I need to use this mechanism from outside via xml configuration.
<bean id="service" class="...Service">
<property name="implementingBeans">
??? tell spring to create a list bean that resolves all beans of the interfaceType.
</property>
</bean>
Does anyone know how to solve this?
EDIT: Additionally, there are more than one spring applications that use this service. So the best solution would be to handle this szenario completely via xml configuration. I can then copy the xml parts to all spriong applications that need this.
I want to avoid having a kind of initializer bean that gets the service injected and must then be copied to all spring applications.
Kind regards.
An XML-only solution would simply have you declare a <bean> of the "external" type and provide an autowire value of "byType".
Controls whether bean properties are "autowired". This is an
automagical process in which bean references don't need to be coded
explicitly in the XML bean definition file, but rather the Spring
container works out dependencies.
[...]
"byType" Autowiring if there is exactly one bean of the property type in the container. If there is more than one, a fatal error is
raised, and you cannot use byType autowiring for that bean. If there
is none, nothing special happens.
The explanation is a little confusing in that we expect multiple InterfaceType beans, but the actual field is of type List and Spring will be able to dynamically instantiate one and add all the InterfaceType beans to it, then inject it.
Your XML would simply look like
<bean id="service" class="...Service" autowire="byType">
</bean>
My original suggested solution made use of SpEL.
In the module that does have Spring dependencies, create a DTO
#Component(value = "beanDTO")
public class BeanDTO {
#Autowire
private List<InterfaceType> implementingBeans;
public List<InterfaceType> getImplementingBeans() {
return implementingBeans;
}
}
and then use SpEL to retrieve the value of implementingBeans from the beanDTO bean.
<bean id="service" depends-on="beanDTO" class="...Service">
<property name="implementingBeans" value="{beanDTO.implementingBeans}" />
</bean>
Spring will create the BeanTDO bean, inject all the beans that are of type InterfaceType. It will then create the service bean and set its property from beanDTO's implementingBeans property.
Following comments on question:
In an effort to be more JSR 330 compliant, Spring has introduced support for Java EE's javax.inject package. You can now annotate your injection targets with #javax.inject.Inject instead of #Autowired. Similarly, you can use #Named instead of #Component. The documentation has more details.
I have a question regarding declaration of classes in applicationContext.xml
In applicationContext.xml do we need to specify all the classes from the application?
E.g.
In my small web application I have a Entity class, Service class and DAO class. So currently it is defined as
<!-- Beans Declaration -->
<bean id="Employees"
class="net.test.model.Employees" />
<!-- User Service Declaration -->
<bean id="
EmployeeService" class="net.test.employees.service.EmployeeService">
<property name="employeesDAO" ref="EmployeeDAOImpl" />
</bean>
<!-- User DAO Declaration -->
<bean id="EmployeeDAO" class="net.test.employee.dao.EmployeeDAOImpl">
<property name="sessionFactory" ref="SessionFactory" />
</bean>
So if I have multiple entity, service and dao classes do I need to mention all those classes in applicationContext.xml?
Any insight into this is highly appreciable.
Regards
Update 1
ManagedBean
#ManagedBean(name="empMB")
#Named
#Scope("request")
public class EmployeesManagedBean implements Serializable {
and I have Inject annotation
#Inject
EmployeesService employeesService;
In EmployeesService I have annotations like
#Named
public class EmployeesService implements IEmployeesService {
#Inject
EmployeesDAO employeesDAO;
#Override
public List<Employees> getEmployees() {
return getEmployeesDAO().getEmployees();
}
and finally in applicationContext.xml I have
<context:component-scan base-package="net.test" />
Now the problem is when I run my application I am getting
java.lang.NullPointerException at
net.test.managed.bean.EmployeesManagedBean.getEmpList(EmployeesManagedBean.java:53)
What am I doing wrongly to get nullpointer exception?
In applicationContext.xml do we need to specify all the classes from
the application?
No. Declaring model classes like your net.test.model.Employees is pointless unless you need a prototype to work with, something like initializing its values, but you can do this directly in the class and just instantiate it.
So if I have multiple entity, service and dao classes do I need to
mention all those classes in applicationContext.xml?
As I explained before, entity classes no. Services and DAOs are ok because most of the time you need DAOs injected to the Services (and that's the point of DI). But of course, if you create 3 DAOs and you want them to be injected in your 3 Services, then mention them in your Spring XML Bean Definition file (what you call applicationContext.xml).
But one thing, you may want to use package scanning autodetection and annotation based config to avoid writing everything in your Bean Definition File.
The bean declaration in the application context is to register the bean in the application container.
If the bean is not registered, the container wouldn't be able to dependency inject any instance of that class, or apply interceptors to the object of the class.
So unless the reference of bean is not required for any task like intercepting it or inject it, or create default singleton object of it, there is no need to declare it in the applicationContext.xml
Hope this helps.
Ideally yes, another way can be using Spring Annotations so that you don't to add multiple entries in 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" />