<?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>DEV Community: Akriti Keswani</title>
    <description>The latest articles on DEV Community by Akriti Keswani (@akritikeswani).</description>
    <link>https://dev.to/akritikeswani</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%2F1261256%2F53010a63-895d-4121-ac27-83d2efc459a6.jpg</url>
      <title>DEV Community: Akriti Keswani</title>
      <link>https://dev.to/akritikeswani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akritikeswani"/>
    <language>en</language>
    <item>
      <title>Debug Smarter: Multimodal Error Analysis for Next.js with Daft.ai</title>
      <dc:creator>Akriti Keswani</dc:creator>
      <pubDate>Wed, 13 Aug 2025 23:19:04 +0000</pubDate>
      <link>https://dev.to/akritikeswani/debug-smarter-multimodal-error-analysis-for-nextjs-with-daftai-34mj</link>
      <guid>https://dev.to/akritikeswani/debug-smarter-multimodal-error-analysis-for-nextjs-with-daftai-34mj</guid>
      <description>&lt;p&gt;&lt;strong&gt;Late-night debugging?&lt;/strong&gt; &lt;em&gt;We've all been there.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It’s 11 PM on a Thursday. You should be winding down, but your Next.js app is throwing cryptic hydration errors and 500s are flooding your logs. Your desktop’s cluttered with screenshots and log files, and you're hopping between ChatGPT, Claude, and Cursor hoping someone (or something) can help you connect the dots.&lt;/p&gt;

&lt;p&gt;But nothing clicks. The AI doesn’t seem to understand that the broken UI might be linked to that failed API call you saw 10 minutes ago. And now you’re the one trying to piece together the story from screenshots, console logs, and error messages. If this sounds familiar, you're not alone—and you’re definitely not doing anything wrong. The reality is: debugging multimodal errors (text + visual + structured data) is still way harder than it should be.&lt;/p&gt;

&lt;p&gt;So, what if you could search your error data like a knowledge base? What if you could say, “Show me all auth errors with matching screenshots,” and get a real answer? In this tutorial, we’ll show you how to do exactly that—with Daft.ai, a framework built to handle and analyze structured + unstructured data at scale. We'll walk through how to:&lt;/p&gt;

&lt;p&gt;• Load and process error logs and screenshots &lt;br&gt;
• Generate embeddings for both text and images using &lt;a href="https://docs.daft.ai/en/stable/" rel="noopener noreferrer"&gt;UDFs&lt;/a&gt;&lt;br&gt;
• Run semantic + similarity search across modalities &lt;br&gt;
• Get insights and recommendations - all from one place&lt;/p&gt;

&lt;p&gt;Let’s build a better way to debug!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What We're Building&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By the end of this post, you’ll have a fully working multimodal debugging tool that can:&lt;/p&gt;

&lt;p&gt;• Ingest logs and screenshots&lt;br&gt;
• Generate embeddings using &lt;a href="https://www.daft.ai/" rel="noopener noreferrer"&gt;Daft.ai&lt;/a&gt;'s &lt;a href="https://docs.daft.ai/en/stable/" rel="noopener noreferrer"&gt;UDF&lt;/a&gt;s&lt;br&gt;
• Classify errors automatically&lt;br&gt;
• Run similarity search across both text and images&lt;br&gt;
• Answer RAG-style queries with actual context&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Organize Your Error Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start by structuring your Next.js error artifacts like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nextjs_errors/
├── screenshots/
│   ├── auth_error.png
│   ├── hydration_error.png
│   ├── runtime_error.png
│   └── build_error.png
└── logs/
    ├── api_auth_error.txt
    ├── hydration_error.txt
    ├── runtime_error.txt
    └── build_error.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These can be pulled from Sentry, your browser dev tools, Vercel logs—&lt;br&gt;
