com.flipkart.aesop.serializer.batch.reader.UserInfoServiceScanReader.java Source code

Java tutorial

Introduction

Here is the source code for com.flipkart.aesop.serializer.batch.reader.UserInfoServiceScanReader.java

Source

/*
 * Copyright 2012-2015, the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.flipkart.aesop.serializer.batch.reader;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Semaphore;

import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamException;
import org.springframework.batch.item.ItemStreamReader;
import org.springframework.batch.item.ParseException;
import org.springframework.batch.item.UnexpectedInputException;
import org.trpr.platform.core.impl.logging.LogFactory;
import org.trpr.platform.core.spi.logging.Logger;

import com.flipkart.aesop.serializer.model.UserInfo;

/**
 * The <code>UserInfoServiceScanReader</code> class is an implementation of the {@link ItemStreamReader} that invokes JSON over REST calls to a deployed service 
 * for scanning and retrieving the entire set of sample data item {@link UserInfo} instances
 * 
 * @author Regunath B
 * @version 1.0, 25 Mar 2014
 */

public class UserInfoServiceScanReader<T extends UserInfo> implements ItemStreamReader<UserInfo> {

    /** The Logger interface*/
    private static final Logger LOGGER = LogFactory.getLogger(UserInfoServiceScanReader.class);

    /** The max results count*/
    private static final int MAX_RESULTS = 10000;

    /** The service endpoint URL. Note: This is for testing and very specific to this sample*/
    private static final String BATCH_SERVICE_URL = "http://localhost:25151/userservice/v0.1/customer/batch";

    /** The batch size*/
    private static final int BATCH_SIZE = 500;

    /** The ObjectMapper to use for JSON deserialization*/
    private ObjectMapper objectMapper = new ObjectMapper();

    /** The result counter*/
    private int resultCount = (0 - BATCH_SIZE);

    /** The Semaphore to control concurrency */
    private Semaphore parallelFetch = new Semaphore(5);

    /** The local list containing data items*/
    private Queue<UserInfo> localQueue = new ConcurrentLinkedQueue<UserInfo>();

    /**
     * Interface method implementation.Scans and retrieves a number of {@link UserInfo} instances looked up from a service end-point. The scan stops once no more 
     * data is returned by the service endpoint.
     * Note : The end-point and parameters used here are very specific to this sample. Also the code is mostly for testing and production 
     * ready (no Http connection pools etc.) 
     * @see org.springframework.batch.item.ItemReader#read()
     */
    public UserInfo read() throws Exception, UnexpectedInputException, ParseException {
        // return data from local queue if available already
        synchronized (this) { // include the check for empty and remove in one synchronized block to avoid race conditions
            if (!this.localQueue.isEmpty()) {
                LOGGER.debug("Returning data from local cache. Cache size : " + this.localQueue.size());
                return this.localQueue.poll();
            }
        }
        parallelFetch.acquire();
        int startIndex = 0;
        synchronized (this) {
            startIndex = resultCount += BATCH_SIZE;
        }
        if (this.resultCount < MAX_RESULTS) {
            DefaultHttpClient httpclient = new DefaultHttpClient();
            HttpGet executionGet = new HttpGet(BATCH_SERVICE_URL);
            URIBuilder uriBuilder = new URIBuilder(executionGet.getURI());
            uriBuilder.addParameter("start", String.valueOf(startIndex));
            uriBuilder.addParameter("count", String.valueOf(BATCH_SIZE));
            ((HttpRequestBase) executionGet).setURI(uriBuilder.build());
            HttpResponse httpResponse = httpclient.execute(executionGet);
            String response = new String(EntityUtils.toByteArray(httpResponse.getEntity()));
            ScanResult scanResult = objectMapper.readValue(response, ScanResult.class);
            if (scanResult.getCount() <= 0) {
                parallelFetch.release();
                return null;
            }
            LOGGER.info("Fetched User Info objects in range - Start : {}. Count : {}", startIndex,
                    scanResult.getCount());
            for (UserInfo userInfo : scanResult.getResponse()) {
                this.localQueue.add(userInfo);
            }
        }
        parallelFetch.release();
        return this.localQueue.poll();
    }

    /**
     * Interface method implementation. Reinitializes the result count
     * @see org.springframework.batch.item.ItemStream#open(org.springframework.batch.item.ExecutionContext)
     */
    public void open(ExecutionContext context) throws ItemStreamException {
        this.resultCount = (0 - BATCH_SIZE);
    }

    /**
     * Interface method implementations. Does nothing
     * @see org.springframework.batch.item.ItemStream#update(org.springframework.batch.item.ExecutionContext)
     */
    public void update(ExecutionContext context) throws ItemStreamException {
    }

    public void close() throws ItemStreamException {
    }

}