<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/scripts/pretty-feed-v3.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:h="http://www.w3.org/TR/html4/"><channel><title>Krishan Chawla</title><description>Technical Lead | Software Engineer | Automation Expert | Tech Enthusiast in the Telecom Industry</description><link>https://krishanchawla.com</link><item><title>K6 Performance Testing for APIs – Quick Start Guide</title><link>https://krishanchawla.com/blog/setup-api-performance-testing-using-k6-performance-tool</link><guid isPermaLink="true">https://krishanchawla.com/blog/setup-api-performance-testing-using-k6-performance-tool</guid><description>Learn how to install, configure, and run K6 performance tests on REST APIs</description><pubDate>Tue, 16 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Performance testing is no longer optional for modern APIs. Even a perfectly functional API can fail under load if performance is not validated early.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;K6&lt;/strong&gt; is a modern, open-source performance testing tool designed for developers, QA engineers, and DevOps teams. It allows you to write readable performance tests using JavaScript and run them locally or in CI/CD pipelines.&lt;/p&gt;
&lt;h3&gt;What is K6 and When Should You Use It&lt;/h3&gt;
&lt;p&gt;K6 is best suited for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;REST and GraphQL API performance testing&lt;/li&gt;
&lt;li&gt;Load testing microservices&lt;/li&gt;
&lt;li&gt;Stress and spike testing&lt;/li&gt;
&lt;li&gt;CI/CD performance gates&lt;/li&gt;
&lt;li&gt;Pre-production validation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Core Performance Testing Concepts&lt;/h3&gt;
&lt;p&gt;| Term |    Meaning |
|-----|--------|
| Virtual User (VU) |   Simulated user executing your test |
| Iteration |   One full execution of the test function |
| Load Test |   Expected production traffic |
| Stress Test |     Gradually increasing load to find limits |
| Spike Test |  Sudden traffic increase |
| Threshold |   SLA or pass/fail condition |&lt;/p&gt;
&lt;h3&gt;Step 1: Install k6&lt;/h3&gt;
&lt;h4&gt;macOS&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;brew install k6
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Windows&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;choco install k6
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Linux (Debian / Ubuntu)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo apt update
sudo apt install k6
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Docker (CI/CD Friendly)&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker pull grafana/k6
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verify installation:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;k6 version
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 3: Your First K6 API Test&lt;/h3&gt;
&lt;p&gt;Create &lt;code&gt;api-test.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;import http from &apos;k6/http&apos;
import { check, sleep } from &apos;k6&apos;

export const options = {
  vus: 10,
  duration: &apos;30s&apos;,
}

