3

Just password protected solr on Jetty server. I am able to read/access data from solr using solrj :->

HttpSolrServer solr = new HttpSolrServer("http://111.111.111:8983/solr/mysolr");
   HttpClientUtil.setBasicAuth((DefaultHttpClient) solr.getHttpClient(), "admin", "akshaybhatt");

but it gives me I/O Exception as below. There are other examples on SO about authentication but I have no idea how do I use authentication in Solrj. The below error comes only when I try to update a record (and possibly add a record, not tested yet)

org.apache.solr.client.solrj.SolrServerException: IOException occured when talking to server at: http://111.111.111.138:8983/solr/mysolrcore
    at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:507)
    at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:199)
    at org.apache.solr.client.solrj.request.AbstractUpdateRequest.process(AbstractUpdateRequest.java:118)
    at org.apache.solr.client.solrj.SolrServer.add(SolrServer.java:116)
    at org.apache.solr.client.solrj.SolrServer.add(SolrServer.java:102)
    at UpdateSolrTesting.AddToSolr(UpdateSolrTesting.java:228)
    at UpdateSolrTesting.performaction(UpdateSolrTesting.java:141)
    at UpdateSolrTesting.main(UpdateSolrTesting.java:101)
Caused by: org.apache.http.client.ClientProtocolException
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:867)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:57)
    at org.apache.solr.client.solrj.impl.HttpSolrServer.request(HttpSolrServer.java:395)
    ... 7 more
Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity.
    at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:660)
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:486)
    at org.apache.http.impl.client.AbstractHttpClient.doExecute(AbstractHttpClient.java:863)
    ... 11 more
Community
  • 1
  • 1
akshayb
  • 1,219
  • 2
  • 18
  • 44

3 Answers3

3

It is happening only because authentication parameter is not being sent while doing POST or DELETE calls, so so solution is you need to fix that in your http client

I am using solr 6.2.0 and its corresponding java client

So i created a new SolrHttp client which looks like below

public class TEHttpSolrClient extends HttpSolrClient {

private static final String UTF_8 = StandardCharsets.UTF_8.name();

public TEHttpSolrClient(String baseURL) {
    super(baseURL);
}

@Override
public NamedList<Object> request(final SolrRequest request, String collection) throws SolrServerException, IOException {
    ResponseParser responseParser = request.getResponseParser();
    if (responseParser == null) {
        responseParser = parser;
    }
    return request(request, responseParser, collection);
}

public NamedList<Object> request(final SolrRequest request, final ResponseParser processor, String collection)
        throws SolrServerException, IOException {
    HttpRequestBase method = createMethod(request, collection);
    String userPass = "<username>:<password>";
    String encoded = Base64.byteArrayToBase64(userPass.getBytes(UTF_8));
    // below line will make sure that it sends authorization token every time in all your requests
    method.setHeader(new BasicHeader("Authorization", "Basic " + encoded));
    return executeMethod(method, processor);
}

}

Also to call the client you should call it like below

private static SolrClient solr = new TEHttpSolrClient.Builder("<solr core url>").build();
3

What you need is called "preemptive authentication". This tells the http client to authenticate on the first call to the url. The default behaviour is to send two request, when basic authentication is used. This might fail, as in your case, when the entity in the http call is not reusable.

Luckyly solr allready has a build in way to enable preemptive authentication by using a different client building factory for SolrHttpClientBuilder.

String userName = "someUserName";
String password = "secretPassword";

ModifiableSolrParams params = new ModifiableSolrParams();
params.set(HttpClientUtil.PROP_BASIC_AUTH_USER, userName);
params.set(HttpClientUtil.PROP_BASIC_AUTH_PASS, password);

// set the params for authentication here
PreemptiveBasicAuthClientBuilderFactory.setDefaultSolrParams(params);
PreemptiveBasicAuthClientBuilderFactory preemptiveBasicAuthClientBuilderFactory = new PreemptiveBasicAuthClientBuilderFactory();

// create a new client builder from the preemptive client builder factory
SolrHttpClientBuilder httpClientBuilder = preemptiveBasicAuthClientBuilderFactory
            .getHttpClientBuilder(Optional.empty());

// set the client builder to be used by the clientUtil 
HttpClientUtil.setHttpClientBuilder(httpClientBuilder);

// the params need to be passed here too
CloseableHttpClient httpAuthClient = HttpClientUtil.createClient(params);

// now build the solr client with the special http client
Builder solrClientBuilder = new HttpSolrClient.Builder(solrClientConfig.getSolrUrl()).withHttpClient(httpAuthClient);

// create solr client
SolrClient client = solrClientBuilder.build();

Remember not to set the authorization params at the request level, otherwise the preemptive auth won't work.

defonion
  • 121
  • 2
  • 1
    I think it is the most related answer according to solr document [Global (JVM) Basic Auth Credentials](https://solr.apache.org/guide/8_8/basic-authentication-plugin.html#global-jvm-basic-auth-credentials) – saba safavi Apr 18 '21 at 07:31
  • This is the best answer: has the correct assumption about the root cause and the solution mentioned in the official documentation. One might think that this is related e.g. POST requests and them being non-repeatable (which might be the case) but actually it is about the "entity" (abstraction on httpcore level) not being repeatable: https://www.javadoc.io/doc/org.apache.httpcomponents/httpcore/4.4.4/org/apache/http/HttpEntity.html – JSamir Jul 22 '21 at 21:16
  • It is also worth noting that if you need multiple clients in your application you should use the Sytem Property as described in the official documentation, that way you do not need to change the existing code too much. – JSamir Jul 22 '21 at 21:46
0

Similar question asked already, you can look at the below links to get some idea.

Community
  • 1
  • 1
Kumar
  • 3,782
  • 4
  • 39
  • 87
  • @akshayb i am facing similar kind of issue, can you help me on my problem thanks. http://stackoverflow.com/questions/35825280/solrj-deletebyquery-is-not-working – Sthita Mar 06 '16 at 09:36