JavaFX : Supply arguments to Task - java

I am working on a JavaFX project in which I am making network calls with Task. Unfortunately, I have not been able to find how I can pass arguments to it. I have searched many links, but none of them provides. One link from java2s claims they are passing, but the code does not reflect that.
As you can see from the code below, I am using a for-loop and passing the ID parameter of RestGroupAccount in the URL. This time it's okay because I anyways need all of the RestCanvas.
But I am interested in knowing how to give parameters to Task
Code :
private Task<List<RestCanvas>> fetchCanvases = new Task<List<RestCanvas>>() {
#Override
protected List<RestCanvas> call() throws Exception {
List<RestCanvas> list = new ArrayList<>();
try{
for(RestGroupAccount groupAccount : groupAccounts) {
RestTemplate rest = StaticRestTemplate.getRest();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + StaticRestTemplate.jsessionid);
HttpEntity<RestCanvas> requestEntity = new HttpEntity<>(requestHeaders);
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<RestCanvas[]> responseEntity = rest.exchange(getCanvasForGroupAccount+groupAccount.getGroupId(), HttpMethod.GET, requestEntity, RestCanvas[].class);
RestCanvas[] restCanvasArray = responseEntity.getBody();
Collections.addAll(list, restCanvasArray);
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
};
If any more information is required, kindly let me know. Thank you.

I had a similar need, where I needed to create tasks that would take in a File and perform tasks on it. In my case I needed to do different things with files in multiple places, so I created the following class:
public abstract class FileOperationTask<V> extends Task<V> {
protected File file;
public FileOperationTask(File file) {
this.file = file;
}
}
This allows me in my controllers to define the following:
FileOperationTask<List<RaffleTicket>> task = new FileOperationTask<List<RaffleTicket>>(file){
#Override
protected List<RaffleTicket> call() throws Exception {
this.file.toString();
return null;
}
};
new Thread(task).run();
As you can see, I'm able to operate on the File object, and implementing my asynchronous task is now more or less identical to implementing a normal task.

If you need to use the code inside your Task more than once, you should consider creating non-anonymous subclass and instantiate it every time you need it with the construction parameter.
In your example this might be:
private Task<List<RestCanvas>> fetchCanvases = new MyTask(getCanvasForGroupAccount + groupAccount.getGroupId());
// ...
// please don't use this name :)
private static class MyTask extends Task<List<RestCanvas>> {
private final String id;
public MyTask(String id) {
this.id = id;
}
#Override
protected List<RestCanvas> call() throws Exception {
List<RestCanvas> list = new ArrayList<>();
try{
for(RestGroupAccount groupAccount : groupAccounts) {
RestTemplate rest = StaticRestTemplate.getRest();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", "JSESSIONID=" + StaticRestTemplate.jsessionid);
HttpEntity<RestCanvas> requestEntity = new HttpEntity<>(requestHeaders);
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
rest.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ResponseEntity<RestCanvas[]> responseEntity = rest.exchange(id, HttpMethod.GET, requestEntity, RestCanvas[].class);
RestCanvas[] restCanvasArray = responseEntity.getBody();
Collections.addAll(list, restCanvasArray);
}
}catch (Exception e){
e.printStackTrace();
}
return list;
}
}

Related

How can I associate JSON object of the api response to java classes when having the intermediate json "data" attribute?

Thank you for clicking here.
I have an JSON REST API (providing by Directus CMS). All API responses contains a json object with a "data" attribute containing what I want.
{
"data": {
"id": 1,
"status": "published",
"sort": null,
"user_created": "5a91c184-908d-465e-a7d5-4b648029bbe0",
"date_created": "2022-04-26T09:43:37.000Z",
"user_updated": "5a91c184-908d-465e-a7d5-4b648029bbe0",
"date_updated": "2022-05-30T14:23:50.000Z",
"Titre": "Réseaux Sociaux",
"Description": "Retrouvez les dernières news en direct sur nos réseaux sociaux!",
"Lien": "https://www.instagram.com/univlorraine/",
"ImageArrierePlan": "f23ffd53-7244-4439-a8cf-41bd0fd3aa72",
"Erreur_Bloc": null
}
}
This data attribute can be a object or a list of objects depending the request.
I have a Java Spring application with a service consuming the API. I'm using RestTemplate with exchange method.
public Object callAPI(String url, HttpMethod httpMethod, Object body, MultiValueMap<String, String> headers, Class<?> classe) {
final RestTemplate rt = new RestTemplate();
try {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
rt.setRequestFactory(requestFactory);
final HttpEntity<?> request = new HttpEntity<>(body, headers);
final ResponseEntity<?> response = rt.exchange(url, httpMethod, request, classe);
if (response.getStatusCode().equals(HttpStatus.OK)) {
return response.getBody();
}
else return response.getStatusCode();
} catch (final Exception e) {
System.out.println(e);
return null;
}
}
In the exchange method I pass an existing class to directly link response data with the provided class.
The probleme is that I have this data attribute which prevents me from linking the data.
Does anyone have a solution to this probleme please?
----UPDATE----
Thanks to the response of AlbiKai, I created a generic Wrapper class :
public class Wrapper<T> {
private T data;
public void set(T data) {
this.data = data;
}
public T get() {
return data;
}
}
I then tried to put this Wrapper in the exchange :
public <classe> Object callAPI(String url, HttpMethod httpMethod, Object body, MultiValueMap<String, String> headers, Class<?> classe) {
final RestTemplate rt = new RestTemplate();
try {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
rt.setRequestFactory(requestFactory);
final HttpEntity<?> request = new HttpEntity<>(body, headers);
final ResponseEntity<?> response = rt.exchange(url, httpMethod, request, Wrapper<classe>.class);
But I get the error "Cannot select from parameterized type" on the Wrapper :/
You can create a wrapper class that match the json response : an object with only one attribute named "data" type of desire final class (or a list) and use it in the exchange method.
public class wrapper {
YourClass data;
}
I gave up with the Wrapper etc...
I just pass a String class and work with it in my controllers to delete this "data" property and map the string with a class.
Service :
public String callAPI(String url, HttpMethod httpMethod, Object body, MultiValueMap<String, String> headers) {
final RestTemplate rt = new RestTemplate();
try {
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
rt.setRequestFactory(requestFactory);
final HttpEntity<?> request = new HttpEntity<>(body, headers);
final ResponseEntity<String> response = rt.exchange(url, httpMethod, request, String.class);
if (response.getStatusCode().equals(HttpStatus.OK)) {
return response.getBody();
}
else return response.getStatusCode().toString();
} catch (final Exception e) {
System.out.println(e);
return null;
}
}
One controller :
public List<BlocInformation> getBlocInformation() {
String url = "http://localhost:8055/items/bloc_information/?fields=*,Erreur_Bloc.*";
final RestAPIService blocService = new RestAPIService();
String response = blocService.callAPI(url, HttpMethod.GET, null, null);
if (response != null) {
String result = response.substring(8, response.length() - 1);
ObjectMapper mapper = new ObjectMapper();
List<BlocInformation> blocInformationList = null;
try {
blocInformationList = Arrays.asList(mapper.readValue(result, BlocInformation[].class));
} catch (IOException e) {
e.printStackTrace();
}
return blocInformationList;
}
return null;
}

How to cover method inside arrayList in mockito junits

I am trying to cover below main class if (!Utility.isEmpty(errors)) block code coverage and i tried below code for adding errors in array List inside client class but still array showing as empty can some one help me to solve this issue.
Main class
public void processDiohShippingMethod(ShippingMethodRequest request) {
List<ResolvableErrorEnum> errors = new ArrayList<>();
checkoutRestClient.updateShippingMethod(request, errors);
if (!Utility.isEmpty(errors)) {
logger.info("ProcessDiohShippingMethod: Shipping method update failure from {} -> {}. Reverting. ",
existingSm, request.getShippingMethodType());
if (existingShippingMethod != null && Constants.RTG_ENJOY.equalsIgnoreCase(existingSm)) {
request.setStartTime(existingShippingMethod.getDropOffShippingInfo().getStartTime());
request.setEndTime(existingShippingMethod.getDropOffShippingInfo().getEndTime());
request.setScheduleType(existingShippingMethod.getDropOffShippingInfo().getCustomerScheduleType());
}
}
}
Client
public void updateShippingMethod(ShippingMethodRequest request, List<ResolvableErrorEnum> errors) {
String url = Utils.formatHttpUrl(url, Cart_Request);
try {
HttpEntity<?> entity = new HttpEntity<>(request);
JsonNode jsonNode = restTemplate.postForObject(url, entity, JsonNode.class);
if (!jsonNode.has(Constants.CONTENT)
|| !jsonNode.path(Constants.CONTENT).path(Constants.ERRORS).isMissingNode()) {
errors.add(ErrorMessages.SM_ERR_01);
return;
}
} catch (HttpClientErrorException e) {
errors.add(ErrorMessages.SM_ERR_01);
} catch (HttpServerErrorException e) {
errors.add(ErrorMessages.SM_ERR_01);
}
}
Test
#Test
public void test_processMethod() throws Exception {
Request req = new Request();
HttpEntity<?> entity = new HttpEntity<>(req);
String jsonResponse = "{\"error\":{\"errorId\":\"1234\",\"message\":\"error message\"}},\"status\":\"success\"}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(jsonResponse);
when(restTemplate.postForObject("url", entity, JsonNode.class)).thenReturn(actualObj);
ShippingMethodResponse response = helper.processDiohShippingMethod(req);
}
Since you didn't post the whole test code this is just an educated guess, but the most probable cause is that your helper object (the one from the test method) uses a different instance, but not the one you mocked (since I can't see any code in the test, that would set the client).
So a solution could look like this:
#Test
public void test_processMethod() throws Exception {
Request req = new Request();
HttpEntity<?> entity = new HttpEntity<>(req);
String jsonResponse = "{\"error\":{\"errorId\":\"1234\",\"message\":\"error message\"}},\"status\":\"success\"}}";
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree(jsonResponse);
when(restTemplate.postForObject("url", entity, JsonNode.class)).thenReturn(actualObj);
//get this mocked object into the helper object somehow
//otherwhise the mocked method will never be called
helper.setClient(restTemplate);
ShippingMethodResponse response = helper.processDiohShippingMethod(req);
}
You probably assumed the mocking call when(restTemplate.postForObject(...))... to mock the method for all objects of this class. But it will just create a decorator- / wrapper-object arround the object. So you've got to make shure that you call the mocked method on the mocked object, but not on any other object.

I cannot send an HTTP request (500 internal server error)

I am currently receiving the following error for the http request am sending. I am trying to send a JSON Array list to trigger a method in the receiving end so as it saves the list in its database.
The 500 Internal Server Error is a very general HTTP status code that means something has gone wrong on the website's server, but the server could not be more specific on what the exact problem is.
Websites phrase 500 errors in many ways but they're all basically saying the same thing: there's a general server issue going on right now.
Most of the time there isn't anything you can do but contact the website directly and then wait on them to fix it.
In the off chance there is a problem on your end, try clearing the cache and deleting any cookies from the site with the error.
Please find the error below:
org.springframework.web.client.HttpServerErrorException: 500 Internal Server
public static String FRONT_URL;
public static String BACK_URL;
public static final String REST_SYNC = "rest/sync";
public static final String REST_API = "rest/api";
private Logger log = Logger.getLogger(FrontSynchronizer.class);
static final Logger synclog = Logger.getLogger("sync");
ResourceBundle rb = ResourceBundle.getBundle("bundles.sync-application-resources", Locale.getDefault());
//method sending the request
public void syncApplications(List<SchemeApplication> accList) {
schemeApplicationDto=new SchemeApplicationDto();
FRONT_URL = rb.getString("sync.front.url").concat(REST_SYNC);
BACK_URL = rb.getString("sync.back.url").concat(REST_API);
JSONArray array = new JSONArray();
if (accList != null && accList.size() > 0) {
for (SchemeApplication student : accList) {
schemeApplicationDto.setId(student.getId());
schemeApplicationDto.setAccountID(student.getAccountID());
schemeApplicationDto.setNoOfPersonsEmployedLocal(student.getNoOfPersonsEmployedLocal());
schemeApplicationDto.setLocalmainclients(student.getLocalmainclients());
JSONObject studentJSON = new JSONObject(schemeApplicationDto);
array.put(studentJSON);
}
}
HttpHeaders headers = new HttpHeaders();
JSONObject object = new JSONObject();
object.put("array", array);
headers.setContentType(MediaType.APPLICATION_JSON);
RestTemplate restTemplate = this.createnewTemplate();
String url = BACK_URL.concat("/application");
HttpEntity<String> requestEntity = new HttpEntity<String>(object.toString(), headers);
ResponseEntity<Boolean> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity,
Boolean.class);
if (responseEntity.getBody())
{
for(SchemeApplication scheme:accList) {
schemeApplicationService.getDao().delete(scheme);
}
}
}
public RestTemplate createnewTemplate() {
// RestTemplate restTemplate = new RestTemplate(clientHttpRequestFactory());
HttpComponentsClientHttpRequestFactory httpRequestFactory = new HttpComponentsClientHttpRequestFactory();
httpRequestFactory.setConnectTimeout(120000);
RestTemplate restTemplate = new RestTemplate(httpRequestFactory);
return restTemplate;
}
// method that needs to process the request
//The method is trying to send an Array list so as the receiving end can receive the list and save it in its database.
#RequestMapping(value = "application", method = RequestMethod.POST)
public Boolean getAllArchivedpplications(#RequestBody String schemeJson) {
List<SchemeApplication> accList = null;
try {
accList = new ArrayList<SchemeApplication>();
if (StringUtils.isNotEmpty(schemeJson)) {
JSONObject listObject = new JSONObject(schemeJson);
JSONArray entryArray = listObject.getJSONArray("array");
for (int i = 0; i < entryArray.length(); i++) {
JSONObject res = new JSONObject(entryArray.get(i).toString());
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
schemeApplication doc = mapper.readValue(res.toString(),
new TypeReference<schemeApplication>() {
});
accList.add(doc);
}
schemeService.getDao().save(accList); // Service.save accountlist;
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
#RequestBody must work on an object.
Standard way to do this kind of work in two ways:
Form a class having class files with same name and structure with your json data you are sending and capture that data in by #RequestBody annotation
As you are sending data as String, send it as request param, and use #RequestParam instead of #RequestBody and parse the way you need to do things. For I think for this kind of arrayList of bulk data you are working with, option 1 will be better/feasible.
For details you can check here: #RequestBody and #ResponseBody annotations in Spring

How to make a rest api call in java and map the response object?

I'm currently developing my first java program who'll make a call to a rest api(jira rest api, to be more especific).
So, if i go to my browser and type the url =
"http://my-jira-domain/rest/api/latest/search?jql=assignee=currentuser()&fields=worklog"
I get a response(json) with all the worklogs of the current user.
But my problem is, how i do my java program to do this ?
Like,connect to this url, get the response and store it in a object ?
I use spring, with someone know how to this with it.
Thx in advance guys.
Im adding, my code here:
RestTemplate restTemplate = new RestTemplate();
String url;
url = http://my-jira-domain/rest/api/latest/search/jql=assignee=currentuser()&fields=worklog
jiraResponse = restTemplate.getForObject(url,JiraWorklogResponse.class);
JiraWorkLogResponse is a simple class with some attributes only.
Edit,
My entire class:
#Controller
#RequestMapping("/jira/worklogs")
public class JiraWorkLog {
private static final Logger logger = Logger.getLogger(JiraWorkLog.class.getName() );
#RequestMapping(path = "/get", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity getWorkLog() {
RestTemplate restTemplate = new RestTemplate();
String url;
JiraProperties jiraProperties = null;
url = "http://my-jira-domain/rest/api/latest/search?jql=assignee=currentuser()&fields=worklog";
ResponseEntity<JiraWorklogResponse> jiraResponse;
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders = this.createHeaders();
try {
jiraResponse = restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<Object>(httpHeaders),JiraWorklogResponse.class);
}catch (Exception e){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(e.getMessage());
}
return ResponseEntity.status(HttpStatus.OK).body(jiraResponse);
}
private HttpHeaders createHeaders(){
HttpHeaders headers = new HttpHeaders(){
{
set("Authorization", "Basic something");
}
};
return headers;
}
This code is returning :
org.springframework.http.converter.HttpMessageNotWritableException
Anyone knows why ?
All you need is http client. It could be for example RestTemplate (related to spring, easy client) or more advanced and a little more readable for me Retrofit (or your favorite client).
With this client you can execute requests like this to obtain JSON:
RestTemplate coolRestTemplate = new RestTemplate();
String url = "http://host/user/";
ResponseEntity<String> response
= restTemplate.getForEntity(userResourceUrl + "/userId", String.class);
Generally recommened way to map beetwen JSON and objects/collections in Java is Jackson/Gson libraries. Instead them for quickly check you can:
Define POJO object:
public class User implements Serializable {
private String name;
private String surname;
// standard getters and setters
}
Use getForObject() method of RestTemplate.
User user = restTemplate.getForObject(userResourceUrl + "/userId", User.class);
To get basic knowledge about working with RestTemplate and Jackson , I recommend you, really great articles from baeldung:
http://www.baeldung.com/rest-template
http://www.baeldung.com/jackson-object-mapper-tutorial
Since you are using Spring you can take a look at RestTemplate of spring-web project.
A simple rest call using the RestTemplate can be:
RestTemplate restTemplate = new RestTemplate();
String fooResourceUrl = "http://localhost:8080/spring-rest/foos";
ResponseEntity<String> response = restTemplate.getForEntity(fooResourceUrl + "/1", String.class);
assertThat(response.getStatusCode(), equalTo(HttpStatus.OK));
The issue could be because of the serialization. Define a proper Model with fields coming to the response. That should solve your problem.
May not be a better option for a newbie, but I felt spring-cloud-feign has helped me to keep the code clean.
Basically, you will be having an interface for invoking the JIRA api.
#FeignClient("http://my-jira-domain/")
public interface JiraClient {
#RequestMapping(value = "rest/api/latest/search?jql=assignee=currentuser()&fields=", method = GET)
JiraWorklogResponse search();
}
And in your controller, you just have to inject the JiraClient and invoke the method
jiraClient.search();
And it also provides easy way to pass the headers.
i'm back and with a solution (:
#Controller
#RequestMapping("/jira/worklogs")
public class JiraWorkLog {
private static final Logger logger = Logger.getLogger(JiraWorkLog.class.getName() );
#RequestMapping(path = "/get", method = RequestMethod.GET, produces = "application/json")
public ResponseEntity<JiraWorklogIssue> getWorkLog(#RequestParam(name = "username") String username) {
String theUrl = "http://my-jira-domain/rest/api/latest/search?jql=assignee="+username+"&fields=worklog";
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<JiraWorklogIssue> response = null;
try {
HttpHeaders headers = createHttpHeaders();
HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, JiraWorklogIssue.class);
System.out.println("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
}
catch (Exception eek) {
System.out.println("** Exception: "+ eek.getMessage());
}
return response;
}
private HttpHeaders createHttpHeaders()
{
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.add("Authorization", "Basic encoded64 username:password");
return headers;
}
}
The code above works, but can someone explain to me these two lines ?
HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, JiraWorklogIssue.class);
And, this is a good code ?
thx (:

Using CompletableFuture with #Async returns an empty response for spring boot API

Here is my controller. I used postman to test if it's working but I am getting an empty response. I used #EnableAsync in application configuration and #Async on the service. If I remove #Async on service layer it works but it doesn't run asynchronously.
#ApiOperation(value = "search person by passing search criteria event/title/role/host/is_current", response = ElasticSearchResultData.class)
#RequestMapping(value = "/async2/searchPerson", produces = "application/json", method = RequestMethod.POST)
public #ResponseBody CompletableFuture<ElasticSearchResultData> searchPersonAsync2(#RequestBody SearchCriteriaTo criteriaForDivNetFolderTo,
HttpServletRequest request, HttpServletResponse response){
LOGGER.info("searchPerson controller start");
SearchCriteria searchCriteria = criteriaForDivNetFolderTo.getSearchCriteria();
if (Util.isNull(searchCriteria))
throw new IllegalArgumentException("search criteria should not be null.");
try {
CompletableFuture<ElasticSearchResultData> searchPerson = cubService.searchPersonAsync2(criteriaForDivNetFolderTo);
ObjectMapper mapper = new ObjectMapper();
LOGGER.info("search Person "+mapper.writeValueAsString(searchPerson));
return searchPerson;
} catch (Exception e) {
LOGGER.error("Exception in searchPersonAsync controller "+e.getMessage());
}
return null;
}
Service
#Async
#Override
public CompletableFuture<ElasticSearchResultData> searchPersonAsync2(SearchCriteriaTo searchCriteriaForDivNetFolderTo) {
Long start = System.currentTimeMillis();
LOGGER.info(":in searchPerson");
CompletableFuture<ElasticSearchResultData> completableFuture = new CompletableFuture<>();
ElasticSearchResultData searchResultData = null;
SearchCriteria searchCriteria = searchCriteriaForDivNetFolderTo.getSearchCriteria();
try {
LOGGER.info("************ Started searchPerson by criteria ************");
StringBuilder url = new StringBuilder();
url.append(equilarSearchEngineApiUrl)
.append(focusCompanySearchUrl)
.append("/")
.append("searchPerson")
.append("?view=").append(VIEW_ALL)
.append("&isProcessing=true");
LOGGER.debug("Calling equilar search engine for focused company search, URL : " + url);
LOGGER.info(searchCriteria.toString());
String output = null;
if (redisEnable != null && redisEnable) {
output = cacheDao.getDataFromRestApi(url.toString(), RequestMethod.POST.name(), searchCriteria);
} else {
output = Util.getDataFromRestApi(url.toString(), RequestMethod.POST.name(), searchCriteria);
}
if (!Util.isEmptyString(output)) {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
searchResultData = objectMapper.readValue(output,
objectMapper.getTypeFactory().constructType(ElasticSearchResultData.class));
}
List<PersonSearchDetails> newPersonDetails = new ArrayList<PersonSearchDetails>();
if (!Util.isNull(searchResultData) && !Util.isNullOrEmptyCollection(searchResultData.getPersonDetails())
&& !Util.isNullOrEmptyCollection(searchCriteriaForDivNetFolderTo.getNetworkFoldersData())) {
for (PersonSearchDetails personDetail : searchResultData.getPersonDetails()) {
String logoUrl = null;
if(!Util.isNull(searchCriteria.getTargetFolderId())){
List<DiversityNetworkFolderTo> filteredFolderTos = searchCriteriaForDivNetFolderTo
.getNetworkFoldersData()
.stream()
.filter(folder -> folder.getId()
.longValue() == searchCriteria
.getTargetFolderId())
.collect(Collectors.toList());
logoUrl = getLogoUrl(personDetail.getPersonId(),
filteredFolderTos);
} else {
logoUrl = getLogoUrl(personDetail.getPersonId(),
searchCriteriaForDivNetFolderTo.getNetworkFoldersData());
}
personDetail.setLogoUrl(logoUrl);
newPersonDetails.add(personDetail);
}
searchResultData.setPersonDetails(newPersonDetails);
}
completableFuture.complete(searchResultData);
return completableFuture;
} catch (Exception e) {
completableFuture.completeExceptionally(e);
LOGGER.error(
" ************** Error in proccessing searchPerson by criteria ************** " + e.getMessage());
}
Long end = System.currentTimeMillis();
LOGGER.info(TIME_DURATION+(end - start)+"ms");
return null;
}
It would be good to read more about async processing. javadocs are usually a great start!
If you really want to get the result from a Future method, you need to wait for it.
There is a method public T get() method in the CompletableFuture API to wait for wait for the result to be created and return the result once it's done.
If your job is to search a database for the result and then return it - you will still have to wait for it async is not much help in here. It would help you if you had to make multiple things at the same time, e.g. a call to DB, a web service and something else at the same time, then you can create an array of futures and wait for all of them to complete.
Or, let's say you're creating a POST method, so you can quickly validate the input and send to store to DB async while quickly returning the response to UI and hoping that your async method will be completed in another thread and not returning any errors to UI.
This is a great technique when you know what you're doing, but think if & when you really need it before using it.
The short way to "fix" this is:
CompletableFuture<ElasticSearchResultData> searchPerson = cubService.searchPersonAsync2(criteriaForDivNetFolderTo);
ElasticSearchResultData result = searchPerson.get();
ObjectMapper mapper = new ObjectMapper();
LOGGER.info("search Person "+mapper.writeValueAsString(result));
return result;
( and obviously change the method return signature )

Categories