export default function () {
  const response = http.get(&apos;https://jsonplaceholder.typicode.com/posts&apos;)

  check(response, {
    &apos;status is 200&apos;: (r) =&gt; r.status === 200,
    &apos;response time &amp;#x3C; 500ms&apos;: (r) =&gt; r.timings.duration &amp;#x3C; 500,
  })

  sleep(1)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;What this test does&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;Runs 10 virtual users&lt;/li&gt;
&lt;li&gt;Executes for 30 seconds&lt;/li&gt;
&lt;li&gt;Sends HTTP GET requests&lt;/li&gt;
&lt;li&gt;Validates response status and performance&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Step 4: Running the Test&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;k6 run tests/api-test.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;K6 will immediately start printing live metrics to the terminal.&lt;/p&gt;
&lt;h3&gt;Step 5: Understanding K6 Output&lt;/h3&gt;
&lt;p&gt;Key Metrics to Watch&lt;/p&gt;
&lt;p&gt;| Metric | What It Tells You |
|------|------------------|
| &lt;strong&gt;http_req_duration&lt;/strong&gt; | End-to-end request latency |
| &lt;strong&gt;http_req_failed&lt;/strong&gt; | Percentage of failed requests |
| &lt;strong&gt;vus&lt;/strong&gt; | Number of active virtual users |
| &lt;strong&gt;iterations&lt;/strong&gt; | Total test executions |
| &lt;strong&gt;checks&lt;/strong&gt; | Assertion success rate |&lt;/p&gt;
&lt;p&gt;Focus First On&lt;/p&gt;
&lt;h3&gt;Load Testing Example&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;export const options = {
  vus: 50,
  duration: &apos;2m&apos;,
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use this to simulate &lt;strong&gt;normal expected traffic&lt;/strong&gt;.&lt;/p&gt;
&lt;h3&gt;Stress Testing Example&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;export const options = {
  stages: [
    { duration: &apos;1m&apos;, target: 20 },
    { duration: &apos;1m&apos;, target: 50 },
    { duration: &apos;1m&apos;, target: 100 },
    { duration: &apos;1m&apos;, target: 0 },
  ],
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Use this to identify:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Performance degradation&lt;/li&gt;
&lt;li&gt;Breaking points&lt;/li&gt;
&lt;li&gt;Resource bottlenecks&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;API Testing with Headers and Auth&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;const params = {
  headers: {
    Authorization: &apos;Bearer YOUR_TOKEN&apos;,
    &apos;Content-Type&apos;: &apos;application/json&apos;,
  },
}

http.get(&apos;https://api.example.com/users&apos;, params)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 6: Adding Thresholds (SLAs)&lt;/h3&gt;
&lt;p&gt;Thresholds fail the test when SLAs are violated.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;export const options = {
  thresholds: {
    http_req_duration: [&apos;p(95)&amp;#x3C;500&apos;],
    http_req_failed: [&apos;rate&amp;#x3C;0.01&apos;],
  },
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Perfect for CI/CD pipelines.&lt;/p&gt;
&lt;h3&gt;CI/CD Usage (Quick Example)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;k6 run tests/api-test.js --summary-export=summary.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Pipeline can fail if thresholds are breached.&lt;/p&gt;
&lt;h3&gt;Best Practices&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Start small, scale gradually&lt;/li&gt;
&lt;li&gt;Keep tests deterministic&lt;/li&gt;
&lt;li&gt;Version control test scripts&lt;/li&gt;
&lt;li&gt;Avoid testing from unstable networks&lt;/li&gt;
&lt;li&gt;Always define thresholds&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;When NOT to Use K6&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;UI/browser testing&lt;/li&gt;
&lt;li&gt;Visual performance testing&lt;/li&gt;
&lt;li&gt;End-to-end user journey validation&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;K6 enables teams to shift performance testing left and catch issues early.&lt;br&gt;
With minimal setup and readable scripts, it becomes a powerful part of your DevTools ecosystem.&lt;/p&gt;
&lt;h3&gt;Key Takeaways&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;K6 is lightweight and developer-friendly&lt;/li&gt;
&lt;li&gt;Ideal for API and microservice testing&lt;/li&gt;
&lt;li&gt;Easy CI/CD integration&lt;/li&gt;
&lt;li&gt;Clear metrics and strong automation support&lt;/li&gt;
&lt;/ul&gt;</content:encoded><h:img src="/_astro/hero-banner.D0ytrhL-.png"/><enclosure url="/_astro/hero-banner.D0ytrhL-.png"/></item><item><title>How to Install and Configure NGINX Server on CentOS</title><link>https://krishanchawla.com/blog/install-and-configure-nginx-on-centos</link><guid isPermaLink="true">https://krishanchawla.com/blog/install-and-configure-nginx-on-centos</guid><description>A simple and clear step-by-step tutorial on installing NGINX on CentOS, configuring your first website, enabling firewall rules, and verifying everything works.</description><pubDate>Tue, 09 Dec 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;🚀 How to Install and Configure NGINX on CentOS&lt;/h2&gt;
&lt;p&gt;NGINX is one of the most popular web servers in the world. It&apos;s fast, lightweight, and easy to configure — perfect for hosting websites, APIs, or static content.&lt;/p&gt;
&lt;p&gt;In this guide, you’ll learn &lt;strong&gt;how to install NGINX on CentOS&lt;/strong&gt;, start the service, configure a basic website, and verify the installation.&lt;/p&gt;
&lt;h3&gt;Step 1: Update Your System&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo yum update -y
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 2: Install NGINX&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo yum install nginx -y
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 3: Allow NGINX in the Firewall&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 4: Verify NGINX is Running&lt;/h3&gt;
&lt;p&gt;Visit:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;http://&amp;#x3C;your-server-ip&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see the NGINX welcome page.&lt;/p&gt;
&lt;h3&gt;Step 5: Hosting Your First Web Page&lt;/h3&gt;
&lt;p&gt;Default NGINX web root:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/usr/share/nginx/html
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Edit:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nano /usr/share/nginx/html/index.html
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-html&quot;&gt;&amp;#x3C;h1&gt;Hello from NGINX on CentOS!&amp;#x3C;/h1&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 6: Basic Custom NGINX Configuration&lt;/h3&gt;
&lt;p&gt;Create:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nano /etc/nginx/conf.d/mywebsite.conf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-nginx&quot;&gt;server {
    listen 80;
    server_name example.com;
    root /var/www/mywebsite;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reload:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nginx -t
sudo systemctl reload nginx
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;🎉 Done!&lt;/p&gt;
&lt;p&gt;You&apos;ve successfully installed and configured NGINX on CentOS.&lt;/p&gt;</content:encoded><h:img src="/_astro/hero-banner.D9wvGpoL.png"/><enclosure url="/_astro/hero-banner.D9wvGpoL.png"/></item><item><title>MySQL Master-Slave Replication for Data Redundancy</title><link>https://krishanchawla.com/blog/mysql-master-slave-replication</link><guid isPermaLink="true">https://krishanchawla.com/blog/mysql-master-slave-replication</guid><description>Learn how to set up MySQL master-slave replication to ensure data redundancy and high availability in production environments.</description><pubDate>Sat, 22 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In production environments, data redundancy and high availability are critical requirements. MySQL master-slave replication is a proven solution that ensures your data is safely replicated across multiple servers.&lt;/p&gt;
&lt;p&gt;This guide will walk you through setting up MySQL master-slave replication step by step.&lt;/p&gt;
&lt;h2&gt;What is MySQL Replication?&lt;/h2&gt;
&lt;p&gt;MySQL replication enables data from one MySQL database server (the master) to be copied to one or more MySQL database servers (the slaves). Replication is asynchronous by default; slaves do not need to be connected permanently to receive updates from the master.&lt;/p&gt;
&lt;h3&gt;Benefits of Replication&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Data Redundancy&lt;/strong&gt;: Keep multiple copies of your data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Load Distribution&lt;/strong&gt;: Distribute read queries across multiple slaves&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backup Solution&lt;/strong&gt;: Use slaves for backups without locking the master&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Disaster Recovery&lt;/strong&gt;: Quick failover to slave in case of master failure&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Before we begin, make sure you have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MySQL 8.0 or higher installed on both servers&lt;/li&gt;
&lt;li&gt;Root access to both servers&lt;/li&gt;
&lt;li&gt;Network connectivity between servers&lt;/li&gt;
&lt;li&gt;Basic understanding of MySQL&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Step 1: Configure Master Server&lt;/h2&gt;
&lt;p&gt;First, edit the MySQL configuration file on the master server:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add the following lines:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = production_db
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Important Configuration Parameters:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;server-id&lt;/code&gt;: Unique identifier for the server (must be unique across all servers)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;log_bin&lt;/code&gt;: Enable binary logging&lt;/li&gt;
&lt;li&gt;&lt;code&gt;binlog_do_db&lt;/code&gt;: Specify which database to replicate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Restart MySQL after making changes:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl restart mysql
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 2: Create Replication User&lt;/h2&gt;
&lt;p&gt;On the master server, create a dedicated replication user:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE USER &apos;replica&apos;@&apos;%&apos; IDENTIFIED BY &apos;strong_password_here&apos;;
GRANT REPLICATION SLAVE ON *.* TO &apos;replica&apos;@&apos;%&apos;;
FLUSH PRIVILEGES;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 3: Get Master Status&lt;/h2&gt;
&lt;p&gt;Lock the database and note the master status:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;FLUSH TABLES WITH READ LOCK;
SHOW MASTER STATUS;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You&apos;ll see output like:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 | 154      | production_db|                  |
+------------------+----------+--------------+------------------+
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Important&lt;/strong&gt;: Note the File and Position values - you&apos;ll need them for slave configuration.&lt;/p&gt;
&lt;h2&gt;Step 4: Export Data from Master&lt;/h2&gt;
&lt;p&gt;If you have existing data, export it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mysqldump -u root -p --databases production_db &gt; master_backup.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After the export completes, unlock the tables:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;UNLOCK TABLES;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 5: Configure Slave Server&lt;/h2&gt;
&lt;p&gt;Edit the MySQL configuration on the slave server:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add these lines:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ini&quot;&gt;[mysqld]
server-id = 2
relay-log = /var/log/mysql/mysql-relay-bin.log
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = production_db
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Restart MySQL:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo systemctl restart mysql
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 6: Import Data to Slave&lt;/h2&gt;
&lt;p&gt;If you exported data from master:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mysql -u root -p &amp;#x3C; master_backup.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 7: Start Replication&lt;/h2&gt;
&lt;p&gt;On the slave server, configure the master connection:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CHANGE MASTER TO
  MASTER_HOST=&apos;master_ip_address&apos;,
  MASTER_USER=&apos;replica&apos;,
  MASTER_PASSWORD=&apos;strong_password_here&apos;,
  MASTER_LOG_FILE=&apos;mysql-bin.000001&apos;,
  MASTER_LOG_POS=154;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Start the slave:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;START SLAVE;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 8: Verify Replication&lt;/h2&gt;
&lt;p&gt;Check the slave status:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SHOW SLAVE STATUS\G
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Look for these indicators of successful replication:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Slave_IO_Running: Yes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Slave_SQL_Running: Yes&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Seconds_Behind_Master: 0&lt;/code&gt; (or a small number)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Testing Replication&lt;/h2&gt;
&lt;p&gt;Create a test table on the master:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;USE production_db;
CREATE TABLE test_replication (
    id INT PRIMARY KEY,
    message VARCHAR(100)
);

INSERT INTO test_replication VALUES (1, &apos;Replication is working!&apos;);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Check the slave:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;USE production_db;
SELECT * FROM test_replication;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you see the data, congratulations! Replication is working.&lt;/p&gt;
&lt;h2&gt;Monitoring and Maintenance&lt;/h2&gt;
&lt;h3&gt;Key Metrics to Monitor&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Replication Lag&lt;/strong&gt;: &lt;code&gt;Seconds_Behind_Master&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Slave Status&lt;/strong&gt;: Both IO and SQL threads should be running&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Binary Log Size&lt;/strong&gt;: Monitor disk space usage&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Connection Status&lt;/strong&gt;: Ensure slave can reach master&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;Common Issues and Solutions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Issue: Slave_IO_Running: No&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check network connectivity&lt;/li&gt;
&lt;li&gt;Verify replication user credentials&lt;/li&gt;
&lt;li&gt;Check firewall rules&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Issue: Replication Lag&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Check slave server resources (CPU, memory, disk I/O)&lt;/li&gt;
&lt;li&gt;Consider using semi-synchronous replication&lt;/li&gt;
&lt;li&gt;Review long-running queries&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Best Practices&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Use Dedicated Replication User&lt;/strong&gt;: Don&apos;t use root for replication&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Monitor Regularly&lt;/strong&gt;: Set up alerts for replication issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test Failover&lt;/strong&gt;: Regularly test your failover procedures&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Secure Connections&lt;/strong&gt;: Use SSL for replication traffic&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Backup Binary Logs&lt;/strong&gt;: Keep backups of binary logs&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Document Configuration&lt;/strong&gt;: Maintain documentation of your setup&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;You now have a working MySQL master-slave replication setup! This configuration provides data redundancy and can help with read load distribution.&lt;/p&gt;
&lt;h3&gt;Next Steps&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Set up monitoring using tools like MySQL Workbench or Prometheus&lt;/li&gt;
&lt;li&gt;Implement automatic failover with MySQL Router or ProxySQL&lt;/li&gt;
&lt;li&gt;Consider setting up semi-synchronous replication for better durability&lt;/li&gt;
&lt;li&gt;Explore multi-source replication for complex scenarios&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Additional Resources&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.mysql.com/doc/refman/8.0/en/replication.html&quot;&gt;MySQL Replication Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.mysql.com/products/enterprise/high_availability.html&quot;&gt;MySQL High Availability Solutions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.percona.com/software/mysql-database/percona-xtradb-cluster&quot;&gt;Percona XtraDB Cluster&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Happy replicating! 🚀&lt;/p&gt;</content:encoded><h:img src="/_astro/hero-banner.CyNu2jC_.png"/><enclosure url="/_astro/hero-banner.CyNu2jC_.png"/></item><item><title>Java Spring Boot Docker Deployment with Oracle Made Simple</title><link>https://krishanchawla.com/blog/java-spring-boot-docker-deployment-with-oracle-made-simple</link><guid isPermaLink="true">https://krishanchawla.com/blog/java-spring-boot-docker-deployment-with-oracle-made-simple</guid><description>Learn how to setup docker deployment of your Java Spring Boot application including Oracle Database dependency easily.</description><pubDate>Wed, 19 Mar 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In today’s DevOps-driven world, containerization has become a crucial aspect of deploying applications efficiently. Docker enables developers to package applications along with their dependencies, ensuring seamless deployment across different environments.&lt;/p&gt;
&lt;p&gt;In this blog, we will walk through the step-by-step process of deploying a Java Spring Boot application on Docker with Oracle Database, including how to tackle the challenge of downloading the OJDBC driver, which is not available through Maven.&lt;/p&gt;
&lt;h2&gt;Why Use Docker for Java Spring Boot Applications?&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Consistency:&lt;/strong&gt; Ensures the application runs the same way across different environments.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scalability:&lt;/strong&gt; Containers can be easily scaled using tools like Kubernetes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Isolation:&lt;/strong&gt; Each application runs in an isolated environment, avoiding dependency conflicts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Efficiency:&lt;/strong&gt; Docker containers are lightweight and resource-efficient compared to VMs.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;Prerequisites:&lt;/h2&gt;
&lt;p&gt;Before getting started, ensure you have the following installed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Java JDK 17+&lt;/li&gt;
&lt;li&gt;Spring Boot Application (Maven/Gradle)&lt;/li&gt;
&lt;li&gt;Docker (Installed and running)&lt;/li&gt;
&lt;li&gt;Oracle Database (Running in Docker or accessible remotely)&lt;/li&gt;
&lt;li&gt;OJDBC Jar (Manually downloaded from &lt;a href=&quot;https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html&quot;&gt;Oracle website&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Basic knowledge of Docker and Spring Boot&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Step 1: Create a Simple Spring Boot Application&lt;/h2&gt;
&lt;p&gt;If you already have a Spring Boot project, skip this step. Otherwise, create a new one using &lt;em&gt;Spring Initializr&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl https://start.spring.io/starter.zip -d dependencies=web -o demo.zip
unzip demo.zip -d demo
cd demo
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ensure your &lt;em&gt;pom.xml&lt;/em&gt; has the following dependencies:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;#x3C;dependency&gt;
	&amp;#x3C;groupId&gt;org.springframework.boot&amp;#x3C;/groupId&gt;
	&amp;#x3C;artifactId&gt;spring-boot-strarter-web&amp;#x3C;artifactId&gt;
&amp;#x3C;/dependency&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create a simple REST controller in &lt;code&gt;/src/main/java/com/example/demo/HelloController.java&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;@RestController
@RequestMapping(“/api”)
Public class HelloController {

	@GetMapping(“helloWorld”)
	public String sayHello() {
		return “”Hello, Dockerized Spring Boot Application!”;
	}

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, build the application:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mvn clean package -DskipTests
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 2: Download and Add the Oracle JDBC Driver&lt;/h2&gt;
&lt;p&gt;Since Oracle’s JDBC driver is not available in public Maven repositories, you must download it manually from &lt;a href=&quot;https://www.oracle.com/database/technologies/appdev/jdbc-downloads.html&quot;&gt;Oracle JDBC Downloads page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Once downloaded, add it to your local Maven repository:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;mvn install:install \
	-Dfile=ojdbc8.jar \
	-DgroupId=com.oracle \
	-DartifactId=ojdbc8 \
	-Dversion=21.9.0.0 \
	-Dpackaging=jar
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then, include the dependency in your &lt;code&gt;pom.xml&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;#x3C;dependency&gt;
	&amp;#x3C;groupId&gt;com.oracle&amp;#x3C;/groupId&gt;
	&amp;#x3C;artifactId&gt;ojdbc8&amp;#x3C;/artifactId&gt;
	&amp;#x3C;version&gt;21.9.0.0&amp;#x3C;/version&gt;
&amp;#x3C;/dependency&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 3: Create a Dockerfile&lt;/h2&gt;
&lt;p&gt;A Dockerfile defines the environment needed to run your application. Create a Dockerfile in the project root:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Use an official OpenJDK runtime as base image
FROM openjdk:17-jdk-slim

# Set working directory in container
WORKDIR /app

# Copy JAR file into the container
COPY target/demo-0.0.1-SNAPSHOT.jar app.jar 

# Expose the port the app runs on
EXPOSE 8080

# Run the application
CMD [“java”, “”-jar, “app.jar”]
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Step 4: Build and Run the Docker Container&lt;/h2&gt;
&lt;p&gt;Now, build your Docker image:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Docker build -t my-spring-app .
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run the container:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Docker run -d -p 8080:8080 —name spring-app my-spring-app
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Verify that the application is running by opening your browser and visiting:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;http://localhost:8080/api/hello&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Step 5: Run Oracle Database in a Docker Container&lt;/h2&gt;
&lt;p&gt;To run an Oracle Database instance in Docker, use:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;Docker run -d —name oracle-test \
	-p 1521:1521 \
	-e ORACLE_SID=ORCL \
	-e ORACLE_PBD=ORCLPDB1 \
	-e ORACLE_PWD=admin123 \
	container-registry.oracle.com/database/enterprise:latest
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Update your &lt;em&gt;application.properties&lt;/em&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;spring.datasource.url=jdbc:oracle:thin:@//oracle-db:1521/ORCLPDB1
spring.datasource.username=system
spring.datasource.password=admin123
spring.datasource.driver-class-name=oracle.jdbc.OracleDriver
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ensure both services are running on the same Docker network:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;docker network create mynetwork
docker network connect mynetwork spring-app
docker network connect mynetwork oracle-db
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;By following this guide, you have successfully Dockerized a Java Spring Boot application, connected it to an Oracle database using Docker, and resolved the OJDBC download challenge.&lt;/p&gt;
&lt;h2&gt;Key Takeaways&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Docker ensures portability and scalability for Java applications.&lt;/li&gt;
&lt;li&gt;Using Docker Compose simplifies multi-container deployment.&lt;/li&gt;
&lt;li&gt;Overcoming OJDBC driver challenges is possible with manual integration.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><h:img src="/_astro/hero-banner.D3qvwIjM.png"/><enclosure url="/_astro/hero-banner.D3qvwIjM.png"/></item><item><title>Oracle XE In Docker On Windows: An Ultimate Guide</title><link>https://krishanchawla.com/blog/ultimate-guide-to-setting-up-oracle-xe-in-docker-on-windows</link><guid isPermaLink="true">https://krishanchawla.com/blog/ultimate-guide-to-setting-up-oracle-xe-in-docker-on-windows</guid><description>Learn how to set up Oracle XE on Windows using Docker. Follow this step-by-step guide to create a local database environment and streamline development.</description><pubDate>Wed, 25 Dec 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Setting up Oracle XE in your local development environment can significantly speed up application development by giving you a powerful relational database to work with. This guide provides a straightforward approach to setting up Oracle XE using Docker on a Windows system, followed by creating a schema to start your development journey.&lt;/p&gt;
&lt;h2&gt;Why Use Oracle XE with Docker for Local Development?&lt;/h2&gt;
&lt;p&gt;Oracle XE is a lightweight, free version of Oracle Database that caters to the needs of developers and small-scale applications. Running it in Docker adds the benefit of containerization, allowing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Easy setup and cleanup.&lt;/li&gt;
&lt;li&gt;Isolation from your host environment.&lt;/li&gt;
&lt;li&gt;Seamless portability across systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;Before we dive into the setup, ensure you have the following installed on your Windows machine:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Docker Desktop: &lt;a href=&quot;https://www.docker.com/products/docker-desktop/&quot;&gt;Download and install Docker.&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Windows Subsystem for Linux (WSL): Enable WSL if not already configured.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/docker-desktop.BHw5u08C_DVOpo.webp&quot; alt=&quot;Docker Desktop&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Containerize An Oracle Database&lt;/h2&gt;
&lt;h3&gt;Step 1: Pull the Oracle XE Docker Image&lt;/h3&gt;
&lt;p&gt;The first step is to pull the Oracle XE Docker image from Oracle’s repository or Docker Hub. Open a terminal and run:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/docker-pull.CMAqQuWJ_ZzEF5w.webp&quot; alt=&quot;Docker Pull Oracle&quot;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker pull container-registry.oracle.com/database/express:21.3.0-xe
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This command downloads the Oracle XE 21c image to your local system.&lt;/p&gt;
&lt;h3&gt;Step 2: Run the Oracle XE Container&lt;/h3&gt;
&lt;p&gt;Create and run a Docker container using the image you just pulled. Execute the following command:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/docker-create-container.YTeU3mfm_rc18p.webp&quot; alt=&quot;Create a Docker Container&quot;&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker container create `
   -it ` # Run the container in interactive mode
   --name [container-name] `  # Name of the container
   -p [host-port]:1521 `  # Map the port from host to container for DB
   -e ORACLE_PWD=[custom-pass] `  # Password for default user
   container-registry.oracle.com/database/express:[version]  # Image
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Explanation:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;--name oracle-xe-container:&lt;/em&gt; Names your container for easier reference.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;-p 1521:1521:&lt;/em&gt; Maps the database’s port to your local machine.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;-e ORACLE_PWD=your_password_here:&lt;/em&gt; Sets the password for the default SYS and SYSTEM users.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After running the command, Oracle XE will initialize inside the container. It may take a few minutes to start up.&lt;/p&gt;
&lt;h3&gt;Step 3: Verify the Container is Running&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/docker-container-status.B0OPFaxR_Zv5Do4.webp&quot; alt=&quot;Docker Container Status&quot;&gt;&lt;/p&gt;
&lt;p&gt;To ensure the Oracle XE container is up and running, execute:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker ps
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Look for a container named &lt;strong&gt;oracle-xe-container&lt;/strong&gt; in the list. If it’s not running, check the logs for any issues:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker logs oracle-xe-container
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 4: Connect to the Oracle XE Database&lt;/h3&gt;
&lt;p&gt;You can connect to Oracle XE using any database client, such as SQL*Plus or Oracle SQL Developer. Use the following connection details:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Host:&lt;/strong&gt; localhost&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Port:&lt;/strong&gt; 1521&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service Name:&lt;/strong&gt; XEPDB1&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Username:&lt;/strong&gt; SYS&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Password:&lt;/strong&gt; The password you set with ORACLE_PWD&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Role:&lt;/strong&gt; SYSDBA&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Oracle XE database container should be up and running now. Once the database is accessible, we need to create schema.&lt;/p&gt;
&lt;h2&gt;Create an Oracle XE Schema&lt;/h2&gt;
&lt;h3&gt;Step 1: Access the Oracle Database Container&lt;/h3&gt;
&lt;p&gt;First, connect to the running container:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;docker exec -it &amp;#x3C;container_name_or_id&gt; bash 
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/docker-exec-container.BeDGsBAW_mQhUg.webp&quot; alt=&quot;Docker Execute Container&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Step 2: Log in to SQL*Plus&lt;/h3&gt;
&lt;p&gt;Inside the container, use the sqlplus utility to log in as the default database user (e.g., &lt;em&gt;SYS&lt;/em&gt; or &lt;em&gt;SYSTEM&lt;/em&gt;):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sqlplus SYS/&amp;#x3C;password&gt;@localhost/XEPDB1 as sysdba
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;&amp;#x3C;password&gt;&lt;/code&gt; with the SYS password you provided when running the container. XEPDB1 is the default pluggable database name for Oracle XE.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/sqlplus-connet.BefSa6Ff_QmW6V.webp&quot; alt=&quot;SQL Plus Connectivity&quot;&gt;&lt;/p&gt;
&lt;h3&gt;Step 3: Create a New User (Schema)&lt;/h3&gt;
&lt;p&gt;A schema in Oracle is effectively a user. To create one:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;CREATE USER your_schema_name IDENTIFIED BY your_password;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 4: Grant Privileges to the User&lt;/h3&gt;
&lt;p&gt;To allow the user to connect to the database and create objects:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;GRANT CONNECT, RESOURCE TO your_schema_name;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Optionally, you can grant additional privileges as needed, such as:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;GRANT DBA TO your_schema_name;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 5: Connect to the New Schema&lt;/h3&gt;
&lt;p&gt;Exit SQL*Plus by typing exit, and log back in as the new user:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sqlplus your_schema_name/your_password@localhost/XEPDB1
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Step 6: Test the Schema&lt;/h3&gt;
&lt;p&gt;You can now create tables and other objects in the new schema:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;CREATE TABLE Test (
    id NUMBER PRIMARY KEY,
    name VARCHAR2(100)
);
&lt;/code&gt;&lt;/pre&gt;</content:encoded><h:img src="/_astro/hero-banner.mgrudWxv.png"/><enclosure url="/_astro/hero-banner.mgrudWxv.png"/></item><item><title>Instrument JaCoCo Code Coverage agent with WebLogic</title><link>https://krishanchawla.com/blog/quickly-instrument-jacoco-agent-with-weblogic</link><guid isPermaLink="true">https://krishanchawla.com/blog/quickly-instrument-jacoco-agent-with-weblogic</guid><description>Learn how to instrument JaCoCo code coverage agent with WebLogic server.</description><pubDate>Sat, 18 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;JaCoCo is an open-source library created by the EclEmma team for measuring and reporting code coverage in an application.
It is quite popular among the variety of code coverage libraries for Java out there.
If you wish to setup JaCoCo with Maven, you can go through my previous blog which provides a detailed &lt;a href=&quot;/blog/setup-jacoco-code-coverage-with-maven&quot;&gt;Guide to setup JacoCo Code Coverage Tool with Maven.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In this blog, we will be talking about how to set up a JaCoCo agent on the WebLogic server. To get started, we have a sample License Eligibility Checker application.&lt;/p&gt;
&lt;h2&gt;Sample Application&lt;/h2&gt;
&lt;p&gt;For demonstration, we are going to use a simple License Eligibility Checker application consisting of a UI that prints if the user is eligible for a license or not based on the provided age.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/license-eligibility-checker-sample-app.Jsex0B25_1NzlVG.webp&quot; alt=&quot;License Eligibility Application&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Integrating Jacoco Agent with WebLogic Server&lt;/h2&gt;
&lt;p&gt;JaCoCo uses class file instrumentation to record the coverage data against the test execution. Class files are instrumented on the fly using a so-called Java agent. When a Java agent is attached to the JVM, the agent can see when the class file is called and what lines are executed.&lt;/p&gt;
&lt;h4&gt;Download the latest JaCoCo distribution from JaCoCo’s official website&lt;/h4&gt;
&lt;p&gt;https://www.eclemma.org/jacoco/index.html&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/jacoco-official-website.uT76kBEL_gHnRO.webp&quot; alt=&quot;JaCoCo official website&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Extract the JaCoCo Distribution file&lt;/h4&gt;
&lt;p&gt;Once downloaded, extract the downloaded JaCoCo distribution zip file. You will be able to see multiple JAR’s in the lib folder inside the extracted distribution, which we will be needing in further steps.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/jacoco-extracted-zip.D-2ADeiz_2f7h90.webp&quot; alt=&quot;Extracted Jacoco distribution file&quot;&gt;&lt;/p&gt;
&lt;h4&gt;Move the JaCoCo distribution under WebLogic&lt;/h4&gt;
&lt;p&gt;Create a new directory inside &lt;code&gt;&amp;#x3C;WEBLOGIC_HOME&gt;/user_projects/domains/&amp;#x3C;DOMAIN_DIRECTORY&gt;/&lt;/code&gt; named &lt;strong&gt;jacoco&lt;/strong&gt;. Copy the &lt;strong&gt;jacocoagent.jar&lt;/strong&gt;, &lt;strong&gt;jacocoant.jar&lt;/strong&gt;, and &lt;strong&gt;jacococli.jar&lt;/strong&gt; inside the newly-created directory.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please Note -&lt;/strong&gt; Creating the jacoco directory inside the above provided path is not mandatory. You can create the directory anywhere according to your convivence. I generally prefer the above path for better maintenance.&lt;/p&gt;
&lt;h4&gt;Attach JaCoCo Agent to JVM&lt;/h4&gt;
&lt;p&gt;We now need to attach the JaCoCo agent with WebLogic JVM. To attach the JaCoCo agent, add the below argument to &lt;strong&gt;setDomainEnv.sh (For Linux) / setDomainEnv.cmd (For Windows)&lt;/strong&gt; file available inside &lt;code&gt;&amp;#x3C;WEBLOGIC_HOME&gt;/user_projects/domains/&amp;#x3C;DOMAIN_DIRECTORY&gt;/bin/&lt;/code&gt; directory.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;set JAVA_OPTIONS=-javaagent:PATH_TO_JACOCO_AGENT_JAR/jacocoagent.jar=destfile=PATH_TO_GENERATE_JACOCO_EXEC_FILE/jacoco.exec,output=file,append=false
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;JaCoCo agent is successfully attached to JVM now. When we start the WebLogic server, there should be a jacoco.exec file generated at the provided destination file path.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Please Note –&lt;/strong&gt; The size of jacoco.exec file is zero initially. On successful WebLogic server shutdown, the Jacoco agent appends the coverage data to an already created binary file.&lt;/p&gt;
&lt;h2&gt;Convert JaCoCo Binary to HTML report&lt;/h2&gt;
&lt;p&gt;The Java agent generates a Binary file that is not human readable. The file cannot be singlehandedly interpreted. In order to convert the generated binary file (jacoco.exec) we will utilize jacococli.jar. In order to generate the HTML report, perform the following steps:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1 –&lt;/strong&gt; Create a new directory inside the jacoco directory which we previously created with name ‘reports’. We will utilize this folder to generate the HTML report.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2 –&lt;/strong&gt; Execute the following jacococli.jar with parameters:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;java -jar PATH_TO_JACOCO_DIRECTORY/jacococli.jar report jacoco.exec --classfiles PATH_TO_APPLICATION_CLASS_FILES --html PATH_TO_HTML_REPORT_DIRECTORY
&lt;/code&gt;&lt;/pre&gt;</content:encoded><h:img src="/_astro/hero-banner.CZMiUFoq.png"/><enclosure url="/_astro/hero-banner.CZMiUFoq.png"/></item><item><title>JaCoCo Code Coverage Setup with Maven</title><link>https://krishanchawla.com/blog/setup-jacoco-code-coverage-with-maven</link><guid isPermaLink="true">https://krishanchawla.com/blog/setup-jacoco-code-coverage-with-maven</guid><description>Step-by-step guide to integrate JaCoCo code coverage tool with Maven for measuring and improving test coverage in Java projects.</description><pubDate>Sat, 11 May 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;JaCoCo is an open-source library created by the EclEmma team for measuring and reporting code coverage in an application. It is quite popular among the variety of code coverage libraries for Java out there.&lt;/p&gt;
&lt;p&gt;In this blog, we will be talking about how to set up JaCoCo with Maven Project. To understand JaCoCo’s code coverage capabilities, we need to have a code sample.&lt;/p&gt;
&lt;h2&gt;Sample Maven Project&lt;/h2&gt;
&lt;p&gt;Here, we are going to use a simple class named ‘LicensingService’ consisting of a simple Java Function that prints if the user is eligible for a license or not based on the provided age and ‘LicensingServiceTest’ consisting of Unit Tests.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class LicensingService {

    public void eligibilityChecker(int age) {
         System.out.println(&quot;User Provided Age: &quot; + age);
         if (age &gt;= 18) {
              System.out.println(&quot;You are eligible to apply for license&quot;);     
         } else {
              System.out.println(&quot;Sorry, you are not eligible to apply for license&quot;);     
        }
    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/java-project-for-jacoco.CZlMFaRh_lUTPE.webp&quot; alt=&quot;Sample Project Code for JaCoCo&quot;&gt;&lt;/p&gt;
&lt;p&gt;Now, we need to add JUnit Tests against which the coverage will be generated.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;public class LicensingServiceTest {

     @Test
     public void licenseEligibilityChecker() {
          LicensingService licensingService = new LicensingService();
          licensingService.eligibilityChecker(18);
     }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Configuring Jacoco Maven Plugin&lt;/h2&gt;
&lt;p&gt;Now to configure Jacoco with the project, we need to declare this maven plugin in our pom.xml file:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;#x3C;build&gt;
    &amp;#x3C;plugins&gt;
        &amp;#x3C;plugin&gt;
            &amp;#x3C;groupId&gt;org.jacoco&amp;#x3C;/groupId&gt;
            &amp;#x3C;artifactId&gt;jacoco-maven-plugin&amp;#x3C;/artifactId&gt;
            &amp;#x3C;executions&gt;
                &amp;#x3C;execution&gt;
                    &amp;#x3C;goals&gt;
                        &amp;#x3C;goal&gt;prepare-agent&amp;#x3C;/goal&gt;
                    &amp;#x3C;/goals&gt;
                &amp;#x3C;/execution&gt;
                &amp;#x3C;execution&gt;
                    &amp;#x3C;id&gt;report&amp;#x3C;/id&gt;
                    &amp;#x3C;phase&gt;prepare-package&amp;#x3C;/phase&gt;
                    &amp;#x3C;goals&gt;
                        &amp;#x3C;goal&gt;report&amp;#x3C;/goal&gt;
                    &amp;#x3C;/goals&gt;
                &amp;#x3C;/execution&gt;
            &amp;#x3C;/executions&gt;
        &amp;#x3C;/plugin&gt;
    &amp;#x3C;/plugins&gt;
&amp;#x3C;/build&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The JaCoCo Java agent will collect coverage information when maven-surefire-plugin runs the tests. It will write it to &lt;code&gt;target/jacoco.exec&lt;/code&gt; by default. &lt;a href=&quot;https://www.eclemma.org/jacoco/trunk/doc/prepare-agent-mojo.html&quot;&gt;Read more&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Executing the Tests and Creating the Coverage Reports&lt;/h2&gt;
&lt;p&gt;Execute the Tests using &lt;code&gt;mvn clean test&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;On execution of tests, Jacoco agent will automatically instrument to the code, thus, it will create a coverage report in binary format in the target directory – &lt;code&gt;target/jacoco.exec&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The generated report can further be interpreted through two different ways.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#interactive-intellij-report&quot;&gt;Display Interactive Report in IntelliJ&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#binary-html-report&quot;&gt;Interpret Binary Report to HTML format&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt; 1. Display Interactive Report in IntelliJ&lt;/h2&gt;
&lt;p&gt;IntelliJ provides an interactive coverage interface that can be utilized to analyze line-by-line coverage of complete code. The &lt;em&gt;jacoco.exec&lt;/em&gt; binary file generated after the execution of tests can simply be accessed in the IntelliJ Coverage window using the below steps.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 1&lt;/em&gt; – Click on Run -&gt; Show Coverage Data. [Shortcut : Ctrl + Alt + F6]&lt;/p&gt;
&lt;p&gt;A new Coverage Suite Dialog box will appear.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/intellij-show-code-coverage-data.3OAdzjIn_ZNbhUA.webp&quot; alt=&quot;Show Code Coverage Data in IntelliJ&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Step 2&lt;/em&gt; – Click on (+) add button in the Coverage Suite Dialog box. Select the jacoco.exec binary file and click Show Selected.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/intellij-show-code-coverage-data-jacoco-file-selector.C_YfgKoZ_MV1YA.webp&quot; alt=&quot;Show Code Coverage Data in IntelliJ Jacoco File Selector&quot;&gt;&lt;/p&gt;
&lt;p&gt;You will now be able to view the line-by-line coverage.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/intellij-jacoco-interactive-report.9c804wpZ_1tfVTL.webp&quot; alt=&quot;Interactive Jacoco Report in IntelliJ&quot;&gt;&lt;/p&gt;
&lt;h2&gt; 2. Interpret Binary Report to HTML format&lt;/h2&gt;
&lt;p&gt;The generated jacoco.exec can be interpreted to the HTML, CSV, XML Report format which is human readable. To achieve this, we can simply run the below maven command.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;bash mvn jacoco:report&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Please Note:&lt;/em&gt; This step can be completely avoided by adding the above goal during the test execution itself.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Example: mvn clean test jacoco:report&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;We can now take a look at the &lt;code&gt;target/site/jacoco/index.html&lt;/code&gt; page to see what the generated report looks like.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://krishanchawla.com/_astro/jacoco_code_coverage_html_report.DaGg7UGv_mMCWh.webp&quot; alt=&quot;JaCoCo HTML Based Report&quot;&gt;&lt;/p&gt;</content:encoded><h:img src="/_astro/hero-banner.HdyowiqI.png"/><enclosure url="/_astro/hero-banner.HdyowiqI.png"/></item><item><title>Automate MySQL Database Backups on Linux</title><link>https://krishanchawla.com/blog/automate-mysql-backups-on-linux</link><guid isPermaLink="true">https://krishanchawla.com/blog/automate-mysql-backups-on-linux</guid><description>Learn how to automate MySQL database backups on Linux using a simple shell script. Ensure your data is safe and secure with scheduled backups.</description><pubDate>Tue, 30 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Ensuring the safety and security of your MySQL databases is crucial for any business. Regular MySQL database backups are a key component of a solid data protection strategy. In this blog, I’ll show you how to automate MySQL database backups on Linux using a simple shell script.&lt;/p&gt;
&lt;h2&gt;STEP 1: Create a Backup Shell Script&lt;/h2&gt;
&lt;p&gt;First, create a new shell script named mysql_backup_script.sh and add the following content:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/bin/bash

# MySQL database credentials
DB_USER=&quot;&amp;#x3C;DB_USER&gt;&quot;
DB_PASS=&quot;&amp;#x3C;DB_PASSWORD&gt;&quot;
DB_NAME=&quot;&amp;#x3C;DB_NAME&gt;&quot;

# Backup directory
BACKUP_DIR=&quot;&amp;#x3C;path/to/backup/directory&gt;&quot;

# Backup file name
BACKUP_FILE=&quot;$BACKUP_DIR/$DB_NAME-$(date +%Y%m%d%H%M%S).sql&quot;

# Dump the MySQL database
mysqldump --user=$DB_USER --password=$DB_PASS $DB_NAME &gt; $BACKUP_FILE

# Optional: Compress the backup file
# gzip $BACKUP_FILE
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Replace &lt;code&gt;&amp;#x3C;DB_USER&gt;&lt;/code&gt;, &lt;code&gt;&amp;#x3C;DB_PASSWORD&gt;&lt;/code&gt;, &lt;code&gt;&amp;#x3C;DB_NAME&gt;&lt;/code&gt;, and &lt;code&gt;&amp;#x3C;path/to/backup/directory&gt;&lt;/code&gt; with your actual MySQL credentials, database name, and backup directory path.&lt;/p&gt;
&lt;h2&gt;Step 2: Configure executable permissions for the script&lt;/h2&gt;
&lt;p&gt;Add the executable permissions to the script file by running:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;chmod +x mysql_backup.sh&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Step 3: Schedule the MySQL database Backups&lt;/h2&gt;
&lt;p&gt;Schedule the backup script to run automatically on a specified time using cron. Open your crontab file by running:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;crontab -e&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Add the following line to schedule the backup to run daily at midnight:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;0 0 * * * /path/to/mysql_backup_script.sh&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Replace &lt;code&gt;/path/to/mysql_backup_script.sh&lt;/code&gt; with the actual path to your backup script.&lt;/p&gt;
&lt;p&gt;You can utilize the following &lt;a href=&quot;https://crontab.guru/&quot;&gt;reference&lt;/a&gt;, if you wish to configure different schedule for your backup.&lt;/p&gt;</content:encoded><h:img src="/_astro/hero-banner.Dy7jNV2v.png"/><enclosure url="/_astro/hero-banner.Dy7jNV2v.png"/></item><item><title>How to download maven dependencies behind organization proxy</title><link>https://krishanchawla.com/blog/maven-dependencies-behind-proxy</link><guid isPermaLink="true">https://krishanchawla.com/blog/maven-dependencies-behind-proxy</guid><description>A quick guide on how to download Maven dependencies behind your organization’s proxy.</description><pubDate>Wed, 10 Apr 2024 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;Whether you’re a Software Developer or an Automation Engineer, Maven is a widely used build tool today. One common challenge in some environments is the inability to download Maven dependencies due to organizational proxies. In this article, I’ll share a quick guide on how to download Maven dependencies behind your organization’s proxy.&lt;/p&gt;
&lt;h2&gt;Proxy Configuration&lt;/h2&gt;
&lt;p&gt;Let’s understand how to setup proxy configuration. This configuration can be done in settings.xml file.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open your settings.xml file located in &lt;code&gt;&amp;#x3C;user_home&gt;/.m2&lt;/code&gt; directory. If the file does not exist, you can create it.&lt;/li&gt;
&lt;li&gt;Add the following &lt;code&gt;&amp;#x3C;proxies&gt;&lt;/code&gt; configuration inside the &lt;code&gt;&amp;#x3C;settings&gt;&lt;/code&gt; element, replacing proxy.example.com and 8080 with your server’s hostname and port:&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;&amp;#x3C;proxies&gt;
    &amp;#x3C;proxy&gt;
        &amp;#x3C;id&gt;example-proxy&amp;#x3C;/id&gt;
        &amp;#x3C;active&gt;true&amp;#x3C;/active&gt;
        &amp;#x3C;protocol&gt;http&amp;#x3C;/protocol&gt;
        &amp;#x3C;host&gt;proxy.example.com&amp;#x3C;/host&gt;
        &amp;#x3C;port&gt;8080&amp;#x3C;/port&gt;
        &amp;#x3C;!-- Optional: Proxy username and password --&gt;
        &amp;#x3C;!--&amp;#x3C;username&gt;proxy-username&amp;#x3C;/username&gt;--&gt;
        &amp;#x3C;!--&amp;#x3C;password&gt;proxy-password&amp;#x3C;/password&gt;--&gt;
        &amp;#x3C;!--&amp;#x3C;nonProxyHosts&gt;localhost|127.0.0.1&amp;#x3C;/nonProxyHosts&gt;--&gt;
    &amp;#x3C;/proxy&gt;
&amp;#x3C;/proxies&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If your organization requires authentication, uncomment the &lt;code&gt;&amp;#x3C;username&gt;&lt;/code&gt; and &lt;code&gt;&amp;#x3C;password&gt;&lt;/code&gt; tags and provide your credentials. Additionally, you can specify hosts that should bypass the proxy in the &lt;code&gt;&amp;#x3C;nonProxyHosts&gt;&lt;/code&gt; tag.&lt;/p&gt;
&lt;h2&gt;Test the Configuration:&lt;/h2&gt;
&lt;p&gt;To test the proxy configuration, run a Maven command such as mvn clean install for a Maven project. Maven should now be able to download dependencies through the proxy.&lt;/p&gt;</content:encoded><h:img src="/_astro/hero-banner.CZy6VbyU.png"/><enclosure url="/_astro/hero-banner.CZy6VbyU.png"/></item></channel></rss>