Can we use Autowiring byName and byType on same bean? if yes then how? - spring

I have tried autowiring byName and byType for different beans and it's working fine. But I want to use byName and byType autowiring on the same bean, can it be done? I have tried several way but it doesn't work.
<beans>
<bean id="car" class="com.Car" autowire="byName">
<property name="carName" value="BMW" />
</bean>
<bean id="wheel" class="com.Wheel">
<property name="wheelType" value="with Tube" />
</bean>
<bean id="wheel1" class="com.Wheel">
<property name="wheelType" value="tubeless" />
</bean>
<bean id="Byke" class="com.Byke" autowire="byType">
<property name="bykeName" value="Honda" />
</bean>
<bean id="Wheel" class="com.Wheel">
<property name="wheelType" value="No Information" />
</bean>
</beans>

In short answer is NO. For explanation see the relevant API doc which clearly takes only one argument for type of autowiring you need viz. autowireMode For quick reference pasting signature - java.lang.Object createBean(java.lang.Class<?> beanClass, int autowireMode ,boolean dependencyCheck) throws BeansException

Related

Spring static factory with factory-method and parameter

I have a problem transfering code to Spring applicationContext.xml
The source is:
File inFile = new File ("path/to/file/", "fileName.docx")
WordprocessingMLPackage wordMLPackage = Docx4J.load(inFile);
My not working solution is:
<bean id="inFile" class="java.io.File">
<constructor-arg value="path/to/file/" />
<constructor-arg value="fileName.docx" />
</bean>
<bean id="docx4j" class="org.docx4j.Docx4J" factory-method="load">
<constructor-arg ref="inFile" />
</bean>
<bean id="wordprocessingMLPackage" class="org.docx4j.openpackaging.packages.WordprocessingMLPackage" factory-bean="docx4j" />
What I'm getting out of the bean "wordprocessingMLPackage" is indeed an instance of the Class WordprocessingMLPackage, but it seems empty although the File I'm trying to load isn't (and yes, the path is doublechecked).
When trying
MainDocumentPart mdp = wordprocessingMLPackage.getMainDocumentPart();
List<Object> content = mdp.getContent();
I'm getting a NullPointerException because mdp is null!
Has anyone an idea... or even a solution?
============================================================
I found a solution especially for my problem.
Here is the source of Docx4j.load():
public static WordprocessingMLPackage load(File inFile) throws Docx4JException {
return WordprocessingMLPackage.load(inFile);
}
That means I can create an instance of WordprocessingMLPackage by its static self!
The code which is working:
<bean id="wordprocessingMLPackage" class="org.docx4j.openpackaging.packages.WordprocessingMLPackage" factory-method="load">
<constructor-arg ref="baseDocument" />
</bean>
So I found a lucky "workaround" for the original problem.
Since this question isn't urgent any more, I'm still interested in the correct solution, especially in a solution which allows injecting the WordprocessingMLPackage in other beans.
Thank you!
Here you need to make use of MethodInvokingFactoryBean as detailed below.
<bean id="beanId"
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.docx4j.Docx4J" />
<property name="targetMethod" value="load"/>
<property name="arguments">
<list>
<ref bean="inFile" />
</list>
</property>
</bean>
In your code get hold of applicationContext instance and invoke the below LOC
WordprocessingMLPackage ml = (WordprocessingMLPackage) applicationContext.getBean("beanId");
Let know in comments if you face any issues.
As Bond - Java Bond stated this works:
<bean id="inFile" class="java.io.File">
<constructor-arg value="path/to/file/" />
<constructor-arg value="fileName.docx" />
</bean>
<bean id="beanId" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.docx4j.Docx4J" />
<property name="targetMethod" value="load"/>
<property name="arguments">
<list>
<ref bean="inFile" />
</list>
</property>
</bean>
You can now use the bean as
WordprocessingMLPackage ml = (WordprocessingMLPackage) applicationContext.getBean("beanId");
or you can inject the bean directly as
<bean id="service" class="app.service.Service">
<property name="wordprocessingMLPackage" ref="beanId" />
</bean>
Thank you!!!

