Firstly includes the dependencies for Guava in your spring MVC project.
Implementation using Guava in Spring MVC
Now write a simple spring service something like the one below:
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyLongRunningServiceImpl extends MyLongRunningService {
private ListeningExecutorService service;
public MyLongRunningService(){
service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
}
public ListenableFuture<Date> doLongRunningProcess(final int milliseconds){
ListenableFuture<date> future = service.submit(new Callable<date>() {
public Date call() throws Exception {
Thread.sleep(milliseconds
return new Date();
}
});
return future;
}
}
As shown in the code above the service has a method which delay a number user-specified milliseconds before returning a Date object. Next write a simple controller that autowires with the service:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.request.async.DeferredResult;
@Controller
public class MyLongRunningController {
@Autowired
private MyLongRunningService service;
@RequestMapping(value="/longRun", method = RequestMethod.GET)
public @ResponseBody DeferredResult<Date> doLongRunningProcess(){
DeferredResult<Date> deferredResult = new DeferredResult<>();
logger.info("start long running process");
ListenableFuture<Date> future = service.doLongRunningProcess(60000);
Futures.addCallback(future, new FutureCallback<Date>(){
@Override
public void onFailure(Throwable throwable) {
logger.error("long running process failed", throwable);
}
@Override
public void onSuccess(Date res) {
logger.info("long running process returns");
deferredResult.setResult(res);
}
});
return deferredResult;
}
}
This completes the coding part. There are two notes apart from the above implementation in order to make the asynchronous RESTful service to work:
<async-supported>true</async-supported>
The first thing is that the user needs to add in the following XML element into their web.xml configuration
<async-supported>true</async-supported>
This should be put under both <servlet> section (for the servlet which contains the spring controller above) as well as the <filter> section of the "org.springframework.web.filter.DelegatingFilterProxy"
asyncTimeout
If you are using Tomcat server as the servlet and http container for your spring MVC, that the asyncTimeout need to be added into the <Connector> element of the /conf/server.xml in tomcat directory, so that async services won't be terminated before tomcat's timeout, e.g.,<Connector asyncTimeout="60000" ... >
If you are using javascript to interact with the asynchronous RESTful services, you may also need to specify the timeout property (e.g., in the $http of angularjs) so that the http call will not terminate before the asynchronous service call is completed.
No comments:
Post a Comment