<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Mehuli Mukherjee</title>
    <description>The latest articles on Forem by Mehuli Mukherjee (@mehulimukherjee).</description>
    <link>https://forem.com/mehulimukherjee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3098123%2F2e445d4a-3883-4642-9f76-2effd7c0eee8.png</url>
      <title>Forem: Mehuli Mukherjee</title>
      <link>https://forem.com/mehulimukherjee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/mehulimukherjee"/>
    <language>en</language>
    <item>
      <title>The Java PDF Table Extraction Library You’ve Been Waiting For..</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Tue, 06 Jan 2026 22:31:32 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/the-java-pdf-table-extraction-library-youve-been-waiting-for-4khh</link>
      <guid>https://forem.com/mehulimukherjee/the-java-pdf-table-extraction-library-youve-been-waiting-for-4khh</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rz5a02arfbu8hgc3i6j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rz5a02arfbu8hgc3i6j.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/shorts/hE0zcv1G2W4" rel="noopener noreferrer"&gt;Watch the YouTube video&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Extracting structured data from PDFs has always been one of the most frustrating parts of working with document-centric data pipelines. Whether you’re automating financial reporting, processing invoices, auditing bank statements, or building analytics systems, the challenge is always the same:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How do you reliably get clean, structured tabular data out of PDFs — including scanned and image-based documents — in Java?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Today, I’am excited to introduce ExtractPDF4J 2.0, a major release that brings robust, hybrid PDF table extraction to the Java ecosystem — for both text-based and scanned PDFs — with enterprise-ready features, multiple parsing strategies, and a simple API.&lt;/p&gt;

&lt;h2&gt;
  
  
  GitHub Repo :
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ExtractPDF4J/ExtractPDF4J" rel="noopener noreferrer"&gt;https://github.com/ExtractPDF4J/ExtractPDF4J&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;"Star the repo for more reach"&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  READMe for Details: How it works!
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/ExtractPDF4J/ExtractPDF4J/blob/main/README.md" rel="noopener noreferrer"&gt;https://github.com/ExtractPDF4J/ExtractPDF4J/blob/main/README.md&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why PDF Table Extraction is Hard&lt;/strong&gt;&lt;br&gt;
PDF files are notoriously difficult to work with because they were never designed as data containers. In contrast to e.g. CSV or Excel, PDF:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Has no explicit table metadata.&lt;/li&gt;
&lt;li&gt;Often stores text as independent glyphs without semantic structure.&lt;/li&gt;
&lt;li&gt;May contain tables spread across pages, inconsistent formats, or mixed text + graphics.&lt;/li&gt;
&lt;li&gt;Scanned PDFs have no text layer at all — requiring OCR.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Traditional Java tools like Apache PDFBox can extract text, and Tabula-Java can identify tables, but they struggle with scanned images, complex layouts, and multi-strategy extraction. ExtractPDF4J 2.0 addresses this gap natively in Java — no Python, no external wrappers.&lt;/p&gt;

&lt;h2&gt;
  
  
  What ExtractPDF4J Offers
&lt;/h2&gt;

&lt;p&gt;ExtractPDF4J 2.0 is a production-grade Java library that brings together multiple extraction strategies under one roof:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;StreamParser — For text-based PDFs, leveraging PDF text coordinates.&lt;/li&gt;
&lt;li&gt;LatticeParser — For PDFs with grid lines or structured outlines.&lt;/li&gt;
&lt;li&gt;OcrStreamParser — For image or scanned PDFs with OCR support.&lt;/li&gt;
&lt;li&gt;HybridParser — Combines all approaches to maximize extraction quality.
This hybrid strategy gives developers both accuracy and robustness regardless of PDF type.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Key Features in Version 2.0:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Hybrid Parsing Out of the Box
ExtractPDF4J’s HybridParser intelligently combines:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Text analysis (for digital PDFs),&lt;/li&gt;
&lt;li&gt;Structural grid detection (lattice),&lt;/li&gt;
&lt;li&gt;OCR fallback for image PDFs.
This is crucial for real-world workflows where documents often come in mixed forms.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Native OCR Support&lt;br&gt;
Unlike many Java libraries, ExtractPDF4J includes native OCR integration (via Tesseract/OpenCV) — no separate Python service required. Configure the DPI and OCR mode and get accurate text from scanned documents.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple API &amp;amp; Annotation Configuration&lt;br&gt;
Whether you prefer quick code snippets or declarative configuration, ExtractPDF4J supports both:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List&amp;lt;Table&amp;gt; tables = new HybridParser("scanned_invoice.pdf")
 .dpi(300f)
 .parse();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or use annotated config classes for reusable parsers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;CLI and Microservice Support
2.0 also includes:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;A command-line interface for bulk extraction jobs.&lt;/li&gt;
&lt;li&gt;A Docker-ready microservice exposing a REST endpoint.
This makes ExtractPDF4J a great choice for automation, batch processing, and cloud deployments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How ExtractPDF4J Compares
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vxo335hy3u3fmavwsc1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vxo335hy3u3fmavwsc1.png" alt=" " width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That means if you need &lt;strong&gt;high-quality&lt;/strong&gt;, &lt;strong&gt;reliable tabular extraction&lt;/strong&gt; — including scans and mixed documents — Java developers finally have a tool built for the job.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;p&gt;ExtractPDF4J 2.0 serves a range of workflows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Accounting &amp;amp; Finance Automation
Extract tables from bank statements, invoices, balance sheets, and regulatory filings.&lt;/li&gt;
&lt;li&gt;Data Engineering &amp;amp; ETL Pipelines
Integrate structured PDF extraction directly into JVM-based processing systems.&lt;/li&gt;
&lt;li&gt;Document Archiving and Analytics
Convert historical scanned documents into structured CSV/JSON for analytics.&lt;/li&gt;
&lt;li&gt;Compliance &amp;amp; Auditing Tools
Extract evidence tables for audit trails, tax filings, and compliance reports.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What’s Next
&lt;/h2&gt;

&lt;p&gt;2.0 lays a strong foundation. Going forward, ExtractPDF4J aims to expand on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enhanced machine-learning driven table layout detection&lt;/li&gt;
&lt;li&gt;Improved integration with JVM microservices&lt;/li&gt;
&lt;li&gt;More output formats (Excel, JSON/GraphQL directly)&lt;/li&gt;
&lt;li&gt;Cloud-native serverless workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;"Need Contribution for expansion"&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you’ve ever wrestled with extracting tables from PDFs — especially scanned or mixed documents — ExtractPDF4J 2.0 delivers the most comprehensive Java solution available today. With hybrid extraction strategies, OCR support, and flexible deployment options, it’s now easier than ever to convert messy PDFs into clean, structured data.&lt;/p&gt;

