Within my web application, I am trying to create a directory polling bean using Java SDK7 WatchService. What I would like to achieve is to run this bean in its own thread so that it does not block the application. Something like:
<bean id="directoryPoller" class="org...MyDirectoryPoller" scope="thread"/>
I am afraid you will have to create this thread manually with Spring:
<bean id="pollThread" class="java.lang.Thread" init-method="start" destroy-method="interrupt">
<constructor-arg ref="watchServiceRunnableWrapper"/>
</bean>
<bean id="watchServiceRunnableWrapper" class="WatchServiceRunnableWrapper">
<constructor-arg ref="watchService"/>
</bean>
<bean id="WatchService" class="java.nio.file.WatchService" destroy-method="close"/>
The WatchServiceRunnableWrapper is simple:
public class WatchServiceRunnableWrapper implements Runnable {
private WatchService WatchService;
public WatchServiceRunnableWrapper(WatchService watchService) {
this.watchService = watchService;
}
public void run() {
watchService.poll();
//
}
}
I haven't tested it, but it more-or-less should work and shutdown gracefully.
I'm not familiar with Java 7's WatchService, but you could use Springs' scheduling support for this. Here's yet another tutorial and googling for something like Spring Scheduled probably finds loads more.
Related
I am using a third party library in my application to do some task. They have provided a wrapper that I've added in my project using maven. For using this wrapper we have to give an access key to their client class in order to use it's functionality. For ex:
final WeatherApiService was = new WeatherApiServiceImpl(accessKey);
final WeatherApiClient weatherApiClient = new WeatherApiClient(was);
What I want is to remove the above code (Since it's kind of Singleton and should be registered in spring context when the application is being started) and do something so that I can just autowire the WeatherApiClient and we are good to go. (wrapper isn't using spring FYI). Below is what I did is in my spring context I registered two beans and put the access-key is web.xml.
spring-context.xml
<bean id="was" class="my.librarypath.WeatherApiService ">
<constructor-arg type="java.lang.String" value="${accessKeyFromWebXml}"/>
</bean>
<bean id="weatherApiClient" class="my.librarypath.WeatherApiClient">
<constructor-arg type="my.librarypath.WeatherApiService" value="was"/>
</bean>
my component that will use the third party library
#Component("myComponent")
public class MyComponent IComponent {
#Resource(name = "weatherApiClient") // <--- getting Error here i.e: Couldn't aurtowire, bean should be of String type
private String weatherApiClient;
public void myFunction() {
weatherApiClient.getWeather();
}
}
Can someone confirm if I'm doing it right or is there any best practices options available !?
Ther were two issues:
<bean id="weatherApiClient" class="my.librarypath.WeatherApiClient">
<constructor-arg type="my.librarypath.WeatherApiService" value="was"/>
// ^---- should be ref
</bean>
Secondly, I was using String instead of WeatherApiClient. MY BAD :/
#Resource(name = "weatherApiClient")
private String weatherApiClient;
// ^---- this one should have to be WeatherApiClient
Is there a way to turn on Spring's Async configuration from XML? All the examples I saw are using programmatic context declaration and use #EnableAsync
Is there an XML equivalent for this. In some places I saw <context:annotation-config /> being used, but this doesn't mention anything about async .
I am using Spring 4.
Did you try using this
<task:annotation-driven />
Yes, you can use something like this
<beans>
<task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/>
<task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/>
<bean id="asyncBean" class="com.foo.MyAsyncBean"/>
<bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/>
</beans>
According to the Spring documentation, this is equivalent to using #EnableAsync
In the annotation based approach you have to have #EnableAsync on the Configuration class. Something like as shown below:
#Configuration
#EnableAsync
#ComponentScan(basePackages ="com.spring.sample.demoAsync")
public class SpringAsyncConfig {
}
Then you create a component class to have a function that is called Asynchronously. Something like as shown below:
#Component
public class AsyncClass {
#Async
public Future<String> asyncMethod() {
System.out.println("Executing Thread Async:" +Thread.currentThread().getName());
return new AsyncResult<String>(Thread.currentThread().getName());
}
}
To have the xml equivalent of this approach, you can create a bean in the applicationContext.xml file as shown below:
<bean id="AsyncClass" class="com.spring.sample.demoAsync.AsyncClass"/>
To call the function asyncMethod() in your flow, you can refer AsyncClass bean from any other bean or service. Below is something that I tried to stitch the flow:
<bean id="callingBean" class="comspring.sample.demoAsync.CallingBeanClass">
<property name="AsyncClassBean" ref="AsyncClass"/>
</bean>
It's not necessary to follow this step but is an alternative approach.
In my applicationContext.xml file, I also imported the task schema by using:
xmlns:task="http://www.springframework.org/schema/task
xsi:schemaLocation="http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd"
and then mentioning the executor as a task in the same file:
<task:executor id="myexecutor" pool-size="5" />
Now my AsyncClass looks like this without #component annotation.
public class AsyncClass {
#Async("myexecutor")
public Future<String> asyncMethod() {
System.out.println("Executing Thread Async:" +Thread.currentThread().getName());
return new AsyncResult<String>(Thread.currentThread().getName());
}
}
and then finally invoking the asyncMethod() asynchronously from the CallingBeanClass.
I am migrating from iBatis 2.3 to MyBatis 3.2.8. Everything is going well, but I do have a question when it comes to transactions and batch operations. Towards the bottom of https://mybatis.github.io/spring/sqlsession.html, it says:
The caveat to this form is that there cannot be an existing transaction running >with a different ExecutorType when this method is called. Either ensure that >calls to SqlSessionTemplates with different executor types run in a separate >transaction (e.g. with PROPAGATION_REQUIRES_NEW) or completely outside of a >transaction.
I have a service call that is annotated with #Transactional that makes multiple Dao Calls:
#Override
#Transactional
public void saveMassUploadOrder(List<IndividualOrder> orders) {
List<IndividualOrderItem> ioItems = new ArrayList<IndividualOrderItem>();
for (IndividualOrder order : orders) {
ioItems.addAll(order.getIoItems());
}
individualOrderDao.insertBatch(orders);
individualOrderItemDao.insertBatch(ioItems);
}
The DAOs would look like:
public class IndividualOrderDAOImpl implements IndividualOrderDAO{
private SqlSession sqlSession;
public void setSqlSession(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public void insertBatch(final List<IndividualOrder> orders) {
for (IndividualOrder order: orders){
sqlSession.insert("namespace.insert", order);
}
}
}
The config looks like:
<bean id="batchSqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg index="0" ref="doeSqlSessionFactory" />
<constructor-arg index="1" value="BATCH" />
</bean>
<bean id="individualOrderDao" class="com.doe.mybatis.jdoe.dao.IndividualOrderDAOImpl">
<property name="sqlSession" ref="batchSqlSession" />
</bean>
<bean id="individualOrderItemDao" class="com.doe.mybatis.jdoe.dao.IndividualOrderItemDAOImpl">
<property name="sqlSession" ref="batchSqlSession" />
</bean>
So - would the multiple DAO calls within this service call be OK since the service is opening a transaction and its not working in a batch mode and making calls to these DAOs? Obviously, I am wanting the call to this service to not actually insert any orders or order items if there is a failure somewhere during the execution.
I haven't migrated these DAOs yet, and I can probably set up a catastrophic event during a test batch insert and check the data, I was just wanting to get some other opinions before I started to see if I have to set this up differently or not.
Any help appreciated!
My problem is that I have a function implemented on my website which searches for Particular Tweet when I press the button. I want it to make it automatic such that, that function is called again and again after every two minutes, regardless some one uses the website or not.. How to do this in java?? Spring Solution is better
You could use Spring scheduling (see documentation here)
From the doc:
XML config
<context:component-scan base-package="some.package" />
<task:annotation-driven executor="myExecutor" scheduler="myScheduler"/>
<task:executor id="myExecutor" pool-size="5"/>
<task:scheduler id="myScheduler" pool-size="10"/>
Java bean
#Component
public class SomeBean {
#Scheduled(fixedRate=5000)
public void doSomething() {
// something that should execute periodically
}
}
How do i use the spring TaskExecutor to spawn tasks such that the outof memory exception are not thrown.
Current task pool configuration:
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="56" />
<property name="maxPoolSize" value="112" />
<property name="queueCapacity" value="100" />
</bean>
<bean id="threadExecutor" class="com.content.ThreadHandler.ThreadExecutor">
<constructor-arg ref="taskExecutor" />
</bean>
</beans>
and i am using the bean in my request handler by using the load bean as:
ApplicationContext context=new ClassPathXmlApplicationContext(new String[]{"ThreadPoolConfig.xml"});
BeanFactory factory=context;
ThreadExecutor myBean=(ThreadExecutor)factory.getBean("threadExecutor");
and then i use the taskexecutor as mybean.execute(task);
Does this configuration create a new pool for each request?
SUGGESTION 1
You shouldn't be instantiating the Spring application context for each request. You should have a singleton class named SpringContext or something like that and that should instantiate the Spring application context only once. So your client code should just be
ThreadExecutor myBean=(ThreadExecutor)SpringContext.getInstance().getBean("threadExecutor");
As mentioned earlier, the SpringContext should just be a regular singleton class; where in the initialization method, you will instantiate the spring applicationcontext.
public class SpringContext {
public ClassPathXmlApplicationContext context;
private static SpringContext _instance = new SpringContext();
private SpringContext() {
context = new ClassPathXmlApplicationContext(new String[]{"ThreadPoolConfig.xml"});
}
public static SpringContext getInstance() {
return _instance;
}
public Object getBean(String bean) {
Object beanObj = (context != null) ? context.getBean(bean) : null;
return beanObj;
}
}
SUGGESTION 2
In case this doesn't work, then you should look into the following :
The spring bean element has a scope attribute. Two of the values you can specify there are request and session, corresponding to HTTPRequest and HTTPSession. Try using one of them in your case.
http://static.springsource.org/spring/docs/3.0.x/reference/beans.html#beans-factory-scopes
So your bean definition should look something like
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="session">
Are you creating a new ClassPathXmlApplicationContext for every request? In that case you would create a new pool for every request, which would be very inefficient.
Judging from the fact that you are getting OutOfMemory errors, I would assume that you are. Make sure that you are calling context.destroy() after you are finished using the context as otherwise the garbage collection will not collect all the memory used by your beans and your app will leak with every request.
Normally (if we're talking about a web application), you'd use the ContextLoaderListener in web.xml to create a single WebApplicationContext which would then mean that you're using only one pool.
Note, if you are talking about a web application, it generally isn't wise to create your own thread pool as these threads won't be managed by the application server, which can negatively influence performance by having two many threads on a server instance (unless you are using a Work Manager)
Edit: for further info on ContextLoaderListener see Here