wherever your pain lives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Load Logs + Screenshots into Daft&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%2Femkpskptib5eeiyjnbyb.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%2Femkpskptib5eeiyjnbyb.png" alt=" " width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Embed Your Data (Text + Image)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now we’ll write custom UDFs (user-defined functions) to simulate embeddings. These help Daft understand the meaning behind each log or screenshot:&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%2Fb4r4jmvw9ytpzjfw10q3.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%2Fb4r4jmvw9ytpzjfw10q3.png" alt=" " width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note: In production, you'd replace these with actual embedding models like OpenAI's text-embedding-ada-002 or CLIP for images.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Classify Errors Automatically&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s tag our logs with some basic intelligence:&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%2Fdt3e5zknzgbfd6hmnd5c.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%2Fdt3e5zknzgbfd6hmnd5c.png" alt=" " width="800" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Run RAG Queries&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can now run natural queries like:&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%2F7l9sm57437ybnqaqj2zf.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%2F7l9sm57437ybnqaqj2zf.png" alt=" " width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Search for Similar Errors&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Want to find logs or screenshots that look like the one you just debugged? Use cosine similarity across your embeddings:&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%2F9ut5eldmhy1qod8b47bj.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%2F9ut5eldmhy1qod8b47bj.png" alt=" " width="800" height="596"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Results&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%2Fc6qdrpfjsnj173qpd7ps.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%2Fc6qdrpfjsnj173qpd7ps.png" alt=" " width="800" height="776"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's Next?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this tutorial, I chose Next.js as the focus because it's where I spend most of my time as a developer, and honestly, it's where I have the most fun building. But beyond personal passion, the numbers tell a compelling story: with over 5 million developers using Next.js weekly, we're talking about a massive chunk of the global developer experience that's still stuck in manual debugging workflows.&lt;br&gt;
Every week, millions of developers are doing exactly what I described in the intro—copying screenshots into AI assistants, losing context between logs and visual breakdowns, manually connecting dots that should be automated. The scale of this inefficiency is staggering when you think about it globally.&lt;/p&gt;

&lt;p&gt;That's what excites me most about this project. We've built a functional multimodal error analysis pipeline with Daft.ai that demonstrates:&lt;/p&gt;

&lt;p&gt;• Custom UDFs for embedding generation&lt;br&gt;
• Classification of real-world Next.js error patterns &lt;br&gt;
• Embedding similarity search across modalities &lt;br&gt;
• RAG-style queries over multimodal error datasets&lt;br&gt;
• Insight generation with actionable debugging recommendations&lt;/p&gt;

&lt;p&gt;This isn't just a cool technical demo—it's a proof of concept for streamlining debugging workflows for millions of developers. The foundation shows what's possible when you combine Daft's UDF capabilities with real developer pain points at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Final Thoughts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead of manually copying screenshots into Cursor and losing context, you can now process your error data programmatically and find patterns across both text logs and visual breakdowns. With Daft.ai, your debugging workflow becomes data-driven—and that efficiency multiplied across developers could fundamentally change how we approach debugging.&lt;/p&gt;

&lt;p&gt;👉 See full &lt;a href="https://github.com/AkritiKeswani/daft-nextjsdemo" rel="noopener noreferrer"&gt;code&lt;/a&gt; on Github! &lt;/p&gt;

</description>
      <category>multimodal</category>
      <category>ai</category>
      <category>python</category>
      <category>data</category>
    </item>
    <item>
      <title>RAG Pipeline Permissions for iPaaS Platforms</title>
      <dc:creator>Akriti Keswani</dc:creator>
      <pubDate>Tue, 20 Aug 2024 21:38:42 +0000</pubDate>
      <link>https://dev.to/akritikeswani/rag-pipeline-permissions-for-ipaas-platforms-48dh</link>
      <guid>https://dev.to/akritikeswani/rag-pipeline-permissions-for-ipaas-platforms-48dh</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The AI revolution in the B2B SaaS world is more intense than ever, with new tools empowering developers to build products that customers not only desire but require. As these SaaS companies grow and scale, managing customer data privacy becomes increasingly complex. How can companies enforce strict access control for each customer while ensuring that the AI components in their SaaS applications use the correct information efficiently and securely?&lt;/p&gt;

