Java rest elastic search json documents - java

I am trying to sends json documents to elasticsearch by using java rest .
I just need to know how to initialize the variable "entities[i]" and put json documents in its.I have try many ways but still do not get something which work.
here is the code from elastticsearch website: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/_example_requests.html
int numRequests = 10;
final CountDownLatch latch = new CountDownLatch(numRequests);
for (int i = 0; i < numRequests; i++) {
restClient.performRequestAsync(
"PUT",
"/twitter/tweet/" + i,
Collections.<String, String>emptyMap(),
//assume that the documents are stored in an entities array
entities[i],
new ResponseListener() {
#Override
public void onSuccess(Response response) {
System.out.println(response);
latch.countDown();
}
#Override
public void onFailure(Exception exception) {
latch.countDown();
}
}
);
}
//wait for all requests to be completed
latch.await();
Thanks you

int numRequests = 1;
final CountDownLatch latch = new CountDownLatch(numRequests);
HttpEntity entity = new NStringEntity(
"{\n" +
" \"user\" : \"kimchy\",\n" +
" \"post_date\" : \"2009-11-15T14:12:12\",\n" +
" \"message\" : \"trying out Elasticsearch\"\n" +
"}", ContentType.APPLICATION_JSON);
List<HttpEntity> entities = asList(entity);
for (int i = 0; i < numRequests; i++) {
restClient.performRequestAsync(
"PUT",
"/twitter/tweet/" + i,
Collections.<String, String>emptyMap(),
entities.get(i),
new ResponseListener() {
#Override
public void onSuccess(Response response) {
System.out.println(response);
latch.countDown();
}
#Override
public void onFailure(Exception exception) {
latch.countDown();
}
}
);
}
latch.await();
The entity is a type HttpEntity.You need to create list of HttpEntity objects in the list and use them.

Related

How To Use Response value In Another Method

