Search This Blog

Breaking

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>

Monday, 5 September 2022

September 05, 2022

[Selenium UI] -> How to do file upload from System and handling InvalidElementStateException in Webdriver?

 Whenever there is a use case of file upload from the system to your application, you should always check whether the DOM is having an element of the "Input" tag whose type is "File". If there is such an element available, you need to make sure that the element is present and you just need to pass the "File path" from your system to this element as a string.








For Example: If we need to tweet an image from our system to twitter, We can check "Is there any input tag available with a type file".


<input accept="image/jpeg,image/png,image/webp,image/gif,video/mp4,video/quicktime" multiple="" tabindex="-1" type="file" class="r-8akbif r-orgf3d r-1udh08x r-u8s1d r-xjis5s r-1wyyakw" data-testid="fileInput">


You will see that, there is an element available with an input field whose type is "File". Now, in your selenium script, you need to pass the path of your file.


imagePath = driver.find_element(By.XPATH, "//*[@data-testid='fileInput']")

imagePath.send_keys("C:\\Users\\username\\Documents\\Personal\\selenium.png")

It will upload the file to Twitter for the tweet.


If while doing this activity, you see InvalidElementStateException, it means the element is not clickable.

So you need to make sure, that the element is in active/clickable status before interacting with it.

WebDriverWait(driver,20).until(EC.element_to_be_clickable("element")).send_keys("C:\\Users\\username\\Documents\\Personal\\selenium.png")


The same can be done in Java:

new WebDriverWait(driver, Duration.ofSeconds(20)).until(ExpectedConditions.elementToBeClickable(By.xpath(""))).sendKeys("imagePath");


This will resolve the issue and will upload the file.

Note: In both cases, it will not open any windows dialogue. So don't get confused that you need to use "AutoIT", "Robot Class" or any other hack to upload files there.


#invalidSateException #fileUploadInSelenium #HowToUploadFileInSelenium