com.mmj.app.lucene.solr.client.SolrClient.java Source code

Java tutorial

Introduction

Here is the source code for com.mmj.app.lucene.solr.client.SolrClient.java

Source

/*
 * Copyright 2011-2016 ZuoBian.com All right reserved. This software is the confidential and proprietary information of
 * ZuoBian.com ("Confidential Information"). You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the license agreement you entered into with ZuoBian.com.
 */
package com.mmj.app.lucene.solr.client;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import javax.annotation.PostConstruct;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.lang.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrRequest;
import org.apache.solr.client.solrj.SolrServer;
import org.apache.solr.client.solrj.SolrServerException;
import org.apache.solr.client.solrj.impl.BinaryRequestWriter;
import org.apache.solr.client.solrj.impl.BinaryResponseParser;
import org.apache.solr.client.solrj.impl.HttpSolrServer;
import org.apache.solr.client.solrj.request.CoreAdminRequest;
import org.apache.solr.client.solrj.request.CoreAdminRequest.Create;
import org.apache.solr.client.solrj.response.CoreAdminResponse;
import org.apache.solr.client.solrj.response.QueryResponse;
import org.apache.solr.client.solrj.response.TermsResponse;
import org.apache.solr.client.solrj.response.TermsResponse.Term;
import org.apache.solr.client.solrj.response.UpdateResponse;
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.mmj.app.common.core.lang.Argument;
import com.mmj.app.common.result.Result;
import com.mmj.app.lucene.solr.callback.SolrCallback;
import com.mmj.app.lucene.solr.exception.SolrServerUnAvailableException;
import com.mmj.app.lucene.solr.utils.BaseSolrQueryConvert;
import com.mmj.app.lucene.solr.utils.CounterMonitor;

/**
 * Solr Client interacts with the class
 * 
 * @author zxc Sep 2, 2014 1:40:14 PM
 */
@Component
public class SolrClient {

    private Logger logger = LoggerFactory.getLogger(SolrClient.class);

    // RFC255???2000IE8+ ?2083,?2048?
    private static final int ERROR_STATUS = 0;
    private static final int MAX_URL_LENGTH = 200;
    private CounterMonitor counterMonitor = null;
    private volatile ConcurrentHashMap<String, HttpSolrServer> httpSolrServerMap = new ConcurrentHashMap<String, HttpSolrServer>();

    @Value("${root.solr.server.url}")
    protected String rootSolrServerUrl;
    @Value("${root.index.dir}")
    protected String rootIndexDir;
    @Value("${is.load.solr}")
    protected boolean isLoadSolr;

    SolrServer solrServer;

    /**
     * client?
     * 
     * <pre>
     * 1.properits?SolrServer?,?
     * 2.???
     * </pre>
     */
    @PostConstruct
    public void init() {
        if (isLoadSolr) {
            if (StringUtils.isEmpty(rootSolrServerUrl) || StringUtils.isEmpty(rootIndexDir)) {
                throw new RuntimeException("rootSolrServerUrl and rootIndexDir should not empty");
            }
            counterMonitor = new CounterMonitor(0, TimeUnit.SECONDS.toMillis(15));
            solrServer = getRootSolrServer();
            logger.debug("create or connection root solr server,successful! solr server url={}", rootSolrServerUrl);
        }
    }

    /**
     * solr
     * 
     * @param corename ?????
     * @param returnType Class
     * @param solrQuery {@link SolrQueryConvert}
     * @return
     */
    public <T> List<T> query(String corename, final Class<T> returnType, final SolrQuery solrQuery,
            final SolrCallback... callbacks) {
        final HttpSolrServer server = getOrCreateSolrServer(corename);
        final List<T> queryResult = new ArrayList<T>();
        exec(new Executor() {

            public Result exec() throws SolrServerException, IOException {
                QueryResponse query = null;
                if (solrQuery.toString().length() > MAX_URL_LENGTH) {
                    query = server.query(solrQuery, SolrRequest.METHOD.POST);
                } else {
                    query = server.query(solrQuery, SolrRequest.METHOD.GET);
                }
                List<T> beans = query.getBeans(returnType);
                if (beans != null) {
                    queryResult.addAll(beans);
                }
                if (Argument.isNotEmptyArray(callbacks)) {
                    for (SolrCallback callback : callbacks) {
                        callback.handleSolrResult(query);
                    }
                }
                return Result.success();
            }
        });
        return queryResult;
    }

