<?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: Joao Marques</title>
    <description>The latest articles on Forem by Joao Marques (@joaomarques).</description>
    <link>https://forem.com/joaomarques</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%2F1569672%2F29adf56e-e605-4cf0-a4cc-a6dc2328a51b.png</url>
      <title>Forem: Joao Marques</title>
      <link>https://forem.com/joaomarques</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/joaomarques"/>
    <language>en</language>
    <item>
      <title>Backend Authority</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Thu, 06 Nov 2025 19:25:08 +0000</pubDate>
      <link>https://forem.com/joaomarques/backend-authority-2533</link>
      <guid>https://forem.com/joaomarques/backend-authority-2533</guid>
      <description>&lt;p&gt;In modern business software, backend authority is more than just a technical concept, it’s the backbone of trust and consistency. When we talk about “backend authority,” we’re referring to the backend system being the single source of truth that governs data integrity, rules, and business logic. Without it, multiple systems can start interpreting or mutating data differently, leading to mismatches, errors, and costly confusion.&lt;/p&gt;

&lt;p&gt;A strong backend authority ensures that every transaction, update, and rule enforcement flows from one verified source. This allows frontends and external services to focus on user experience, while the backend maintains governance on validating inputs, applying business rules, and auditing activity. For business applications, especially those involving financial transactions or compliance, backend authority prevents data drift and keeps the system accountable.&lt;/p&gt;

</description>
      <category>backend</category>
      <category>frontend</category>
      <category>java</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Spring Boot Logging convention - JMLogFlow</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Wed, 11 Jun 2025 14:11:12 +0000</pubDate>
      <link>https://forem.com/joaomarques/spring-boot-logging-convention-jmlogflow-23ci</link>
      <guid>https://forem.com/joaomarques/spring-boot-logging-convention-jmlogflow-23ci</guid>
      <description>&lt;p&gt;&lt;strong&gt;JMLogFlow&lt;/strong&gt; is a lightweight, pragmatic logging convention designed to improve maintainability of Spring Boot applications.&lt;br&gt;
It’s centered around placing meaningful log messages in strategic locations throughout the application to trace execution and data flow, without overwhelming the log files.&lt;/p&gt;

&lt;h2&gt;
  
  
  1 - Controller Logging
&lt;/h2&gt;

&lt;p&gt;Log once at the start of every controller method.&lt;/p&gt;

&lt;p&gt;What to log:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Http method&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Endpoint path&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Path variables&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Query parameters&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Important Custom headers (Except the ones with sensitive information)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;❌ Do not log the entire request body or object, and do not log any authorization information.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;log.info("PUT /users/{userId} called with userId={} and userRequestDTO={} with X-ServiceNumber={} with Authorization={}", userId, userRequestDTO, serviceNumber, token);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;✅ Log only the necessary&lt;/p&gt;

