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