JMeter Java Test - ${__UUID()} function in JSON doesn't work - java

The task:
I need to perform a post request to an endpoint.
Request body type is JSON:
{
"id": "${__UUID()}"
}
I want to simulate 10 users that each will send a payload with unique "id" field generated.
From JMeter GUI it works as expected, but from Java Code it seems not to be recognized and reads it like a simple string or so.
Here is the Java Code:
public JMeterClient httpSamplerProxy(String name, String endpoint, String payload, String httpMethod) {
Arguments arguments = new Arguments();
HTTPArgument httpArgument = new HTTPArgument();
httpArgument.setMetaData("=");
httpArgument.setValue(payload);
List<Argument> args = new ArrayList<>();
args.add(httpArgument);
arguments.setArguments(args);
HTTPSamplerProxy httpSamplerProxy = new HTTPSamplerProxy();
httpSamplerProxy.setProperty(TestElement.TEST_CLASS, HTTPSamplerProxy.class.getName());
httpSamplerProxy.setProperty(TestElement.GUI_CLASS, HttpTestSampleGui.class.getName());
httpSamplerProxy.setName(name);
httpSamplerProxy.setEnabled(true);
httpSamplerProxy.setPostBodyRaw(true);
httpSamplerProxy.setFollowRedirects(true);
httpSamplerProxy.setAutoRedirects(false);
httpSamplerProxy.setUseKeepAlive(true);
httpSamplerProxy.setDoMultipart(false);
httpSamplerProxy.setPath(endpoint);
httpSamplerProxy.setMethod(httpMethod);
httpSamplerProxy.setArguments(arguments);
httpSamplerProxies.add(httpSamplerProxy);
return this;
}
where payload is a json in a string representative.
I Use JMeter 5.4.1
Besides that I need this to work, how can I enable logging of Post Body in Java to see it in console?

I was missing dependency of functions:
<dependency>
<groupId>org.apache.jmeter</groupId>
<artifactId>ApacheJMeter_functions</artifactId>
<version>5.4.1</version>
</dependency>
After adding this to class path the function got recognized

Related

Saving an object to a Json file as a key [duplicate]