&lt;p&gt;Try it today. Build faster. Ship reliable data pipelines.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect with me:&lt;/strong&gt; &lt;a href="https://www.linkedin.com/posts/mehulimukherjee_java-opensource-pdf-activity-7414116558110769152-ti6T?utm_source=share&amp;amp;utm_medium=member_desktop&amp;amp;rcm=ACoAACoHKyYBphUYH2QNjvFcwRhmqwXc3y9Yg5U" rel="noopener noreferrer"&gt;https://www.linkedin.com/posts/mehulimukherjee_java-opensource-pdf-activity-7414116558110769152-ti6T?utm_source=share&amp;amp;utm_medium=member_desktop&amp;amp;rcm=ACoAACoHKyYBphUYH2QNjvFcwRhmqwXc3y9Yg5U&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>fintech</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Why Should Python have all the fun? Meet my new Java Library..</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Wed, 20 Aug 2025 05:00:28 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/why-should-python-have-all-the-fun-meet-my-new-java-library-18eo</link>
      <guid>https://forem.com/mehulimukherjee/why-should-python-have-all-the-fun-meet-my-new-java-library-18eo</guid>
      <description>&lt;p&gt;&lt;em&gt;I built ExtractPDF4J — a pure-Java library to pull clean tables from messy PDFs (even scanned ones)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclrsqixjri7didw8b93h.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fclrsqixjri7didw8b93h.jpeg" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ExtractPDF4J&lt;/strong&gt; is a Java library that finds and extracts tabular data from both text-based and scanned PDFs using stream (layout/text) and lattice (line/vision) parsing—plus OCR. It’s on Maven Central, designed for server-side use (Spring Boot, microservices), and aims for Camelot-style features in the JVM ecosystem.&lt;/p&gt;

&lt;p&gt;Maven Central: io.github.mehulimukherjee:extractpdf4j-parser:0.1.0&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyte5jryfia8we8jptujb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyte5jryfia8we8jptujb.jpeg" alt="Maven Central" width="800" height="624"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/mehulimukherjee/ExtractPDF4J" rel="noopener noreferrer"&gt;ExtractPDF4J&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What Java had before
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Apache PDFBox (and earlier iText)&lt;/strong&gt;:&lt;br&gt;
These are general PDF libraries. They let you parse page text, metadata, and sometimes low-level drawing instructions. But they don’t provide high-level table extraction APIs. You’d have to implement your own heuristics for columns, bounding boxes, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tabula Java&lt;/strong&gt;:&lt;br&gt;
The Tabula desktop tool (originally Java + JRuby) could extract tables, but it wasn’t built as a clean, embeddable Java library. Most devs ended up using Tabula’s command-line wrapper or calling the Python-based Camelot instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commercial SDKs (e.g., ABBYY, Aspose)&lt;/strong&gt;:&lt;br&gt;
Paid libraries offered OCR + table recognition, but they’re proprietary and heavy. For open source Java projects, that’s not ideal.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why I built it?
&lt;/h2&gt;

&lt;p&gt;Most robust PDF table extractors are Python-first. In fintech/banking backends running on the JVM, pulling Python into prod creates friction (containers, ops, warm-up). I wanted a native Java option with strong accuracy on real-world documents like bank statements, invoices, and reports—without shelling out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;The gap ExtractPDF4J fills&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Camelot-like API in pure Java, with both stream (text-based layout) and lattice (grid/vision) parsing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;What it does (today)&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Two parsing modes:&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stream: infers columns from text layout—great for digital PDFs.&lt;/li&gt;
&lt;li&gt;Lattice: uses OpenCV-like line and joint detection + OCR—great for scanned PDFs.&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;OCR support (Tesseract): assigns text to detected grid cells for image-based PDFs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-page &amp;amp; multi-table: parse page ranges; detect multiple tables per page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Merged cell handling: rowSpan / colSpan support in lattice mode.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Export helpers: get tables as CSV/JSON (and access cell-wise metadata).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Production-friendly: built for Java 17+ services (e.g., Spring Boot, AWS/EKS, microservices where Python dependencies aren’t welcome).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quick start&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;1) Add the dependency&lt;br&gt;
&lt;strong&gt;Maven&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;dependency&amp;gt;
  &amp;lt;groupId&amp;gt;io.github.mehulimukherjee&amp;lt;/groupId&amp;gt;
  &amp;lt;artifactId&amp;gt;extractpdf4j-parser&amp;lt;/artifactId&amp;gt;
  &amp;lt;version&amp;gt;0.1.0&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Gradle (Kotlin)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation("io.github.mehulimukherjee:extractpdf4j-parser:0.1.0")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Optional (for OCR features): install Tesseract OCR and ensure it’s on your PATH.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;&lt;strong&gt;Minimal examples&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;A) Text-based PDF (Stream mode)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.extractpdf4j.*;