    /**
     * solrautoComplete
     * 
     * @param corename
     * @param solrQuery
     * @return
     */
    public List<Term> suggest(String corename, final SolrQuery solrQuery) {
        final HttpSolrServer server = getOrCreateSolrServer(corename);
        // final List<FacetField> queryResult = new ArrayList<FacetField>();
        final List<Term> queryResult = new ArrayList<Term>();
        exec(new Executor() {

            public Result exec() throws SolrServerException, IOException {
                QueryResponse query = null;
                if (solrQuery.toString().length() > MAX_URL_LENGTH) {
                    query = server.query(solrQuery, SolrRequest.METHOD.POST);
                } else {
                    query = server.query(solrQuery, SolrRequest.METHOD.GET);
                }
                // List<FacetField> list = query.getFacetFields();
                // if (Argument.isNotEmpty(list)) {
                // queryResult.addAll(list);
                // }
                TermsResponse resp = query.getTermsResponse();
                queryResult.addAll(resp.getTerms(solrQuery.getTermsRegexFlags()[0]));
                return Result.success();
            }
        });
        return queryResult;
    }

    public <T> boolean addBean(String corename, final T bean) {
        ArrayList<T> beans = new ArrayList<T>();
        beans.add(bean);
        return addBeans(corename, beans);
    }

    /**
     * 
     */
    public boolean addBeans(String corename, final List<?> beans) {
        final HttpSolrServer server = getOrCreateSolrServer(corename);
        Result result = exec(new Executor() {

            @Override
            public Result exec() throws SolrServerException, IOException {
                UpdateResponse addBeans = server.addBeans(beans);
                server.commit();
                return new Result().setSuccess(addBeans.getStatus() == ERROR_STATUS);
            }
        });
        return result.isSuccess();
    }

    /**
     * 
     * 
     * @param corename
     * @return
     */
    public boolean delAll(String corename) {
        final HttpSolrServer server = getOrCreateSolrServer(corename);
        Result result = exec(new Executor() {

            @Override
            public Result exec() throws SolrServerException, IOException {
                String query = BaseSolrQueryConvert.toAll().getQuery();
                UpdateResponse deleteByQuery = server.deleteByQuery(query);
                server.commit();
                return new Result().setSuccess(deleteByQuery.getStatus() == ERROR_STATUS);
            }
        });
        return result.isSuccess();
    }

    /**
     * 
     */
    public boolean del(String corename, final SolrQuery solrQuery) {
        final HttpSolrServer server = getOrCreateSolrServer(corename);
        final String query = solrQuery.getQuery();
        Result result = exec(new Executor() {

            @Override
            public Result exec() throws SolrServerException, IOException {
                UpdateResponse deleteByQuery = server.deleteByQuery(query);
                server.commit();
                return new Result().setSuccess(deleteByQuery.getStatus() == ERROR_STATUS);
            }
        });
        return result.isSuccess();
    }

    public boolean commit() {
        Result result = exec(new Executor() {

            @Override
            public Result exec() throws SolrServerException, IOException {
                for (HttpSolrServer solrServ : httpSolrServerMap.values()) {
                    UpdateResponse updateResponse = solrServ.commit();
                    if (updateResponse.getStatus() != 0) {
                        return Result.failed();
                    }
                }
                return Result.success();
            }
        });
        return result.isSuccess();
    }

    protected void commitAndNewServer() {
        try {
            this.commit();
        } catch (Throwable t) {
            // pass away
        }
        httpSolrServerMap = new ConcurrentHashMap<String, HttpSolrServer>();
    }

