okhttpclient for android and Laravel API - java

Currently building an Android App that has a Web Service. Trying to get data from the SQL Database using the okhttp3 but I'm getting a weird response and I can't figure it out. My API in Laravel is:
public function getAccount(Request $request, User $user)
{
$email = $request->input('email');
//$response = Users::find($email);
$response = DB::table('users')->where('email', $email)->first();
$count = count($response);
if($count == 0) {
return Response::json([
'message' => 'An error occured',
], 401);
} else {
return Response::json([
'user' => $response->name,
'lastName' => $response->lastName,
'weight' => $response->weight,
'height' => $response->height,
'dob' => $response->DOB,
'email' => $response->email,
], 200);
}
And my Android code is:
private void getDetails() {
Thread thread = new Thread(new Runnable(){
public void run() {
OkHttpClient client = new OkHttpClient();
// Json string with email and password
String bodyString = "{\n\t\"email\" : \"" + email +"\"\n}";
// Make HTTP POST request
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, bodyString);
Request request = new Request.Builder()
.url("http://192.168.1.100/CAB398/public/api/auth/getAccount")
.post(body)
.addHeader("accept", "application/json")
.addHeader("content-type", "application/json")
//.addHeader("cache-control", "no-cache")
//.addHeader("postman-token", "c3d60511-7e0f-5155-b5ad-66031ad76578")
.build();
// execute request
try {
Response response = client.newCall(request).execute();
String responseData = response.body().toString();
// Response code 200 means login details found in DB
if(response.code() == 200){
etfirstName.setText(responseData);
} else if(response.code() == 401){
}
} catch (IOException e) {
e.printStackTrace();
}
}
});
thread.start();
//wait for thread to finish
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
The issue is that I am getting the response of: okhttp3.internal.http.RealResponseBody#b8a47c8 as the response.body().toString(). I have tested the API call using postman and do get the correct response of:
{"user":"Joe","lastName":"smith","weight":108,"height":179,"dob":"1980-09-06","email":"JoeSmith#gmail.com"}
I think I am messing up the Request. Builder but I can't figure this out.
Cheers
Peter

You have mistaken the string() method from the ResponseBody object with the usual toString() method.. Here are some docs for it.
Just have:
String responseData = response.body().string();
instead of:
String responseData = response.body().toString();
You can find some info in here also

Related

How to extract data from POST request in azure functions java

I send form data in POST request from angular app to my azure functions who wrriten in java.
the client side look like this:
#Injectable({
providedIn: 'root'
})
export class SendItemToAzureFunctionsService {
private functionURI: string;
constructor(private http: HttpClient) {
this.functionURI = 'https://newsfunctions.azurewebsites.net/api/HttpTrigger-Java?code=k6e/VlXltNs7CmJBu7lmBbzaY4tlo21lXaLuvfG/tI7m/XXXX';
}
// {responseType: 'text'}
sendItem(item: Item){
let body = new FormData();
body.append('title', item.title);
body.append('description', item.description);
body.append('link', item.link);
return this.http.post(this.functionURI, body)
.pipe(
map((data: string) => {
return data;
}), catchError( error => {
return throwError( 'Something went wrong!' );
})
)
}
}
when Item recived to azure functions.
the aim of functions is to send this item in push notifications via firebase to android app.
the azure functions with HTTP trigger look like this:
#FunctionName("HttpTrigger-Java")
public HttpResponseMessage run(#HttpTrigger(name = "req", methods = { HttpMethod.GET,
HttpMethod.POST }, authLevel = AuthorizationLevel.FUNCTION) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) {
context.getLogger().info("Java HTTP trigger processed a request.");
// Parse query parameter
String itemDetails = request.getBody().get();
if (itemDetails == null) {
return request.createResponseBuilder(HttpStatus.BAD_REQUEST)
.body("Please pass a name on the query string or in the request body").build();
} else {
// ======
String postUrl = "https://fcm.googleapis.com/fcm/send";
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(postUrl);
post.setHeader("authorization", FIREBAE_AUTH);
post.setHeader("Content-type", "application/json");
JSONObject contentJson = new JSONObject();
contentJson.put("title", "example title");
contentJson.put("description", "example text");
JSONObject pushNotificationJson = new JSONObject();
pushNotificationJson.put("data", contentJson);
pushNotificationJson.put("to", "/topics/newsUpdateTopic");
try {
StringEntity stringEntity = new StringEntity(pushNotificationJson.toString(), "UTF-8");
post.setEntity(stringEntity);
HttpResponse response = httpClient.execute(post);
System.out.println(response.getEntity().getContent().toString());
} catch (IOException var9) {
var9.printStackTrace();
}
// =========
}
return request.createResponseBuilder(HttpStatus.OK)
.body("succeed to send new item in push notification to clients").build();
}
when I am running String itemDetails = request.getBody().get();
I am getting:
------WebKitFormBoundary2gNlxQx5pqyAeDL3
Content-Disposition: form-data; ....
I will be glad to know how to get data item from that?
If you want to parse from-date type data in Azure function with java, you can try to use MultipartStream in SDK org.apache.commons.fileupload to implement it. For example
code
public HttpResponseMessage run(
#HttpTrigger(name = "req", methods = {HttpMethod.GET, HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
final ExecutionContext context) throws IOException {
context.getLogger().info("Java HTTP trigger processed a request.");
String contentType = request.getHeaders().get("content-type");
String body = request.getBody().get(); // Get request body
String boundary = contentType.split(";")[1].split("=")[1]; // Get boundary from content-type header
int bufSize = 1024;
InputStream in = new ByteArrayInputStream(body.getBytes()); // Convert body to an input stream
MultipartStream multipartStream = new MultipartStream(in, boundary.getBytes(), bufSize, null); // Using MultipartStream to parse body input stream
boolean nextPart = multipartStream.skipPreamble();
while (nextPart) {
String header = multipartStream.readHeaders();
int start =header.indexOf("name=") + "name=".length()+1;
int end = header.indexOf("\r\n")-1;
String name = header.substring(start, end);
System.out.println(name);
multipartStream.readBodyData(System.out);
System.out.println("");
nextPart = multipartStream.readBoundary();
}
return request.createResponseBuilder(HttpStatus.OK).body("success").build();
}
Test. I test with postman
I've used #Jim Xu's code and created a class to get the data in easier way. Here is the gist - https://gist.github.com/musa-pro/dcef0bc23e48227e4b89f6e2095f7c1e