&lt;p&gt;To visualize these challenges better, one must begin by understanding the value of &lt;strong&gt;retrieval-augmented generation&lt;/strong&gt;, commonly known as &lt;strong&gt;RAG&lt;/strong&gt; in the developer community, which has become a key ingredient for enhancing AI outputs with relevant context. To use RAG in multi-tenant SaaS applications however, poses its own set of hurdles, and perhaps the most critical one is implementing robust permissions.&lt;/p&gt;

&lt;p&gt;This article explores the challenges and best practices for managing permissions in RAG pipelines for AI-powered SaaS products. It aims to deep dive into why this is so essential for engineering and product leaders, tackling how to overcome common obstacles and strategize building secure, scalable systems.&lt;/p&gt;

&lt;p&gt;To start visualizing these concepts in a more practical way, we can take an example use case of building secure enterprise search, and further handling permissions of users utilizing this feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Leveraging iPaaS Platforms for RAG Pipeline Permissions&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;While implementing robust permissions in a RAG pipeline is complex, embedded iPaaS platforms can significantly accelerate the process. These platforms provide key capabilities that align with the best practices outlined above:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flexible Authentication&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Many iPaaS platforms offer OAuth management, simplifying the process of authenticating users and obtaining the necessary permissions from various data sources like Google Drive, Slack, or Notion.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Authenticate Third-Party Service&lt;/span&gt;
&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GET&lt;/span&gt;
&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Initiate OAuth Flow&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;third_party_service.start_auth&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;redirect_uri&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;env.REDIRECT_URI&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Redirect to Service&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http.redirect&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.Initiate_OAuth_Flow.output.auth_url&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Granular Access Controls&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Utilize the iPaaS platform's built-in access control features to implement fine-grained permissions across your RAG pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check Document Access&lt;/span&gt;
&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Verify User Permission&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;document_service.check_permission&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;document_id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trigger.body.document_id&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
      &lt;span class="na"&gt;user_email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trigger.body.user_email&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Return Access Status&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http.respond&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;has_access&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.Verify_User_Permission.output.has_permission&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scalable Processing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most iPaaS platforms offer cloud-native architectures that can handle high volumes of permission checks and data processing, with built-in error handling and smart rate limiting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Workflow Automation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use the iPaaS platform's workflow engine to build complex permission enforcement logic without managing infrastructure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Permission-Aware Search&lt;/span&gt;
&lt;span class="na"&gt;trigger&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;POST&lt;/span&gt;
&lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Perform Search&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;custom_action.search_documents&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trigger.body.query&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
      &lt;span class="na"&gt;user_email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trigger.body.user_email&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Filter Results&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;custom_action.apply_permission_filter&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;search_results&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.Perform_Search.output.results&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
      &lt;span class="na"&gt;user_email&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;trigger.body.user_email&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Generate AI Summary&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ai_service.generate_summary&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;advanced_summarization'&lt;/span&gt;
      &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Summarize:&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.Filter_Results.output.filtered_results&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Return Results&lt;/span&gt;
    &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http.respond&lt;/span&gt;
    &lt;span class="na"&gt;input&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;results&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.Filter_Results.output.filtered_results&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
        &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;steps.Generate_AI_Summary.output.summary&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Audit Logging&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Leverage the iPaaS platform's logging capabilities to maintain detailed audit trails of all data accesses and permission checks.&lt;/p&gt;

&lt;p&gt;By using an embedded iPaaS platform, engineering teams can focus on building differentiating AI features rather than reinventing the wheel on permission infrastructure. These platforms' pre-built integrations, scalable architecture, and flexible workflow engines provide a solid foundation for implementing secure, permission-aware RAG pipelines.&lt;/p&gt;

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

&lt;p&gt;Implementing robust permissions in RAG pipelines is crucial for AI-powered B2B SaaS products to deliver secure, compliant, and personalized experiences. While the challenges are significant, a thoughtful approach combining architectural best practices with powerful iPaaS tools can help engineering teams build secure, scalable RAG systems.&lt;/p&gt;

