Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Solr 7 with Spring data and basic authentication not working

@SpringBootApplication public class SpringDataSolarApplication {

public static void main(String[] args) {
    SpringApplication.run(SpringDataSolarApplication.class, args);
}

@Bean
SolrTemplate solrTemplate() {
  return new SolrTemplate(solrClientFactory());
}

@Bean
SolrClientFactory solrClientFactory() {
  Credentials credentials = new UsernamePasswordCredentials("solr", "SolrRocks");
  return new HttpSolrClientFactory(solrClient(), credentials , "BASIC");
}

@Bean
SolrClient solrClient() {

  return new HttpSolrClient.Builder("http://localhost:8983/solr").build();
}

}

public interface EmployeeRepository extends SolrCrudRepository{

Employee findByName(String name);

}

@RestController public class EmployeeController {

@Autowired
private EmployeeRepository repository;

@PostConstruct
public void addEmployees() {
    List<Employee> employees = new ArrayList<>();
    employees.add(new Employee("373", "Basant", new String[] { "Bangalore", "BTM" }));
    employees.add(new Employee("908", "Santosh", new String[] { "Hyderbad", "XYZ" }));
    employees.add(new Employee("321", "Sagar", new String[] { "Pune", "PQR" }));
    repository.saveAll(employees);

}

@GetMapping("/getALL")
public Iterable<Employee> getEmployees() {
    return repository.findAll();
}

@GetMapping("/getEmployee/{name}")
public Employee getEmployeeByName(@PathVariable String name) {
    return repository.findByName(name);
}

}

the getALL operation is working fine but the save operation failed with this error. Please help

Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity. at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:225) ~[httpclient-4.5.7.jar:4.5.7] at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:185) ~[httpclient-4.5.7.jar:4.5.7] at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) ~[httpclient-4.5.7.jar:4.5.7] at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.7.jar:4.5.7] at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) ~[httpclient-4.5.7.jar:4.5.7] ... 63 common frames omitted

like image 825
Robert Nguyen Avatar asked Dec 01 '25 02:12

Robert Nguyen


1 Answers

Came across same issue and solved with extending HttpSolrClient and applying same backend approach with recommended way mentioned on Solr docs but getting credentials from constructor not setting on each request.

class CustomSolrClient extends HttpSolrClient {
    @Nullable
    private final String username;
    @Nullable
    private final String password;

    CustomSolrClient(Builder builder, String username, String password) {
        super(builder);
        this.username = username;
        this.password = password;
    }

    @Override
    public NamedList<Object> request(SolrRequest request, ResponseParser processor, String collection) throws SolrServerException, IOException {
        HttpRequestBase method = createMethod(request, collection);
        if (username != null && password != null) {
            String userPass = username + ":" + password;
            String encoded = Base64.byteArrayToBase64(userPass.getBytes(UTF_8));
            method.setHeader(new BasicHeader("Authorization", "Basic " + encoded));
        }
        return executeMethod(method, processor, request instanceof V2Request || request.getPath().contains("/____v2"));
    }
}

And create bean using that:

    @Bean
    public SolrClient solrClient() {
        return new CustomSolrClient(new HttpSolrClient.Builder(properties.getHost()), properties.getUsername(), properties.getPassword());
    }

This may seem as an ugly approach but if you check HttpSolrClientFactory sources it's even more uglier which actually accesses private field of HttpClient belongs to Solr client.

like image 71
Soner Koksal Avatar answered Dec 07 '25 13:12

Soner Koksal