public class StreamExample {
  public static void main(String[] args) throws Exception {
    PdfHandler pdf = PdfHandler.from("samples/statement.pdf");
    StreamParser parser = StreamParser.builder()
        .pages("1-3")               // or "all"
        .detectHeaders(true)        // heuristics for Date/Description/Amount etc.
        .build();

    TableResult result = parser.parse(pdf);
    result.tables().forEach(t -&amp;gt; {
      System.out.println("---- TABLE ----");
      System.out.println(t.toCsv());     // or t.toJson()
    });
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;B) Scanned PDF (Lattice + OCR)&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.extractpdf4j.*;

public class LatticeExample {
  public static void main(String[] args) throws Exception {
    PdfHandler pdf = PdfHandler.from("samples/scanned_statement.pdf");
    LatticeParser parser = LatticeParser.builder()
        .pages("1-2")
        .enableOcr(true)            // assigns OCR text into grid cells
        .exportDebug(false)         // set true to dump grid/joints as images
        .build();

    TableResult result = parser.parse(pdf);
    result.tables().forEach(t -&amp;gt; {
      // Access structured cells, spans, and metadata
      System.out.println(t.toJson());
    });
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;C) Not sure which mode? Auto-detect&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AutoParser auto = AutoParser.builder()
    .pages("all")
    .enableOcr(true)
    .build();

TableResult result = auto.parse(PdfHandler.from("samples/mixed.pdf"));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;The rule of thumb:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use Stream for digital PDFs (selectable text).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Lattice for scanned/image PDFs or documents with strong ruling lines.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use Auto if you want the library to decide per page/table.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Real-world: bank statement extraction&lt;/p&gt;

&lt;p&gt;Detects transaction tables across pages&lt;/p&gt;

&lt;p&gt;Heuristically identifies headers like Date, Description, Amount&lt;/p&gt;

&lt;p&gt;Handles multi-line descriptions and merged cells&lt;/p&gt;

&lt;p&gt;Exports clean CSV/JSON ready for downstream reconciliation or analytics&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Roadmap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;✅ Multi-page, multi-table, spans, OCR assignment&lt;/p&gt;

&lt;p&gt;🚧 Hybrid parser: combine Stream output with Lattice boundaries&lt;/p&gt;

&lt;p&gt;🚧 Better automatic header detection across global bank formats&lt;/p&gt;

&lt;p&gt;🚧 Optional ML table detection backends (e.g., PubTabNet/Donut-style)&lt;/p&gt;

&lt;p&gt;🚧 CLI &amp;amp; Docker image for batch pipelines&lt;/p&gt;

&lt;p&gt;(If you’d like any of these faster, open an issue or PR!)&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Performance notes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Designed to run in containerized Java services alongside your other microservices.&lt;/p&gt;

&lt;p&gt;For OCR workloads, consider caching, concurrency limits, and page-selection to control runtime.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Contributing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Try it on a tricky PDF (bank statements, invoices) and share a redacted sample.&lt;/p&gt;

&lt;p&gt;File issues for false positives/negatives, header detection edge cases, and speedups.&lt;/p&gt;

&lt;p&gt;Feedbacks and PRs welcome for new detectors, exporters, and language packs. Help me make it stronger and sharper tool for JVM..&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;License &amp;amp; credits&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open source (see LICENSE in the repo).&lt;/p&gt;

&lt;p&gt;Inspired by the ideas behind Camelot/Tabula; implemented natively for the Java ecosystem.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Call to action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;⭐ Star the repo and try 0.1.0 from Maven Central.&lt;/p&gt;

&lt;p&gt;Comment with PDFs you want to handle better—I’ll prioritize those use cases.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;P.S.&lt;/strong&gt;&lt;/em&gt; If you write in Python but deploy on JVM, this might save you a few containers and some ops headaches.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Sun, 17 Aug 2025 22:58:15 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/-5hel</link>
      <guid>https://forem.com/mehulimukherjee/-5hel</guid>
      <description>&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/mehulimukherjee/stop-deploying-ai-models-like-its-2010-meet-gitops-for-ml-55oh" class="crayons-story__hidden-navigation-link"&gt;Stop Deploying AI Models Like It’s 2010 — Meet GitOps for ML&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/mehulimukherjee" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3098123%2F2e445d4a-3883-4642-9f76-2effd7c0eee8.png" alt="mehulimukherjee profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/mehulimukherjee" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Mehuli Mukherjee
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Mehuli Mukherjee
                
              
              &lt;div id="story-author-preview-content-2766890" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/mehulimukherjee" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3098123%2F2e445d4a-3883-4642-9f76-2effd7c0eee8.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Mehuli Mukherjee&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/mehulimukherjee/stop-deploying-ai-models-like-its-2010-meet-gitops-for-ml-55oh" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 11 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/mehulimukherjee/stop-deploying-ai-models-like-its-2010-meet-gitops-for-ml-55oh" id="article-link-2766890"&gt;
          Stop Deploying AI Models Like It’s 2010 — Meet GitOps for ML
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/git"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;git&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/github"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;github&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aiops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aiops&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/mehulimukherjee/stop-deploying-ai-models-like-its-2010-meet-gitops-for-ml-55oh" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;5&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/mehulimukherjee/stop-deploying-ai-models-like-its-2010-meet-gitops-for-ml-55oh#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


</description>
      <category>ai</category>
      <category>git</category>
      <category>github</category>
      <category>aiops</category>
    </item>
    <item>
      <title>Stop Deploying AI Models Like It’s 2010 — Meet GitOps for ML</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Mon, 11 Aug 2025 05:11:24 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/stop-deploying-ai-models-like-its-2010-meet-gitops-for-ml-55oh</link>
      <guid>https://forem.com/mehulimukherjee/stop-deploying-ai-models-like-its-2010-meet-gitops-for-ml-55oh</guid>
      <description>&lt;p&gt;We’ve all been there.&lt;/p&gt;

&lt;p&gt;You train a shiny new AI model. It predicts cats, stock prices, or coffee orders with 98% accuracy (according to your very scientific local tests). You push it to production and...boom!!! it starts predicting… something else entirely.&lt;br&gt;
Suddenly, your “future of AI” project is now the “future of why did I trust my laptop.”&lt;/p&gt;

&lt;p&gt;This is where GitOps for AI models comes in - the magical combo of version control, automation, and reproducibility that makes “it works on my laptop” a quaint relic of the past.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7p4svmpsxncrvyr0uqbp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7p4svmpsxncrvyr0uqbp.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wait, GitOps… for ML?&lt;/strong&gt;&lt;br&gt;
If GitOps and MLOps had a baby, it’d be this.&lt;/p&gt;

&lt;p&gt;In plain English:&lt;br&gt;
&lt;em&gt;You manage your AI models like you manage your code — with Git as the single source of truth, and automation doing the heavy lifting.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;No more:&lt;br&gt;
“Which model version is live?”&lt;br&gt;
“Why did accuracy drop 10% last night?”&lt;br&gt;
“Who deployed this model? And why is it predicting everything as a banana?”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Should You Care?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Reproducibility – Roll back to a previous working model in minutes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Auditability – Every change is tracked.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Consistency – No more “dev, staging, and prod” being completely different universes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automated Deployment – No more FTP-ing to prod at 3 a.m. like it’s 2005.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How It Works (Without Melting Your Brain)&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Everything in Git&lt;br&gt;
Model weights, configs, training scripts, Dockerfiles.&lt;br&gt;
Tag commits with model versions (v1.2.0-cat-classifier).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Define Deployment in Code&lt;br&gt;
Kubernetes manifests or Helm charts describe how the model runs.&lt;br&gt;
Use Seldon Core or KFServing for model serving.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automate Rollouts&lt;br&gt;
ArgoCD or Flux watches the Git repo.&lt;br&gt;
When a new model version is committed, it’s auto-deployed to Kubernetes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monitor Like a Hawk&lt;br&gt;
Prometheus + Grafana for inference latency, request counts, accuracy drift.&lt;br&gt;
Alerts for “accuracy below X%” so you don’t learn about failures from angry tweets.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;A Real-Life Example (with made-up names)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;ML Alice trains “MochaNet” to recommend coffee sizes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;She commits the model + configs to Git.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ArgoCD sees the update and deploys it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Two days later, Data Bob notices accuracy drift (everyone’s getting Venti instead of Tall).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;He rolls back with git revert. Caffeine crisis averted.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example GitOps Pipeline for AI Models&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;GitHub Actions Workflow&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .github/workflows/deploy-model.yml
name: Deploy AI Model via GitOps

on:
  push:
    branches:
      - main
    paths:
      - "models/**"
      - "deployment/**"

jobs:
  build-and-push-model:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Repo
        uses: actions/checkout@v3

