Best way to refactor this in Spring? - java

private final ExecutorService executorParsers = Executors.newFixedThreadPool(10);
public void parse(List<MyObjInt> objs) {
//... bunch of elided stuff ....
CompletionService<AsupParseObj> parserService = new ExecutorCompletionService<AsupParseObj>(executorParsers);
for (final AsupStoreObj obj : objs) {
parserService.submit(new ParseThread(obj));
}
}
I would like to DI the "ParseThread" but surely there has to be a better way to do this than burying a call to getBean on a prototype scoped bean and as I am new to Spring I figured I would ask...

Here is the full configuration using lookup-method (see 3.4.6.1 Lookup method injection):
<bean id="executorParsers" class="java.util.concurrent.Executors"
factory-method="newFixedThreadPool"
destroy-method="shutdownNow">
<constructor-arg value="10"/>
</bean>
<bean id="parserService" class="java.util.concurrent.CompletionService">
<constructor-arg ref="executorParsers"/>
</bean>
<bean id="foo" class="Foo">
<lookup-method name="createThread" bean="parseThread"/>
</bean>
<bean id="parseThread" class="ParseThread" scope="prototype" lazy-init="true"/>
And the Java code:
abstract class Foo {
#Autowired
CompletionService parserService;
protected abstract ParseThread createThread();
public void parse(List<MyObjInt> objs) {
for (final AsupStoreObj obj : objs) {
ParseThread t = createThread();
t.setObject(obj);
parserService.submit(t);
}
}
}
Unfortunately you cannot pass any parameters to lookup-method (see SPR-7431 and my article Creating prototype Spring beans on demand using lookup-method), hence the need for artificial setObject().
If you don't like abstract methods/classes, lookup method can be non-abstract no-op method or (better) the default implementation can throw an exception. Spring will override the implementation at runtime, effectively calling getBean() for you.
Bonus: I translated Executor/CompletionService to Spring managed beans as well. Note that Spring supports these out-of-the-box: Task Execution and Scheduling.

Well, I am not sure what you think Spring is going to buy you here, but I would inject a factory of some sort that spits out Runnable/Callable's.
private final ExecutorService executorParsers = Executors.newFixedThreadPool(10);
#Autowired
private CallableFactory myCallableFactory = new MyCallableFactory(); //create this factory
public void parse(List<MyObjInt> objs) {
//... bunch of elided stuff ....
CompletionService<AsupParseObj> parserService = new ExecutorCompletionService<AsupParseObj>(executorParsers);
for (final AsupStoreObj obj : objs) {
parserService.submit(myCallableFactory.createCallable(obj));
}
}
You could also inject the ExecutorService with Spring too.

Related

Spring bean interface declaring

I have a work class :
public class WorkClass implements ApplicationContextAware {
... // has access to ApplicationContext
}
Have some useful interface :
public interface UsefulInterface {
void doUseful();
}
Have some impl class that can do much more:
public class CanDoAlmostEverything implements UsefulInterface {
...
}
I want to provide UsefulInterface implementation (via CanDoAlmostEverything) to WorkClass using Spring, but NOT to access any other CanDoAlmostEverything methods exept "doUseful"
In other words I want to declare my bean[s] like :
<bean id="workerA" interface="UsefulInterface" class="CanDoAlmostEverything"/>
<bean id="workerB" interface="UsefulInterface" class="AnotherUsefulImpl"/>
WorkClass will know about interface impl only during runtime and code must look like:
String todayWorker = getWorkerNameFromDataBase();
UsefulInterface worker = appCtx.getBean(todayWorker, UsefulInterface.class);
worker.doUseful();
Is it possible? And how it must look like?
I don't recommend you to use getBean this way. In the Spring documentation, it is written that it could be bad for performance.
http://docs.spring.io/spring/docs/1.0.2/api/org/springframework/beans/factory/BeanFactory.html#getBean%28java.lang.String%29
Return an instance (possibly shared or independent) of the given bean
name. Provides a measure of type safety by throwing an exception if
the bean is not of the required type.
Note that callers should retain references to returned objects. There
is no guarantee that this method will be implemented to be efficient.
For example, it may be synchronized, or may need to run an RDBMS
query.
Will ask the parent factory if the bean cannot be found in this
factory instance.
It really depends of what do you want to do. Did you tought that you Workclass could be a bean ?
public class WorkClass implements ApplicationContextAware {
private UsefulInterface workerA;
private UsefulInterface workerB;
public void setWorkerA(UsefulInterface workerA) {
this.workerA = workerA;
}
public void setWorkerB(UsefulInterface workerB) {
this.workerB = workerB;
}
public void work() {
UsefulInterface workerToUse;
if(condition) {
workerToUse = workerA;
} else {
workerToUse = workerB;
}
// treatment
}
}
Here the configuration file :
<bean id="workerA" interface="UsefulInterface" class="CanDoAlmostEverything"/>
<bean id="workerB" interface="UsefulInterface" class="AnotherUsefulImpl"/>
<bean id="mainWorker" class="package.of.WorkClass">
<property name="workerA" ref="workerA" />
<property name="workerB" ref="workerB" />
</bean>
Your main class will have to call getBean, but only one time to get the instance of WorkClass.