&lt;p&gt;As AI becomes increasingly central to SaaS offerings, mastering permissions in RAG pipelines will be a key differentiator. By investing in this capability and leveraging iPaaS platforms, engineering and product leaders can position their products to deliver intelligent, trustworthy AI features while maintaining the strict data controls that enterprise customers demand.&lt;/p&gt;

&lt;p&gt;The example of secure enterprise search illustrates the complexity and importance of getting permissions right in RAG pipelines. However, the principles and practices discussed here apply broadly across various AI-powered SaaS applications, from customer support chatbots to data analysis tools. By leveraging iPaaS platforms and following best practices, teams can accelerate their development of secure, scalable AI features that respect the nuanced permission requirements of enterprise environments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>rag</category>
      <category>permissions</category>
      <category>saas</category>
    </item>
    <item>
      <title>Annotations in Java Spring</title>
      <dc:creator>Akriti Keswani</dc:creator>
      <pubDate>Mon, 03 Jun 2024 06:37:29 +0000</pubDate>
      <link>https://dev.to/akritikeswani/annotations-in-java-spring-1d0h</link>
      <guid>https://dev.to/akritikeswani/annotations-in-java-spring-1d0h</guid>
      <description>&lt;p&gt;For decades as of today, Java is undoubtedly one of the most popular programming languages used at companies with massive codebases. You would think that now with languages such as Kotlin and Scala, companies probably want to pivot and entirely modernize their codebases, but there must be something so special about Java that makes people want to stay and revert to it. I wonder what that is… &lt;/p&gt;

&lt;p&gt;Well, one could argue that it is the mere fact of Java being such a popular choice for object-oriented programming and that the JVM makes it so dynamic to run and deploy across complex operating systems. One must also consider though, the sheer flexibility of Java, especially with frameworks such as Spring that leverage containerizing objects and method calls, which essentially make applications easier to scale, which is quite necessary in enterprise software environments. &lt;/p&gt;

&lt;p&gt;Let’s get into why Spring is so awesome as a framework, especially when you are dealing with huge codebases that require you to sift through hundreds of services in several interconnected repositories - we have all been there! &lt;/p&gt;

&lt;p&gt;So in most normal applications, you definitely need a lot of boilerplate code to get started, especially if you are running a client on top of a server, and Spring makes this seamless with the abstraction and layering of classes, as well as annotations classifying objects, services, and the lines of code actually executing the other lines of code. All that sort of may seem confusing, but here’s the thing, annotations can really enhance the way your code looks, operates, and performs after more code has been written. &lt;/p&gt;

&lt;p&gt;So, in Java Spring, it is a known concept to use annotations, which can get pretty tricky fast, because it abstracts away so much code that you would otherwise have to write. Annotations such as &lt;code&gt;@Slf4j&lt;/code&gt; (used for logging) can be super confusing to someone who is just starting to write classes in a Spring application. I'm here to tell you that it all gets easier, and makes sense eventually, like all things in life!&lt;/p&gt;

&lt;p&gt;Typically, in these Java Spring applications, you usually have a main file that is like the runner, the one that calls the entire application, often denoted with a &lt;code&gt;@SpringBootApplication&lt;/code&gt; annotation. In its bare form, this file looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@SpringBootApplication&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyApplication&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;SpringApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;MyApplication&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In reality &lt;code&gt;@SpringBootApplication&lt;/code&gt; is actually  a combination of  &lt;code&gt;@SpringBootConfiguration&lt;/code&gt;  (specialized version of &lt;code&gt;@Configuration&lt;/code&gt;) &lt;code&gt;@EnableAutoConfiguration,&lt;/code&gt; and &lt;code&gt;@ComponentScan.&lt;/code&gt; The reason for this is that we need to reduce the boilerplate code and make the code more readable. We can see this in the way that &lt;code&gt;@EnableAutoConfiguration&lt;/code&gt; minimizes the need to write configuration code manually. Lastly, &lt;code&gt;@ComponentScan&lt;/code&gt; can do the work of registering beans in the application context for the build to work without explicitly declaring each component. &lt;/p&gt;