    /**
     * ?corenameserver
     */
    public HttpSolrServer getOrCreateSolrServer(String corename) {
        if (httpSolrServerMap.get(corename) != null) {
            return httpSolrServerMap.get(corename);
        }
        // create
        synchronized (httpSolrServerMap) {
            if (!httpSolrServerMap.contains(corename)) {
                HttpSolrServer solrServer = createSolrServer(corename);
                httpSolrServerMap.putIfAbsent(corename, solrServer);
            }
        }
        return httpSolrServerMap.get(corename);
    }

    private HttpSolrServer createSolrServer(String corename) {
        createDateDirIfNotExisted(corename);
        String solrServerUrl = this.rootSolrServerUrl + corename + "/";
        HttpSolrServer solrServer = newSolrServer(solrServerUrl);
        return solrServer;
    }

    private HttpSolrServer newSolrServer(String solrServerUrl) {
        HttpSolrServer solrServer = new HttpSolrServer(solrServerUrl);
        solrServer.setSoTimeout(60000);
        solrServer.setConnectionTimeout(5000);
        solrServer.setDefaultMaxConnectionsPerHost(50);
        solrServer.setMaxTotalConnections(100);
        solrServer.setFollowRedirects(false);
        solrServer.setAllowCompression(false);
        solrServer.setMaxRetries(1);
        solrServer.setParser(new BinaryResponseParser());
        solrServer.setRequestWriter(new BinaryRequestWriter());
        commit();
        return solrServer;
    }

    private void createDateDirIfNotExisted(String corename) {
        boolean solrCoreExist = isDataDirExsited(corename);
        if (!solrCoreExist) {
            Create create = new Create();
            create.setCoreName(corename);
            create.setDataDir(rootIndexDir + File.separator + corename);
            create.setInstanceDir(rootIndexDir + File.separator + corename);
            try {
                solrServer.request(create);
            } catch (SolrServerException e) {
                logger.error("createSolrCore", e);
                throw new RuntimeException("createSolrCore", e);
            } catch (IOException e) {
                logger.error("createSolrCore", e);
                throw new RuntimeException("createSolrCore", e);
            }
            this.commit();
        }
    }

    private SolrServer getRootSolrServer() {
        if (solrServer == null) {
            synchronized (SolrClient.class) {
                if (solrServer == null) {
                    solrServer = newSolrServer(rootSolrServerUrl);
                }
            }
        }
        return solrServer;
    }

    private boolean isDataDirExsited(String namespace) {
        CoreAdminResponse status;
        try {
            status = CoreAdminRequest.getStatus(namespace, solrServer);
        } catch (SolrServerException e) {
            logger.error("isSolrCoreExist", e);
            throw new SolrServerUnAvailableException("isSolrCoreExist", e);
        } catch (IOException e) {
            logger.error("isSolrCoreExist", e);
            throw new SolrServerUnAvailableException("isSolrCoreExist", e);
        }
        return status != null && status.getCoreStatus(namespace).get("instanceDir") != null;
    }

    protected Result exec(Executor executor) {
        try {
            return executor.exec();
        } catch (SolrServerException e) {
            logger.error(e.getMessage(), e);
            counterMonitor.pulse();
            if (counterMonitor.isExceedWithInForOnce()) {
                commitAndNewServer();
            }
            return Result.failed();
        } catch (IOException e) {
            logger.error(e.getMessage(), e);
            return Result.failed();
        }
    }

    static interface Executor {

        Result exec() throws SolrServerException, IOException;
    }

    public static Object toBean(SolrDocument record, Class<?> clazz) {

        Object o = null;
        try {
            o = clazz.newInstance();
        } catch (InstantiationException e1) {
            e1.printStackTrace();
        } catch (IllegalAccessException e1) {
            e1.printStackTrace();
        }
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            Object value = record.get(field.getName());
            ConvertUtils.register(new DateConverter(null), java.util.Date.class);
            try {
                BeanUtils.setProperty(o, field.getName(), value);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
        return o;
    }

    public static Object toBeanList(SolrDocumentList records, Class<?> clazz) {
        List<Object> list = new ArrayList<Object>();
        for (SolrDocument record : records) {
            list.add(toBean(record, clazz));
        }
        return list;
    }
}