How to use ExposeBeanNameAdvisors`

I have a requirement to find the name of a bean that I have proxied. Here is some background:
I have the following xml configuration that uses a BeanNameAutoProxyCreator that proxies different beans based on their name (using the NameMatchMethodPointcutAdvisor):
<bean id="myAdvisor" class="some.package.MyAdvisor"/>
<bean id="myProxy"
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
p:proxyTargetClass="true">
<property name="beanNames">
<list>
<value>*someBean</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>someInterceptor</value>
</list>
</property>
</bean>
<bean id="someInterceptor"
class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="mappedName" value="methodName"/>
<property name="advice" ref="myAdvisor"/>
</bean>
Here is the implementation of my advisor. I want to be able to get the name of the bean in this advisor.
public class MyAdvisor implements MethodInterceptor {
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
// I want to be able to get the bean name of this method invocation here
try {
long startTime = System.nanoTime();
log(startTime);
return methodInvocation.proceed();
}
finally {
long endTime = System.nanoTime();
log(endTime);
}
}
}
I understand that there is a ExposeBeanNameAdvisors class that provides a convenient getBeanName(MethodInvocation mi) method I can use. However, I do not understand what is meant by "Assumes that an ExposeBeanNameAdvisor has been included in the interceptor chain." (from javadoc) Can you guys give me an example of how to use ExposeBeanNameAdvisors?
Thanks!
The ExposeBeanNameAdvisors has two static methods createAdvisorWithoutIntroduction and createAdvisorIntroducingNamedBean which return an Advisor object which should be added to your stack of advisors.
If you look at the implementation of one of these
private static class ExposeBeanNameInterceptor implements MethodInterceptor {
private final String beanName;
public ExposeBeanNameInterceptor(String beanName) {
this.beanName = beanName;
}
public Object invoke(MethodInvocation mi) throws Throwable {
if (!(mi instanceof ProxyMethodInvocation)) {
throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi);
}
ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi;
pmi.setUserAttribute(BEAN_NAME_ATTRIBUTE, this.beanName);
return mi.proceed();
}
}
you notice that the bean name is added as an attribute to the MethodInvocation, which is cast to a ProxyMethodInvocation. This needs to be in the proxy invocation stack before your custom advisor so that you can retrieve the bean name with ExposeBeanNameAdvisors.getBeanName(), otherwise you would get an Exception.

factory method pattern in java

Is it a good practice to have objects specific to some implementation as member variables in a factory class ?
For e.g., in the code below, s1 and s2 are required for constructing OneChannel and secondChannel objects respectively. Is it a good practice to declare these as member variables inside the factory ? If not, what can e the other alternative.
public class CommunicationChannelFactoryImpl {
#Autowired
SomeClass s1;
#Autowired
SomeOtherClass s2;
public CommunicationChannel getCommunicationChannel(String channel, Map<String, String> channelProperties) {
if(channel.equals("ONE") {
return new OneChannel(s1);
}
if(channel.equals("TWO") {
return new SecondChannel(s2);
}
}
}
Please note that s1 ad s2 are singleton beans
Since you need those beans for constructing those particular channel implementations, I think you can keep them as properties in that particular factory implementation. You are injecting the required components, so you have the flexibility to change the implementations later if you need.
Also, it will be better if SomeClass and SomeOtherClass are some abstractions/interfaces/super type. In this way if you ever need to provide different implementations for building those channel objects in the future, you'll be able to do so pretty easily.
Why don't let Spring create OneChannel() and SecondChannel() object using BeanFactoryAware?
public class CommunicationChannelFactoryImpl implements BeanFactoryAware {
FactoryBean factoryBean;
public void setBeanFactory(FactoryBean factoryBean) {
this.factoryBean = factoryBean;
}
public CommunicationChannel getCommunicationChannel(String channel, Map<String, String> channelProperties) {
if(channel.equals("ONE") {
return this.factoryBean.getBean("oneChannel");
}
if(channel.equals("TWO") {
return this.factoryBean.getBean("secondChannel");
}
}
}
and define your XML (or JavaConfig, but I'm not using it) as:
<bean id="oneChannel" scope="prototype">
<constructor-arg index="0" ref="s1" />
</bean>
<bean id="secondChannel" scope="prototype">
<constructor-arg index="0" ref="s2" />
</bean>
<bean id="s1" class="path.to.SomeClass" />
<bean id="s2" class="path.to.SomeOtherClass" />

How to declare a bean which has a constructor which takes String and Map as parameters?

I am using ThreadPoolExecutor utility and passing the values thru constructor in called class. The constructor takes two arguments (1) a map (2) a string.
I am confused on how to declare a bean for the called class which takes two arguments( a map and a string). My code is as below.
***Calling Class***
public class Starter {
ProcessScheduler deleteBatch;
public ProcessScheduler getDeleteBatch() {
return deleteBatch;
}
public void setDeleteBatch(ProcessScheduler deleteBatch) {
this.deleteBatch = deleteBatch;
}
public void start() {
ThreadPoolExecutor executor = testThreadPoolExecutorService.createNewThreadPool();
for (int i=0;i<=5;i++)
{
Map m4 = arrayRecords.get(i);
executor.execute(new ProcessScheduler("Thread #"+i,m4)); // Comment - started
The above line executes fine but it gives null pointer error if I will call any other method from the run() inside called class(ProcessScheduler). So I have use a Bean such as executor.execute(getDeleteBatch("Thread #"+i,m4)) to get the instance of the bean. But I dont know how to do this in this case?
// Comment - ended
}
***Called Class***
public class ProcessScheduler implements Runnable {
public ProcessScheduler(String taskName, Map m) {
this.taskName = taskName;
this.deleteRecordsMap = (HashMap) m;
}
Processor processor;
public Processor getProcessor()
{
return processor;
}
public void setProcessor(Processor mappProcessor) {
this.mappProcessor = mappProcessor;
}
public void run()
{
// This returns null
processor.getNumbers();
}
}
I have some confusions as below.
(1) How to declare a bean for ProcessScheduler in this case.
(2) Is the declaration of getDeleteBatch is correct in this case like below?
public ProcessScheduler getDeleteBatch() {
return deleteBatch;
}
Thanks
Gendaful
Do you really think this is a good idea?
public ProcessScheduler(String taskName, Map m) {
this.taskName = taskName;
this.RecordsMap = (HashMap) m;
}
I think it should be more like this:
public ProcessScheduler(String taskName, Map m) {
this.taskName = taskName;
this.recordsMap = new HashMap(m); // You don't want changes to the Map passed in to show up in your private data member.
}
I'm not sure that you can inject ProcessScheduler instances from Spring as Beans; this might be a case where you really want to create a new one for each executor service.
Spring need not control every bean in your app.
http://jonathanhui.com/spring-framework-xml-configuration summarizes the various ways of configuring spring beans and supported tags for instantiating and embedding collections.
Something like below should work for you.
<?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.0.xsd">
<bean id="processscheduler"
class="ProcessScheduler">
<constructor-arg index="0" value="task1"/>
<constructor-arg index="1">
<map>
<entry key="key1" value="v1"/>
<entry key ="key2" value-ref="someBean"/>
</map>
</constructor-arg>
</bean>
</beans>
I have solved this issue as below,
From my calling class, I am passing the instance of Processor class in the execute method.
executor.execute
(newProcessScheduler("Thread#"+Thread.currentThread().getName(),hm,processor))
So, what it does is, since I am passing the processor as an argument in the execute(), it will not throw nullpointerexception if I call a method of processor inside run() of ProcessScheduler class.

Null Inner Bean with Spring IoC

I have a singleton bean definition like this:
<bean id="exampleBean" class="com.examples.ExampleBean">
<property name="exampleBean2">
<bean class="com.examples.ExampleBean2" />
</property>
</bean>
where ExampleBean could be:
public class ExampleBean {
private ExampleBean2 exampleBean2;
public ExampleBean() { }
public ExampleBean2 getExampleBean2() { return exampleBean2; }
public void setExampleBean2(ExampleBean2 exampleBean2) { this.exampleBean2 = exampleBean2; }
}
The problem is that, in certain conditions, the com.examples.ExampleBean2 class might not exist at runtime witch will cause an error when the IoC tries to instantiate exampleBean.
What I need is to ignore this error from IoC and allow the exampleBean to be created but leaving the exampleBean2 property null.
So the question is: is this possible in any way?
Thanks for all your help.
If you use autowire, what you wish to achieve is possible.
<bean class="com.examples.ExampleBean" autowire="byType" />
<bean class="com.examples.ExampleBean2" />
Or via annotations
#Autowired(required=false)
ExampleBean2 exampleBean2;
Is it an option to declare an init-method on your ExampleBean, and in this init-method check if the class ExampleBean2 exists, and if so setting it?
<bean id="exampleBean" class="com.examples.ExampleBean" init-method="init"/>
Maybe a better way of doing things here would be to use some form of the NullPattern, where you always provide an implementation of ExampleBean2, even if it only is its 'null' value.
If I got it right ExampleBean2 isn't loaded when Spring tries to instantiate the beans. Is this correct? In that case I don't thing you could do much with Spring's built in capabilities.
Perhaps you could create a container class that will always be present. This class will check if ExampleBean2 is loaded and if yes, it will instantiate an instance of it. The container class will have an Object property that could either be null or the instance of the ExampleBean2.
maybe lazy-init will do it, but i think spring will at least check if the bean implementation class is available at creation of the application context
Perhaps this will work:
public class NullFactoryBean implements FactoryBean {
#Override
public Object getObject() throws Exception {
return null;
}
#Override
public Class<?> getObjectType() {
return Object.class;
}
#Override
public boolean isSingleton() {
return false;
}
}
And then...
public class ClassNotFoundPostProcessor implements BeanFactoryPostProcessor {
#Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionName);
String beanClassName = beanDefinition.getBeanClassName();
try {
Class.forName(beanClassName);
} catch (ClassNotFoundException e) {
beanDefinition.setBeanClassName(NullFactoryBean.class.getName());
}
}
}
}
And then...
<beans>
<bean id="exampleBean" class="com.examples.ExampleBean">
<property name="exampleBean2">
<bean class="com.examples.ExampleBean2" />
</property>
</bean>
<bean class="ClassNotFoundPostProcessor" />
</beans>
EDIT: Sorry about that, it appears that this did not catch the inner beans. I missed this detail when I tested it. It only catches top-level beans. By the way, com.examples.ExampleBean probably won't load anyway because it itself depends directly upon the ExampleBean2 class, which the virtual machine won't find, causing an Error

Categories

Resources