&lt;p&gt;&lt;code&gt;log.info("POST /users/{} called with X-ServiceNumber={}, userId, serviceNumber);&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2 - Service Layer Logging
&lt;/h2&gt;

&lt;p&gt;Log at the start and end of &lt;strong&gt;every&lt;/strong&gt; public service method.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;log.info("Starting UserService.getUserById with userId={}", userId);&lt;/code&gt;&lt;br&gt;
&lt;em&gt;// ... business logic ...&lt;/em&gt;&lt;br&gt;
&lt;code&gt;log.info("Finished UserService.getUserById for userId={}", userId);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This creates a clear log bracket that makes tracing the flow between layers easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  3 - Repository Layer Logging
&lt;/h2&gt;

&lt;p&gt;When data is retrieved from the database:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log the number of rows returned.&lt;/li&gt;
&lt;li&gt;If it’s a count query, log the result count.&lt;/li&gt;
&lt;li&gt;If the query is suposed to return one item, like find by id, log only 1 important information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;log.info("Fetched {} users from the database for active={}", users.size(), active);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;log.info("Total number of active users in the system: {}", userCount);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;log.info("Retrieved user with id: {} from database", userId);&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4 - External Service Logging
&lt;/h2&gt;

&lt;p&gt;When receiving data from an external system, from a rest api or soap, or even a 3rd party sdk.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If it returns a list, log how many rows were returned.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If it returns a single object, log &lt;strong&gt;only&lt;/strong&gt; key information (e.g., an ID or status, etc)&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;log.info("External billing service returned {} invoices for accountId={}", invoices.size(), accountId);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;log.info("Payment gateway responded with transactionId={} and status={}", transaction.getId(), transaction.getStatus());&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5 - Business Decision Logging
&lt;/h2&gt;

&lt;p&gt;Every business decision branch should be logged.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What is a business decision branch?&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A business decision branch is any point in the logic where the behavior of the application diverges based on rules, conditions, or domain-specific decisions. These aren’t just technical if/else branches, they are meaningful choices based on business rules.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a user is eligible for a discount:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;log.info("User {} is eligible for a {}% discount based on subscription plan", userId, discountAmount);&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the system decides to skip billing:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;log.info("Billing skipped for account {} because the billing period is not yet complete", accountId);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Logging these moments creates an audit trail of why the application behaved in a certain way.&lt;/p&gt;

&lt;h2&gt;
  
  
  6 - General Rules
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Every log should explain in plain English what’s happening.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Do not log sensitive information (passwords, tokens, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;JMLogFlow&lt;/strong&gt; is strict to log.info, you can use your team convention for log.debug, log.warn and log.error&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Example Summary
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;// 2 - Service Layer Logging&lt;/em&gt;&lt;br&gt;
&lt;code&gt;log.info("Starting createInvoice for accountId={}", accountId);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;// 3 - Repository Layer Logging: only 1 important information&lt;/em&gt;&lt;br&gt;
&lt;code&gt;Account account = accountRepository.findById(accountId)&lt;br&gt;
    .orElseThrow(() -&amp;gt; new NotFoundException("Account not found with id " + accountId));&lt;br&gt;
log.info("Account {} retrieved from database", accountId);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;// 5 - Business Decision Logging: check if account is in trial&lt;/em&gt;&lt;br&gt;
&lt;code&gt;if (account.isTrial()) {&lt;br&gt;
    log.info("Account {} is in trial mode, skipping invoice generation", accountId);&lt;br&gt;
    return;&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;// 3 - Repository Layer Logging: Fetch billable items&lt;/em&gt;&lt;br&gt;
&lt;code&gt;List&amp;lt;Item&amp;gt; billableItems = repository.findBillableItems(accountId);&lt;br&gt;
log.info("Found {} billable items for accountId={}", billableItems.size(), accountId);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;// 4 - External Service Logging: Send to external billing service&lt;/em&gt;&lt;br&gt;
&lt;code&gt;ExternalInvoiceResponseDTO invoice = invoiceService.sendToBillingSystem(billableItems);&lt;br&gt;
log.info("Invoice created with id={} and status={}", invoice.getId(), invoice.getStatus());&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;// 2 - Service Layer Logging: End of service&lt;/em&gt;&lt;br&gt;
&lt;code&gt;log.info("Finished createInvoice for accountId={}", accountId);&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;By placing logs at meaningful points of the flow and writing them in clear, understandable English, developers can quickly find issues issues, understand behavior, and maintain confidence in prod environment.&lt;/p&gt;

</description>
      <category>java</category>
      <category>springboot</category>
    </item>
    <item>
      <title>Internal Browsers Are Slowly Driving Us Insane</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Tue, 04 Feb 2025 13:22:07 +0000</pubDate>
      <link>https://forem.com/joaomarques/internal-browsers-are-slowly-driving-us-insane-gab</link>
      <guid>https://forem.com/joaomarques/internal-browsers-are-slowly-driving-us-insane-gab</guid>
      <description>&lt;h2&gt;
  
  
  Why Do Apps Have to Be So Annoying with Their Internal Browsers?
&lt;/h2&gt;

&lt;p&gt;Okay, let’s talk about something that’s been driving me absolutely nuts lately. Every time I click a link in an app. Whether it’s LinkedIn, GitHub, Slack, or whatever... it doesn’t open in my nice, familiar browser. Nope, it’s always some weird internal browser (probably a WebView or whatever) inside the app. And let me tell you: it sucks...&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Internal Browsers Are Just the Worst
&lt;/h2&gt;

&lt;p&gt;These internal browsers are bad, and here’s why:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I’m Already Logged In, But It Doesn’t Care&lt;/strong&gt;&lt;br&gt;
Oh, you want to check out a private repo on GitHub? Too bad! Log in again brother, because this internal browser has no idea you’re already signed in on Chrome. Same thing for Google Docs, or any other link where you need to be logged in. It’s like the app is trolling you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Features? What Features?&lt;/strong&gt;&lt;br&gt;
My main browser has all the cool extensions, bookmarks, tabs that actually work well. But these internal browsers? They’re stripped down to the bare minimum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let Me Choose, Please!&lt;/strong&gt;&lt;br&gt;
If I’m a Chrome person (or Safari, Firefox, whatever), I want to use that browser. Not some half-baked in-app thing that’s there just to trap me.&lt;/p&gt;

&lt;p&gt;Why Do Apps Even Do This?&lt;/p&gt;

&lt;p&gt;Honestly, it’s probably about two things:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1 - Keeping You Stuck in the App&lt;/strong&gt;&lt;br&gt;
They don’t want you wandering off. If you open a link in Chrome, you might forget to come back. So, boom!! internal browser. That way, you’re still technically in their app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2 - They Wanna Track You&lt;/strong&gt;&lt;br&gt;
Internal browsers let apps track what you’re doing, gather data, and maybe even throw some extra ads in your face. Unacceptable!!&lt;/p&gt;

&lt;h2&gt;
  
  
  How About Some Options?
&lt;/h2&gt;

&lt;p&gt;Here’s an idea: just let us pick how links open. It’s not that hard. A few suggestions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Let Me Use My Default Browser: Just add a setting to open links in my actual browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Big “Open in Browser” Button: If you’re gonna force me into your WebView, at least give me an easy way to jump to my browser.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Sync It Up: If you’re so desperate to keep me in your app, at least sync cookies and logins so I don’t have to re-enter passwords.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;At the end of the day, it’s all about user experience. Nobody likes being forced into a clunky, limited web view when they could just use their preferred browser. It’s frustrating, unnecessary, and makes simple tasks way harder than they need to be. Movile dev colleagues, please give us the control we deserve. Until then, I’ll keep long-pressing every link to force it open in my actual browser because I refuse to let these apps win.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why Do We Still Need Jackson or Gson in Java?</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Wed, 01 Jan 2025 19:49:39 +0000</pubDate>
      <link>https://forem.com/joaomarques/why-do-we-still-need-jackson-or-gson-in-java-1994</link>
      <guid>https://forem.com/joaomarques/why-do-we-still-need-jackson-or-gson-in-java-1994</guid>
      <description>&lt;p&gt;Alright, let’s talk about something that’s been bugging me for ages: JSON handling in Java. Why do we still need libraries like Jackson or Gson for something so basic? Seriously, it’s 2025... shouldn’t parsing and serializing JSON be a built-in feature by now?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Eternal Setup 🛠️&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every time we start a new Java project, it’s the same story. Add Jackson or Gson to the dependencies, configure the object mapper, and write boilerplate code for something that feels like it should just work out of the box. Other languages have this figured out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Is This Still a Thing? 🤔&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JSON is the language of the web. APIs are everywhere, and nearly every Java project needs to read or parse it. So why hasn’t JSON handling become a standard part of the Java SDK? I mean, we got things like &lt;code&gt;java.time&lt;/code&gt; for dates (finally), so why can’t we have &lt;code&gt;java.json&lt;/code&gt; or something?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Dream 🌟&lt;/strong&gt;&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.json.*&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;  

&lt;span class="c1"&gt;// Parse JSON to object  &lt;/span&gt;
&lt;span class="nc"&gt;MyObject&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;parse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonString&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;MyObject&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="c1"&gt;// Serialize object to JSON&lt;/span&gt;
&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;My opinion about this 💬&lt;/strong&gt;&lt;br&gt;
Java’s all about being enterprise-ready, right? Well, enterprises use JSON all the time. It’s high time the language embraced that and gave us native JSON support. Until then, I guess we’ll keep adding Jackson and Gson to our pom.xml and pretending it’s fine.&lt;/p&gt;

</description>
      <category>java</category>
      <category>jackson</category>
      <category>json</category>
    </item>
    <item>
      <title>5 Best Practices for Securing Your AWS Environment with IAM</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Sun, 22 Dec 2024 23:15:07 +0000</pubDate>
      <link>https://forem.com/joaomarques/5-best-practices-for-securing-your-aws-environment-with-iam-5ci3</link>
      <guid>https://forem.com/joaomarques/5-best-practices-for-securing-your-aws-environment-with-iam-5ci3</guid>
      <description>&lt;p&gt;Managing access and permissions in AWS is critical for maintaining the security and integrity of your cloud environment. IAM is a strong framework designed by aws, and you are responsible for making good use of it and keep your project safe from hackers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Create IAM groups to separate access&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%2F8n8rwpvd4bu3kpoy9uum.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%2F8n8rwpvd4bu3kpoy9uum.png" alt="image_1" width="800" height="196"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;image_1&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;IAM groups are collections of IAM users. Instead of assigning policies directly to each user, you can attach them to a group. Users in the group inherit the group's permissions, making it easier to manage access at scale.&lt;/p&gt;

&lt;p&gt;In this image, you have the flexibility to assign custom privileges specifically to Nick. Additionally, you can grant extra custom privileges to any other user within any group as needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Principle of least privilege&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Grant users, roles, and services only the permissions they need to perform their tasks. Avoid using overly permissive policies like Administrator Access or * permissions.&lt;/p&gt;

&lt;p&gt;Instead of this policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use short permissions for specific actions and resources:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::example-bucket/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Use multi-factor authentication (MFA)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Enable MFA for all users, especially for high privileged accounts like root user or admin users who has AdministradorAccess policy. MFA provides an additional layer of security by requiring a second factor, you can use your mobile or an external device.&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%2Fg8moffq02zehxp1f5jdk.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%2Fg8moffq02zehxp1f5jdk.png" alt="image_2" width="800" height="202"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;image_2&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are some Apps that you can download in app Store like google authenticator (my preferred), authy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Avoid using root account for daily operations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The root account has unrestricted access to all resources in your AWS environment. Use it only for initial account setup and specific administrative tasks. Create individual IAM users or roles for daily operations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Configure the password policy for your users&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Access keys and passwords should be rotated periodically to reduce the risk of unauthorized access.&lt;/p&gt;

&lt;p&gt;You can configure this in:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;IAM &amp;gt; Account Settings &amp;gt; Edit password policy&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%2Fm3wzh4v5geponug3oqkw.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%2Fm3wzh4v5geponug3oqkw.png" alt="image_3" width="800" height="321"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;image_3&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Align with industry standards or your company policies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;My opinion about this:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Aws is responsible for everything that they do, for example their infrastructure, their network security and the vulnerability analysis of the services they offer.&lt;/p&gt;

&lt;p&gt;But regarding IAM, you are responsible for creating your own Users, groups, roles, policies, monitoring, for enabling MFA to the accounts, rotating your keys often, analysing the access patterns and review given permissions to groups/users/roles.&lt;/p&gt;

&lt;p&gt;Never forget these concepts because it can lead to security breaches for your organization, I hope I helped you somehow! &lt;/p&gt;

</description>
      <category>aws</category>
      <category>iam</category>
    </item>
    <item>
      <title>Error when retrieving token from sso Token has expired and refresh failed</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Wed, 13 Nov 2024 12:56:14 +0000</pubDate>
      <link>https://forem.com/joaomarques/error-when-retrieving-token-from-sso-token-has-expired-and-refresh-failed-2769</link>
      <guid>https://forem.com/joaomarques/error-when-retrieving-token-from-sso-token-has-expired-and-refresh-failed-2769</guid>
      <description>&lt;p&gt;Working with AWS services often involves authentication using AWS Single Sign-On (SSO). While AWS CLI simplifies this process, you may occasionally encounter the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error when retrieving token from sso: Token has expired and refresh failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This error indicates that your SSO session token has expired, and AWS CLI couldn't refresh it automatically. Let's explore why this happens and how you can resolve it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does This Error Occur?
&lt;/h2&gt;

&lt;p&gt;AWS SSO tokens are temporary credentials that expire after a set period, usually defined by your organization's policies. When the token expires, AWS CLI attempts to refresh it. However, if the refresh attempt fails—perhaps due to a network issue, an expired session, or corrupted cached credentials—you'll see this error.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Fix It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1 - Re-authenticate with AWS SSO.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The quickest way to resolve this error is to re-authenticate your AWS SSO session. Use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws sso login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will open your default browser, prompting you to log in and refresh your session token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2 - Retry Your Original Command&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After re-authenticating, retry the command that triggered the error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3 - Clear Cached Tokens&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If re-authentication doesn’t work, your cached SSO tokens might be corrupted. Clear them manually:&lt;/p&gt;

&lt;p&gt;delete the folder: &lt;code&gt;~/.aws/sso/cache/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;or execute this if you are lazy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rm -rf ~/.aws/sso/cache/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4 - Check AWS CLI Version&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Older versions of AWS CLI might have issues with SSO token management. Check your AWS CLI version with this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and analyse if you can update it for the latest.&lt;/p&gt;

&lt;h2&gt;
  
  
  My view
&lt;/h2&gt;

&lt;p&gt;Running into the "Token has expired and refresh failed" error can be frustrating, especially when you're in the middle of an important task. Luckily, the fix is usually straightforward: re-authenticate your session or clear the cache. Taking a few extra steps, like keeping your AWS CLI updated or automating token management, can help you avoid these interruptions in the future.&lt;/p&gt;

&lt;p&gt;Remember, AWS is designed to make things easier, not harder! If you run into this error, don’t panic. Follow the steps outlined here, and you’ll be back on track in no time.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>sso</category>
    </item>
    <item>
      <title>Regex for a Java Software Engineer</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Mon, 28 Oct 2024 13:18:38 +0000</pubDate>
      <link>https://forem.com/joaomarques/regex-for-a-java-software-engineer-3np4</link>
      <guid>https://forem.com/joaomarques/regex-for-a-java-software-engineer-3np4</guid>
      <description>&lt;h2&gt;
  
  
  Why do I need Regex?
&lt;/h2&gt;

&lt;p&gt;Regular expressions are patterns that help us search for specific sequences in a text. In Java, they are used with classes in the &lt;code&gt;java.util.regex&lt;/code&gt; package. &lt;br&gt;
With regex, we can find patterns, replace text, and validate inputs without adding too much code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Basic Syntax
&lt;/h2&gt;

&lt;p&gt;Let’s go over some common regex symbols and what they do:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Literal Characters&lt;/strong&gt;: The simplest regex is just plain text. &lt;code&gt;hello&lt;/code&gt; matches any occurrence of &lt;code&gt;hello&lt;/code&gt; in a string.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Wildcards&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;.&lt;/code&gt;: Matches any single character (&lt;code&gt;h.llo&lt;/code&gt; matches &lt;code&gt;hello&lt;/code&gt;, &lt;code&gt;hallo&lt;/code&gt;, &lt;code&gt;hxllo&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Character Sets&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;[abc]&lt;/code&gt;: Matches any character within the brackets (&lt;code&gt;h[aeiou]llo&lt;/code&gt; matches &lt;code&gt;hello&lt;/code&gt;, &lt;code&gt;hallo&lt;/code&gt;).&lt;br&gt;
&lt;code&gt;[a-z]&lt;/code&gt;: Matches any lowercase letter from &lt;code&gt;a&lt;/code&gt; to &lt;code&gt;z&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Quantifiers&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;*&lt;/code&gt;: Matches zero or more occurrences of the letter behind it(&lt;code&gt;go*gle&lt;/code&gt; matches &lt;code&gt;google&lt;/code&gt;, &lt;code&gt;ggle&lt;/code&gt;, &lt;code&gt;goooooooogle&lt;/code&gt;).&lt;br&gt;
&lt;code&gt;+&lt;/code&gt;: Matches one or more occurrences (&lt;code&gt;go+gle&lt;/code&gt; matches &lt;code&gt;google&lt;/code&gt;, &lt;code&gt;gooogle&lt;/code&gt;but not &lt;code&gt;ggle&lt;/code&gt;).&lt;br&gt;
&lt;code&gt;?&lt;/code&gt;: Matches zero or one occurrence of the letter behind it(&lt;code&gt;colo?ur&lt;/code&gt; matches both &lt;code&gt;colur&lt;/code&gt;and &lt;code&gt;colour&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Anchors&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;^&lt;/code&gt;: Indicates the start of a line (&lt;code&gt;^hello&lt;/code&gt; matches any line that begins with &lt;code&gt;hello&lt;/code&gt;).&lt;br&gt;
&lt;code&gt;$&lt;/code&gt;: Indicates the end of a line (&lt;code&gt;world$&lt;/code&gt; matches any line that ends with &lt;code&gt;world&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Groups&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;(abc)&lt;/code&gt;: Groups multiple characters as a single unit (&lt;code&gt;(ha)+&lt;/code&gt; matches &lt;code&gt;ha&lt;/code&gt;, &lt;code&gt;haha&lt;/code&gt;, &lt;code&gt;hahaha&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Escape Characters&lt;/strong&gt;:&lt;br&gt;
Some characters (like &lt;code&gt;.&lt;/code&gt; or &lt;code&gt;*&lt;/code&gt;) have special meanings, so prefix them with a backslash &lt;code&gt;\&lt;/code&gt; to use them literally. For instance, &lt;code&gt;\&lt;/code&gt;. will match a literal dot.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Short example:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Pattern&lt;/strong&gt;: Compiles the regular expression and matches it in a text.&lt;br&gt;
&lt;strong&gt;Matcher&lt;/strong&gt;: Applies the pattern to a specific text and helps find matches.&lt;/p&gt;

&lt;p&gt;Here’s a quick example of how these classes work together:&lt;/p&gt;

&lt;p&gt;import java.util.regex.*;&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.regex.*&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;class&lt;/span&gt; &lt;span class="nc"&gt;RegexBasicsDemo&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;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hxllo hallo hbllllllo hello"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;Pattern&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h.llo"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Matcher&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;find&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Wildcard match found: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;group&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;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What will be printed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Wildcard match found: hxllo&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Wildcard match found: hallo&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Wildcard match found: hello&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.regex.*&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;class&lt;/span&gt; &lt;span class="nc"&gt;RegexReplaceExample&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;String&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"hello hzllo hallo hillo"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="nc"&gt;Pattern&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;compile&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h[aeiou]llo"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;Matcher&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;text&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;replaceAll&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hi"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Original text: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;out&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;println&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Text after replacement: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;result&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;What will be printed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Original text: &lt;code&gt;hello hzllo hallo hillo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Text after replacement: &lt;code&gt;hi hzllo hi hi&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Useful Java Regex Methods&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;matches()&lt;/code&gt;: Checks if the whole text matches the regex pattern.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;find()&lt;/code&gt;: Searches for occurrences of the pattern in the text (returns true if, and only if, a subsequence of the input sequence matches this matcher's pattern)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;group()&lt;/code&gt;: Returns the matched text after calling find().&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;replaceAll()&lt;/code&gt;: Replaces matches in the text with a replacement string&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My opinion about regex
&lt;/h2&gt;

&lt;p&gt;As a Java developer, I’ve come to really appreciate regex for how powerful it can be with text processing. It’s amazing to see how one well-crafted line of regex can handle tasks that might otherwise need an entire block of code. For straightforward matching, regex feels perfect: it’s concise, efficient, and ideal for things like validating formats or extracting patterns.&lt;/p&gt;

&lt;p&gt;But I know not everyone feels the same way. Regex can be far from intuitive, and when patterns start getting complex, readability suffers. It’s easy to create patterns that work like magic, yet are nearly impossible for anyone else (or even yourself, later on, after you came back from a nice vacation) to understand at a glance. Complex patterns can quickly become "write-only" code.&lt;/p&gt;

&lt;p&gt;In these situations, I’ve found it better to break validation down into smaller, simpler steps. This keeps things clearer and makes it easier for others to follow the logic. While regex is such a valuable tool in Java, I think it’s best used with a bit of restraint, especially in team environments. After all, writing maintainable code means thinking of the next person who’ll read it.&lt;/p&gt;

</description>
      <category>java</category>
      <category>regex</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Preventing Multiple Processing of SQS Messages</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Mon, 22 Jul 2024 03:38:17 +0000</pubDate>
      <link>https://forem.com/joaomarques/preventing-multiple-processing-of-sqs-messages-3i9</link>
      <guid>https://forem.com/joaomarques/preventing-multiple-processing-of-sqs-messages-3i9</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Amazon SQS (Simple Queue Service) is a fully managed message queuing service that enables you to decouple and scale microservices, distributed systems, and serverless applications. AWS Lambda can process messages from an SQS queue, making it a powerful combination for event-driven applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scenario
&lt;/h2&gt;

&lt;p&gt;Imagine an AWS architecure like this:&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%2Fuurktj860num8vh7lj3f.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%2Fuurktj860num8vh7lj3f.png" alt="Architecture" width="800" height="232"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Imagine a scenario where your Lambda function fails to tag an SQS message as successfully processed. By default, Lambda retries the message up to 4 times before ignoring it. This retry behavior can lead to exponential execution of your handler:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First Lambda: Retries 4 times, potentially sending 4 messages to the next queue.&lt;/li&gt;
&lt;li&gt;Second Lambda: Each of the 4 messages triggers 4 retries, resulting in 16 executions.&lt;/li&gt;
&lt;li&gt;Third Lambda: Each of the 16 messages triggers 4 retries, resulting in 64 executions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This exponential growth can significantly inflate your AWS costs by the end of the month.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause
&lt;/h2&gt;

&lt;p&gt;The root cause of this issue is that AWS Lambda handlers processing SQS events are expected to return an SQSBatchResponse object. If your handler returns a different type, you risk losing control over what AWS recognizes as a successful execution.&lt;/p&gt;

&lt;p&gt;Here's an example of the expected handler signature:&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SQSLambdaHandler&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;RequestHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SQSEvent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SQSBatchResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SQSBatchResponse&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQSEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&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;The SQSBatchResponse should contain a list of message IDs that failed to process. If your handler returns an SQSBatchResponse with an empty list of failed message IDs, AWS interprets this as a successful execution, and the Lambda function will not be retried for those messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code example
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SQSLambdaHandler&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;RequestHandler&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;SQSEvent&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SQSBatchResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;SQSBatchResponse&lt;/span&gt; &lt;span class="nf"&gt;handleRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQSEvent&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Context&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&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;BatchItemFailure&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;batchItemFailures&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ArrayList&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SQSMessage&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getRecords&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Message received: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getBody&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
                &lt;span class="c1"&gt;// Process the message here&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Error processing message: "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessageId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;" - "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
                &lt;span class="n"&gt;batchItemFailures&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BatchItemFailure&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessageId&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;SQSBatchResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batchItemFailures&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;When an exception is caught, we give the message another chance to be processed correctly by adding its ID to the batchItemFailures list:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;batchItemFailures.add(new BatchItemFailure(msg.getMessageId()));&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This tells Lambda to retry the message with the specified ID &lt;code&gt;msg.getMessageId()&lt;/code&gt;. The number of retry attempts is based on the configuration you have set in your cdk-stack.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>sqs</category>
      <category>lambda</category>
      <category>java</category>
    </item>
    <item>
      <title>How to Avoid the Lottery Factor</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Tue, 16 Jul 2024 04:37:41 +0000</pubDate>
      <link>https://forem.com/joaomarques/how-to-avoid-the-lottery-factor-52e2</link>
      <guid>https://forem.com/joaomarques/how-to-avoid-the-lottery-factor-52e2</guid>
      <description>&lt;p&gt;During your experience you might have heard about the &lt;strong&gt;Bus Factor&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the Bus Factor? 🚌
&lt;/h3&gt;

&lt;p&gt;The bus factor is a measure of risk in a team or project. Specifically, it refers to the number of key team members who, if suddenly unable to work (imagine they were hit by a bus), would cause the project to come to a halt or face significant delays.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the Lottery Factor? 💰
&lt;/h3&gt;

&lt;p&gt;The lottery factor is almost the same thing as the bus factor, it represents the sudden and unexpected departure of a key team member for any reason. but, instead of worrying about a key team member getting hit by a bus, imagine if they suddenly won the lottery and decided they didn't want to work anymore.&lt;/p&gt;

&lt;p&gt;Picture this: a critical member of your team hits the jackpot and becomes an instant millionaire. The next day, they walk into the office and announce that they're quitting, effective immediately. They're so eager to start their new life that they even offer the company $20,000 to find a new developer to take over their work right away.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is this a real risk? ⚠️
&lt;/h3&gt;

&lt;p&gt;If critical knowledge is concentrated in one person, their sudden exit can leave a huge gap. It’s not just about the code they wrote, but also the nuances and insights that come with experience.&lt;br&gt;
When a key player leaves abruptly, it can cause significant delays. The new person taking over needs time to get up to speed, which can slow down the whole project.&lt;br&gt;
Finding and training a new developer to handle specialized tasks isn't quick or cheap. There are recruitment costs, onboarding time, and the inevitable learning curve as the new hire gets acquainted with the project.&lt;/p&gt;

&lt;h3&gt;
  
  
  Avoid the Lottery Factor is good only for the company? 🤔
&lt;/h3&gt;

&lt;p&gt;It’s clear that avoiding these risks is crucial for the company’s market survival. However, it’s also highly beneficial for developers themselves.&lt;/p&gt;

&lt;p&gt;When developers take the time to document their code and create documentation, it shows that they care about the company’s success, not just their monthly paycheck. This can enhance their reputation within the company and demonstrate their commitment to the business.&lt;/p&gt;

&lt;p&gt;By contributing to a culture of knowledge sharing and collaboration, developers who do that position themselves as valuable team members who invest in the long-term success of the project and the organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Strategies to Avoid the Lottery Factor
&lt;/h2&gt;

&lt;p&gt;The Lottery Factor might sound like a joke, but it's a real risk. Check out some ways to avoid it:&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross Training ✝️
&lt;/h3&gt;

&lt;p&gt;Rotate team members through different parts of the project regularly, &lt;br&gt;
ensuring knowledge distribution.&lt;br&gt;
For developers, cross-training is an opportunity for professional growth. It shows that the company values their development and is willing to invest in their skill set.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Reviews 💻
&lt;/h3&gt;

&lt;p&gt;Code reviews are excellent for mitigating the lottery factor because they promote knowledge sharing, improve code quality, and build a collaborative team culture. By allowing team members to see each other's work, code reviews spread knowledge about different parts of the codebase, ensuring more people understand critical components. They also help catch bugs, identify potential issues, and enforce coding standards, making the code easier to understand and maintain. Additionally, code reviews provide a platform for mentorship, allowing less experienced developers to learn from their more experienced colleagues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Documentation ✏️
&lt;/h3&gt;

&lt;p&gt;Code documentation is crucial for mitigating the lottery factor because it ensures that knowledge about the codebase is accessible to everyone, not just the original developers. Good documentation provides clear explanations of how the code and infrastructure works, its purpose, and how to use it, which makes it easier for new or other team members to understand and work with the code.&lt;/p&gt;

&lt;h3&gt;
  
  
  A powerful readme file ⚡
&lt;/h3&gt;

&lt;p&gt;A powerful README file is essential for mitigating the lottery factor because it serves as a comprehensive guide to the project's purpose, setup, usage, and key components.&lt;br&gt;
A well-crafted README ensures that critical information is not confined to a single individual. This allows anyone to quickly understand and contribute to the project, minimizing disruption if a key developer leaves. Additionally, it supports smoother onboarding and maintenance, enhancing the project's resilience and continuity.&lt;/p&gt;

&lt;h2&gt;
  
  
  My opinion in all of this ✨
&lt;/h2&gt;

&lt;p&gt;As a developer, I've often received appreciation from my colleagues for the documentation I've created. It has helped them get unblocked and continue their work smoothly.&lt;/p&gt;

&lt;p&gt;If I ever leave the company, for any reason (not just winning the lottery), I want to ensure that I can still support my team by providing them with links to documentation I've already worked on, I can make my transition seamless. While I'm happy to join calls to answer any questions they might have, having comprehensive documentation ensures that they have a reliable reference even in my absence.&lt;/p&gt;

&lt;p&gt;Good documentation not only helps your colleagues but also maintains your own peace of mind. If you fall sick or need to take an unplanned vacation, knowing that everything is written down means you don't have to worry about the team being stuck without you. It’s a win-win for everyone involved.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>4 Database tips for Java Developers 💡</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Mon, 08 Jul 2024 00:18:44 +0000</pubDate>
      <link>https://forem.com/joaomarques/4-database-tips-for-java-developers-2hg9</link>
      <guid>https://forem.com/joaomarques/4-database-tips-for-java-developers-2hg9</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;🔍 Understanding databases is essential for Java developers, as they frequently handle critical data such as user information, past actions, application settings, and feature flags. As applications expand, databases must scale to meet performance demands and ensure efficient data management. For insights into scaling databases effectively, refer to my &lt;a href="https://dev.to/joaomarques/optimizing-bank-data-growth-with-sharding-architecture-3pnf"&gt;article on optimizing bank data growth with sharding architecture.&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;🚀 Drawing from my experience, I've wrote 4 essential tips to enhance your database practices in Java.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Always use an ORM Framework (Please do that, think about your future dev colleagues 😅)
&lt;/h3&gt;

&lt;p&gt;💡 &lt;strong&gt;Why:&lt;/strong&gt; ORM frameworks like Hibernate or JPA help manage database interactions efficiently, reducing boilerplate code and they manage the protection for SQL injections.&lt;br&gt;
Trust me, big applications without orm are very hard to maintain and takes more time than you think to manage simple things.&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;Example:&lt;/strong&gt; Using Hibernate with JPA annotations.&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.persistence.*&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Table&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"users"&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;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="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unique&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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;username&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Column&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"email"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nullable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;unique&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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 (I'd ratter use lombok)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Repository:&lt;/strong&gt;&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="c1"&gt;// Repository class using Spring Data JPA&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.data.jpa.repository.JpaRepository&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;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="nc"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;findByUsername&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;username&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;h3&gt;
  
  
  2. Validate Input Data
&lt;/h3&gt;

&lt;p&gt;💡 &lt;strong&gt;Why:&lt;/strong&gt; Validating data ensures that only correct and expected data is stored, preventing corruption and errors.&lt;br&gt;
Make sure your services are ready catch exceptions coming from the database.&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;Example:&lt;/strong&gt; Using Hibernate Validator.&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.validation.constraints.*&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Table&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"users"&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;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="nd"&gt;@NotNull&lt;/span&gt;
    &lt;span class="nd"&gt;@Size&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&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;username&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@NotNull&lt;/span&gt;
    &lt;span class="nd"&gt;@Email&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 (I'd ratter use lombok)&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Implement Database Transactions
&lt;/h3&gt;

&lt;p&gt;💡 &lt;strong&gt;Why:&lt;/strong&gt; Transactions ensure that you database transactions can always rollback in case an exception happens during thread execution.&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;Example:&lt;/strong&gt; Using Spring's &lt;code&gt;@Transactional&lt;/code&gt; annotation.&lt;br&gt;
In this example, in case &lt;code&gt;userActivityRepository.save(activity)&lt;/code&gt; throws an exception &lt;code&gt;userRepository.save(user)&lt;/code&gt; will be rolled back.&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.stereotype.Service&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.transaction.annotation.Transactional&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&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="nd"&gt;@Transactional&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;createUserAndSaveActivity&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="nc"&gt;UserActivity&lt;/span&gt; &lt;span class="n"&gt;activity&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&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="n"&gt;userActivityRepository&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;activity&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;h3&gt;
  
  
  4. Monitor Queries
&lt;/h3&gt;

&lt;p&gt;💡 &lt;strong&gt;Why:&lt;/strong&gt; Monitoring queries can inform your team where in your application is causing the bottleneck.&lt;br&gt;
The team can create jira tickets to work on the performance for those bottleneck queries.&lt;/p&gt;

&lt;p&gt;💻 &lt;strong&gt;Example:&lt;/strong&gt; Using Hibernate's statistics with the &lt;code&gt;@Timed&lt;/code&gt; annotation from the Spring Metrics module to monitor the performance.&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.stereotype.Repository&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.springframework.metrics.annotation.Timed&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.persistence.EntityManager&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;javax.persistence.PersistenceContext&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.List&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Repository&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;UserRepository&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// PersistenceContext was used only for example&lt;/span&gt;
    &lt;span class="nd"&gt;@PersistenceContext&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;EntityManager&lt;/span&gt; &lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@Timed&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&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;getUsersWithOptimizedQuery&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;role&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;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createQuery&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"SELECT u FROM User u WHERE u.role.name = :roleName"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;User&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="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"roleName"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                            &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getResultList&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;📈 Implementing these strategies are just the basis to keep your database clean and efficient when working with Java applications, that can grow anytime.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Mastering API Integrations: A Step-by-Step Guide to Secure API Authentication in Java</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Mon, 17 Jun 2024 22:55:08 +0000</pubDate>
      <link>https://forem.com/joaomarques/mastering-api-integrations-a-step-by-step-guide-to-secure-api-authentication-in-java-3b36</link>
      <guid>https://forem.com/joaomarques/mastering-api-integrations-a-step-by-step-guide-to-secure-api-authentication-in-java-3b36</guid>
      <description>&lt;h3&gt;
  
  
  Introduction 🛤️
&lt;/h3&gt;

&lt;p&gt;Integrating with external APIs is a common practice in software development, allowing your applications to consume third-party services and expand their functionalities. Among these APIs, some stand out as robust solutions for managing subscriptions, products, and other variety of operations.&lt;/p&gt;

&lt;p&gt;In this article, I will explain how to configure a service in Java to authenticate and interact with a REST API, specifically focusing on the authentication process. The goal is to provide a detailed guide that facilitates the creation of a secure and efficient integration with the external API, ensuring that your applications can fully leverage the resources offered by the platform without making unnecessary refresh token requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  About ♟️
&lt;/h3&gt;

&lt;p&gt;An external API allows you to manage the lifecycle of items related to the data that you need, and it will charge you for the amount of requests you make. To interact with the API, you need to authenticate your requests using a token-based authentication method. This method ensures that only authorized users can access the API resources.&lt;/p&gt;

&lt;p&gt;This is the structure that we will talk about in this article:&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%2Fakvlnnm3mchywdgmxdc0.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%2Fakvlnnm3mchywdgmxdc0.png" alt="The auth service structure in the project" width="481" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Environment 🧩
&lt;/h3&gt;

&lt;p&gt;To test and develop integrations with an external API, you can use the development environment provided by the service, accessible at a specific URL. This environment allows you to perform test operations without affecting production data, providing a safe space for developing and validating your integrations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creating a Sandbox Account&lt;/strong&gt;: First, you need to create a sandbox account with the external service. This account allows you to access the development environment and test all API functionalities without risks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Obtaining API Credentials&lt;/strong&gt;: After creating your sandbox account, obtain your API credentials (client ID and client secret). These credentials will be used to authenticate your requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;API Endpoints&lt;/strong&gt;: Use the development environment's endpoints to make your requests. For example, the endpoint for authentication might be something like &lt;code&gt;https://rest.test.external-service.com/oauth/token&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Note that it is possible to define requests that require the presence of the authentication token and those that do not.&lt;/p&gt;

&lt;h3&gt;
  
  
  The basis 🥾
&lt;/h3&gt;

&lt;p&gt;First, I'll create the base of the HTTP service, where the base HTTP methods will be present.&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BaseHttpService&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;DEFAULT_CHARSET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"UTF-8"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;post&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;url&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;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&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;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;HttpPost&lt;/span&gt; &lt;span class="n"&gt;httpPost&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpPost&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;addHeadersToRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpPost&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;StringEntity&lt;/span&gt; &lt;span class="n"&gt;requestBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StringEntity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;DEFAULT_CHARSET&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;httpPost&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setEntity&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestBody&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;executeRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpPost&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;get&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;url&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&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;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;HttpGet&lt;/span&gt; &lt;span class="n"&gt;httpGet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HttpGet&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;addHeadersToRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpGet&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;executeRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;httpGet&lt;/span&gt;&lt;span class="o"&gt;);&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="nf"&gt;executeRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpUriRequest&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="nc"&gt;CloseableHttpClient&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;HttpClients&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;createDefault&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;HttpResponse&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;HttpEntity&lt;/span&gt; &lt;span class="n"&gt;entity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEntity&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&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="k"&gt;return&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="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;jsonResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;EntityUtils&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entity&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;httpClient&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;close&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;jsonResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;addHeadersToRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;HttpRequestBase&lt;/span&gt; &lt;span class="n"&gt;httpRequest&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&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;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headers&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="k"&gt;return&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;entrySet&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;httpRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;addHeader&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getKey&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getValue&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;span class="o"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;These methods will be used to authenticate with the external API and also to complement the methods that require authentication. Therefore, they form the base of the service.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Auth class 🛂
&lt;/h3&gt;

&lt;p&gt;The next class we'll discuss is &lt;code&gt;ExternalApiAuthenticatedRequestService&lt;/code&gt;. Since it is quite large, I'll divide it into smaller parts to explain each one individually.&lt;/p&gt;

&lt;p&gt;The first part, and the most important, is to know which properties we will use in this class to maintain maximum encapsulation. These properties should be related to authentication, such as:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SecretValues&lt;/strong&gt;: An object created to store the client ID and client secret, depending on the environment your application is running in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;baseUrl&lt;/strong&gt;: The URL of your external service environment.&lt;br&gt;
&lt;code&gt;EXTERNAL_API_AUTH_PATH&lt;/code&gt;: The path to obtain the authentication token.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;isAuthenticated&lt;/strong&gt;: A boolean used to facilitate authentication control.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;bearerToken&lt;/strong&gt;: The authentication token, defined as private to ensure complete control and encapsulation over this property, being acesses only through this class.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;externalApiTokenExpirationTimeInMillis&lt;/strong&gt;: The expiration time of the token in milliseconds. We check this value when calling the getBearerToken method. If it has expired, we need to authenticate again.&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="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;SecretValues&lt;/span&gt; &lt;span class="n"&gt;secretValues&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;EXTERNAL_API_AUTH_PATH&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/oauth/token"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;isAuthenticated&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;bearerToken&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;externalApiTokenExpirationTimeInMillis&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Constructor Method 🏗️
&lt;/h3&gt;

&lt;p&gt;The constructor method should set the values for secretValues and baseUrl. This depends on each application.&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="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ExternalApiAuthenticatedRequestService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SecretValues&lt;/span&gt; &lt;span class="n"&gt;secretValues&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;baseUrl&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;secretValues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;secretValues&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;baseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;baseUrl&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// We authenticate with external Api on start, so it's faster when the first request comes&lt;/span&gt;
    &lt;span class="n"&gt;authenticateWithExternalApi&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Started ExternalApiAuthenticatedRequestService"&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;h3&gt;
  
  
  The Authentication Method 🔑
&lt;/h3&gt;

&lt;p&gt;Here is the most crucial method, which we use to authenticate with the external service by calling the post method defined above.&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="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;authenticateWithExternalApi&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authenticating to {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getAuthUrl&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;authRequestBody&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buildAuthRequestBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secretValues&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&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;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;authHeaders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class="n"&gt;authHeaders&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/x-www-form-urlencoded"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;try&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getAuthUrl&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;authRequestBody&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;authHeaders&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;ExternalApiAuthenticationResponseDTO&lt;/span&gt; &lt;span class="n"&gt;externalApiTokenExpirationTimeInMillis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
                &lt;span class="nc"&gt;Utility&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;convertStringToObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExternalApiAuthenticationResponseDTO&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;externalApiTokenExpirationTimeInMillis&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;.&lt;/span&gt;&lt;span class="na"&gt;parseLong&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;externalApiAuthenticationResponseDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getExpiresIn&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;bearerToken&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;externalApiAuthenticationResponseDTO&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getAccessToken&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;isAuthenticated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Auth token retrieved from {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;getAuthUrl&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;isAuthenticated&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not authenticate with external Api, error: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getMessage&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;Important Points about this Method&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It sends a POST request using the post method from the base class.&lt;/li&gt;
&lt;li&gt;It obtains the token from the external API and stores it in the bearerToken variable.&lt;/li&gt;
&lt;li&gt;It updates the token expiration time. We will use this value later.&lt;/li&gt;
&lt;li&gt;Calls &lt;code&gt;buildAuthRequestBody&lt;/code&gt; and &lt;code&gt;getAuthUrl&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The methods that hold hands 🧑‍🤝‍🧑
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;buildAuthRequestBody&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SecretValues&lt;/span&gt; &lt;span class="n"&gt;secretValues&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="s"&gt;"grant_type=client_credentials&amp;amp;client_id="&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;secretValues&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClientId&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="s"&gt;"&amp;amp;client_secret="&lt;/span&gt;
            &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;secretValues&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getClientSecret&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;This is to good way to not leave too much responsibility to &lt;code&gt;authenticateWithExternalApi&lt;/code&gt; method. Its easy to create tests with this separation of concerns.&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="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getAuthUrl&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;baseUrl&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;EXTERNAL_API_AUTH_PATH&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;h3&gt;
  
  
  Get the precious bearer token 💍
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getBearerToken&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;ExternalApiAuthenticationException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Validate token existence&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;isAuthenticated&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"External Api is not authenticated, authenticating"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;reAuthenticateWithExternalApi&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// Validate token expiration&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;externalApiTokenExpirationTimeInMillis&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;currentTimeMillis&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"External Api token expired, authenticating again"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;reAuthenticateWithExternalApi&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;bearerToken&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;Notice that here we cannot just call &lt;code&gt;authenticateWithExternalApi&lt;/code&gt;, because in case it fails we wanna do something about it.&lt;br&gt;
That's why I added this method &lt;code&gt;reAuthenticateWithExternalApi&lt;/code&gt;, in some application you might wanna try authenting again one or two times before throwing your exception.&lt;br&gt;
You might want to define a variable called &lt;code&gt;numberOfTrialsForAuthentication&lt;/code&gt; in your &lt;code&gt;application-{environment}.xml&lt;/code&gt; to call &lt;code&gt;reAuthenticateWithExternalApi&lt;/code&gt; recursively.&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="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;reAuthenticateWithExternalApi&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;ExternalApiAuthenticationException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;authenticateWithExternalApi&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(!&lt;/span&gt;&lt;span class="n"&gt;isAuthenticated&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ExternalApiAuthenticationException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Could not authenticate with external Api"&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;h3&gt;
  
  
  The magic methods 🖌️
&lt;/h3&gt;

&lt;p&gt;And finally your service can make authenticated get and post requests:&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;@Override&lt;/span&gt;
&lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;post&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;url&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;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&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;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headers&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="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bearer "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;getBearerToken&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;post&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Override&lt;/span&gt;
&lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;get&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;url&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&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;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;headers&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="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Authorization"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"bearer "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;getBearerToken&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&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;Note that we re-use the &lt;code&gt;get&lt;/code&gt; and &lt;code&gt;post&lt;/code&gt; methods from the base http service.&lt;/p&gt;

&lt;p&gt;Please, leave in the comments if you could understand the thought process.&lt;/p&gt;

&lt;h3&gt;
  
  
  The action 👨‍💻
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExternalApiHttpService&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;ExternalApiAuthenticatedRequestService&lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;Logger&lt;/span&gt; &lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;LoggerFactory&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ExternalApiHttpService&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="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;API_VERSION&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/v1"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="no"&gt;GET_PRODUCTS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/products/accounts/%s"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ExternalApiHttpService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;SecretValues&lt;/span&gt; &lt;span class="n"&gt;secretValues&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;baseUrl&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;super&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;secretValues&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;baseUrl&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;ProductsResponseDTO&lt;/span&gt; &lt;span class="nf"&gt;retrieveProductsFromAccount&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;accountId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
            &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;IOException&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ExternalApiAuthenticationException&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Retrieving products from account: {}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountId&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;requestPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;buildBaseUrl&lt;/span&gt;&lt;span class="o"&gt;()&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="na"&gt;format&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;GET_PRODUCTS&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;accountId&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;jsonResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requestPath&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;());&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Utility&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;convertStringToObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jsonResponse&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;ProductsResponseDTO&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="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="nf"&gt;buildBaseUrl&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;baseUrl&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="no"&gt;API_VERSION&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;And finally, you can add some http api requests in this class.&lt;/p&gt;

&lt;p&gt;notice that I only added &lt;code&gt;/products/accounts/%s&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;but you can find a good way to organize your project using this structure.&lt;/p&gt;

&lt;p&gt;If you feel that this class will grow too much, maybe would be a good idea to create a separated auth service, and call this auth service with your requests.&lt;br&gt;
In my case I added it as a parent class because at the moment only few requests are necessary. So I don't need to hold the authentication service reference and it saves me some minutes of coding 😌.&lt;/p&gt;

&lt;p&gt;Please share with me your thoughts, there is no right and wrong in this dev community, there are alternatives and developers should identify which one fits better for their outcome.&lt;/p&gt;

</description>
      <category>java</category>
      <category>api</category>
      <category>webdev</category>
      <category>codequality</category>
    </item>
    <item>
      <title>Optimizing Bank Data Growth with Sharding Architecture</title>
      <dc:creator>Joao Marques</dc:creator>
      <pubDate>Tue, 11 Jun 2024 04:22:46 +0000</pubDate>
      <link>https://forem.com/joaomarques/optimizing-bank-data-growth-with-sharding-architecture-3pnf</link>
      <guid>https://forem.com/joaomarques/optimizing-bank-data-growth-with-sharding-architecture-3pnf</guid>
      <description>&lt;p&gt;As the number of customers and the volume of related data increase, applications tend to become slower due to bottlenecks in the database. Databases need to perform increasingly complex searches on larger volumes of data.&lt;/p&gt;

&lt;p&gt;In the case of banks, this is crucial! Most financial institutions prefer to have millions of customers rather than just hundreds. Therefore, developers need to architect the backend and the database from the outset to expand exponentially and avoid bottlenecks caused by data growth.&lt;/p&gt;

&lt;p&gt;By adopting certain practices, developers can build robust and scalable systems that meet the demands of large financial institutions. The use of the Spring Framework, with its tools and libraries, facilitates the implementation of these techniques, providing a backend capable of growing along with the bank and its customers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Importance of Scalability in Banks
&lt;/h3&gt;

&lt;p&gt;For banks, database scalability is crucial for several reasons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High Availability&lt;/strong&gt;: In a bank, any interruption in services can have significant consequences. A scalable database helps ensure that services remain available even with a sudden increase in the number of transactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Consistent Performance&lt;/strong&gt;: As the volume of data increases, it is vital that queries and operations in the database maintain consistent performance to provide a good customer experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compliance and Security&lt;/strong&gt;: Banks handle sensitive data and face strict regulations. A scalable database architecture must also consider security and regulatory compliance aspects. Without this care, validations can become very costly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database Sharding
&lt;/h3&gt;

&lt;p&gt;In this article, I will discuss one of the most commonly used techniques by large banks to ensure the scalability and efficiency of their databases: database sharding.&lt;/p&gt;

&lt;p&gt;Sharding, a form of horizontal partitioning, is a scalability technique that involves dividing a large database into smaller, more manageable pieces called shards. Each shard is a complete and independent database containing a portion of the total data. These shards can be distributed across different servers, which helps distribute the workload and improve system performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is Sharding Important for Banks?
&lt;/h3&gt;

&lt;p&gt;For large banks, sharding offers several advantages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better Performance&lt;/strong&gt;: By dividing the data into shards, queries and operations are distributed among multiple servers. This reduces the load on each individual server, resulting in faster response times.&lt;br&gt;
&lt;strong&gt;Horizontal Scalability&lt;/strong&gt;: As the volume of data and transactions grows, new shards can be added as needed. This allows the system to expand efficiently and economically.&lt;br&gt;
&lt;strong&gt;Fault Isolation&lt;/strong&gt;: If a shard fails, only a portion of the data is affected, while the other shards continue to operate normally. This increases the resilience and availability of the system.&lt;br&gt;
&lt;strong&gt;Region-Specific Data Management&lt;/strong&gt;: For banks that expand internationally, like Nubank, shards can be located near the regions where the data is most accessed, further improving performance.&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%2Fnp1z7n3beytcctauibus.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%2Fnp1z7n3beytcctauibus.png" alt="architecture" width="774" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that in the image, the information about which shard contains the user's data is stored in the authentication database. After login, this information is passed to the API Gateway and then to the Spring Framework components. This ensures that requests are correctly directed to the appropriate shard, optimizing system performance and scalability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Architecture Advantage for Banks&lt;/strong&gt;&lt;br&gt;
Banks have a significant advantage: users do not need to be aware of other users within the bank. Some banks, like PicPay, offer this functionality, but they are rare. The relationship is always between the user and the central bank. This simplifies the backend design since it only needs to capture user data during authentication. After that, all account data can be located in the shards.&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%2F9f76p78sqaoeemoow9nz.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%2F9f76p78sqaoeemoow9nz.png" alt="Central bank data flow" width="91" height="441"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Microservice code example
&lt;/h3&gt;

&lt;p&gt;In order to receive the shard information, you can get it from the request coming from the API gateway.&lt;br&gt;
And immediatly set the it to the shard context:&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;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/user/deposit"&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;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;depositResponseDTO&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;userDeposit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nd"&gt;@RequestAttribute&lt;/span&gt; &lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nd"&gt;@RequestAttribute&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;shard&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nd"&gt;@Valid&lt;/span&gt; &lt;span class="nd"&gt;@RequestBody&lt;/span&gt; &lt;span class="n"&gt;depositRequestDTO&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="no"&gt;USER_DEPOSIT&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="nc"&gt;ShardContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setCurrentShard&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shard&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;userService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;deposit&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;OK&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 create a class &lt;code&gt;ShardContext&lt;/code&gt;Used to hold information of which shard the request belongs. During the execution of the current thread, we can always call &lt;code&gt;ShardContext.getCurrentShard()&lt;/code&gt; to know which shard we should access.&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ShardContext&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ThreadLocal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;currentShard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ThreadLocal&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;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;setCurrentShard&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;shardKey&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;currentShard&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;set&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shardKey&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="kd"&gt;static&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="nf"&gt;getCurrentShard&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;currentShard&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&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="kd"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;clear&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;currentShard&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;remove&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 dynamically determine the actual datasource on the current context, calling the method that i explained above.&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RoutingDataSource&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractRoutingDataSource&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Override&lt;/span&gt;
    &lt;span class="kd"&gt;protected&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt; &lt;span class="nf"&gt;determineCurrentLookupKey&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="nc"&gt;ShardContext&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCurrentShard&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;And finally, we define the datasources, you should do it using the &lt;code&gt;application-{profile}.yml&lt;/code&gt; file, but here I'm just explaining to you how it works.&lt;/p&gt;

&lt;p&gt;Notice that Im using the class &lt;code&gt;RoutingDataSource&lt;/code&gt; defined above.&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;@Configuration&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;DataSourceConfig&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Bean&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="nf"&gt;dataSource&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Configuration of multiple data sources (shards)&lt;/span&gt;
        &lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="n"&gt;shard1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createDataSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jdbc:mysql://shard1-url"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="nc"&gt;DataSource&lt;/span&gt; &lt;span class="n"&gt;shard2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;createDataSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"jdbc:mysql://shard2-url"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"username"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"password"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Routing data source&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;targetDataSources&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;
        &lt;span class="n"&gt;targetDataSources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"shard1"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shard1&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;targetDataSources&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"shard2"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;shard2&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

        &lt;span class="nc"&gt;RoutingDataSource&lt;/span&gt; &lt;span class="n"&gt;routingDataSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RoutingDataSource&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;routingDataSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setTargetDataSources&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;targetDataSources&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;routingDataSource&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setDefaultTargetDataSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;shard1&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;routingDataSource&lt;/span&gt;&lt;span class="o"&gt;;&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;DataSource&lt;/span&gt; &lt;span class="nf"&gt;createDataSource&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;url&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;username&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;password&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;HikariConfig&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;HikariConfig&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setJdbcUrl&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setUsername&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setPassword&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;HikariDataSource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&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;And these principles form the foundation of a robust architecture. Banks, more than any other institutions, require highly scalable systems to manage the ever-increasing volume of data efficiently. By implementing sharding and leveraging frameworks like Spring, developers can ensure that banking systems remain resilient, performant, and capable of growing alongside their customer base. In an industry where high availability, consistent performance, and stringent security are paramount, a scalable database architecture isn't just an advantage, it's a necessity.&lt;/p&gt;

</description>
      <category>java</category>
      <category>architecture</category>
      <category>aws</category>
      <category>microservices</category>
    </item>
  </channel>
</rss>
