Search This Blog

Breaking

Tuesday, 5 December 2023

December 05, 2023

[Rest Assured][Fix] Getting API Response from Postman, but when same request hit from Rest assured code, API does not respond

 Recently, I was debugging an issue for a team mate for which API was not responding when ran through java code. The same API was responding from the same code from my machine, from his postman, from any other machines, but just not responding when he was running from the java code.


Below was the request which code were making:



RestAssured.baseURI = “URL”;

RestAssured.useRelaxedHTTPSValidation();


Response response = RestAssured.given()

                                          .auth()

                                          .preemptive()

                                          .basic(username, password)

                                          .header("Content-Type", "application\json")

                                          .body(requestBody)

                                          .post(endPoint)

                                          .then().extract().response();

                                          .


When we were hitting this code, It was not returning any response and the code was in execution mode. We tried to debug it also, but we could not get much information.


Fix

After an hour debug, we tried to play with the config settings. We got to know after reading the doc, 

that by default REST Assured adds the charset header automatically. 

To disable this completely we can configure the EncoderConfig like this:


 given()

.config(RestAssured.config()

.encoderConfig(encoderconfig.appendDefaultContentCharsetToContentTypeIfUndefined(false)));


With the EncoderConfig we can specify the default content encoding charset (if it's not specified in the content-type header) and query parameter charset for all requests. If no content charset is specified then ISO-8859-1 is used and if no query parameter charset is specified then UTF-8 is used. Usage example:


RestAssured.config = RestAssured.config().encoderConfig(encoderConfig().defaultContentCharset("US-ASCII"));


This solved our issue when we started getting the response.


The other notable thing was, when we removed it later, we were started getting the response too. Though we didn't check the server logs, however, it seems that the other responses were coming from cache.


Thursday, 23 November 2023

November 23, 2023

[Jenkins] [Fix] Unable to create file, File Name too large error while taking clone from repo

Recently, we started getting an issue in our Automation jobs where when ran automation from Jenkins, it started failing while taking clone from the git.

The error was : 

error: unable to create file 

src/......../path/to/that/file/abc.java is too long.




When looked into the issue, we got to know that the root cause of this issue is the "Windows API limitation of file paths having 260 characters or fewer."


To fix this issue, we can simple follow below steps:


1. Open git bash in the machine where issue is coming with admin rights.

2. Run this command: git config --system core.longpaths true

Once this command will ran successfully, it will fix this issue.
 


Friday, 14 July 2023

July 14, 2023

Access Denied Exception [java.nio.file.AccessDeniedException] [Debug/Fix] while accessing file data from java

 Recently, I got an issue where when I was trying to access file inside a folder in windows with Jenkin Job, I got "AccessDeniedException". Surprisingly, the folder was accessible when checked manually.

To debug the issue, we tried multiple aspects. For example:

1. We checked how we are creating folder/file path.

-> Reason for this :  If the Jenkin machine where the execution happening is "Linux", then it might be the path which works fine in windows will not work in Linux.

The best way to construct your path for files and directories in java is to use : File Sperator

(https://stackoverflow.com/questions/36663023/java-file-path-windows-linux)


Outcome: The path was correct.

2. After ensuring that the path was correct, next we tried to check that wheather from the system where execution is happening, that folder is accessible or not.

-> Reason for this: As it was a shared location, so it is important to check that the path should be accessible.

Outcome: We ensured that the folder is accessible from that machine.


3. The next analysis, brought us to check , if we ran the code directly in the machine, where issue is occurring, what will be the output?


Reason for this: To ensure, that there is not java, dependency issue.

Outcome: Code worked fine from that location.


It leads to a conclusion that, there is no issue in the code, the issue comes only when the execution happens via Jenkin.

4. We have narrowed down the analysis now, but it looked more complex. The code was working fine in local machine, it was working fine when we were running it from the Jenkins machines directly, but only fails when we trigger the execution from the Jenkins

5. We checked the user now from which the execution is triggering from Jenkins.

Reasons for this: To check weather the user is having rights to that folder or not.

Output: User was same with which we logged to that machine. This made it more complex.

6. Restart the machine where execution was happening

Reason for this: It came out just as a normal discussion. When we were giving access to anyone to that folder, we were rebooting our system too.

Outcome: The access started working.

I still could not figure out , that why the code was working fine when we were running it from the same machine and why it failed, when we were triggering it from Jenkins.

That analysis I will do on my free time, but if you are reading this article, and if you have any idea about it, feel free to comment. It would be interesting to know.


Tuesday, 16 May 2023

May 16, 2023

[Java8] Avoid "ConcurrentModificationException" while removing elements from `ArrayList` while iterating it

 Have you ever removed some element while iterating over the arrayList or collection objects? If yes, Have you encountered "ConcurrentModificationException" at run time.

If your answer is yes, it means you also tried to avoid creating another list which can hold items which salsify your condition.

As per java doc:

This exception may be thrown by methods that have detected concurrent modification of an object when such modification is not permissible.

To understand it from code point, we can check below code:   


List<String> values = new ArrayList<>();
values.add("A");
values.add("b-");
values.add("c");
values.add("D-");
for(String value: values) {
if(value.endsWith("-")) {
values.remove(value);
}


Here we are trying to remove value which is ending with "-" from the list "Values".

What we tried to do here, is to iterate the list elements and checking the condition, if satisficed, removing list items, which reduces the list size.

If you will debug this code, you will see:

When the first condition satisfies and it reduces the size of the list, and at that moment, when it reaches to for loop iteration with the updated list size, it throws ConcurrentModificationException.

So to avoid, this exception in java 8, we can use removeIf method.

values.removeIf(value -> value.endsWith("-"));
System.out.println("Values are: " + values);


removeIf() Removes all of the elements from the collection that satisfy the given predicate. If you will see it's implementation, it is based on the iterator. 

Friday, 28 April 2023

April 28, 2023

[Rest API][JsonPath] [GSON]-> How to Add a node to JSON in JAVA with JSONPath

 Recentally, I came across a situation, where I need to update my JSON with new node which can include jsonArray, JsonMap and just updating a node value.











My JSON was like this:

{
"firstName": "John",
"age": 26,
"address": {
"streetAddress": "naist street",
"city": "Nara",
"postalCode": "630-0192"
}
}

And I was expecting it to be like this:


{ "firstName": "John", "lastName": "Mathpal", "address": { "streetAddress": "naist street", "city":
"Ranikhet", "postalCode": "630-0192", "landmark": "More Market" }, "age": 26.0, "vehicle": { "name": "honda", "model": "GS", "price": "15.8 L" }, "phoneDetails": [{ "type": "iphone", "number": "123" }, { "type": "android", "number": "456" }] }


So this first change, I was expecting to change the value of city from "Nara" to "Ranikhet".

So to implement it, I used JSONPath DocumentContext which have the set method to set a node value.

So first I read the json file:

String requestBody = readRequestBody(path);
private static String readRequestBody(String requestBodyPath) throws IOException {
File requestBody = new File(requestBodyPath);
return JsonPath.parse(requestBody).jsonString();
}
String valueToBeAddedUpdated = "Ranikhet";
String nodeWhereValueNeedToUpdate = "$.address.city";
requestBody = setJsonDataValue(nodeWhereValueNeedToUpdate, valueToBeAddedUpdated, requestBody);

so to set the value:

private static String setJsonDataValue(String nodeWhereValueNeedToUpdate, Object valueToBeAddedUpdated, String requestBody) {
return JsonPath.parse(requestBody).set(nodeWhereValueNeedToUpdate, valueToBeAddedUpdated).jsonString();
}

It sets the value in the json for city value to :

{

"firstName": "John",

"age": 26,

"address": {

"streetAddress": "naist street",

"city": "Ranikhet",

"postalCode": "630-0192"

}

}


After settign the value, I added a node "lastName": "Mathpal",

requestBody = addJsonNode("$","lastName", "Mathpal",requestBody);
private static String addJsonNode(String jsonpath, String nodeName, String nodeValue, String requestBody) {
DocumentContext documentContext = JsonPath.parse(requestBody);
documentContext.put(JsonPath.compile(jsonpath), nodeName, nodeValue);
String updatedRequestBody = documentContext.jsonString();
return updatedRequestBody;
}

After setting the value, I added a node inside the address: "landmark": "More Market"

requestBody = addJsonNode("$.address","landmark", "More Market",requestBody);

Once this is added, I tried to add a JSONMap vehicle to the existing json.

So to set it, I first prepared a map with vehicle and its details.

String nodeName = "vehicle";
Map<String, Object> finalMap = prepareJsonMapForVehicle(nodeName);
private static Map<String, Object> prepareJsonMapForVehicle(String nodeName) {
Map<String, Object> finalMap = new LinkedHashMap<>();
Map<String, Object> vehicleMap = new LinkedHashMap<>();
vehicleMap.put("name", "honda");
vehicleMap.put("model", "GS");
vehicleMap.put("price", "15.8 L");
finalMap.put(nodeName, vehicleMap);
return finalMap;
}

Once that is done, I used GSON to add that map to the existign requestBody.

requestBody = addJsonMap(requestBody, finalMap);
private static String addJsonMap(String requestBody, Map<String, Object> finalMap) {
HashMap<String, Object> map = new Gson().fromJson(requestBody, HashMap.class);
map.putAll(finalMap);
return new Gson().toJson(map);
}

GSON have 2 methods fromJSON and toJSON which helps to convert java map to json and vice versa.


Once that is done, now added the json array "phoneDetails" field.

So to add it, i first created the jsonArray field as an jsonArray.

String nodeName1 = "phoneDetails";
JsonArray phoneDetails = new JsonArray();

And then added that JSONArray to existing json with the help of JSONPath put method.

 String nodeName1 = "phoneDetails";

JsonArray phoneDetails = new JsonArray();
requestBody =addJsonNodeAsArray("$", nodeName1,phoneDetails,requestBody);

in the addJsonNodeAsArray method, I used the JSONPath put method to set the value.

private static String addJsonNodeAsArray(String jsonpath, String nodeName, JsonArray nodeValue, String requestBody) {
DocumentContext documentContext = JsonPath.parse(requestBody);
documentContext.put(JsonPath.compile(jsonpath), nodeName, nodeValue);
String updatedRequestBody = documentContext.jsonString();
return updatedRequestBody;
}


Once the json Array is added, we cans et value for it.

requestBody = addJsonArrayValues("$.phoneDetails", requestBody,  "iphone", "123") ;
System.out.println("-------------------------------------------------------------------------------------------");

The only change in this method is, that it takes a map while adding. 

private static String addJsonArrayValues(String jsonPath, String requestBody, String arrayNodeName, String arrayNodeValue) {
DocumentContext documentContext= JsonPath.parse(requestBody);
documentContext.add(JsonPath.compile(jsonPath),prepareJsonMapForPhone(arrayNodeName, arrayNodeValue));
String latestIne = documentContext.jsonString();
return latestIne;
}

Once that is done, we can add another json value inside into it too.

requestBody = addJsonArrayValues("$.phoneDetails", requestBody,  "android", "456") ;
System.out.println("After adding another value to the jsonArray inside a json:" +requestBody);


This is how I update a json value, added a new json node with value, a json array and a jsonMap into an existing JSON.














April 28, 2023

[JIRA API] -> Set JIRA description field with formatting

 Recentally, while doing my jirafication activity, I came across a situation, when I was trying to create a JIRA Story with sonar issue description, but the JIRA Issue, was not updating the formatted description.

It was coming as a plain text which was not much impressive.

So to  implement it, I did the same steps manually first and then check the request from network console. And below are some of my findings:










1. To make text bold: just put the text between *.

For Example: 

Input Text: This isssue is related to Thread.

Expected Output: *This isssue is related to Thread*

This will make this line bold when you will hit with your API.

API: {{JIRA_URL}}/ rest/api/latest/issue

Method: POST

{

"fields": {

"description": "*This isssue is related to Thread*"

}

}

2. To make text in color: put the color code like this:

"{color:#0747a6}This isssue is related to Thread.{color}"

For Example: 

Input Text: This isssue is related to Thread.

Expected Output: This isssue is related to Thread


3. To put Java code: "{code:java} your java code {code}"

As of now, I have just used these formattings. I will update others, if will use them.



Wednesday, 19 April 2023

April 19, 2023

Sonar Findings - JIRA FIcation


Recentally, I am working on to JIRAfy all our projects Sonar findings. To get start to implement it, I first created a flow diagram. To segregate Sonar issues, I used sonar rule filter. Rule is a filter on the basis of which all soanr issues are categorized. 

For Example: Thread.sleep(1000) should not be a part of test code. 

Every rule is associated with a rule id. So with the help of rule id, I filtered issues. Once i got all the issues, the next step I took, to create JIRA issues for them. 

To jiraficatiom, I first created a epic mentioning the rule and it's description. Inside the epic, I created a story if it does not exist in JIRA. To verify, that a story alredy exist in jira, I used label as a filter, whose value will be rule. Once the story will be created, we will link subtask to it.





This is right now in initial stage, will share details how it will proceede.





 

Thursday, 30 March 2023

March 30, 2023

[Jenkins] How to pass choice parameter in Jenkins file

 Recentally I was working in converting our pipeline jenkin jobs to Jenkinsfiles so that it can be better managed and tracked. In the jenkin file, I was using declarative pipeline.

In one of the jenkin file, I have to pass the choice parameters from one job to another. 

To implement this, I first created the choice parameter in jenkin file as:


properties([

                 paramteres([

                  choice(choices:['https://www.google.com', 'https://s-www.google.com', 'https://d-www.google.com'], description: 'Select your env?', name:'url')

                ])

])


Then I stored the url value inside a variable: 

def env = params.url


After getting the env, we can pass it in the job as :








pipeline {

           agenet none{

                             stages('') {

                                            parallel {

                                                          stage('Run your first job') {

                                                           steps {

                                                                    script {

                  build(job: 'Job path' , paramters:[string(name:'url', value:String.valueof(params.url))]) 

                                                                   }

                                                               } 

                                                         }

                                                        stage('Run your second job') {

                                                         ......................

                                                       }

                                               }

                                      } // close stages

post {

   always {

    }

}

This allows to pass the chocie aprameter from parent job to downstream jobs.


                    

                               


   

Tuesday, 28 February 2023

February 28, 2023

[JSOUP] [Fix]-> Not fetching whole page data from page

Recently, I encountered an issue with our JSOUP bases automation project where, we were not getting whole page data in the document.

Document doc = Jsoup.connect(performanceTabURL).get(); 











When I printed this doc, I didn't see the whole page data. Now the intresting part of this issue was, that the problem was coming in 1 machine/network (client) while in another network, this was fetching the all data.

Though, I could not still figure out why this is happening in 1 machine/network, but to fix this problem, I increased the size of the body in jsoup request, which by default is set to hold for only 1 MB size of data.

So I tweaked the above code and added maxBodySize which takes size as an integer value.

Document doc = Jsoup.connect(performanceTabURL).maxBodySize(0).get();

Size as 0 means, that it will not have restriction on size.

With this change, I waas able to fetch the whole data without worrying the size of the body.

Wednesday, 22 February 2023

February 22, 2023

How to print logs in colors in Intelij Idea console?

 Recently, for a demo, I felt that the logs which I am going to present should be in some colors so that it can make more impact. So to implement it, we can create a call/enum where we can define the ascii values for the color code.








public class ConsoleColors {

    // Reset

    public static final String RESET = "\033[0m";  // Text Reset


    // Regular Colors

    public static final String BLACK = "\033[0;30m";   // BLACK

    public static final String RED = "\033[0;31m";     // RED

    public static final String GREEN = "\033[0;32m";   // GREEN

    public static final String YELLOW = "\033[0;33m";  // YELLOW

    public static final String BLUE = "\033[0;34m";    // BLUE

    public static final String PURPLE = "\033[0;35m";  // PURPLE

    public static final String CYAN = "\033[0;36m";    // CYAN

    public static final String WHITE = "\033[0;37m";   // WHITE


    // Bold

    public static final String BLACK_BOLD = "\033[1;30m";  // BLACK

    public static final String RED_BOLD = "\033[1;31m";    // RED

    public static final String GREEN_BOLD = "\033[1;32m";  // GREEN

    public static final String YELLOW_BOLD = "\033[1;33m"; // YELLOW

    public static final String BLUE_BOLD = "\033[1;34m";   // BLUE

    public static final String PURPLE_BOLD = "\033[1;35m"; // PURPLE

    public static final String CYAN_BOLD = "\033[1;36m";   // CYAN

    public static final String WHITE_BOLD = "\033[1;37m";  // WHITE


    // Underline

    public static final String BLACK_UNDERLINED = "\033[4;30m";  // BLACK

    public static final String RED_UNDERLINED = "\033[4;31m";    // RED

    public static final String GREEN_UNDERLINED = "\033[4;32m";  // GREEN

    public static final String YELLOW_UNDERLINED = "\033[4;33m"; // YELLOW

    public static final String BLUE_UNDERLINED = "\033[4;34m";   // BLUE

    public static final String PURPLE_UNDERLINED = "\033[4;35m"; // PURPLE

    public static final String CYAN_UNDERLINED = "\033[4;36m";   // CYAN

    public static final String WHITE_UNDERLINED = "\033[4;37m";  // WHITE


    // Background

    public static final String BLACK_BACKGROUND = "\033[40m";  // BLACK

    public static final String RED_BACKGROUND = "\033[41m";    // RED

    public static final String GREEN_BACKGROUND = "\033[42m";  // GREEN

    public static final String YELLOW_BACKGROUND = "\033[43m"; // YELLOW

    public static final String BLUE_BACKGROUND = "\033[44m";   // BLUE

    public static final String PURPLE_BACKGROUND = "\033[45m"; // PURPLE

    public static final String CYAN_BACKGROUND = "\033[46m";   // CYAN

    public static final String WHITE_BACKGROUND = "\033[47m";  // WHITE


    // High Intensity

    public static final String BLACK_BRIGHT = "\033[0;90m";  // BLACK

    public static final String RED_BRIGHT = "\033[0;91m";    // RED

    public static final String GREEN_BRIGHT = "\033[0;92m";  // GREEN

    public static final String YELLOW_BRIGHT = "\033[0;93m"; // YELLOW

    public static final String BLUE_BRIGHT = "\033[0;94m";   // BLUE

    public static final String PURPLE_BRIGHT = "\033[0;95m"; // PURPLE

    public static final String CYAN_BRIGHT = "\033[0;96m";   // CYAN

    public static final String WHITE_BRIGHT = "\033[0;97m";  // WHITE


    // Bold High Intensity

    public static final String BLACK_BOLD_BRIGHT = "\033[1;90m"; // BLACK

    public static final String RED_BOLD_BRIGHT = "\033[1;91m";   // RED

    public static final String GREEN_BOLD_BRIGHT = "\033[1;92m"; // GREEN

    public static final String YELLOW_BOLD_BRIGHT = "\033[1;93m";// YELLOW

    public static final String BLUE_BOLD_BRIGHT = "\033[1;94m";  // BLUE

    public static final String PURPLE_BOLD_BRIGHT = "\033[1;95m";// PURPLE

    public static final String CYAN_BOLD_BRIGHT = "\033[1;96m";  // CYAN

    public static final String WHITE_BOLD_BRIGHT = "\033[1;97m"; // WHITE


    // High Intensity backgrounds

    public static final String BLACK_BACKGROUND_BRIGHT = "\033[0;100m";// BLACK

    public static final String RED_BACKGROUND_BRIGHT = "\033[0;101m";// RED

    public static final String GREEN_BACKGROUND_BRIGHT = "\033[0;102m";// GREEN

    public static final String YELLOW_BACKGROUND_BRIGHT = "\033[0;103m";// YELLOW

    public static final String BLUE_BACKGROUND_BRIGHT = "\033[0;104m";// BLUE

    public static final String PURPLE_BACKGROUND_BRIGHT = "\033[0;105m"; // PURPLE

    public static final String CYAN_BACKGROUND_BRIGHT = "\033[0;106m";  // CYAN

    public static final String WHITE_BACKGROUND_BRIGHT = "\033[0;107m";   // WHITE

}


Now, we can call those color codes in our sysout logs like this:


System.out.println(ConsoleColors.GREEN + "Total time spent fetching all data for all funds from UI is: " + totalTimeElapsed.toSeconds() + " seconds "+ ConsoleColors.RESET);

ConsoleColors.RESET is mandatory so that it will the color setting.


Friday, 20 January 2023

January 20, 2023

How I reduced 9 hour execution time to 1 hour with Java threads and ChatGPT Help?

 Recently, I was writing a utility which is comparing data from 3 different data sources. Here the first source was UI, second was Web Services and third was Excel where Data was dumped through some sequel queries. 













As the data (UI and Services) which needs to validate against was Excel data, So my initial implementation was:

1. To read data from excel and store it inside a HashMap

2. Hit the UI for the fund data read from excel with JSOUP library and store the data

3. Hit the Services with JSOUP and store the data

After getting the data, I was performing 2 comparisons:

-> UI data to services

-> UI Data to Excel data

When I ran it for almost 2200+ funds, it took me almost 8 hour to complete the comparison.

I checked the logs and find out that:

1-> Getting data from UI was taking ~7-9 seconds from JSOUP

2-> Rest all was completing within 1 second


As I have all the funds name already available with me when I read it first from excel, and after that, 1 by 1 I was making UI call for those funds, so I thought to implement Thread concept here.

So I built a new approach for which ChatGPT helped me.

I asked a question in chatGPT something similar to below:

-> Provide me a sample java code to create no of threads as per the array list size and later execute them all altogether.


ArrayList<String> values = new ArrayList<>();
values.add("a");
values.add("b");
values.add("c");
values.add("d");
ArrayList<Runnable> tasks = new ArrayList<>();

for(String value: values) {
tasks.add(()-> {
System.out.println( " Executing Task for " + value); // Add you method here
});
}
ExecutorService executor = Executors.newFixedThreadPool(tasks.size());
for (Runnable task : tasks) {
executor.execute(task);
}
executor.shutdown();
}


1-> After reading the fund names from excel, I will create task for all these funds which will hold method to read data from UI.

2-> After creating task, I will execute these task with Thread Pool.


So My implementation code changed to: (Dummy Code)


This saved the overall execution to 1/3rd drastically. I used all the available resources (machines in Jenkins) and created a parallel pipeline also and further reduced this 1/3rd to further 1/3rd which means I brought 9 hour execution to 1 hour.

This was the best way I learned a concept in my life and chatGPT helped me a lot in it.

Tuesday, 10 January 2023

January 10, 2023

How to in Git?

 1. How to remove a file from a remote feature branch without deleting it from local branch?


1. Checkout to the local branch and run below command:

>git rm --cached sampletextfile.txt




2. run git status. It will show 


Changes to be committed:

  (use "git restore --staged <file>..." to unstage)

        deleted:    sampletextfile.txt

3. Now commit the changes

git commit -m "pushing changes"


4. After commit , perform git push.

gitDemo>git push origin HEAD

2. How to Create and checkout the new branch with one command in git?

>$ git checkout -b test origin/test

where origin/test is the remote branch name and test is branch name in local.


Note: Always take a fresh pull from the main branch first, so that this new branch is created with latest changes.


3. How to delete a remote branch? (Assuming you have the permission)

-> Check all the branches

git remote show origin

-> Delete the specific branch

git push origin --delete <branch-name>