I am working on restassured and here is my 2 methods. I want to use the albumId returned from the AlbumList method in the other method
public void AlbumList() {
Response response1 = given().spec(url).queryParam("page", 0).queryParam("size", 100)
.queryParam("sortBy", "createdDate").queryParam("contentType", "album/photo")
.queryParam("sortOrder", "ASC")
.header("Content-type", "application/json")
.header("Accept", "application/json")
.header("X-Auth-Token", payload.userAuth())
.when().get("/album")
.then().assertThat().statusCode(200).extract().response();
Assert.assertEquals(response1.jsonPath().get("[4].label"), "TLOTR");
JsonPath js = new JsonPath(response1.asString());
int count = js.getInt("size()");
// Response check part
for (int i = 0; i < count; i++) {
assertEqual(js, i, "createdDate", AlbumAttributes.actual_createdDate());
assertEqual(js, i, "lastModifiedDate", AlbumAttributes.actual_modifiedDate());
assertEqual(js, i, "uuid", AlbumAttributes.actual_uuid());
if (js.get("[" + i + "].coverPhoto") != null) {
String d = response1.jsonPath().get("[" + i + "].coverPhoto.tempDownloadURL").toString();
Assert.assertTrue(d.matches(AlbumAttributes.actual_temp_url()));
System.out.println(js.get("[" + i + "].coverPhoto.tempDownloadURL").toString() + " is equalent to : " + AlbumAttributes.actual_temp_url());
}
if (js.get("[" + i + "].coverPhoto.metadata['Thumbnail-Large']") != null) {
String e = response1.jsonPath().get("[" + i + "].coverPhoto.metadata['Thumbnail-Large']").toString();
Assert.assertTrue(e.matches(AlbumAttributes.actual_metaData_url()));
System.out.println(js.get("[" + i + "].coverPhoto.metadata['Thumbnail-Large']").toString() + " is equalent to : " + AlbumAttributes.actual_metaData_url());
}
}
String albumId = response1.jsonPath().get("[0].uuid").toString();
String albumId2 = response1.jsonPath().get("[1].uuid").toString();
}
I know these are void and doesnt return anything but idk how to use it. Bye the these methods are in the same class. Thanks in advance
public void AlbumDetails() {
Response response = given().queryParam("page", 0).queryParam("size", 100)
.queryParam("sortBy", "createdDate").queryParam("sortOrder", "DESC")
.header("Content-type", "application/json")
.header("Accept", "application/json")
.header("X-Auth-Token", payload.userAuth())
.when().get("/album/" + albumId)
.then().assertThat().statusCode(200).extract().response();
// Response check part
Assert.assertEquals("[]", response.jsonPath().get("fileList").toString());
Assert.assertEquals("album/photo", response.jsonPath().get("contentType").toString());
Assert.assertEquals("false", response.jsonPath().get("readOnly").toString());
Assert.assertTrue(response.jsonPath().get("createdDate").toString().matches(AlbumAttributes.actual_createdDate()));
Assert.assertTrue(response.jsonPath().get("lastModifiedDate").toString().matches(AlbumAttributes.actual_modifiedDate()));
Assert.assertTrue(response.jsonPath().get("uuid").toString().matches(AlbumAttributes.actual_uuid()));
System.out.println("Album Details Response Test PASS");
long albumDetails_time = response.getTime();
System.out.println("\tAlbum Detail's Api response time is : " + albumDetails_time);
}
The easiest way is to change the return type of the AlbumList() method from void to String:
public String AlbumList() {
And in AlbumDetails() method we should change:
.when().get("/album/" + AlbumList())
Another option is to create instance variable albumId, not locally in AlbumList() method, and use it:
public class SomeClass {
public String albumId;
public void AlbumList() {
...
albumId = response1.jsonPath().get("[0].uuid").toString();
}
public void AlbumDetails() {
...
.when().get("/album/" + albumId)
...
}
}
P.S. Here are some more tips:
due to clean code more correct name describes what these methods do, e.g. getAlbumList() or storeAlbumList() and smth similar for another method;
for extracting jsonPath from response we can use: JsonPath js = given()....extract().jsonPath();

Using ScheduledExecutorService to save(Entites), I get detached Entity passed to persist error

I have a very curious Error that I cant seem to get my head around.
I need to use a ScheduledExecutorService to pass the Survey Entity I created to be edited and then saved as a new Entity.
public void executeScheduled(Survey eventObject, long interval) {
HashMap<String, String> eventRRules = StringUtils.extractSerialDetails(eventObject.getvCalendarRRule());
long delay = 10000;
ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
Runnable runnable = new Runnable() {
private int counter = 1;
private int executions = Integer.parseInt(eventRRules.get("COUNT"));
Survey survey = eventObject;
public void run() {
String uid = eventObject.getUniqueEventId();
logger.info("SurveyController - executeScheduled - Iteration: " + counter);
String serialUid = null;
if (counter == 1) {
serialUid = uid + "-" + counter;
} else {
serialUid = StringUtils.removeLastAndConcatVar(eventObject.getUniqueEventId(), Integer.toString(counter));
}
if (++counter > executions) {
service.shutdown();
}
survey.setUniqueEventId(serialUid);
try {
executeCreateSurvey(survey);
} catch(Exception e) {
logger.debug("SurveyController - executeScheduled - Exception caught: ");
e.printStackTrace();
}
}
};
service.scheduleAtFixedRate(runnable, delay, interval, TimeUnit.MILLISECONDS);
}
When the executeCreateSurvey(survey) Method is run without the ScheduleExecutorService, it works flawlessly.
Yet when it is executed inside the run() Method, I get the "detached entity passed to persist" Error each time the save(survey) Method is run within the executeCreateSurvey() Method....
The executeCreateSurvey() Method where the .save() Method is called:
public ResponseEntity<?> executeCreateSurvey(Survey eventObject) {
MailService mailService = new MailService(applicationProperties);
Participant eventOwner = participantRepositoryImpl.createOrFindParticipant(eventObject.getEventOwner());
eventObject.setEventOwner(eventOwner);
Survey survey = surveyRepositoryImpl.createSurveyOrFindSurvey((Survey) eventObject);
// Saves additional information if small errors (content
// errors,.. )
// occurs
String warnMessage = "";
List<Participant> participants = new ArrayList<Participant>();
for (Participant participantDetached : eventObject.getParticipants()) {
// Check if participant already exists
Participant participant = participantRepositoryImpl.createOrFindParticipant(participantDetached);
participants.add(participant);
// Only create PartSur if not existing (Update case)
if (partSurRepository.findAllByParticipantAndSurvey(participant, survey).isEmpty()) {
PartSur partSur = new PartSur(participant, survey);
partSurRepository.save(partSur);
try {
mailService.sendRatingInvitationEmail(partSur);
surveyRepository.save(survey);
} catch (Exception e) {
// no special exception for "security" reasons
String errorMessage = "error sending mail for participant: " + e.getMessage() + "\n";
warnMessage += errorMessage;
logger.warn("createSurvey() - " + errorMessage);
}
}
}
// Delete all PartSurs and Answers from removed participants
List<PartSur> partSursForParticipantsRemoved = partSurRepository.findAllByParticipantNotIn(participants);
logger.warn("createSurvey() - participants removed: " + partSursForParticipantsRemoved.size());
partSurRepositoryImpl.invalidatePartSurs(partSursForParticipantsRemoved);
return new ResponseEntity<>("Umfrage wurde angelegt. Warnungen: " + warnMessage, HttpStatus.OK);
}
What could the reason be for this?
I have not been able to find this Problem anywhere so far.

Volley JSONArrayRequest - not sending params properly?

I've tried with normal JSONArrayRequests and StringRequests and everything was fine untill now. I want to send an JSONArrayRequest with POST parameters to get some MySQL result in JSON format from the script. Unfortunately I get [] everytime in response. I have checked .php file and query with _GET method and the script worked perfectly returning desired rows in Json format.
I read here (https://stackoverflow.com/a/18052417/4959185) Volley Team have added JSONArrayRequest with _POST parameter to their class. However it does not work in my case. Could you please look what is wrong with that function:
private void getFavouriteRecipes(final String userUniqueId, final int offset) {
JsonArrayRequest favouriteRecipesReq = new JsonArrayRequest(Request.Method.POST,
AppConfig.URL_GETFAVOURITERECIPES, new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d("odpowiedz", "Odpowiedź ulubionych: " + response);
for (int i = 0; i < response.length(); i++) {
try {
JSONObject jObj = response.getJSONObject(i);
RecipeItem recipeItem = new RecipeItem();
recipeItem.setRecipeUniqueID(jObj.getString("unique_id"));
recipeItem.setRecipeTitle(jObj.getString("title"));
recipeItem.setRecipeImgThumbnailLink(jObj.getString(
"img_tumbnail_link"));
recipeItem.setRecipeAddAte(jObj.getString("add_date"));
recipeItem.setRecipeKitchenType(jObj.getString("kitchen_type"));
recipeItem.setRecipeMealType(jObj.getString("meal_type"));
recipeItem.setRecipeName(jObj.getString("name"));
recipeItem.setRecipeSurname(jObj.getString("surname"));
recipeItem.setRecipeLikeCount(jObj.getString("like_count"));
recipeFavouriteItems.add(recipeItem);
} catch (JSONException e) {
e.printStackTrace();
showSnackbarInfo("Błąd Json: " + e.getMessage(),
R.color.snackbar_error_msg);
}
}
recipeFavouriteItemsAdapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("odpowiedz", "Błąd pobierania ulubionych: " +
Integer.toString(error.networkResponse.statusCode));
showSnackbarInfo(Integer.toString(error.networkResponse.statusCode),
R.color.snackbar_error_msg);
}
}) {
#Override
protected Map<String, String> getParams() {
// Posting Parameters to Login URL
Map<String, String> params = new HashMap<>();
params.put("user_unique_id", userUniqueId);
params.put("offset", Integer.toString(offset));
Log.d(TAG, "wysylam parametry: " + userUniqueId + ", " + Integer.toString(offset));
return params;
}
};
// Adding Request to Request Queue
AppController.getInstance().addToRequestQueue(favouriteRecipesReq);
}
My PHP Script:
https://ideone.com/ZxYzHr
I have found another way to get JSONArrayResponse with sending parameters. I think that will help somebody.
U just write standard JSONArrayRequest liek this:
JsonArrayRequest favouriteRecipesReq = new JsonArrayRequest(prepareGetMethodUrl(),
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
Log.d("odpowiedz", "Odpowiedź ulubionych: " + response.toString());
for (int i = 0; i < response.length(); i++) {
try {
JSONObject jObj = response.getJSONObject(i);
RecipeItem recipeItem = new RecipeItem();
recipeItem.setRecipeUniqueID(jObj.getString("unique_id"));
recipeItem.setRecipeTitle(jObj.getString("title"));
recipeItem.setRecipeImgThumbnailLink(jObj.getString(
"img_tumbnail_link"));
recipeItem.setRecipeAddAte(jObj.getString("add_date"));
recipeItem.setRecipeKitchenType(jObj.getString("kitchen_type"));
recipeItem.setRecipeMealType(jObj.getString("meal_type"));
recipeItem.setRecipeName(jObj.getString("name"));
recipeItem.setRecipeSurname(jObj.getString("surname"));
recipeItem.setRecipeLikeCount(jObj.getString("like_count"));
recipeFavouriteItems.add(recipeItem);
} catch (JSONException e) {
e.printStackTrace();
}
}
recipeFavouriteItemsAdapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("odpowiedz", "Błąd pobierania ulubionych: " +
Integer.toString(error.networkResponse.statusCode));
showSnackbarInfo(Integer.toString(error.networkResponse.statusCode),
R.color.snackbar_error_msg);
}
});
// Adding Request to Request Queue
AppController.getInstance().addToRequestQueue(favouriteRecipesReq);
Instead of standard URL to the PHP script I inserted function returning String called prepareGetMethodUrl().
Let's look inside it:
private String prepareGetMethodUrl() {
return AppConfig.URL_GETFAVOURITERECIPES + "?user_unique_id=" + userUniqueId + "&offset=" +
Integer.toString(offset);
}
As you can see it's very simple. I get standard AppConfig.URL_GETFAVOURITERECIPES which is static field in AppConfig class conatining direct link to my PHP script on my serwer f.e http://www.someserversite.com/my_api/gmy_php_script.php and combine it with parametres values I need to send to the script: user_unique_id and it's content userUniqueId and offset which content is offset parsed from int to String.
Inside my script I just call:
<?php
// some code
// Receiving The Post Params
$user_unique_id = $_GET['user_unique_id'];
$offset = $_GET['offset'];
echo $user_unique_id . "<br />";
echo $offset;
?>