Changing a 404 response for REST API to a 200 empty response

I have a Spring Boot application written in Java that is a REST API. This service (Svc A) calls a REST API service (Svc B) with is also a Spring Boot Application written in Java. Svc B returns a 404 status code when no data was found. I need to change this response to a 200 status code and return an empty response object. I am not sure if or how to do this.
I can catch the error and determine if the 404 is this no data found error. However, I don't know how to change the response to a 200 empty response.
I am using a FeignClient to call the service. This is the error code that catches the 404:
#Component
public class FeignErrorDecoder implements ErrorDecoder {
Logger logger = LoggerFactory.getLogger(this.getClass());
#Override
public Exception decode(String methodKey, Response response) {
Reader reader = null;
String messageText = null;
switch (response.status()){
case 400:
logger.error("Status code " + response.status() + ", methodKey = " + methodKey);
case 404:
{
logger.error("Error took place when using Feign client to send HTTP Request. Status code " + response.status() + ", methodKey = " + methodKey);
try {
reader = response.body().asReader();
//Easy way to read the stream and get a String object
String result = CharStreams.toString(reader);
logger.error("RESPONSE BODY: " + result);
ObjectMapper mapper = new ObjectMapper();
//just in case you missed an attribute in the Pojo
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//init the Pojo
ExceptionMessage exceptionMessage = mapper.readValue(result,
ExceptionMessage.class);
messageText = exceptionMessage.getMessage();
logger.info("message: " + messageText);
} catch(IOException ex) {
logger.error(ex.getMessage());
}
finally {
try {
if (reader != null)
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return new ResponseStatusException(HttpStatus.valueOf(200), messageText);
}
default:
return new Exception(response.reason());
}
}
}
I can change the status code to a 200 and it returns a 200 but I need to the response to have an empty response object.
The above code will return this response body of an error response object:
{
"statusCd" : "200",
"message" : "The Location not found for given Location Number and Facility Type Code",
"detailDesc" : "The Location not found for given Location Number and Facility Type Code. Error Timestamp : 2020-01-31 18:19:13"
}
I need it to return a response body like this:
200 - Empty Response
{
"facilityNumber": "923",
"facilityTimeZone": null,
"facilityAbbr": null,
"scheduledOperations": []
}
In case 404 just try
return new ResponseStatusException(HttpStatus.valueOf(200));
For anyone that has to do something this crazy...here is my solution:
Removed the FeignErrorCode file.
Added an exception to ControllerAdvice class like this:
#ExceptionHandler(FeignException.class)
public ResponseEntity<?> handleFeignException(FeignException fe, WebRequest request) {
ErrorDetails errorDetails = new ErrorDetails(new Date(), HttpStatus.valueOf(fe.status()), fe.getMessage(), request.getDescription(false));
String response = fe.contentUTF8();
if(response != null) {
ScheduledOperationsViewResponse scheduledOperationsViewResponse = new ScheduledOperationsViewResponse();
if (response.contains("Scheduled") || response.contains("Location")) {
HttpHeaders headers = new HttpHeaders();
scheduledOperationsViewResponse.setFacilityNumber(request.getParameter("facilityNumber"));
return new ResponseEntity<ScheduledOperationsViewResponse>(scheduledOperationsViewResponse, headers, HttpStatus.OK);
}
}
return new ResponseEntity<>(errorDetails, errorDetails.getStatus());
}

Angular Post request goes to pending status and does not hit the server

I am trying to get the user list for a email Id using a post request , Sometimes the post request goes to pending status and it stays in the same status forever.If I restart the tomcat then the request works but after some times the same issue occurs.
Below is the post method calling in angular
loadBOEDetailsListByEmail(emailId, password) {
const url = `${environment.url}backofficeemployee/detailsByBoeEmailId/`;
const params = {
resetEmail: emailId
};
const myHeader = new HttpHeaders();
myHeader.append('Content-Type', 'application/x-www-form-urlencoded');
return Observable.create(observer => {
this.http.post(url, params, { headers: myHeader }).subscribe(
(response: any) => {
if (response && response.data && response.data[0] !== undefined) {
this.accountList = response.data;
const boe = response.data[0];
this.checkAccountValidity(boe, password, observer);
} else {
observer.error('No account found');
}
},
() => observer.error('Employee service call failed')
);
});
}
In the java side this is how I am receiving
// Backoffice employee - Details by BoeUserId
#PostMapping(value = "/detailsByBoeEmailId/")
public #ResponseBody Map<String, Object> getBackofficeemployeeDetailsByBoeEmailId(#RequestBody ResetpasswordRequestDto requestDto) {
log.info(" boeEmailId in getBackofficeemployeeDetails {}", requestDto.getResetEmail());
try {
List<BackofficeemployeeResponseDto> backofficeemployeeResponseDto = backofficeemployeeService
.getByBoeEmailId(requestDto.getResetEmail());
return JsonUtils.mapOK(backofficeemployeeResponseDto);
} catch (Exception e) {
log.error("Exception in getBackofficeemployeeDetailsByBoeEmailId", e);
return JsonUtils.mapError(ERROR_MSG + e.getMessage());
}
}

ResponseBody inconsistent JSON string (OKHttp 3.10.0)

Firstly I searched about this issue but couldn't find any solution.
I am sending a POST request to a web service. This web service returns response but I see that the response is not complete.
With PostMan I get full response without issue. But OKHttp cuts the response.
public List<Product> getProducts(String token, long bill_acct_id, long customer_id, Context context) {
if(token != null && !token.equals("")) {
Gson gson = new Gson();
List<Product> prods;
Map<String, String> list_of_headers = new HashMap<>();
list_of_headers.put("WSC-AUTH-TOKEN", token);
list_of_headers.put("Accept", "application/json, text/plain, */*");
list_of_headers.put("Content-Type", "application/json");
Headers headers = Headers.of(list_of_headers);
try {
Response response = RequestSender.post2("URL", "{\"billingAccountId\":\""+bill_acct_id+"\", \"customerId\":\""+customer_id+"\"}", headers, context);
int returnCode = response.code();
ResponseBody body = response.body();
Log.e("INFO", body.string());
if (returnCode == 200) {
prods = gson.fromJson(body.string(), new TypeToken<List<Product>>() {
}.getType());
return prods;
}
} catch (Exception ex) {
Log.e("Error", ex.getMessage());
ex.printStackTrace();
}
}
return null;
}
The response:
Solved.
Response from Postman:
Solved
Anyone faced this issue? I need your help. Thanks.
**EDIT: ** Actually it was complete. Log.e() and System.out.println(); methods doesn't show complete JSON.

405 error code while calling from Jersey REST client

I am requesting for put operation and after request performed I am redirecting to GET service URL.Here, I am facing the issue of 405 HTTP error code. However, same code works for me in the case of POST operation.
Below code is EndPoint:
#PUT
#Produces({ MediaType.APPLICATION_JSON })
public Response put(InputStream objInputStream) {
// System.out.println("AckService.put()");
String strOutput = "";
Status objStatus = Status.OK;
URI objRedirectionURI = null;
try {
this.submitRequest(objInputStream);
objRedirectionURI = new URI("https://local.test.com:8443/Reply/fetch");
System.err.println("\n\nredirecting the put request...... to get operation\n\n");
return Response.seeOther(objRedirectionURI).build();
} catch (Exception e) {
e.printStackTrace();
objStatus = Status.INTERNAL_SERVER_ERROR;
}
}
Client:
ClientResponse response = null;
try {
response = objWebResource.accept(MediaType.APPLICATION_JSON)
.type(MediaType.APPLICATION_JSON)
.put(ClientResponse.class, strInputData);
}catch (Exception e) {
blnIsOk = false;
if(null != e.getMessage())
lstExceptionMessage.add(e.getMessage());
e.printStackTrace();
}
Please let me know how I can resolve this.
In that question I think you can find the answer:
PUT-POST Rest Information

Categories