I have this method:
public static Object parseStringToObject(String json) {
String Object = json;
Gson gson = new Gson();
Object objects = gson.fromJson(object, Object.class);
parseConfigFromObjectToString(object);
return objects;
}
And I want to parse a JSON with:
public static void addObject(String IP, Object addObject) {
try {
String json = sendPostRequest("http://" + IP + ":3000/config/add_Object", ConfigJSONParser.parseConfigFromObjectToString(addObject));
addObject = ConfigJSONParser.parseStringToObject(json);
} catch (Exception ex) {
ex.printStackTrace();
}
}
But I get an error message:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_OBJECT but was STRING at line 1 column 1
Even without seeing your JSON string you can tell from the error message that it is not the correct structure to be parsed into an instance of your class.
Gson is expecting your JSON string to begin with an object opening brace. e.g.
{
But the string you have passed to it starts with an open quotes
"
Invalid JSON from the server should always be an expected use case. A million things can go wrong during transmission. Gson is a bit tricky, because its error output will give you one problem, and the actual exception you catch will be of a different type.
With all that in mind, the proper fix on the client side is
try
{
gson.fromJSON(ad, Ad.class);
//...
}
catch (IllegalStateException | JsonSyntaxException exception)
{
//...
If you want to know why the JSON you received from the server is wrong, you can look inside your catch block at the exception. But even if it is your problem, it's not the client's responsibility to fix JSON it is receiving from the internet.
Either way, it is the client's responsibility to decide what to do when it gets bad JSON. Two possibilities are rejecting the JSON and doing nothing, and trying again.
If you are going to try again, I highly recommend setting a flag inside the try / catch block and then responding to that flag outside the try / catch block. Nested try / catch is likely how Gson got us into this mess with our stack trace and exceptions not matching up.
In other words, even though I'll admit it doesn't look very elegant, I would recommend
boolean failed = false;
try
{
gson.fromJSON(ad, Ad.class);
//...
}
catch (IllegalStateException | JsonSyntaxException exception)
{
failed = true;
//...
}
if (failed)
{
//...
I had a similar problem recently and found an interesting solution. Basically I needed to deserialize following nested JSON String into my POJO:
"{\"restaurant\":{\"id\":\"abc-012\",\"name\":\"good restaurant\",\"foodType\":\"American\",\"phoneNumber\":\"123-456-7890\",\"currency\":\"USD\",\"website\":\"website.com\",\"location\":{\"address\":{\"street\":\" Good Street\",\"city\":\"Good City\",\"state\":\"CA\",\"country\":\"USA\",\"postalCode\":\"12345\"},\"coordinates\":{\"latitude\":\"00.7904692\",\"longitude\":\"-000.4047208\"}},\"restaurantUser\":{\"firstName\":\"test\",\"lastName\":\"test\",\"email\":\"test#test.com\",\"title\":\"server\",\"phone\":\"0000000000\"}}}"
I ended up using regex to remove the open quotes from beginning and the end of JSON and then used apache.commons unescapeJava() method to unescape it. Basically passed the unclean JSON into following method to get back a cleansed one:
private String removeQuotesAndUnescape(String uncleanJson) {
String noQuotes = uncleanJson.replaceAll("^\"|\"$", "");
return StringEscapeUtils.unescapeJava(noQuotes);
}
then used Google GSON to parse it into my own Object:
MyObject myObject = new.Gson().fromJson(this.removeQuotesAndUnescape(uncleanJson));
In Retrofit2, When you want to send your parameters in raw you must use Scalars.
first add this in your gradle:
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
public interface ApiInterface {
String URL_BASE = "http://10.157.102.22/rest/";
#Headers("Content-Type: application/json")
#POST("login")
Call<User> getUser(#Body String body);
}
my SampleActivity :
public class SampleActivity extends AppCompatActivity implements Callback<User> {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.URL_BASE)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
// prepare call in Retrofit 2.0
try {
JSONObject paramObject = new JSONObject();
paramObject.put("email", "sample#gmail.com");
paramObject.put("pass", "4384984938943");
Call<User> userCall = apiInterface.getUser(paramObject.toString());
userCall.enqueue(this);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onResponse(Call<User> call, Response<User> response) {
}
#Override
public void onFailure(Call<User> call, Throwable t) {
}
}
Reference: [How to POST raw whole JSON in the body of a Retrofit request?
I have come to share an solution. The error happened to me after forcing the notbook to hang up. possible solution clean preject.
Maybe your JSON Object is right,but the response that you received is not your valid data.Just like when you connect the invalid WiFi,you may received a strange response < html>.....< /html> that GSON can not parse.
you may need to do some try..catch.. for this strange response to avoid crash.
Make sure you have DESERIALIZED objects like DATE/DATETIME etc. If you are directly sending JSON without deserializing it then it can cause this problem.
In my situation, I have a "model", consist of several String parameters, with the exception of one: it is byte array byte[].
Some code snippet:
String response = args[0].toString();
Gson gson = new Gson();
BaseModel responseModel = gson.fromJson(response, BaseModel.class);
The last line above is when the
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column
is triggered. Searching through the SO, I realised I need to have some form of Adapter to convert my BaseModel to and fro a JsonObject. Having mixed of String and byte[] in a model does complicate thing. Apparently, Gson don't really like the situation.
I end up making an Adapter to ensure byte[] is converted to Base64 format. Here is my Adapter class:
public class ByteArrayToBase64Adapter implements JsonSerializer<byte[]>, JsonDeserializer<byte[]> {
#Override
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return Base64.decode(json.getAsString(), Base64.NO_WRAP);
}
#Override
public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(Base64.encodeToString(src, Base64.NO_WRAP));
}
}
To convert JSONObject to model, I used the following:
Gson customGson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64Adapter()).create();
BaseModel responseModel = customGson.fromJson(response, BaseModel.class);
Similarly, to convert the model to JSONObject, I used the following:
Gson customGson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64Adapter()).create();
String responseJSon = customGson.toJson(response);
What the code is doing is basically to push the intended class/object (in this case, byte[] class) through the Adapter whenever it is encountered during the convertion to/fro JSONObject.
Don't use jsonObject.toString on a JSON object.
In my case, I am Returning JSON Object as
{"data":"","message":"Attendance Saved
Successfully..!!!","status":"success"}
Resolved by changing it as
{"data":{},"message":"Attendance Saved
Successfully..!!!","status":"success"}
Here data is a sub JsonObject and it should starts from { not ""
Don't forget to convert your object into Json first using Gson()
val fromUserJson = Gson().toJson(notificationRequest.fromUser)
Then you can easily convert it back into an object using this awesome library
val fromUser = Gson().fromJson(fromUserJson, User::class.java)
if your json format and variables are okay then check your database queries...even if data is saved in db correctly the actual problem might be in there...recheck your queries and try again.. Hope it helps
I had a case where I read from a handwritten json file. The json is perfect. However, this error occurred. So I write from a java object to json file, then read from that json file. things are fine. I could not see any difference between the handwritten json and the one from java object. Tried beyondCompare it sees no difference.
I finally noticed the two file sizes are slightly different, and I used winHex tool and detected extra stuff.
So the solution for my situation is, make copy of the good json file, paste content into it and use.
In my case, my custom http-client didn't support the gzip encoding. I was sending the "Accept-Encoding: gzip" header, and so the response was sent back as a gzip string and couldn't be decoded.
The solution was to not send that header.
I was making a POST request with some parameters using Retrofit in Android
WHAT I FACED:
The error I was getting in Android Studio logcat:
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at line 2 column 1 path $
[but it was working fine with VOLLY library]
when I googled it...
you know[ Obviously json is expecting a OBJECT but...]
BUT when I changed my service to return a simple string [ like print_r("don't lose hope") ] or
Noting at all
It was getting printed fine in Postman
but in Android studio logcat, it was still SAME ERROR [
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at line 2 column 1 path $
]
Hold up now, I am sending a simple message or not sending anything in response and still studio is
telling me "...Expected BEGIN_OBJECT but was STRING..."
SOMETHING IS WRONG
On 4th day:
I finally stopped for looking "QUICK SOLUTIONS" and REALLY READ some stack overflow questions
and articles carefully.
WHAT I GOT:
Logging interceptor
It will show you whatever data comes from your server[even eco messages] which are not shown in
Andorid studios logcat,
that way you can FIND THE PROBLEM.
What I found is I was sending data with #Body like-
#Headers("Content-Type: application/json")
#POST("CreateNewPost")
Call<Resp> createNewPost(#Body ParaModel paraModel);
but no parameter was reaching to server, everything was null [I found using Logging interceptor]
then I simply searched an article "how to make POST request using Retrofit"
here's one
SOLUTION:
from here I changed my method to:
#POST("CreateNewPost")
#FormUrlEncoded
Call<Resp> createNewPost(
#Field("user_id") Integer user_id,
#Field("user_name") String user_name,
#Field("description") String description,
#Field("tags") String tags);
and everything was fine.
CONCLUSION:
I don't understand why Retrofit gave this error
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at line 2 column 1 path $
it doesn't make any sense at all.
So ALWAYS DEBUG in detail then find WHERE THINGS ARE LEAKING and then FIX.
This error solved for by replacing .toString method to .string on the response
toString => string (add in try{...code..}catche(IOException e))
below code is working for me
try {
MainModelResponse model;
Gson gson = new GsonBuilder().create();
if (response.code() == ConstantValues.SUCCESS_OK) {
model = gson.fromJson(response.body().string(), MainModelResponse.class);
} else {
model = gson.fromJson(response.errorBody().string(), MainModelResponse.class);
}
moduleData.postValue(model);
}catch (IllegalStateException | JsonSyntaxException | IOException exception){
exception.printStackTrace();
}
}
use a string begin & end with {}.
such as
final String jsStr = "{\"metric\":\"opentsdb_metric\",\"tags\":{\"testtag\":\"sunbotest\"},\"aggregateTags\":[],\"dps\":{\"1483399261\":18}}";
DataPoint dataPoint = new Gson().fromJson(jsStr, DataPoint.class);
this works for me.
In my case the object was all fine even the Json Validator was giving it a valid resposne but I was using Interface like this
#POST(NetworkConstants.REGISTER_USER)
Call<UserResponse> registerUser(
#Query("name") String name,
#Query("email") String email,
#Query("password") String password,
#Query("created_date") Long creationDate
);
Then I changed the code to
#FormUrlEncoded
#POST(NetworkConstants.REGISTER_USER)
Call<UserResponse> registerUser(
#Field("name") String name,
#Field("email") String email,
#Field("password") String password,
#Field("created_date") Long creationDate
);
And everything was resolved.
my problem not related to my codes
after copy some files from an other project got this issue
in the stack pointed to Gson library
in android studio 4.2.1 this problem not solved when I try file-> invalidate and restart
and
after restart in first time build got same error but in second build this problem solved
I don't understand why this happened
I was using an old version of retrofit library. So what I had to do was to change my code from this after upgrading it to com.squareup.retrofit2:retrofit:2.9.0:
#POST(AppConstants.UPLOAD_TRANSACTION_DETAIL)
fun postPremiumAppTransactionDetail(
#Query("name") planName:String,
#Query("amount") amount:String,
#Query("user_id") userId: String,
#Query("sub_id") planId: String,
#Query("folder") description:String,
#Query("payment_type") paymentType:String):
Call<TransactionResponseModel>
To this:
#FormUrlEncoded
#POST(AppConstants.UPLOAD_TRANSACTION_DETAIL)
fun postPremiumAppTransactionDetail(
#Field("name") planName:String,
#Field("amount") amount:String,
#Field("user_id") userId: String,
#Field("sub_id") planId: String,
#Field("folder") description:String,
#Field("payment_type") paymentType:String):
Call<TransactionResponseModel>
For me it turned out that I was trying to deserialize to an object that used java.time.ZonedDateTime for one of the properties. It worked as soon as I changed it to a java.util.Date instead.

Having issue in Volley [Android] [duplicate]

I have this method:
public static Object parseStringToObject(String json) {
String Object = json;
Gson gson = new Gson();
Object objects = gson.fromJson(object, Object.class);
parseConfigFromObjectToString(object);
return objects;
}
And I want to parse a JSON with:
public static void addObject(String IP, Object addObject) {
try {
String json = sendPostRequest("http://" + IP + ":3000/config/add_Object", ConfigJSONParser.parseConfigFromObjectToString(addObject));
addObject = ConfigJSONParser.parseStringToObject(json);
} catch (Exception ex) {
ex.printStackTrace();
}
}
But I get an error message:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException:
Expected BEGIN_OBJECT but was STRING at line 1 column 1
Even without seeing your JSON string you can tell from the error message that it is not the correct structure to be parsed into an instance of your class.
Gson is expecting your JSON string to begin with an object opening brace. e.g.
{
But the string you have passed to it starts with an open quotes
"
Invalid JSON from the server should always be an expected use case. A million things can go wrong during transmission. Gson is a bit tricky, because its error output will give you one problem, and the actual exception you catch will be of a different type.
With all that in mind, the proper fix on the client side is
try
{
gson.fromJSON(ad, Ad.class);
//...
}
catch (IllegalStateException | JsonSyntaxException exception)
{
//...
If you want to know why the JSON you received from the server is wrong, you can look inside your catch block at the exception. But even if it is your problem, it's not the client's responsibility to fix JSON it is receiving from the internet.
Either way, it is the client's responsibility to decide what to do when it gets bad JSON. Two possibilities are rejecting the JSON and doing nothing, and trying again.
If you are going to try again, I highly recommend setting a flag inside the try / catch block and then responding to that flag outside the try / catch block. Nested try / catch is likely how Gson got us into this mess with our stack trace and exceptions not matching up.
In other words, even though I'll admit it doesn't look very elegant, I would recommend
boolean failed = false;
try
{
gson.fromJSON(ad, Ad.class);
//...
}
catch (IllegalStateException | JsonSyntaxException exception)
{
failed = true;
//...
}
if (failed)
{
//...
I had a similar problem recently and found an interesting solution. Basically I needed to deserialize following nested JSON String into my POJO:
"{\"restaurant\":{\"id\":\"abc-012\",\"name\":\"good restaurant\",\"foodType\":\"American\",\"phoneNumber\":\"123-456-7890\",\"currency\":\"USD\",\"website\":\"website.com\",\"location\":{\"address\":{\"street\":\" Good Street\",\"city\":\"Good City\",\"state\":\"CA\",\"country\":\"USA\",\"postalCode\":\"12345\"},\"coordinates\":{\"latitude\":\"00.7904692\",\"longitude\":\"-000.4047208\"}},\"restaurantUser\":{\"firstName\":\"test\",\"lastName\":\"test\",\"email\":\"test#test.com\",\"title\":\"server\",\"phone\":\"0000000000\"}}}"
I ended up using regex to remove the open quotes from beginning and the end of JSON and then used apache.commons unescapeJava() method to unescape it. Basically passed the unclean JSON into following method to get back a cleansed one:
private String removeQuotesAndUnescape(String uncleanJson) {
String noQuotes = uncleanJson.replaceAll("^\"|\"$", "");
return StringEscapeUtils.unescapeJava(noQuotes);
}
then used Google GSON to parse it into my own Object:
MyObject myObject = new.Gson().fromJson(this.removeQuotesAndUnescape(uncleanJson));
In Retrofit2, When you want to send your parameters in raw you must use Scalars.
first add this in your gradle:
compile 'com.squareup.retrofit2:retrofit:2.3.0'
compile 'com.squareup.retrofit2:converter-gson:2.3.0'
compile 'com.squareup.retrofit2:converter-scalars:2.3.0'
public interface ApiInterface {
String URL_BASE = "http://10.157.102.22/rest/";
#Headers("Content-Type: application/json")
#POST("login")
Call<User> getUser(#Body String body);
}
my SampleActivity :
public class SampleActivity extends AppCompatActivity implements Callback<User> {
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sample);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.URL_BASE)
.addConverterFactory(ScalarsConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
// prepare call in Retrofit 2.0
try {
JSONObject paramObject = new JSONObject();
paramObject.put("email", "sample#gmail.com");
paramObject.put("pass", "4384984938943");
Call<User> userCall = apiInterface.getUser(paramObject.toString());
userCall.enqueue(this);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onResponse(Call<User> call, Response<User> response) {
}
#Override
public void onFailure(Call<User> call, Throwable t) {
}
}
Reference: [How to POST raw whole JSON in the body of a Retrofit request?
I have come to share an solution. The error happened to me after forcing the notbook to hang up. possible solution clean preject.
Maybe your JSON Object is right,but the response that you received is not your valid data.Just like when you connect the invalid WiFi,you may received a strange response < html>.....< /html> that GSON can not parse.
you may need to do some try..catch.. for this strange response to avoid crash.
Make sure you have DESERIALIZED objects like DATE/DATETIME etc. If you are directly sending JSON without deserializing it then it can cause this problem.
In my situation, I have a "model", consist of several String parameters, with the exception of one: it is byte array byte[].
Some code snippet:
String response = args[0].toString();
Gson gson = new Gson();
BaseModel responseModel = gson.fromJson(response, BaseModel.class);
The last line above is when the
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column
is triggered. Searching through the SO, I realised I need to have some form of Adapter to convert my BaseModel to and fro a JsonObject. Having mixed of String and byte[] in a model does complicate thing. Apparently, Gson don't really like the situation.
I end up making an Adapter to ensure byte[] is converted to Base64 format. Here is my Adapter class:
public class ByteArrayToBase64Adapter implements JsonSerializer<byte[]>, JsonDeserializer<byte[]> {
#Override
public byte[] deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return Base64.decode(json.getAsString(), Base64.NO_WRAP);
}
#Override
public JsonElement serialize(byte[] src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(Base64.encodeToString(src, Base64.NO_WRAP));
}
}
To convert JSONObject to model, I used the following:
Gson customGson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64Adapter()).create();
BaseModel responseModel = customGson.fromJson(response, BaseModel.class);
Similarly, to convert the model to JSONObject, I used the following:
Gson customGson = new GsonBuilder().registerTypeHierarchyAdapter(byte[].class, new ByteArrayToBase64Adapter()).create();
String responseJSon = customGson.toJson(response);
What the code is doing is basically to push the intended class/object (in this case, byte[] class) through the Adapter whenever it is encountered during the convertion to/fro JSONObject.
Don't use jsonObject.toString on a JSON object.
In my case, I am Returning JSON Object as
{"data":"","message":"Attendance Saved
Successfully..!!!","status":"success"}
Resolved by changing it as
{"data":{},"message":"Attendance Saved
Successfully..!!!","status":"success"}
Here data is a sub JsonObject and it should starts from { not ""
Don't forget to convert your object into Json first using Gson()
val fromUserJson = Gson().toJson(notificationRequest.fromUser)
Then you can easily convert it back into an object using this awesome library
val fromUser = Gson().fromJson(fromUserJson, User::class.java)
if your json format and variables are okay then check your database queries...even if data is saved in db correctly the actual problem might be in there...recheck your queries and try again.. Hope it helps
I had a case where I read from a handwritten json file. The json is perfect. However, this error occurred. So I write from a java object to json file, then read from that json file. things are fine. I could not see any difference between the handwritten json and the one from java object. Tried beyondCompare it sees no difference.
I finally noticed the two file sizes are slightly different, and I used winHex tool and detected extra stuff.
So the solution for my situation is, make copy of the good json file, paste content into it and use.
In my case, my custom http-client didn't support the gzip encoding. I was sending the "Accept-Encoding: gzip" header, and so the response was sent back as a gzip string and couldn't be decoded.
The solution was to not send that header.
I was making a POST request with some parameters using Retrofit in Android
WHAT I FACED:
The error I was getting in Android Studio logcat:
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at line 2 column 1 path $
[but it was working fine with VOLLY library]
when I googled it...
you know[ Obviously json is expecting a OBJECT but...]
BUT when I changed my service to return a simple string [ like print_r("don't lose hope") ] or
Noting at all
It was getting printed fine in Postman
but in Android studio logcat, it was still SAME ERROR [
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at line 2 column 1 path $
]
Hold up now, I am sending a simple message or not sending anything in response and still studio is
telling me "...Expected BEGIN_OBJECT but was STRING..."
SOMETHING IS WRONG
On 4th day:
I finally stopped for looking "QUICK SOLUTIONS" and REALLY READ some stack overflow questions
and articles carefully.
WHAT I GOT:
Logging interceptor
It will show you whatever data comes from your server[even eco messages] which are not shown in
Andorid studios logcat,
that way you can FIND THE PROBLEM.
What I found is I was sending data with #Body like-
#Headers("Content-Type: application/json")
#POST("CreateNewPost")
Call<Resp> createNewPost(#Body ParaModel paraModel);
but no parameter was reaching to server, everything was null [I found using Logging interceptor]
then I simply searched an article "how to make POST request using Retrofit"
here's one
SOLUTION:
from here I changed my method to:
#POST("CreateNewPost")
#FormUrlEncoded
Call<Resp> createNewPost(
#Field("user_id") Integer user_id,
#Field("user_name") String user_name,
#Field("description") String description,
#Field("tags") String tags);
and everything was fine.
CONCLUSION:
I don't understand why Retrofit gave this error
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING
at line 2 column 1 path $
it doesn't make any sense at all.
So ALWAYS DEBUG in detail then find WHERE THINGS ARE LEAKING and then FIX.
This error solved for by replacing .toString method to .string on the response
toString => string (add in try{...code..}catche(IOException e))
below code is working for me
try {
MainModelResponse model;
Gson gson = new GsonBuilder().create();
if (response.code() == ConstantValues.SUCCESS_OK) {
model = gson.fromJson(response.body().string(), MainModelResponse.class);
} else {
model = gson.fromJson(response.errorBody().string(), MainModelResponse.class);
}
moduleData.postValue(model);
}catch (IllegalStateException | JsonSyntaxException | IOException exception){
exception.printStackTrace();
}
}
use a string begin & end with {}.
such as
final String jsStr = "{\"metric\":\"opentsdb_metric\",\"tags\":{\"testtag\":\"sunbotest\"},\"aggregateTags\":[],\"dps\":{\"1483399261\":18}}";
DataPoint dataPoint = new Gson().fromJson(jsStr, DataPoint.class);
this works for me.
In my case the object was all fine even the Json Validator was giving it a valid resposne but I was using Interface like this
#POST(NetworkConstants.REGISTER_USER)
Call<UserResponse> registerUser(
#Query("name") String name,
#Query("email") String email,
#Query("password") String password,
#Query("created_date") Long creationDate
);
Then I changed the code to
#FormUrlEncoded
#POST(NetworkConstants.REGISTER_USER)
Call<UserResponse> registerUser(
#Field("name") String name,
#Field("email") String email,
#Field("password") String password,
#Field("created_date") Long creationDate
);
And everything was resolved.
my problem not related to my codes
after copy some files from an other project got this issue
in the stack pointed to Gson library
in android studio 4.2.1 this problem not solved when I try file-> invalidate and restart
and
after restart in first time build got same error but in second build this problem solved
I don't understand why this happened
I was using an old version of retrofit library. So what I had to do was to change my code from this after upgrading it to com.squareup.retrofit2:retrofit:2.9.0:
#POST(AppConstants.UPLOAD_TRANSACTION_DETAIL)
fun postPremiumAppTransactionDetail(
#Query("name") planName:String,
#Query("amount") amount:String,
#Query("user_id") userId: String,
#Query("sub_id") planId: String,
#Query("folder") description:String,
#Query("payment_type") paymentType:String):
Call<TransactionResponseModel>
To this:
#FormUrlEncoded
#POST(AppConstants.UPLOAD_TRANSACTION_DETAIL)
fun postPremiumAppTransactionDetail(
#Field("name") planName:String,
#Field("amount") amount:String,
#Field("user_id") userId: String,
#Field("sub_id") planId: String,
#Field("folder") description:String,
#Field("payment_type") paymentType:String):
Call<TransactionResponseModel>
For me it turned out that I was trying to deserialize to an object that used java.time.ZonedDateTime for one of the properties. It worked as soon as I changed it to a java.util.Date instead.

store a randomized integer from a request to property using groovy scripting

I want to store a randomized integer that has been called out in the request body and store it in test case Property so that it can be passed as a body parameter in the next request.
for example:
Request1:
id_num = randomNumeric(10)
Properties:
id_num = 1234567890
Request2:
trfered_IDNum = ${#TestCase#id_num}
The Structure looks like below,
Project
|---TestSuite
|-------TestCase
|------RestRequestTestStep1
|------RestRequestTestStep2
|------GroovyScript
Let's start with some assumptions.
RestRequestTestStep1 Response Body has below fields :
{"Resp1Field1Key":"Resp1Field1Value",
"Resp1Field2Key":"Resp1Field2Value"}
RestRequestTestStep2 Request Body has below fields :
{"Resp2Field1Key":"Resp2Field1Value",
"Resp2Field2Key":"Resp2Field2Value"}
Resp1Field1Value and Resp1Field2Value from first response will be substituted to Resp2Field1Value and Resp2Field2Value of second request.
RestRequestTestStep2 body should be as below as we will be substituting values from the testCase Property that will be set in the groovy script once first request is completed.
{
"Resp2Field1Key":"${#TestCase#Resp2Field1Value}",
"Resp2Field2Key":"${#TestCase#Resp2Field2Value}"
}
The Code..rather Script : The groovy script can be placed under the same Test Case and should do below,
import groovy.json.JsonSlurper
//Substitute with appropriate testSuiteName,testCaseName,testStepName1 and testStepName1 as per the Project Structure you have.
def testSuite = testRunner.testCase.testSuite.project.getTestSuiteByName("testSuiteName")
def testCase = testSuite.getTestCaseByName("testCaseName")
def testStep1 = testCase.getTestStepByName("testStepName1")
def testStep2 = testCase.getTestStepByName("testStepName2")
// Call the first REST Request
testStep1.run(testRunner, context)
def response = testStep1.testRequest.response.responseContent
def jsonSlurper = new JsonSlurper().parseText(response)
//Assign it to a testCase Property to grab for second Rest Request
if (jsonSlurper.size() > 0) {
testCase.setPropertyValue("Resp1Field1Value",Resp1Field1Value)
testCase.setPropertyValue("Resp1Field2Value",Resp1Field2Value)
);
//Call the second Rest Request
testStep2.run(testRunner, context)
def response = testStep2.testRequest.response.responseContent
def jsonSlurper = new JsonSlurper().parseText(response)
// Perform Validation/assertion as desired
Use these 2 lines in your groovy script before second request in the same test case
def id_num = (new Random().nextInt(100000000)).toString()
testRunner.testCase.setPropertyValue( "id_num", id_num )
log.info id_num
Now since you have saved the value in a testcase properties in a soap step, you can use like below in the next request within same testcase
${#TestCase#id_num}
This way it will automatically replace the value once you run. To see the values replacement in soap UI , you can see the Raw Tab
check this out below.. the value got replaced

Lagom Send custom header

I'm working on Lagom POC on sending POST request to Non lagom service with custom Header. In my case I'm trying to hit postman-echo to test the custom header.
However, it looks the headers are not set though I made code changes accordingly:
public CompletionStage<DsapAuthorizationResponse> hitAPI(AuthorizationRequest request) {
DsapWSRequest dsapWSRequest = new DsapWSRequest();
dsapWSRequest.username = request.username;
dsapWSRequest.password = request.password;
CompletionStage<DsapAuthorizationResponse> dsapresponse = dsapExternalService
.authenticate()
.handleRequestHeader(requestHeader -> {
requestHeader.withHeader("Authorization","Basic mncndsjna");
System.out.println("My Headers>>>>>>>> " + requestHeader);
return requestHeader;
})
.handleResponseHeader((responseHeader,b) -> {
System.out.println("RESPonse Header >>>>>>> : "+responseHeader);
return b;
})
.invoke(dsapWSRequest);
return dsapresponse;
}
In the above code header authorization is not set in the request. I am not getting this header in the echo which is mapped correctly in my POJO.
here is the complete code from my GitHub
https://github.com/sourabhsar/Lagom-Unmanaged-Service-Demo/tree/poc/lagom-request-response
I followed the steps mentioned here:
https://groups.google.com/forum/#!topic/lagom-framework/yvKmqvtZWFs
and also followed few other blogs/articles.
However so far I haven't found any blog which they are sending request to unmanaged external service with custom header. I'm not sure whats wrong in my code.
requestHeader.withHeader returns a new object with the added header, but the code you have written returns the original requestHeader object. In general, many Lagom APIs follow a principle of using immutable objects, with methods that return a new, modified instance, rather than changing the instance the method is called on.
Try this:
.handleRequestHeader(requestHeader -> {
RequestHeader modifiedRequestHeader =
requestHeader.withHeader("Authorization","Basic mncndsjna");
System.out.println("My Headers>>>>>>>> " + modifiedRequestHeader);
return modifiedRequestHeader;
})

Passing phone input via Twilio

I'm working on a basic Twilio web application using Java and the Spark Java framework. I'm trying to have the user enter a number as input after the initial prompt through a Gather verb and then process that input. So far, I am able to call my Twilio number and it responds with the initial prompt, but after I enter a number it goes to /handle-number and crashes because the request did not contain any params and it can't find the "Digits" param (params is empty when I print it).
I have tried to mimic the API call via the Postman Chrome extension to debug it, but I get a 500 internal server error.
EDIT: Here is a screenshot of the postman request : Postman screenshot
I am new to Java web applications, HTTP requests, and Twilio, so I am unfamiliar with much of this. I have gone thought the twiml documentation and tutorials and tried to follow along but my I'm definitely missing something in my implementation.
How do I properly pass the phone input to the processNumber Route? Any help is appreciated!
App.java
import static spark.Spark.*;
public class App {
public static void main (String[] args){
post("/receive-call", ReceiveCall.call);
post("/handle-number", ReceiveCall.processNumber);
}
}
ReceiveCall.java
import com.twilio.twiml.voice.Gather;
import com.twilio.twiml.voice.Say;
import com.twilio.twiml.*;
import spark.Route;
public class ReceiveCall {
public static Route call = (request, response) -> {
Say sayMessage = new Say.Builder("Hello! Please enter a number as input. Enter # when finished.").build();
Gather input = new Gather.Builder().timeout(3).say(sayMessage).action("/handle-number").build();
VoiceResponse twiml = new VoiceResponse.Builder().gather(input).build();
System.out.println(response.body());
return twiml.toXml();
};
public static Route processNumber = ((request, response) -> {
String digit = request.params("Digits");
//CRASHES HERE BECAUSE digit IS NULL
int number = Integer.parseInt(digit);
Say message = process(number);
VoiceResponse twiml = new VoiceResponse.Builder().say(message).build();
return twiml.toXml();
});
The reason of "digit IS NULL" is: you are using request.params(...), which is for path parameter.
What is "path parameter"?
"path parameter" means passing parameter as part of URL path, especially in RESTful style request.
For example, if you want to send an HTTP GET request to retrieve a book by its ISBN, the request URL could be: /books/9787121022982 or /books/9787101054491, where the ISBN parameter is passed as part of URL path (9787121022982 and 9787101054491). In Spark framework, the corresponding Route code would be:
get("/books/:isbn", (request, response) -> {
return "Book ISBN is: " + request.params(":isbn");
});
What is "query parameter"?
"query parameter" means passing parameter as part of URL queries (entities after the ? character in URL).
Take the previous book ISBN case for example, if you want to pass ISBN as query parameter, the HTTP GET URL would be: /books?isbn=9787121022982, and the corresponding Spark Route code is:
get("/books", (request, response) -> {
return "Book ISBN is: " + request.queryParams("isbn");
});
What is the best practice to pass data in POST request?
In your case, the /handle-number route accept POST request. For HTTP POST request, it's not a good practice to pass data as parameter in URL. Instead, you need to pass data as request body, and get data from body in Spark code:
post("/handle-number", (request, response) -> {
String body = request.body();
// extract ISBN from request body string
});

Categories

Resources