I use high-level rest client to connect to elasticsearch 6.5 from spring boot application.
I want to create a controller with methods to add commands to bulk request and a method to flush (actually execute) the bulk request operation.
I coded it like this:
BulkRequest bean - note the singleton scope
@Bean
public BulkRequest bulkRequest() {
return new BulkRequest();
}
Bulk Controller
@RestController
@RequestMapping("/bulk")
public class BulkController {
@Autowired
private BulkRequest bulkRequest;
@Autowired
RestHighLevelClient client;
@PostMapping
public void index(@RequestBody String o) {
bulkRequest.add(new IndexRequest(config.INDEX, config.TYPE).source(o, XContentType.JSON));
}
@PostMapping(path = "/flush")
public String flush() throws Exception {
BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
if(bulkResponse.hasFailures()) {
return bulkResponse.buildFailureMessage();
}
else {
return "All operations in the bulk request proceeded successfully!";
}
}
Now the questions:
- is the bulkRequest.add
method synchronized over the scope of the BulkRequest bean (in this case singleton) ?
- how to start a new BulkRequest after the BulkController.flush
method is called ? Do I need to instance a new bean of the BulkRequest and somehow push it to the bean environment ?
- what would need to change in the case of BulkRequest bean having the @session
scope ?
I found a similar question - here on StackOverflow - unfortunately, I forgot to save a link, so I will just interpret here in this response.
I used AtomicReference as a bean type a reinitialized BulkRequest object in the flush method. Then I added synchronization over BulkRequest.add
calls since it uses List in the background.
Note that this solution is kind of dirty and was described as so in the referenced answer - but it WORKS for me..
Code:
Bean
@Bean
public AtomicReference<BulkRequest> bulkRequest() {
return new AtomicReference<BulkRequest>(new BulkRequest());
}
Controller:
@Autowired
private AtomicReference<BulkRequest> bulkRequest;
@PostMapping
public void index(@RequestBody String o) {
synchronized (bulkRequest.get()) {
bulkRequest.get().add(new IndexRequest(config.INDEX, config.TYPE).source(o, XContentType.JSON));
}
}
@DeleteMapping(path="/{id}")
public void delete(@PathVariable String id) {
synchronized (bulkRequest.get()) {
bulkRequest.get().add(new DeleteRequest(config.INDEX, config.TYPE, id));
}
}
@PutMapping(path="/{id}")
public void update(@PathVariable String id, @RequestBody String o) {
synchronized (bulkRequest.get()) {
bulkRequest.get().add(new UpdateRequest(config.INDEX, config.TYPE, id).doc(o, XContentType.JSON));
}
}
@PostMapping(path = "/flush")
public String flush() throws Exception {
synchronized (bulkRequest.get()) {
String result = bulkService.flush(bulkRequest);
bulkRequest.set(new BulkRequest());
return result;
}
}
BulkService
@Service
public class BulkService {
@Autowired
private RestHighLevelClient client;
public String flush( AtomicReference<BulkRequest> bulkRequest) throws Exception {
BulkResponse bulkResponse = client.bulk(bulkRequest.get(), RequestOptions.DEFAULT);
if(bulkResponse.hasFailures()) {
return bulkResponse.buildFailureMessage();
}
else {
return "All operations in the bulk request proceeded successfully!";
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.