ElasticSearch index exists not working / reliable

I am writing a simple Java wrapper around ElasticSearch's admin client. To test it I have a main method that first checks if an index exists (IndicesExistsRequest), if so deletes it (DeleteIndexRequest), and creates the index again. See code below. Yet I consistently get an IndexAlreadyExistsException.
By the way I am trying to get a client for the node that you start from the command prompt (by simply typing "elastic search"). I have tried every combination of methods on nodeBuilder's fluent interface, but I can't seem to get one.
public static void main(String[] args) {
ElasticSearchJavaClient esjc = new ElasticSearchJavaClient("nda");
if (esjc.indexExists()) {
esjc.deleteIndex();
}
esjc.createIndex();
URL url = SchemaCreator.class.getResource("/elasticsearch/specimen.type.json");
String mappings = FileUtil.getContents(url);
esjc.createType("specimen", mappings);
}
final Client esClient;
final IndicesAdminClient adminClient;
final String indexName;
public ElasticSearchJavaClient(String indexName) {
this.indexName = indexName;
esClient = nodeBuilder().clusterName("elasticsearch").client(true).node().client();
adminClient = esClient.admin().indices();
}
public boolean deleteIndex() {
logger.info("Deleting index " + indexName);
DeleteIndexRequest request = new DeleteIndexRequest(indexName);
try {
DeleteIndexResponse response = adminClient.delete(request).actionGet();
if (!response.isAcknowledged()) {
throw new Exception("Failed to delete index " + indexName);
}
logger.info("Index deleted");
return true;
} catch (IndexMissingException e) {
logger.info("No such index: " + indexName);
return false;
}
}
public boolean indexExists() {
logger.info(String.format("Verifying existence of index \"%s\"", indexName));
IndicesExistsRequest request = new IndicesExistsRequest(indexName);
IndicesExistsResponse response = adminClient.exists(request).actionGet();
if (response.isExists()) {
logger.info("Index exists");
return true;
}
logger.info("No such index");
return false;
}
public void createIndex() {
logger.info("Creating index " + indexName);
CreateIndexRequest request = new CreateIndexRequest(indexName);
IndicesAdminClient iac = esClient.admin().indices();
CreateIndexResponse response = iac.create(request).actionGet();
if (!response.isAcknowledged()) {
throw new Exception("Failed to create index " + indexName);
}
logger.info("Index created");
}
You can also execute a synchronous request like this:
boolean exists = client.admin().indices()
.prepareExists(INDEX_NAME)
.execute().actionGet().isExists();
Here is my solution when using RestHighLevelClient client;
Here a code-snippet: :
public boolean checkIfIndexExists(String indexName) throws IOException {
Response response = client.getLowLevelClient().performRequest("HEAD", "/" + indexName);
int statusCode = response.getStatusLine().getStatusCode();
return (statusCode != 404);
}
A contribution for someone else !
The skgemini's answer is ok if you want to check if index is available by the actual index name or any of its aliases.
If you however want to check only by the index name, here is how.
public boolean checkIfIndexExists(String index) {
IndexMetaData indexMetaData = client.admin().cluster()
.state(Requests.clusterStateRequest())
.actionGet()
.getState()
.getMetaData()
.index(index);
return (indexMetaData != null);
}
OK, I figured out a solution. Since the java client's calls are done asynchronously you have to use the variant which takes an action listener. The solution still gets a bit contrived though:
// Inner class because it's just used to be thrown out of
// the action listener implementation to signal that the
// index exists
private class ExistsException extends RuntimeException {
}
public boolean exists() {
logger.info(String.format("Verifying existence of index \"%s\"", indexName));
IndicesExistsRequest request = new IndicesExistsRequest(indexName);
try {
adminClient.exists(request, new ActionListener<IndicesExistsResponse>() {
public void onResponse(IndicesExistsResponse response) {
if (response.isExists()) {
throw new ExistsException();
}
}
public void onFailure(Throwable e) {
ExceptionUtil.smash(e);
}
});
}
catch (ExistsException e) {
return true;
}
return false;
}
I had the same issue but i didn't like the solution which uses an ActionListener. ElasticSearch also offers a Future variant (at least at version 6.1.0).
Here a code-snippet:
public boolean doesIndexExists(String indexName, TransportClient client) {
IndicesExistsRequest request = new IndicesExistsRequest(indexName);
ActionFuture<IndicesExistsResponse> future = client.admin().indices().exists(request);
try {
IndicesExistsResponse response = future.get();
boolean result = response.isExists();
logger.info("Existence of index '" + indexName + "' result is " + result);
return result;
} catch (InterruptedException | ExecutionException e) {
logger.error("Exception at waiting for IndicesExistsResponse", e);
return false;//do some clever exception handling
}
}
May be this helps someone else too. Cheers!
This works on Elasticsearch 7.x:
public boolean indexExists(String indexName) throws IOException {
return client.indices().exists(new org.elasticsearch.client.indices.GetIndexRequest(indexName), RequestOptions.DEFAULT);
}