Dependency Injection returned results of bean init-method

I have two simple beans. In the first bean it calls a init-method and return string value.
Now I want to this returned string from first bean init-method , inject to my second bean
helloWorldBean3 property newKey. Please advise me on how to implement this requirement.
<bean id="helloWorldBean2" init-method="loadKey"
class="com.java.snippets.enterprise.services.HelloWorld2">
<property name="key" value="${key.supportiveFile}" />
<bean id="helloWorldBean3"
class="com.java.snippets.enterprise.services.HelloWorld">
<property name="newKey" ref="???" />
</bean>
Try using Spring EL like so:
<bean id="helloWorldBean3"
class="com.java.snippets.enterprise.services.HelloWorld">
<property name="newKey" value=""#{helloWorldBean2.loadKey()}"" />
</bean>

Multiple SharedEntityManagerBeans and ApplicationContext.getBean issue

I have two databases which I want to access from my Spring application. I configured two SharedEntityManagerBean for both databases. Here is the config:
<jpa:repositories base-package="xxx" entity-manager-factory-ref="entityManagerFactory1" />
<jpa:repositories base-package="xxx" entity-manager-factory-ref="entityManagerFactory2" />
<tx:annotation-driven/>
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager1">
<property name="entityManagerFactory" ref="entityManagerFactory1" />
<property name="dataSource" ref="dataSource1" />
</bean>
<bean class="org.springframework.orm.jpa.JpaTransactionManager"
id="transactionManager2">
<property name="entityManagerFactory" ref="entityManagerFactory2" />
<property name="dataSource" ref="dataSource2" />
</bean>
<bean id="entityManagerFactory1"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:packagesToScan="xxxxxx"
....
</bean>
<bean id="entityManagerFactory2"
class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
p:packagesToScan="xxxxx"
...
</bean>
<bean id="entityManager1" class="org.springframework.orm.jpa.support.SharedEntityManagerBean" >
<property name="entityManagerFactory" ref="entityManagerFactory1" />
</bean>
<bean id="entityManager2" class="org.springframework.orm.jpa.support.SharedEntityManagerBean">
<property name="entityManagerFactory" ref="entityManagerFactory2" />
</bean>
<bean id="dataSource1"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
...
</bean>
<bean id="dataSourceOntology"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
...
</bean>
I have two EntityLocators which are not managed by Spring that access entities in each of the corresponding databases. They look something like that:
public class SpringEntitiyLocator1 {
private EntityManager em;
public SpringEntitiyLocator1() {
}
private EntityManager getEM() {
if (em == null) {
ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(RequestFactoryServlet.getThreadLocalServletContext());
SharedEntityManagerBean bean = context.getBean("entityManager1",SharedEntityManagerBean.class);
em = bean.getObject();
}
return em;
}
}
When I have only one SharedEntityManagerBean defined in my applicationContext the call to getBean() works fine. However once I have both SharedEntityManagerBeans defined I get the error:
Bean named 'x' must be of type [y], but was actually of type [$Proxy]
I read on SO that I should use cglib proxying by adding <aop:config proxy-target-class="true"/> to my application.xml.
Is that the best solution ?
When I add that line I get Caused by: java.lang.NoClassDefFoundError: org/aspectj/util/PartialOrder$PartialComparable errors.
Do I need aspectj for that?
EDIT:
In case I have only one SharedEntityManagerBean defined I can call getBean(SharedEntityManagerBean.class). This works fine.
I debugged the code and it seems that this call will call getBean("&entityManager1",SharedEntityManagerBean.class) (note &) .
However when I pass the name getBean("EntityManager1",SharedEntityManagerBean.class) I get a type cast exception.
Having both SharedEntityManagerBeans defined and call getBean without a name also causes an exception (can't find a bean with that name).
So my current workaround is to call: getBean("&entityManager1",SharedEntityManagerBean.class) and getBean("&entityManager2",SharedEntityManagerBean.class)
This works fine.
Ok apparently SharedEntityManagerBean is a FactoryBean and for that I have to add & before the bean name to retrieve the SharedEntityManagerBean.
Alternatively I could probably just call:
em = context.getBean("entityManager",EntityManager.class);
See here and here for reference.

Inject spring dependency in abstract super class

I have requirement to inject dependency in abstract superclass using spring framework.
class A extends AbstractClassB{
private Xdao daox ;
...
public setXdao() { ... }
}
class AbstractClassB{
..
private yDao daoy;
public seyYdao() { ... }
}
I need to pass superclass dependency everytime i instantiate Abstract class B (which can be subclassed in 100's of ways in my project)
entry in application.xml (spring context file)
<bean id="aClass" class="com.mypro.A"
<property name="daox" ref="SomeXDaoClassRef" />
<property name="daoy" ref="SomeYDaoClassRef"/>
</bean>
How can i just create bean reference of super class AbstractClassB in application.xml so that i can use it in all subclass bean creation?
You can create an abstract bean definition, and then "subtype" that definition, e.g.
<bean id="b" abstract="true" class="com.mypro.AbstractClassB">
<property name="daox" ref="SomeXDaoClassRef" />
</bean>
<bean id="a" parent="b" class="com.mypro.A">
<property name="daoy" ref="SomeYDaoClassRef" />
</bean>
Strictly speaking, the definition for b doesn't even require you to specify the class, you can leave that out:
<bean id="b" abstract="true">
<property name="daox" ref="SomeXDaoClassRef" />
</bean>
<bean id="a" parent="b" class="com.mypro.A">
<property name="daoy" ref="SomeYDaoClassRef" />
</bean>
However, for clarity, and to give your tools a better chance of helping you out, it's often best to leave it in.
Section 3.7 of the Spring Manual discusses bean definition inheritance.
You can use the abstract flag of Spring to tell Spring that a class is abstract. Then all concrete implementations can simply mark this bean as their parent bean.
<bean id="abstractClassB" class="AbstractClassB" abstract="true">
<property name="yDao" ref="yDao" />
</bean>
<bean id="classA" class="A" parent="abstractClassB">
<property name="xDao" ref="xDao" />
</bean>
Have an abstract parent bean:
http://forum.springsource.org/showthread.php?t=55811

How do you acess a property of a bean for reading in a spring xml config file?

I want to do something like the following in spring:
<beans>
...
<bean id="bean1" ... />
<bean id="bean2">
<property name="propName" value="bean1.foo" />
...
I would think that this would access the getFoo() method of bean1 and call the setPropName() method of bean2, but this doesn't seem to work.
What I understood:
You have a bean (bean1) with a
property called "foo"
You have another bean (bean2) with a
property named "propName", wich also
has to have the same "foo" that in
bean1.
why not doing this:
<beans>
...
<bean id="foo" class="foopackage.foo"/>
<bean id="bean1" class="foopackage.bean1">
<property name="foo" ref="foo"/>
</bean>
<bean id="bean2" class="foopackage.bean2">
<property name="propName" ref="foo"/>
</bean>
....
</beans>
Doing this, your bean2 is not coupled to bean1 like in your example. You can change bean1 and bean2 without affecting each other.
If you REALLY need to do the injection you proposed, you can use:
<util:property-path id="propName" path="bean1.foo"/>
You need to use PropertyPathFactoryBean:
<bean id="bean2" depends-on="bean1">
<property name="propName">
<bean class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<property name="targetBeanName" value="bean1"/>
<property name="propertyPath" value="foo"/>
</bean>
</property>
</bean>
I think you have to inject bean1, then get foo manually because of a timing issue. When does the framework resolve the value of the target bean?
You could create a pointer bean and configure that.
class SpringRef {
private String targetProperty;
private Object targetBean;
//getters/setters
public Object getValue() {
//resolve the value of the targetProperty on targetBean.
}
}
Common-BeanUtils should be helpful.

Resources