      - name: Log in to DockerHub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKER_USER }}
          password: ${{ secrets.DOCKER_PASS }}

      - name: Build Model Image
        run: |
          docker build -t myorg/cat-classifier:${{ github.sha }} .
          docker push myorg/cat-classifier:${{ github.sha }}

      - name: Update K8s Manifests
        run: |
          sed -i "s|image: myorg/cat-classifier:.*|image: myorg/cat-classifier:${{ github.sha }}|" deployment/model-deployment.yaml
          git config user.email "bot@github.com"
          git config user.name "GitOps Bot"
          git commit -am "Deploy model ${{ github.sha }}"
          git push

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;em&gt;Kubernetes Deployment (Watched by ArgoCD)&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apps/v1
kind: Deployment
metadata:
  name: cat-classifier
spec:
  replicas: 2
  selector:
    matchLabels:
      app: cat-classifier
  template:
    metadata:
      labels:
        app: cat-classifier
    spec:
      containers:
      - name: cat-classifier
        image: myorg/cat-classifier:latest
        ports:
        - containerPort: 8080

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Common Gotchas&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Large files: Don’t commit 500MB model files directly — use Git LFS or an artifact store (MLflow, DVC, S3).&lt;/li&gt;
&lt;li&gt;Secrets: Keep API keys and DB creds out of Git — use Vault or Kubernetes Secrets.&lt;/li&gt;
&lt;li&gt;Model drift: GitOps can’t stop your model from slowly becoming useless if the world changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why This is the Future&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;With GitOps for AI models:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Deployments are boring (in the best way).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Rollbacks are one commit away.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Your weekends stay yours.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s like DevOps for code… but for those big .pt or .h5 files we keep pretending we fully understand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Words&lt;/strong&gt;&lt;br&gt;
If you’re building AI models in 2025 and still deploying them manually, you’re basically sending faxes in the age of Slack.&lt;/p&gt;

&lt;p&gt;Make Git your single source of truth, automate the boring stuff, and sleep better knowing your model won’t suddenly think every image is a banana.&lt;/p&gt;

&lt;p&gt;Now go forth and GitOps your AI — because the future of MLOps is hands-free, fully versioned, and just a git push away.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>git</category>
      <category>github</category>
      <category>aiops</category>
    </item>
    <item>
      <title>https://dev.to/mehulimukherjee/how-to-boil-potatoes-i-thought-i-knew-until-i-didnt-1b64</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Mon, 05 May 2025 04:42:29 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/httpsdevtomehulimukherjeehow-to-boil-potatoes-i-thought-i-knew-until-i-didnt-1b64-3fp3</link>
      <guid>https://forem.com/mehulimukherjee/httpsdevtomehulimukherjeehow-to-boil-potatoes-i-thought-i-knew-until-i-didnt-1b64-3fp3</guid>
      <description></description>
      <category>watercooler</category>
      <category>howto</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How to Boil Potatoes? I Thought I Knew — Until I Didn't.</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Mon, 05 May 2025 04:34:47 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/how-to-boil-potatoes-i-thought-i-knew-until-i-didnt-1b64</link>
      <guid>https://forem.com/mehulimukherjee/how-to-boil-potatoes-i-thought-i-knew-until-i-didnt-1b64</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;From Potatoes to Threads: A Real-World Journey Into Java Concurrency Optimization&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I thought I knew how to boil potatoes.&lt;/p&gt;

&lt;p&gt;You put them in a pot, add water, wait for it to boil, and eventually they soften up. Simple, right?&lt;/p&gt;

&lt;p&gt;But recently, I visited a friend to help brainstorm his startup idea. While chatting in the kitchen, he tossed a couple of potatoes into a bowl with a splash of water, popped it in the microwave, and seven minutes later, they were done. No mess. No babysitting the stove. Just... done.&lt;/p&gt;

&lt;p&gt;I was amazed.&lt;/p&gt;

&lt;p&gt;It wasn’t just about potatoes. It was a perfect metaphor for something I face every day in software development: &lt;strong&gt;&lt;em&gt;Optimization&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Old Habits Die Hard
&lt;/h2&gt;

&lt;p&gt;In code, we often stick to what works. We rely on familiar patterns and tools. They may not be the fastest, cleanest, or safest, but hey, they get the job done. Just like the stovetop potato.&lt;/p&gt;

&lt;p&gt;But what if there's a better way — one that saves time, reduces complexity, and delivers the same result?&lt;/p&gt;

&lt;p&gt;That’s what optimization is all about.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Real-World Concurrency Mess
&lt;/h2&gt;

&lt;p&gt;Not long after my potato revelation, I faced a hairy Java concurrency problem at work.&lt;/p&gt;

&lt;p&gt;We had a multi-threaded task scheduler in our enterprise application that processed transactional data across shared resources. Under pressure, the system began to crack: deadlocks, inconsistent states, unpredictable behaviors.&lt;/p&gt;

&lt;p&gt;The original solution was layered with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deeply nested ReentrantLocks&lt;/li&gt;
&lt;li&gt;Shared mutable maps guarded with synchronized&lt;/li&gt;
&lt;li&gt;Ad-hoc retry loops and timeouts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It worked on paper. But it was complex, fragile, and hard to reason about. Performance was tanking. Debugging it felt like boiling a potato with a candle.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Microwave Approach: Think Simpler
&lt;/h2&gt;

&lt;p&gt;I paused and asked myself: Are we overcomplicating this?&lt;/p&gt;

&lt;p&gt;Here’s what we did instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ExecutorService (fixed or scalable thread pool)&lt;/li&gt;
&lt;li&gt;ConcurrentHashMap &amp;lt; String, AtomicReference &amp;lt; ResourceState &amp;gt; &amp;gt; — immutable transactional state updates&lt;/li&gt;
&lt;li&gt;Lock-free atomic updates using compareAndSet&lt;/li&gt;
&lt;li&gt;CompletableFuture for chaining + timeout/failure handling&lt;/li&gt;
&lt;li&gt;Backoff with retry scheduler (ScheduledExecutorService)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here's a simplified example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.function.UnaryOperator;

class TransactionProcessor {

    // Represents an immutable transactional state for a resource
    static class ResourceState {
        final int transactionCount;
        final long lastUpdated;

        ResourceState(int transactionCount, long lastUpdated) {
            this.transactionCount = transactionCount;
            this.lastUpdated = lastUpdated;
        }

        ResourceState applyTransaction() {
            return new ResourceState(transactionCount + 1, System.currentTimeMillis());
        }

        @Override
        public String toString() {
            return "count=" + transactionCount + ", time=" + lastUpdated;
        }
    }

    private final ConcurrentHashMap&amp;lt;String, AtomicReference&amp;lt;ResourceState&amp;gt;&amp;gt; resourceMap = new ConcurrentHashMap&amp;lt;&amp;gt;();
    private final ExecutorService executor = Executors.newFixedThreadPool(8);
    private final ScheduledExecutorService retryScheduler = Executors.newScheduledThreadPool(2);

