/** * Copyright (c) 2015 Lemur Consulting Ltd. * <p/> * 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 * <p/> * http://www.apache.org/licenses/LICENSE-2.0 * <p/> * 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 uk.co.flax.biosolr.ontology.storage.solr; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.response.SolrPingResponse; import org.apache.solr.client.solrj.response.UpdateResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import uk.co.flax.biosolr.ontology.api.OntologyEntryBean; import uk.co.flax.biosolr.ontology.config.SolrConfiguration; import uk.co.flax.biosolr.ontology.storage.StorageEngine; import uk.co.flax.biosolr.ontology.storage.StorageEngineException; import java.io.IOException; import java.util.Collections; import java.util.List; import java.util.Map; /** * Solr-specific implementation of the {@link StorageEngine} interface. * * <p> * This is a special case implementation, primarily due to the indexer * application being written with Solr in mind. For this reason, the * {@link #setConfiguration(Map)} and {@link #initialise()} methods * are no-ops. All configuration and initialisation is handled in the * constructor. * </p> * * @author Matt Pearce */ public class SolrStorageEngine implements StorageEngine { private static final Logger LOGGER = LoggerFactory.getLogger(SolrStorageEngine.class); static final int STATUS_OK = 0; private final SolrConfiguration config; private final SolrClient server; public SolrStorageEngine(SolrConfiguration config) { this(config, new HttpSolrClient(config.getBaseUrl())); } // Unit testing constructor with incoming SolrServer SolrStorageEngine(SolrConfiguration config, SolrClient server) { this.config = config; this.server = server; } @Override public boolean isReady() { boolean ready = false; try { SolrPingResponse response = server.ping(); ready = (response != null && response.getStatus() == STATUS_OK); if (!ready) { if (response == null) { LOGGER.error("Search engine returned null response from ping()"); } else { LOGGER.error("Search engine is not ready: ", response.getResponse()); } } } catch (SolrServerException e) { LOGGER.error("Server exception from ping(): {}", e.getMessage()); } catch (IOException e) { LOGGER.error("IO exception when calling server: {}", e.getMessage()); } return ready; } @Override public void storeOntologyEntry(OntologyEntryBean entry) throws StorageEngineException { storeOntologyEntries(Collections.singletonList(entry)); } @Override public void storeOntologyEntries(List<OntologyEntryBean> entries) throws StorageEngineException { if (entries.isEmpty()) { LOGGER.debug("storeOntologyEntries called with empty list - ignoring"); } else { try { UpdateResponse response = server.addBeans(entries, config.getCommitWithinMs()); if (response.getStatus() != STATUS_OK) { LOGGER.error("Unexpected response: {}", response.getResponse()); throw new StorageEngineException("Could not store entries: " + response.getResponse()); } } catch (IOException e) { LOGGER.error("IO exception when calling server: {}", e.getMessage()); throw new StorageEngineException(e); } catch (SolrServerException e) { LOGGER.error("Server exception when storing entries: {}", e.getMessage()); throw new StorageEngineException(e); } } } @Override public void setConfiguration(Map<String, Object> configuration) throws StorageEngineException { // NOP } @Override public void initialise() throws StorageEngineException { // NOP } }