Skip to content
This repository has been archived by the owner on Sep 19, 2023. It is now read-only.

DATASOLR-211 Provide implementation of CloudSolrClientFactory #55

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright 2014 - 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 org.springframework.data.solr.server.support;

import java.util.List;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.springframework.data.solr.core.SolrTemplate;

/**
* A factory class which can be used as a parameter to {@link SolrTemplate} constructor in order to use
* {@link CloudSolrClient} and connect to a SolrCloud collection installation.
*
* @author Christos Manios
*
*/
public class CloudSolrClientFactory extends SolrClientFactoryBase {

public CloudSolrClientFactory() {

}

public CloudSolrClientFactory(SolrClient client) {
super(client);
}

/**
* Returns the same as {@link #getSolrClient()}, as we are in SolrCloud mode.
*/
@Override
public SolrClient getSolrClient(String core) {
return this.getSolrClient();
}

/**
* Returns <code>null</code>, as we are in SolrCloud mode.
*/
@Override
public List<String> getCores() {
return null;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
/*
* Copyright 2014 - 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 org.springframework.data.solr.server.support;

import org.apache.solr.client.solrj.SolrClient;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.apache.solr.client.solrj.impl.LBHttpSolrClient;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

/**
*
* @author Christos Manios
*
*/
public class CloudSolrClientFactoryBean extends CloudSolrClientFactory implements FactoryBean<SolrClient>,
InitializingBean, DisposableBean {

private String zkHost;
private String collection;
private Integer zkClientTimeout;
private Integer zkConnectTimeout;
private Integer httpConnectTimeout;
private Integer httpSoTimeout;

@Override
public void afterPropertiesSet() throws Exception {
Assert.hasText(zkHost);
Assert.hasText(collection);

initSolrClient();
}

private void initSolrClient() {

// create a new CloudSolrClient with a specified comma delimited string
// format which contains IP1:port,IP2:port of Zookeeper ensemble
CloudSolrClient solrClient = new CloudSolrClient(zkHost);

// set collection name
solrClient.setDefaultCollection(collection);

// set Zookeeper ensemble connection timeout
if (zkConnectTimeout != null) {
solrClient.setZkConnectTimeout(zkConnectTimeout);
}

// set Zookeeper ensemble client timeout
if (zkClientTimeout != null) {
solrClient.setZkClientTimeout(zkClientTimeout);
}

// set http connection timeout
if (httpConnectTimeout != null) {
solrClient.getLbClient().setConnectionTimeout(httpConnectTimeout);
}

// set http read timeout
if (httpSoTimeout != null) {
solrClient.getLbClient().setSoTimeout(httpSoTimeout);
}

this.setSolrClient(solrClient);
}

@Override
public SolrClient getObject() throws Exception {
return getSolrClient();
}

@Override
public Class<?> getObjectType() {
if (getSolrClient() == null) {
return CloudSolrClient.class;
}
return getSolrClient().getClass();
}

@Override
public boolean isSingleton() {
return true;
}

/**
* Returns a pair of IP and its respective port of the Zookeeper server which belongs to the Zookeeper ensemble. This
* string can contain multiple IP:port definitions separated by comma.
* <p>
* Example: <code>192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181</code>
* </p>
*
*/
public String getZkHost() {
return zkHost;
}

/**
* Sets the IPs and their respective ports of the Zookeeper servers which belong to the Zookeeper ensemble. This
* string can contain multiple IP:port definitions separated by comma.
* <p>
* Example: <code>192.168.1.1:2181,192.168.1.2:2181,192.168.1.3:2181</code>
* </p>
*
*/
public void setZkHost(String zkHost) {
this.zkHost = zkHost;
}

/**
* Returns the SolrCloud collection name on which this {@link CloudSolrClient} will be connected to.
*/
public String getCollection() {
return collection;
}

/**
* Set the SolrCloud collection name on which this {@link CloudSolrClient} will be connected to.
*/
public void setCollection(String collectionName) {
this.collection = collectionName;
}

/**
* Returns the HTTP connection timeout of underlying {@link LBHttpSolrClient} used for queries, in milliseconds.
* <p>
* Default is 0 (infinite timeout)
* </p>
*/
public Integer getHttpConnectTimeout() {
return httpConnectTimeout;
}

/**
* Sets the HTTP connection timeout of underlying {@link LBHttpSolrClient} in milliseconds.
*
* @param httpConnectTimeout HTTP connect timeout in milliseconds . Default is 0 (infinite timeout)
*
*/
public void setHttpConnectTimeout(Integer httpConnectTimeout) {
this.httpConnectTimeout = httpConnectTimeout;
}

/**
* Returns the HTTP soTimeout (read timeout) of underlying {@link LBHttpSolrClient} used for queries, in milliseconds.
* <p>
* Default is 0 (infinite timeout)
* </p>
*/
public Integer getHttpSoTimeout() {
return httpSoTimeout;
}

/**
* Sets the HTTP soTimeout (read timeout) of underlying {@link LBHttpSolrClient} in milliseconds.
*
* @param httpReadTimeout HTTP read timeout in milliseconds. Default is 0 (infinite timeout)
*/
public void setHttpSoTimeout(Integer httpSoTimeout) {
this.httpSoTimeout = httpSoTimeout;
}

/**
* Returns the client timeout to the zookeeper ensemble in milliseconds
*/
public Integer getZkClientTimeout() {
return zkClientTimeout;
}

/**
* Sets the client timeout to the zookeeper ensemble in milliseconds. Default value: 10000ms
*
* @param zkClientTimeout client timeout to zookeeper ensemble in milliseconds.
*/
public void setZkClientTimeout(Integer zkClientTimeout) {
this.zkClientTimeout = zkClientTimeout;
}

/**
* Returns the connection timeout to the zookeeper ensemble in milliseconds. Default value: 10000ms
*
* @param zkConnectTimeout connection timeout to zookeeper ensemble in milliseconds.
*/
public Integer getZkConnectTimeout() {
return zkConnectTimeout;
}

/**
* Sets the connection timeout to the zookeeper ensemble in milliseconds. Default value: 10000ms
*
* @param zkConnectTimeout connection timeout to zookeeper ensemble in milliseconds.
*/
public void setZkConnectTimeout(Integer zkConnectTimeout) {
this.zkConnectTimeout = zkConnectTimeout;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* 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 org.springframework.data.solr.server.support;

import java.lang.reflect.Field;

import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.solr.client.solrj.impl.CloudSolrClient;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.solr.core.SolrTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
* @author Manios Christos
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("CloudSolrClientFactoryTest-context.xml")
public class CloudSolrClientFactoryTests {

@Autowired
ApplicationContext context;

private static final String zkHost = "127.0.0.1:2181,127.0.0.1:2182";
private static final Integer expectedHttpConnectTimeout = 1500;
private static final Integer expectedHttpSoTimeout = 1800;
private static final Integer expectedZkConnectTimeout = 1300;
private static final Integer expectedZkClientTimeout = 1400;
private static final String collectionName = "jet2pilot";

/**
* Testing issue DATASOLR-211
*/
@Test
public void testCreateCloudSorlClientUsingFactory() {

// test solrtemplate
SolrTemplate solrTemplate = context.getBean("solrTemplate", SolrTemplate.class);
Assert.assertNotNull(solrTemplate);

CloudSolrClient clientFromfactoryBean = context.getBean("cloudSolrClientFactory", CloudSolrClient.class);
Assert.assertNotNull(clientFromfactoryBean);

// check that solr client is not null
CloudSolrClient solrClient = (CloudSolrClient) solrTemplate.getSolrClient();
Assert.assertNotNull(solrClient);

Assert.assertSame(solrClient, clientFromfactoryBean);

Assert.assertEquals(collectionName, solrClient.getDefaultCollection());

// get httpParams() which is deprecated in order to test timeouts
// I could not find another way to get them..
HttpParams httpParams = solrClient.getLbClient().getHttpClient().getParams();

Assert.assertEquals(expectedHttpConnectTimeout, (Integer) HttpConnectionParams.getConnectionTimeout(httpParams));
Assert.assertEquals(expectedHttpSoTimeout, (Integer) HttpConnectionParams.getSoTimeout(httpParams));

// now try to get private fields using reflection

try {
// try to get zkHost
Field actualZkHostField = solrClient.getClass().getDeclaredField("zkHost");

// try to get zkConnectTimeout
Field actualZkConnectTimeoutField = solrClient.getClass().getDeclaredField("zkConnectTimeout");

// try to get zkClientTimeout
Field actualZkClientTimeoutField = solrClient.getClass().getDeclaredField("zkClientTimeout");

Assert.assertEquals(zkHost, (String) actualZkHostField.get(solrClient));
Assert.assertEquals(expectedZkConnectTimeout.intValue(), actualZkConnectTimeoutField.getInt(solrClient));
Assert.assertEquals(expectedZkClientTimeout.intValue(), actualZkClientTimeoutField.getInt(solrClient));

} catch (NoSuchFieldException e) {
} catch (SecurityException e) {
} catch (IllegalArgumentException e) {
} catch (IllegalAccessException e) {
}

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:solr="http://www.springframework.org/schema/data/solr"
xsi:schemaLocation="http://www.springframework.org/schema/data/solr http://www.springframework.org/schema/data/solr/spring-solr-1.0.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<solr:repositories base-package="org.springframework.data.solr.repository.config" />

<!-- Configures CloudSolrClient using a factory bean -->
<bean id="cloudSolrClientFactory"
class="org.springframework.data.solr.server.support.CloudSolrClientFactoryBean">
<property name="zkHost" value="127.0.0.1:2181,127.0.0.1:2182" />
<property name="collection" value="jet2pilot" />
<property name="httpConnectTimeout" value="1500" />
<property name="httpSoTimeout" value="1800" />
<property name="zkConnectTimeout" value="1300" />
<property name="zkClientTimeout" value="1400" />
</bean>

<!-- Configures Solr template -->
<bean id="solrTemplate" class="org.springframework.data.solr.core.SolrTemplate">
<constructor-arg index="0" ref="cloudSolrClientFactory" />
</bean>

</beans>