    private static final int MAX_RETRIES = 3;
    private static final int BACKOFF_MS = 200;

    public void processTransaction(String resourceKey) {
        submitWithRetry(resourceKey, 0);
    }

    private void submitWithRetry(String resourceKey, int attempt) {
        executor.submit(() -&amp;gt; {
            try {
                AtomicReference&amp;lt;ResourceState&amp;gt; ref = resourceMap.computeIfAbsent(
                        resourceKey, k -&amp;gt; new AtomicReference&amp;lt;&amp;gt;(new ResourceState(0, System.currentTimeMillis()))
                );

                boolean updated = false;
                for (int i = 0; i &amp;lt; 5; i++) { // CAS retry loop
                    ResourceState current = ref.get();
                    ResourceState updatedState = current.applyTransaction();
                    if (ref.compareAndSet(current, updatedState)) {
                        System.out.printf("Updated: %s (attempt %d)%n", resourceKey, updatedState, attempt);
                        updated = true;
                        break;
                    }
                }

                if (!updated) throw new RuntimeException("CAS failed after multiple retries");

            } catch (Exception e) {
                if (attempt &amp;lt; MAX_RETRIES) {
                    int delay = BACKOFF_MS * (attempt + 1);
                    System.out.printf("Retry attempt %d after %dms due to: %s%n",
                            resourceKey, attempt + 1, delay, e.getMessage());
                    retryScheduler.schedule(() -&amp;gt; submitWithRetry(resourceKey, attempt + 1),
                            delay, TimeUnit.MILLISECONDS);
                } else {
                    System.err.printf("Failed after %d attempts: %s%n",
                            resourceKey, attempt + 1, e.getMessage());
                }
            }
        });
    }

    public void shutdown() throws InterruptedException {
        executor.shutdown();
        retryScheduler.shutdown();
        executor.awaitTermination(5, TimeUnit.SECONDS);
        retryScheduler.awaitTermination(5, TimeUnit.SECONDS);
        System.out.println("Shutdown complete.");
    }

    public void printFinalStates() {
        System.out.println("\n=== Final Resource States ===");
        resourceMap.forEach((key, ref) -&amp;gt; System.out.println(key + " =&amp;gt; " + ref.get()));
    }