Sending data stream to multiple URLs using org.apache.commons.httpclient.HttpClient

Firstly, let me say I not a java programmer, I am a programmer on the IBM Iseries. However, I've been tasked with changing a current java application that currently sends a stream of data to one URL that will allow that same stream of data to be sent to multiple URLs based on a properties file. Our java app runs on the Iseries and we are using the org.apache.commons.httpclient.HttpClient class to send the data and the response is processed. Everything works great right now, but I wanted to see if anyone could point me in the right direction to complete this task.
Essentially, I need to send the same block of data to multiple URLs within the same thread or instance. I'm not sure if its possible or the best way to try to complete this. So, is there a way to create multiple instances within the same thread that will send the same data stream to multiple URLs? Before you start commenting I will say again that I am not a java programmer and I wasn't even sure how to phrase the question.
Added code sample:
public class Replication_CC implements TextProcessor {
public static String VERSION = "v2014.1.0";
static Logger log = Logger.getLogger(Replication_CC.class);
String url;
int retries = 1;
public Replication_CC(Properties p) {
super();
url = p.getProperty("url");
log.info("Service URL set to " + url);
retries = PropertiesUtil.getOptionalIntProperty(p, "retries", 1);
log.info("Retries set to " + retries);
}
public static void main(String[] args) throws Exception {
log.info("Replication " + VERSION);
log.info("Initializing...");
Properties p = PropertiesUtil.loadProperties(Replication_CC.class.getResource("/Replication_CC.properties"));
DQServer server = new DQServer(p, new Replication_CC(p));
server.run();
}
public String process(String request) throws Exception {
long processStart = System.currentTimeMillis();
String response = null;
for (int i=0; i<=retries; i++) {
try {
response = send(request, url);
if (response!=null) break;
}
catch (Exception e) {
log.warn("Error processing: " + e.getMessage());
if (i<retries) {
log.warn("Trying again (retry " + (i+1) + "...");
}
else {
log.error("Giving up on this transaction.");
break;
}
}
}
long processFinished = System.currentTimeMillis();
log.info("Request was processed in " + (processFinished-processStart) + "ms.");
return response;
}
public String send(String request, String url) throws Exception {
log.debug("Creating request...");
HttpClientParams params = new HttpClientParams();
params.setParameter("http.useragent", "http-api / Replication");
HttpClient client = new HttpClient(params);
PostMethod post = new PostMethod(url);
/*
List<NameValuePair> params = new ArrayList<NameValuePair>();
for (String key : globalRequest.keySet()) {
params.add(nvp(key, globalRequest.get(key)));
}
*/
post.setRequestBody(request);
// Log the request
if (log.isDebugEnabled()) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
post.getRequestEntity().writeRequest(baos);
baos.close();
log.debug("HTTP Request: \n" + StringUtils.repeat("*", 100) + "\n" + "Content Type: "
+ post.getRequestEntity().getContentType() + "\n" + "Content Length: "
+ post.getRequestEntity().getContentLength() + "\n" + "Request Headers: "
+ ArrayUtils.toString(post.getRequestHeaders()) + "\n" + "Request Params: " + baos.toString() + "\n" +
StringUtils.repeat("*", 100));
}
try {
log.info("Sending request...");
int responseCode = client.executeMethod(post);
//log.debug(String.format("Http Response Code [%s]", responseCode));
log.debug("Http Response Code [" + responseCode + "]");
if (responseCode == HttpStatus.SC_OK) {
String charset = post.getResponseCharSet();
log.debug("Response Character Set [" + charset + "]");
/*
byte[] body = post.getResponseBody();
String response = new String(body, charset);
*/
String response = IOUtils.toString(post.getResponseBodyAsStream());
log.debug("Response Body: \n" + response);
return response;
}
else {
throw new Exception(post.getStatusLine().toString());
}
}
catch (IOException ioe) {
log.error(ioe);
throw ioe;
}
finally {
post.releaseConnection();
}
}
One simple way is to include multiple URL's in the existing url property separated by a unique character. I chose "|" (pipe) in this example because it's highly unlikely to see a pipe in a normal url.
Java identifies methods by name and parameter signature. We can use that to our advantage by adding a String url parameter to the existing process method and creating a new process(String request) method that will split and iterate over the url's. The only downside is that it will only return the last response to the DQServer class.
public String process(String request) throws Exception {
String response;
for (String u : url.split("\\|")) {
response = process(request, u);
}
return response;
}
public String process(String request, String url) throws Exception {
long processStart = System.currentTimeMillis();
String response = null;
for (int i=0; i<=retries; i++) {
try {
response = send(request, url);
if (response!=null) break;
}
catch (Exception e) {
log.warn("Error processing: " + e.getMessage());
if (i<retries) {
log.warn("Trying again (retry " + (i+1) + "...");
}
else {
log.error("Giving up on this transaction.");
break;
}
}
}
long processFinished = System.currentTimeMillis();
log.info("Request was processed in " + (processFinished-processStart) + "ms.");
return response;
}
The complete sample is available on GitHub Gist.

Categories

Resources