One of the common requirements these days is getting data from partners, for example getting stock prices, trading prices, checking if an item is available, supply chain information etc. One of my clients is a huge ecommerce company that sells electronics and other consumer goods online. Besides selling items from its own stock it has partnered with other companies for specific items. The sample application presented here is modeled after real world application and shows basic implementation using java queue and executor with spring MVC.
Besides concurrency, our sample application implements producer-consumer problem with BlockingQueue and ExecutorService(A.K.A. threadpoolexecutor (from google adwords suggest)).
Use Case:
When a customer searches for an item, the application searches for matches in its inventory system and partners’ inventory systems. For example, if a customer wants to search cameras he types “camera” in the website’s search box and submits. Upon submit, our application searches for available cameras, in the inventory system combines the results with results it received from external partners for display.
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWDgHzJ7rXHlrOtUKx-PIwo5L1Ls3EFIH8AbjniEIR5e7pQP-RQi1Wq3I3O1_QCzJVwrDHEnhHhXHSy1cZqVR_RiOVj9xXnHpUQAO1zYMobL8kMpra0jGbhfw7PbMaSobYcDF8AWPrDMr5/s320/usercase.jpg)
Sequence Diagram:
The following abstract sequence diagram shows order of processes that take place.
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgX2Ih95lvBRx1p75T5MEzkQtYI6iJvUwK2WC2x1nHInRZwRqRWIu8TUnu8nab_ANCBPUpwgMU7x2Q-h6DdbfF4eNlCovcDpKRNZFssdxLvoNeb68akhgUY8OkNCqdHL-GBzQH1IQzyMaqR/s320/Sequence+Diagram.png)
When a search request for an item comes to SearchController (Spring MVC controller), it invokes RequestProcessor.
List searchResult = RequestProcessor.processRequest("camera");
![](https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEidzYG_kC0kCNcIIsGob_6MuvJNtM2lbD-eo8Uz8-HOGlix-mbyCMhb5yiO4vy90ozqt7OLarUfQzKyvbY7flPAnah0pKIsk8KfpTYJJRpEcJXqHzpNZ8KZc80_tc_gbY0c6rpsZ_G_n0AX/s320/RequestProcessor.png)
RequestProcessor is the main class of the application and it is composed of a thread pool and a queue. Once invoked from the controller as above, it performs the following processes.
1. Get necessary information about partners like names, urls, usernames, passwords etc, search string and submits to ExecutorService, so that it can search all the partners concurrently.
public List<String> processRequest(String searchString) {
…
for (int i = 0; i < partners.size(); i++) {
submitToThreadPool(searchRequest);
…
}
}//end processRequest
private static void submitToThreadPool(SearchRequest request) {
// uses Executors factory methods.
threadPool.execute(new ResultProcessor(request));
}// submitToThreadPool
2. While external partners are being searched for the item, it searches internal inventory system.
3. After results are received from internal inventory system, get results from partners from queue that are put in by ResultProcessor.
String result = resultsQueue.poll(5, TimeUnit.MILLISECONDS);
4. Combine results from internal inventory system with results from external partners for display.
ResultProcessor implements Runnable and gets the search results from the partners. Once the results are received from partners, it puts them on the Queue for RequestProcessor (refer to step 3 above).
private void getSearchResultsFromPartners(SearchRequest request) {
…
//gets results from partners and puts them on the queue
Resultsqueue.offer(partner.getMatchedItems(request .getSearchString()));
}//end getSearchResultsFromPartners
ResultProcessor implements Runnable and runs in a separate thread for each external partner concurrently.
Besides ArrayBlockingQueue, java.util.concurrent package contains bounded and unbounded queues like ConcurrentLinkedQueue, DelayQueue, LinkedBlockingQueue, PriorityBlockingQueue and SynchronousQueue.
BlockingQueue are best suited for producer-consumer queues, as they supports operations that wait for space, so producer threads can place data and wait for queue to be not empty, so consumer threads can get the data. This decoupling of producer and consumer allows for variable rates of data production and consumptions. Take a look at java.util.concurrent package for more information.
Executor is the primary abstraction of task execution in java. Executor provides a way of decoupling task submission from how each task will be run, including details of thread use, scheduling, etc. Combined together Blocking queue and Executor is the perfect recipe to implement producer-consumer pattern like we did.
In our next post we will expand our example to include different ways of connecting to external partners including web services using Apache CXF.
Download code from here. If you like to deploy the application and see it in action, copy ecommerce-concurrent.war file from target directory to your server. If you wish to build it yourself go to ecommerce-concurrent directory from command line and run “mvn package” to build war file.
1 comment:
Thanks, I will check those. I tried dailyrazor, because they have developer hosting but I am not happy with their service.
Post a Comment