&lt;p&gt;As you can see, each annotation serves a specific purpose, and together they enable the entire application to function. Let's dive deeper into &lt;code&gt;@Repository&lt;/code&gt;, another useful annotation that supports storage, retrieval, update, and delete operations on objects. This annotation is a specialization of &lt;code&gt;@Component&lt;/code&gt;, which allows Spring to detect and manage repository classes.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Repository&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;JpaRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Custom query methods can be defined here&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;In the comment area, you can include custom query logic using the &lt;code&gt;@Query&lt;/code&gt; annotation or take advantage of Spring Data JPA's query method conventions. For example, methods like &lt;code&gt;IsStartingWith&lt;/code&gt; or &lt;code&gt;Containing&lt;/code&gt; can be used to filter data.&lt;/p&gt;

&lt;p&gt;A practical example would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;List&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;findByFirstnameContaining&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;fragment&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;This method filters users whose first names contain the specified fragment. Using these conventions makes the code more readable and easier to maintain.&lt;/p&gt;

&lt;p&gt;All this is great, but in order to do some action on the code and perform operations on how we are using all this data, understanding the &lt;code&gt;@Service&lt;/code&gt; annotation is quite necessary. The &lt;code&gt;@Service&lt;/code&gt; annotation is used to define a service class in the service layer of the application. This layer contains the business logic and acts on data passed between the controller and repository layers. Services often operate on models or &lt;strong&gt;POJO&lt;/strong&gt; (Plain Old Java Object) objects, which represent the data in your application.&lt;/p&gt;

&lt;p&gt;Here's an example of how a service can be structured:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Autowired&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserRepository&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Logic on finding a user by ID&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;findUserById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;orElse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Logic on how to create or update a user&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;saveUser&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;save&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Here we see that the &lt;code&gt;@Autowired&lt;/code&gt; annotation is simply ensuring that the service uses the &lt;code&gt;UserRepository&lt;/code&gt; to interface with the database. These methods are simply performing CRUD-like operations on the &lt;code&gt;User&lt;/code&gt; objects which are just POJOs. &lt;/p&gt;

&lt;p&gt;Now, we mentioned POJOs but how do they even represent the data we are using? Most of it is simply having a getter, setter, and maybe a few methods here to represent unique use cases of manipulating the data. An example of a User model associated with the above would look something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Id&lt;/span&gt;
    &lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;IDENTITY&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;firstname&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;lastname&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Getters and setters&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="nf"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setId&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getEmail&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setEmail&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now we see that we also have the &lt;code&gt;@Entity&lt;/code&gt; annotation here, but not to worry, it is simply ensuring that this can be mapped to a table in a database - this lets use the JPA (Java Persistance API) as mentioned earlier!  &lt;code&gt;@Id&lt;/code&gt; is also included in this class to mark a primary key of the entity and this is just a unique identifier as the name implies. &lt;/p&gt;

&lt;p&gt;The service class ensures that these POJOs transfer data between the repository and the controller, which we have not touched upon much, but essentially allows us to separate the presentation later from the application logic. Services are special in the sense that we can make sure the core logic of the application is applied properly before any data is saved, retrieved, or manipulated. &lt;/p&gt;

&lt;p&gt;After going through all of this, it is crucial to understand how a typical Spring application flows together, and some key parts as mentioned are the &lt;strong&gt;controller (handling requests), service (business logic), and the repository (for CRUD operations)&lt;/strong&gt;. To leverage Java Spring’s full potential, these annotations are super useful to know and adapt, as they make the code more readable as well as maintainable! &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Looking Ahead&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In order to take full advantage of Spring and really understand what a brilliant architecture of an application may look like, it is vital to explore the &lt;strong&gt;microservices architecture,&lt;/strong&gt; which I plan to delve into within the next article! Microservices are nice in that they offer more scalability and flexibility, since we can break down the application into smaller, deployable services.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>learning</category>
      <category>java</category>
      <category>backenddevelopment</category>
    </item>
  </channel>
</rss>
