Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get all documents from an index using spring-data-elasticsearch

I am trying to connect to my external ElasticSearch server with Spring Boot.

If I do a curl from command line, I get expected results.

curl "http://ipAddr:9200/indexName/TYPE/_search?pretty=true"

But getting this error when I try to access it via Spring Boot.

<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>Mon Sep 11 12:39:15 IST 2017</div><div>There was an unexpected error (type=Internal Server Error, status=500).</div><div>Could not write JSON: (was java.lang.NullPointerException); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: java.util.ArrayList[0]-&gt;org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl[&quot;facets&quot;])</div></body></html>

Not sure why a NullPointerException and what is aggregartion.impl

Here is my Spring Application:

Controller:

@RestController
public class PojoController {

    @Autowired
    PojoService pojoService;

    @RequestMapping(value = "/", method=RequestMethod.GET)
    public @ResponseBody String index() {
        return new String("Welcome:)");
    }

    @RequestMapping(value = "/all", method = RequestMethod.GET,
            produces = { MediaType.APPLICATION_JSON_VALUE })
    @ResponseBody List<POJO> findAll() {
        try {
            List<POJO> pojoObj = pojoService.findAll();
            return pojoObj;
        } catch (Exception exp) {
            exp.printStackTrace();
            return null;
        }
    }
}

Repository:

@Repository
public interface PojoRepository extends ElasticsearchRepository<POJO, Integer> {

    List<POJO> findAll();

}

Service:

@Service
public class POJOServiceImpl implements POJOService{

    private POJORepository pojoRepository;

    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    public void setPojoRepository(PojoRepository pojoRepository) {
        this.pojoRepository = pojoRepository;
    }

    public POJO findOne(String id) {
        return pojoRepository.findOne(id);
    }

    public List<POJO> findAll() {
        return (List<POJO>) pojoRepository.findAll();
    }

}

POJO class:

@Document(indexName = "INDEX", type = "TYPE")
public class POJO {

     @Id
     private Integer id;
     private String name;

     public POJO(){
         // empty
     }



    public POJO(Integerid, String name) {
        super();
        this.id = id;
        this.name = name;
    }

    // getters and setters
}

I should be able to query all the documents in the index. Later on, I will try and use filters etc.

Any help is appreciated. Thanks :)

like image 337
Anusha Avatar asked Mar 09 '23 02:03

Anusha


1 Answers

It looks like Jackson has a problem with handling your POJO (probably related to this issue: DATAES-274) - the problematic part is casting in repository from Iterable collection to List.

Update

In case of repositories, spring-data-elasticsearch behaves a bit different than you would expect. Taking your example:

@Repository
public interface PojoRepository extends ElasticsearchRepository<POJO, Integer> {
    List<POJO> findAll();
}

and after calling in your rest controller:

List<POJO> pojoObj = pojoService.findAll();

in debugger you will see something like this:

enter image description here

You would expect that pojoObj list contains objects of POJO class. And here comes the surprise - pojoObj ArrayList contains one object of AggregatedPageImpl type and its content field is the right list that contains your POJO objects. This is the reason why you get:

Could not write JSON: ... java.util.ArrayList[0]->org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl[\"facets\"])

As I wrote before, Jackson cannot handle this while serializing POJO objects.

Solution 1

Let repositories return Iterable collection (by default).

@Repository
public interface PojoRepository extends ElasticsearchRepository<POJO, Integer> {

}

Move the conversion part to the service but use some utility method (here with Guava) in order to have it like this:

import com.google.common.collect.Lists;

public List<POJO> findAll() {
    return Lists.newArrayList(pojoRepository.findAll());
}

Solution 2

Use Page in repository (here simplified version without parameters):

@Repository
public interface PojoRepository extends ElasticsearchRepository<POJO, Integer> {
    Page<TestDto> findAll();
}

If you still want to operate on list - get content from page in service:

public List<POJO> findAll() {
    return testDtoRepository.findAll().getContent();
}
like image 94
Joanna Avatar answered Apr 28 '23 04:04

Joanna