I still don't get how to avoid the use of getBean() - spring

I'm new to Spring and I've read many guides on how to inject beans. Curiously, in every example I see, they use getBean in a class main method (not what I need). Also I've read many forums and questions related to how not to use getBean but I still can't figure out the best approach for my app.
I'm refactoring a web app that is highly coupled and without design patterns. Every business class has a corresponding DAO class, every DAO class extends a super DAO which handles the connection and other stuff. The problem here is that every DAO needs, in the constructor, some database config parameters that are being passed from the business class. What I'm trying to do is to put these parameters in a DBConfig bean and inject them into every DAO allowing me to create the DAO object from every business class simply, for example: dao = new myDAO().
How can I inject the DBConfig bean into every DAO "automatically"? Should I use getBean in the super DAO?

Your config could look like this:
<bean id="daoConfig1" class="com.foo.dao.DAOConfig">
<property name="dbUrl" value="jdbc://urlForDao1" />
...
</bean>
<bean id="dao1" class="com.foo.dao.DAO1">
<constructor-arg ref="daoConfig1" />
</bean>
<bean id="business1" class="com.foo.service.Business1">
<property name="dao" ref="dao1" />
</bean>
<bean id="daoConfig2" class="com.foo.dao.DAOConfig">
<property name="dbUrl" value="jdbc://urlForDao2" />
...
</bean>
<bean id="dao2" class="com.foo.dao.DAO2">
<constructor-arg ref="daoConfig2" />
</bean>
<bean id="business2" class="com.foo.service.Business2">
<property name="dao" ref="dao2" />
</bean>
Or share a single daoConfig instance between all daoX beans, if that's what you want.
You can then use the folowing to handle the business logic:
ApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"beans.xml"});
Business1 b1 = (Business1) context.getBean("business1");
b1.doStuff();
Or better still, use something like Spring MVC that can wire the business beans into your controllers without needing to call getBean().

Related

Spring injecting one reference bean into another reference bean

In the below spring configuration snippet, injecting reference of "SomeManager" into bean "SomeWorker" and "SomeLocal". The reference of "SomeLocal" is also injected into "SomeWorker".
My doubt is is it possible to inject the same reference of "SomeManager" injected into "SomeWorker" into another bean, like here in "SomeLocal".
Problem is if i inject it separately into "SomeWorker" and "SomeLocal" than unnecessarily there will be two instances of "SomeManager" which is basically not required in this scenario as "SomeLocal" is referred only within the "SomeWorker"
<bean id="SomeWorker" class="com.test.worker.SomeWorker">
<property name="someManager" ref="SomeManager" />
<property name="someLocal" ref="SomeLocal"/>
<bean id="SomeLocal" class="com.test.local.SomeLocal">
<property name="someManager" ref="SomeManager" />
</bean>
<bean id="SomeManager" class="com.test.manager.SomeManager"/>

jee:remote-slsb use custom factory

i have this definition for calling an EJB
<util:properties id="ejbJndiConfig" location="file:/path/to/ejb-jndi-config.properties" />
<jee:remote-slsb id="myEjbService"
jndi-name="myEjbName"
business-interface="foo.bar.MyBusinessInterface"
cache-home="false"
lookup-home-on-startup="false"
refresh-home-on-connect-failure="true"
environment-ref="ejbJndiConfig"
expose-access-context="true">
</jee:remote-slsb>
All is working great and an instance of:
org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean is created to call the EJB method. But what about if i want to change this default behaviour and change the used class?
With old style spring we can do something like this:
<bean id="service" class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<property name="remoteInvocationFactory" ref="invocationFactory"/>
....
</bean>
<bean id="invocationFactory" class="src.rmi.CustomRemoteInvocationFactory"/>
is possible with new definition style?

#Async annotations being ignored

I'm annotating methods with #Async but they seem to be ignored.
Here's my context file:
<task:annotation-driven executor="taskExecutor" />
<task:executor id="taskExecutor" pool-size="5-25"
queue-capacity="100" rejection-policy="CALLER_RUNS" />
<bean id="taskExecutor"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="5" />
<property name="maxPoolSize" value="10" />
<property name="queueCapacity" value="25" />
</bean>
When I create a runnable and auto wire taskExecutor, then call taskExecutor.execute(runnableThing) it works as expected.
However, Spring promises that if we just put #Async on a method it will functionally do the same thing. This is not happening for me (or at least the performance is nowhere near as good so I'm assuming it's not happening now that I think about it).
The method is very simple, here's some pseudo code:
import org.springframework.scheduling.annotation.Async;
#Controller
public class MyClass{
//some auto wired stuff for db persistence
#Async
void doStuff(MyObject object){
//does some stuff with object
//write object to database
//send email
}
}
Any feedback on where else to look - I imagine this is some config thing but I can't figure it out
Try <task:annotation-driven executor="taskExecutor" proxy-target-class="true" /> and add CGLIB as a dependency to the project
I am not so sure however that should be adding #Async to a controller's method. Best you add it on a service method that is called from the controller
I'm not exactly sure what your problem is, but maybe this will help.
An #Async annotated method is meant to be run asynchronously. However, you still need to invoke it. It won't just run on its own. If you need it to run on its own, use #Scheduled with an appropriate configuration.
With #Async, get a reference to the bean that contains it and invoke the method on that bean. (Because of how proxying works, you won't be able to get this behavior by calling the method from within other methods of the same object.)
Bean yourBean = ...; // get it
yourBean.asyncMethod();

Use Spring Bean in Non-Spring Bean container class

Suppose I have a couple different datasources defined as spring beans:
<bean id="dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/db1?user=root&password=password" />
</bean>
<bean id="dataSource2" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost/db2?user=root&password=password" />
</bean>
Now I'd like to use one of these datasource beans but from a non-spring bean container. I could call appContext.getBean("dataSource1") but I've read that's bad practice since it creates an explicit dependency on the spring framework in your code. Is there are better way to accomplish this in a way that is not implementation specific? Perhaps something like DatasourceFactory.getInstance("datasource1")?
Is this a weird request? I realize this would be very easy if the container class was a Spring bean since I could just use standard dependency injection in that case. But this is something I've been curious about. It seems that using dependency injection creates an endless loop, where if you want to use a spring bean in a class then that class must also be a bean, and then if another class wants to use that bean then it must also be a bean, and so on, and so on. I don't see an elegant way to break the dependency injection chain.
Again, maybe it's not necessary to break the chain, maybe the answer is that you do make all your classes spring beans, but I was just curious.
Can service locator pattern be applied here? If so can someone provide an example? Thanks.
The method you describe is the classic way to do it.
public class UnmanagedBean {
public UnmanagedBean(DataSource dataSource) {
... // do something
}
}
...
ApplicationContext context = ...;
DataSource dataSource2 = context.getBean("dataSource2");
UnmanagedBean bean = new UnmanagedBean(dataSource2);
You can add a level of abstraction with a BeanProvider class that does this for you, but you are limited to getting the beans directly from the ApplicationContext.

Spring parent and child resources

I am using spring+struts2 and I have a large number of action classes that required a single service (mailService). Instead of injecting service into these action classes, I am wondering is there a way to create a parent class and inject the resources and then have all these classes extending the parent. So I do no need to repeat the injection in each class.
Thanks in advance
try defining a baseClass with a setter method for the mailService. your action classes can all extend this baseClass.
ie
<!-- parent class with the mailService injected -->
<bean name="baseAction" class="..." abstract="true">
<property name="mailService" ref="mailService"/>
</bean>
<bean name="someAction" class="..." parent="baseAction" >
</bean>

Resources