    public static void main(String[] args) throws InterruptedException {
        TransactionProcessor processor = new TransactionProcessor();
        for (int i = 0; i &amp;lt; 50; i++) {
            String resourceKey = "resource-" + (i % 5); // 5 shared resources
            processor.processTransaction(resourceKey);
        }

        Thread.sleep(3000); // allow processing time
        processor.printFinalStates();
        processor.shutdown();
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It wasn’t fancy, but it was faster, safer, and a whole lot easier to maintain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What Makes This Optimized?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5vfi3a4j05cb6n4wju8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc5vfi3a4j05cb6n4wju8.png" alt="Image description" width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can Scale To:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Millions of resources using sharded maps or local caches.&lt;/li&gt;
&lt;li&gt;Async I/O or DB commits with CompletableFuture chaining.&lt;/li&gt;
&lt;li&gt;Resilience features like circuit breakers or observability tools (Prometheus, Micrometer).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Real Lesson
&lt;/h2&gt;

&lt;p&gt;Optimization isn’t always about clever hacks or tuning JVM settings. It’s often about rethinking the whole process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Ask yourself:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Am I doing this the hard way just because it’s what I know?&lt;/li&gt;
&lt;li&gt;Is there a tool, pattern, or paradigm that simplifies this?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sometimes the solution is already in the kitchen. You just need someone to show you the microwave.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Whether it's potatoes or production code, the goal is the same: get the job done well, with as little pain as possible.&lt;/p&gt;

&lt;p&gt;Next time you’re stuck in complex, boilerplate-heavy code, step back and ask:&lt;/p&gt;

&lt;p&gt;Am I using a stove when I could be using a microwave?&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>webdev</category>
      <category>performance</category>
    </item>
    <item>
      <title>Can We Create a Self-Destructing NFT for Privacy?</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Mon, 05 May 2025 04:27:19 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/can-we-create-a-self-destructing-nft-for-privacy-34fh</link>
      <guid>https://forem.com/mehulimukherjee/can-we-create-a-self-destructing-nft-for-privacy-34fh</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Exploring the Idea of Expiry-Driven Smart Contracts (in Simple Terms)&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What if your digital stuff could expire — just like in real life?
&lt;/h2&gt;

&lt;p&gt;Let me ask you something simple.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When you buy a movie ticket, it works until the showtime ends.&lt;/li&gt;
&lt;li&gt;When you rent a scooter, it’s yours for the next 30 minutes.&lt;/li&gt;
&lt;li&gt;When you share a document, sometimes you only want someone to view it once.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Now think about this:&lt;/strong&gt;&lt;br&gt;
On the internet — especially on the blockchain — things don’t expire.&lt;/p&gt;

&lt;p&gt;They stay forever.&lt;br&gt;
And that’s… not always a good thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  So here’s the question I’ve been asking myself:
&lt;/h2&gt;

&lt;p&gt;Can we create digital things that are meant to disappear?&lt;br&gt;
Like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A digital pass that deletes itself after one use&lt;/li&gt;
&lt;li&gt;A smart contract that vanishes after 24 hours&lt;/li&gt;
&lt;li&gt;An NFT that self-destructs once it’s fulfilled its purpose&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not as a bug — but by design.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why would we want that?
&lt;/h2&gt;

&lt;p&gt;Because not everything needs to live forever.&lt;/p&gt;

&lt;p&gt;There are plenty of moments where we need temporary access, not permanent records:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sharing a medical file with your doctor for just a day&lt;/li&gt;
&lt;li&gt;Giving someone a one-time access token to a private video&lt;/li&gt;
&lt;li&gt;Issuing an event ticket that’s useless after the show&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the real world, these things expire naturally.&lt;br&gt;
But in the blockchain world? Once it’s there, it’s there forever.&lt;/p&gt;

&lt;p&gt;That might sound cool — but it can also cause problems for privacy, data control, and cleanup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Okay, but… how would that even work?
&lt;/h2&gt;

&lt;p&gt;That’s what I’ve been trying to figure out.&lt;/p&gt;

&lt;p&gt;Imagine creating a smart contract (which is just a fancy way of saying “code on the blockchain”) that comes with a timer.&lt;/p&gt;

&lt;p&gt;It could say:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;“This token only works for 7 days.”&lt;/li&gt;
&lt;li&gt;“After this date, automatically delete or disable this.”&lt;/li&gt;
&lt;li&gt;“If it hasn’t been used in 24 hours, burn it.”&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Kinda like a digital version of Mission Impossible:&lt;/p&gt;

&lt;p&gt;“This message will self-destruct in 5… 4… 3…”&lt;/p&gt;

&lt;h2&gt;
  
  
  I’m still learning, but here’s what I’ve found:
&lt;/h2&gt;

&lt;p&gt;There are already tools and platforms that can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Smart contracts on Ethereum or Polygon&lt;/li&gt;
&lt;li&gt;Automated bots that check time and run actions&lt;/li&gt;
&lt;li&gt;“Burn” functions that can delete tokens&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m not a blockchain expert yet — but I’m curious.&lt;br&gt;
This is the kind of project I’d love to explore further as a personal build.&lt;/p&gt;

&lt;p&gt;Because I think it matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why? Because we deserve digital control.
&lt;/h2&gt;

&lt;p&gt;Think about how much of your life is now online.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wouldn’t it be nice to:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Share something temporarily&lt;/li&gt;
&lt;li&gt;Own something just for now&lt;/li&gt;
&lt;li&gt;Delete something when it’s no longer useful?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The internet remembers everything. But maybe it doesn’t always have to.&lt;/p&gt;

&lt;p&gt;Maybe Web3 can help us forget — when we want to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Just a thought (for now)
&lt;/h2&gt;

&lt;p&gt;I haven’t built this yet.&lt;br&gt;
No startup, no funding, no flashy pitch deck. Just a developer’s brain going: “Hmm… what if?”&lt;/p&gt;

&lt;p&gt;So if you’ve ever thought about digital privacy, NFTs, or weird ideas that might not be that weird, let’s talk. Maybe we’ll build it. Maybe we’ll inspire someone who will.&lt;/p&gt;

&lt;p&gt;Until then… this blog won’t self-destruct. 😄&lt;br&gt;
But if it did, that’d be kinda cool, wouldn’t it?&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>bitcoin</category>
      <category>web3</category>
      <category>nft</category>
    </item>
    <item>
      <title>What If Land Ownership Was Secured on Blockchain? A Thought Experiment from a Developer’s Desk</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Mon, 05 May 2025 04:21:40 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/what-if-land-ownership-was-secured-on-blockchain-a-thought-experiment-from-a-developers-desk-1cp</link>
      <guid>https://forem.com/mehulimukherjee/what-if-land-ownership-was-secured-on-blockchain-a-thought-experiment-from-a-developers-desk-1cp</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flm55qrsnxr5dmyds42j0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flm55qrsnxr5dmyds42j0.png" alt="Image description" width="512" height="288"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem That Got Me Thinking
&lt;/h2&gt;

&lt;p&gt;Property ownership is one of those things we assume is settled — until it’s not.&lt;br&gt;
Across countries, land disputes, forged documents, unclear titles, and bureaucratic opacity make property transfers a slow, error-prone, and in many cases, corruptible process.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What struck me recently was this question:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;What if property records were stored on an immutable, decentralized ledger — visible to all, editable by none?&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I’m Thinking About It
&lt;/h2&gt;

&lt;p&gt;As someone exploring Blockchain through side projects and POCs, I’ve always been fascinated by the idea of “programmable trust.”&lt;br&gt;
We’ve seen its impact in finance and NFTs. But what about real-world systems that desperately need transparency?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Property registries are perfect candidates:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They deal with high-value assets&lt;/p&gt;

&lt;p&gt;They require long-term record integrity&lt;/p&gt;

&lt;p&gt;They suffer from manual inefficiencies and fraud risks&lt;/p&gt;

&lt;h2&gt;
  
  
  The Global Relevance
&lt;/h2&gt;

&lt;p&gt;This isn’t just a developer’s fantasy.&lt;/p&gt;

&lt;p&gt;Countries like India, Sweden, and Ghana have explored or piloted blockchain-based land registries.&lt;br&gt;
But most implementations hit roadblocks — either technical, legal, or political.&lt;/p&gt;

&lt;h2&gt;
  
  
  Still, the idea sticks with me:
&lt;/h2&gt;

&lt;p&gt;What if individuals could verify ownership with a public key, transfer property with on-chain smart contracts, and eliminate forgery using hash-based notarization?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Development Path (In My Head)
&lt;/h2&gt;

&lt;p&gt;Here’s what I’ve been sketching out:&lt;/p&gt;

&lt;p&gt;Ethereum-based Smart Contract to track land parcels, ownership history, and transfer requests.&lt;/p&gt;

&lt;p&gt;Each parcel would have:&lt;br&gt;
a. A unique ID&lt;br&gt;
b. Document hashes (stored on IPFS?)&lt;br&gt;
c. Public address of the verified owner&lt;/p&gt;

&lt;p&gt;Ownership transfers would trigger:&lt;br&gt;
a. Verification of identities&lt;br&gt;
b. Digital signature of both parties&lt;br&gt;
c. Approval (possibly multisig for government authority)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Optional:&lt;/strong&gt; a private blockchain fork if public chain costs become a barrier.&lt;/p&gt;

&lt;p&gt;Still early. Still messy in my head. But possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenges I Know I’ll Face
&lt;/h2&gt;

&lt;p&gt;How do you verify land documents before putting them on-chain?&lt;/p&gt;

&lt;p&gt;Who gets to act as the final evaluator of ownership?&lt;/p&gt;

&lt;p&gt;How do you build trust in the system before the system can be trusted?&lt;/p&gt;

&lt;p&gt;But that’s the thrill of it — thinking about how technology might reshape something as fundamental as property rights.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Could Matter
&lt;/h2&gt;

&lt;p&gt;Because in many parts of the world:&lt;/p&gt;

&lt;p&gt;Land is the most valuable asset most people own.&lt;/p&gt;

&lt;p&gt;Yet ownership is ambiguous, fragile, and easily manipulated.&lt;/p&gt;

&lt;p&gt;Blockchain won’t fix all that. But maybe it can offer a neutral, auditable, and incorruptible foundation for the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;I haven’t built this yet.&lt;br&gt;
But it’s simmering. Sketching. Slowly forming into something real.&lt;/p&gt;

&lt;p&gt;If I do take this forward, I’ll start with a prototype on a testnet. Maybe a small UI. Maybe even simulate a digital deed registry for a fictional city.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would Love to Hear From You
&lt;/h2&gt;

&lt;p&gt;If you’ve worked on anything like this — or know of resources, examples, or projects — I’d love to hear your thoughts.&lt;/p&gt;

&lt;p&gt;This is the kind of idea that only becomes great when many minds think it through.&lt;/p&gt;

&lt;p&gt;Let’s build better systems — starting with better questions.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>blockchain</category>
      <category>web3</category>
      <category>discuss</category>
    </item>
    <item>
      <title>How I Went From Googling “What Is Solidity?” to Writing Smart Contracts for Fun</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Mon, 28 Apr 2025 22:52:21 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/how-i-went-from-googling-what-is-solidity-to-writing-smart-contracts-for-fun-3a3g</link>
      <guid>https://forem.com/mehulimukherjee/how-i-went-from-googling-what-is-solidity-to-writing-smart-contracts-for-fun-3a3g</guid>
      <description>&lt;p&gt;A personal adventure into Blockchain, Smart Contracts, and why securing them is harder than securing my weekend plans.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introduction: The Accidental Blockchain Enthusiast&lt;/strong&gt;&lt;br&gt;
I’ll be honest — my first thought when I heard about Blockchain was:&lt;br&gt;
“Isn’t that the thing they keep talking about on the news whenever Bitcoin crashes?”&lt;/p&gt;

&lt;p&gt;But curiosity (and a healthy dose of FOMO) got the better of me.&lt;br&gt;
Somewhere between late-night YouTube rabbit holes and realizing the future of finance was heading toward decentralization, I decided:&lt;/p&gt;

&lt;p&gt;“I’m going to build a Smart Contract. From scratch. Like a grown-up.”&lt;/p&gt;

&lt;p&gt;And thus began my personal journey into the weird and wonderful world of Ethereum, Solidity, and trying very hard not to create the next DAO hack by accident ;-)&lt;br&gt;
And I ended up getting a Postgraduate Diploma specializing in Blockchain Technology.&lt;/p&gt;

&lt;p&gt;Having completed the diploma,&lt;br&gt;
I had a solid theoretical understanding of distributed systems, consensus algorithms, and smart contract basics.&lt;/p&gt;

&lt;p&gt;But let’s be real — no amount of diagrams in textbooks truly prepares you for the moment when you deploy your first smart contract… and accidentally spend all your test Ether on a single typo.&lt;/p&gt;

&lt;p&gt;This project was my way of making the theory real. A hands-on journey to move beyond paper knowledge — and actually build something that works (and survives a few bugs along the way).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Plan: Make It Real (But Not Risky)&lt;/strong&gt;&lt;br&gt;
Since I work in banking and love secure systems, I wanted my POC to not just work —&lt;br&gt;
but to be secure, scalable, and not accidentally send imaginary millions to strangers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My personal mission:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build a Smart Contract for simple asset tokenization — safely.&lt;/p&gt;

&lt;p&gt;Bonus mission:&lt;/p&gt;

&lt;p&gt;Actually understand what I’m doing, not just copy-paste from Stack Overflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tools I Used (and Googled a Lot)&lt;/strong&gt;&lt;br&gt;
Solidity (the magical programming language of Ethereum)&lt;br&gt;
Remix IDE (because setting up a local dev chain at first felt like fighting a Kraken)&lt;br&gt;
Ganache (for my personal fake Ethereum playground)&lt;br&gt;
Truffle (testing smart contracts without crying too much)&lt;br&gt;
MetaMask (the wallet that gave me more test Ether than my real bank account had)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How I Built It (and How I Almost Gave Up)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Step 1:&lt;/em&gt;&lt;/strong&gt; Write the Smart Contract&lt;br&gt;
At first, my code looked something like this (during the course):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pragma solidity ^0.8.0;

contract AssetToken {
    string public assetName;
    address public owner;

    constructor(string memory _name) {
        assetName = _name;
        owner = msg.sender;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Translation:&lt;br&gt;
I basically made a Hello World for Blockchain.&lt;br&gt;
Victory dance? Not yet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 2:&lt;/em&gt;&lt;/strong&gt; Secure the Contract (So It Doesn’t Explode)&lt;br&gt;
Once I wrote a few more functions (transfer ownership, view details, etc.),&lt;br&gt;
I started reading horror stories about reentrancy attacks, overflows, and hackers smarter than me.&lt;/p&gt;

&lt;p&gt;I used SafeMath to avoid overflow issues.&lt;br&gt;
I added modifiers like onlyOwner to sensitive functions.&lt;br&gt;
I practiced defensive coding like it was cybersecurity finals week.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;_Step 3: _&lt;/strong&gt;Testing, Testing… and More Testing&lt;br&gt;
Deployed to Ganache (local fake blockchain).&lt;br&gt;
Ran unit tests using Truffle.&lt;br&gt;
Found hilarious bugs like:&lt;br&gt;
a. “Anyone can transfer ownership if they spell their name backward.”&lt;br&gt;
b. “Contract thinks 0 is a valid new owner.”&lt;br&gt;
Moral of the story:&lt;br&gt;
Never trust your first deployment. Or your second.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Challenges (aka Lessons in Humility)&lt;/strong&gt;&lt;br&gt;
Understanding Gas Optimization:&lt;br&gt;
I accidentally wrote a function so expensive, it would’ve cost more than my Netflix subscription to run.&lt;/p&gt;

&lt;p&gt;Managing Wallets and Private Keys:&lt;br&gt;
Lost one test wallet. Still having a moment of silence for it.&lt;/p&gt;

&lt;p&gt;Deploying to Real Testnets:&lt;br&gt;
Turns out, testnets are real networks, with real delays, and real lessons in patience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What I Built in the End&lt;/strong&gt;&lt;br&gt;
a. A working, secure-ish Asset Tokenization Smart Contract&lt;br&gt;
b. A deeper understanding of Blockchain security principles&lt;br&gt;
c. A strong desire to always audit your contracts before touching anything live&lt;/p&gt;

&lt;p&gt;[User Interface (MetaMask Wallet)] &lt;br&gt;
    ⬇️&lt;br&gt;
Smart Contract (Deployed on Testnet)&lt;br&gt;
    ⬇️&lt;br&gt;
Blockchain Ledger (Ethereum Public Chain)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: Why This Journey Mattered&lt;/strong&gt;&lt;br&gt;
I didn’t just build a Smart Contract —&lt;br&gt;
I built a new set of skills:&lt;br&gt;
Security-first coding mindset.&lt;br&gt;
Blockchain architecture fundamentals.&lt;br&gt;
Courage to dive into complex, emerging tech without fear.&lt;/p&gt;

&lt;p&gt;Today, I can confidently say I understand how Blockchain fits into real-world financial systems — combining my formal Postgraduate Diploma in Blockchain Technology with real hands-on learning and how small mistakes can become million-dollar news headlines.&lt;/p&gt;

&lt;p&gt;And the best part?&lt;/p&gt;

&lt;p&gt;It all started with a random late-night decision to learn something new.&lt;/p&gt;

</description>
      <category>blockchain</category>
      <category>programming</category>
      <category>discuss</category>
      <category>learning</category>
    </item>
    <item>
      <title>How I Tamed a Wild AI to Answer Banking Questions Without Making Things Up: A Spring Boot + OpenAI Story</title>
      <dc:creator>Mehuli Mukherjee</dc:creator>
      <pubDate>Mon, 28 Apr 2025 22:42:22 +0000</pubDate>
      <link>https://forem.com/mehulimukherjee/how-i-tamed-a-wild-ai-to-answer-banking-questions-without-making-things-up-a-spring-boot-openai-1h2h</link>
      <guid>https://forem.com/mehulimukherjee/how-i-tamed-a-wild-ai-to-answer-banking-questions-without-making-things-up-a-spring-boot-openai-1h2h</guid>
      <description>&lt;p&gt;Banking info should be easier to find than car keys on a Monday morning. Sadly, it isn’t. So we built a chatbot to fix that. A behind-the-scenes look at designing an AI-driven chatbot for the future of banking — And My first encounter with Open AI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Introduction: The Spark Behind the Idea&lt;/strong&gt;&lt;br&gt;
In today’s digital-first world, banks and financial institutions face an ongoing challenge: how to provide quick, reliable, and accessible information to both customers and employees.&lt;br&gt;
Whether it’s finding the nearest branch, understanding service policies, or accessing executive contacts — information is often buried across multiple systems, leading to inefficiencies.&lt;/p&gt;

&lt;p&gt;While working as a Senior Full Stack Developer specializing in innovation projects, I set out to tackle this challenge.&lt;br&gt;
My mission was clear: build a smart, intuitive banking chatbot powered by AI — a solution that could instantly answer banking queries using the capabilities of Azure OpenAI Service and the robustness of a Spring Boot backend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Azure OpenAI + Spring Boot?&lt;/strong&gt;&lt;br&gt;
While OpenAI’s GPT models have demonstrated powerful natural language capabilities, enterprise financial services demand stricter compliance, security, and privacy standards.&lt;br&gt;
This made Azure OpenAI a natural choice — offering both powerful models and enterprise-grade security.&lt;/p&gt;

&lt;p&gt;For backend development, Spring Boot offered the flexibility and reliability needed to create a secure API service layer around the AI model.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution Overview&lt;/strong&gt;&lt;br&gt;
Here’s the high-level system architecture of the solution:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksff5dxy1n8gtldzi6a6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksff5dxy1n8gtldzi6a6.png" alt="Image description" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How the Solution Works&lt;/strong&gt;&lt;br&gt;
Users interact with the chatbot via a simple web UI or mobile app.&lt;br&gt;
They authenticate via OAuth2 or Single Sign-On (SSO).&lt;br&gt;
The query passes through the Chatbot API built using Spring Boot.&lt;br&gt;
The API securely communicates with Azure OpenAI’s fine-tuned endpoint.&lt;br&gt;
Responses are generated based on curated internal banking knowledge.&lt;br&gt;
The answer is sent back to the user — fast, accurate, and secure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implementation Journey: Step-by-Step&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Step 1:&lt;/em&gt;&lt;/strong&gt; Curating the Data&lt;br&gt;
The first step was to build a high-quality, domain-specific dataset.&lt;br&gt;
Collected internal documentation: branch locations, services, executives, operational policies.&lt;br&gt;
Structured the information into Q&amp;amp;A pairs for fine-tuning.&lt;br&gt;
Ensured that sensitive customer data was excluded.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Step 2:&lt;/strong&gt;&lt;/em&gt; Fine-tuning the Azure OpenAI Model&lt;br&gt;
Azure allowed for secure fine-tuning of GPT-3 with financial service-specific data:&lt;br&gt;
Uploaded the curated dataset.&lt;br&gt;
Tuned parameters (e.g., temperature, frequency penalty) for better factual reliability.&lt;br&gt;
Deployed the fine-tuned model under private, secure access environments.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Step 3:&lt;/strong&gt;&lt;/em&gt; Building the Spring Boot Backend&lt;br&gt;
To securely interface with Azure OpenAI:&lt;br&gt;
Created a Spring Boot REST API.&lt;br&gt;
Implemented user authentication middleware.&lt;br&gt;
Built secure, scalable APIs to handle communication with Azure services.&lt;br&gt;
Applied rate limiting and exception handling for better fault tolerance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Step 4:&lt;/em&gt;&lt;/strong&gt; Deployment on Cloud Infrastructure&lt;br&gt;
To ensure scalability and compliance:&lt;br&gt;
Deployed the backend service in a cloud-native environment (using Kubernetes services like AWS EKS).&lt;br&gt;
Applied API Gateway security layers.&lt;br&gt;
Monitored performance with centralized logging and alerting systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Challenges Faced:&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Challenge 1:&lt;/em&gt;&lt;/strong&gt; Data Security Compliance&lt;br&gt;
Building an AI for banking is like inviting a dragon to dinner — cool, but you need a lot of safety rules. Financial institutions demand tight compliance standards.&lt;br&gt;
Solution: All data flows were secured within virtual private clouds (VPCs) and encrypted in transit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Challenge 2:&lt;/em&gt;&lt;/strong&gt; Managing Hallucinations in AI&lt;br&gt;
Large language models sometimes “hallucinate” facts.&lt;br&gt;
Solution: Continuous feedback loops and retraining were established to improve accuracy over time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Challenge 3:&lt;/em&gt;&lt;/strong&gt; API Latency Optimization&lt;br&gt;
External API calls to Azure AI introduced slight latencies.&lt;br&gt;
Solution: We optimized critical paths by implementing query caching for frequent questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Impact: What Changed?&lt;/strong&gt;&lt;br&gt;
Response time for internal banking queries improved dramatically.&lt;br&gt;
Operational efficiency increased, freeing up staff from manual lookups.&lt;br&gt;
Provided a foundation for customer-facing AI-driven banking initiatives.&lt;br&gt;
Demonstrated that enterprise-grade AI solutions can be securely and responsibly implemented in regulated industries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: What I Learned&lt;/strong&gt;&lt;br&gt;
Turns out, AI can answer your branch location faster than your colleague in the next cubicle. If AI can book your travel, recommend your next song, and now answer your banking questions — maybe it’s time we stop fearing it will steal our lunch. One chatbot at a time, we’re making banking conversations a little smarter — and a lot more human.&lt;/p&gt;

&lt;p&gt;Building an AI-powered chatbot was not just about leveraging APIs — it was about building trust.&lt;br&gt;
Trust that the system would deliver accurate answers, keep information secure, and be reliably available when needed.&lt;br&gt;
This project strengthened my expertise in:&lt;/p&gt;

&lt;p&gt;AI integration into real-world systems.&lt;br&gt;
Cloud-native API development.&lt;br&gt;
Enterprise AI compliance and security.&lt;br&gt;
It reaffirmed my belief that true innovation happens at the intersection of cutting-edge technology and real-world business challenges.&lt;/p&gt;

&lt;p&gt;And the journey is just beginning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Note&lt;/strong&gt;&lt;br&gt;
Are you exploring how AI can transform banking or enterprise systems?&lt;br&gt;
Let’s connect — I’m always excited to exchange ideas and build the future together!&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>openai</category>
      <category>discuss</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
