<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ashish Saran Shakya</title>
    <description>The latest articles on DEV Community by Ashish Saran Shakya (@ashishsaranshakya).</description>
    <link>https://dev.to/ashishsaranshakya</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%2F3376655%2Fe814a493-b3f6-40d4-87f8-0ad54f2a8e65.png</url>
      <title>DEV Community: Ashish Saran Shakya</title>
      <link>https://dev.to/ashishsaranshakya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ashishsaranshakya"/>
    <language>en</language>
    <item>
      <title>🛠️ 7 Mistakes I Made Writing My First Spring Boot APIs (And What I Do Differently Now)</title>
      <dc:creator>Ashish Saran Shakya</dc:creator>
      <pubDate>Sat, 30 Aug 2025 21:35:48 +0000</pubDate>
      <link>https://dev.to/ashishsaranshakya/7-mistakes-i-made-writing-my-first-spring-boot-apis-and-what-i-do-differently-now-287</link>
      <guid>https://dev.to/ashishsaranshakya/7-mistakes-i-made-writing-my-first-spring-boot-apis-and-what-i-do-differently-now-287</guid>
      <description>&lt;p&gt;Spring Boot makes building APIs &lt;em&gt;feel&lt;/em&gt; deceptively easy.&lt;/p&gt;

&lt;p&gt;When I started out, I focused on just “getting things working.” But when things break—or just scale badly—you realize that working code isn’t always &lt;strong&gt;good code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Here are &lt;strong&gt;7 mistakes I made writing my first Spring Boot APIs&lt;/strong&gt;, and what I now do to write cleaner, more maintainable backends.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. &lt;strong&gt;Not Using Validation Annotations (&lt;code&gt;@Valid&lt;/code&gt;, &lt;code&gt;@NotNull&lt;/code&gt;, etc.)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I did:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Manually validated request payloads deep inside controllers or services. Missed fields caused confusing errors or null pointer exceptions.&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="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userRequest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getEmail&lt;/span&gt;&lt;span class="o"&gt;()&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;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;IllegalArgumentException&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Email is required"&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;&lt;strong&gt;Why it's a problem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Makes code noisy and repetitive&lt;/li&gt;
&lt;li&gt;Delays validation too deep into the flow&lt;/li&gt;
&lt;li&gt;Prone to human error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use Spring's built-in validation support with annotations and &lt;code&gt;@Valid&lt;/code&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="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserRequest&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="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the controller:&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;"/users"&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;?&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;createUser&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="nc"&gt;UserRequest&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="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;Pair this with &lt;code&gt;@ControllerAdvice&lt;/code&gt; to handle validation exceptions cleanly.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. &lt;strong&gt;Hardcoding config with &lt;code&gt;@Value&lt;/code&gt; instead of using &lt;code&gt;@ConfigurationProperties&lt;/code&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I did:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Injected config values everywhere using &lt;code&gt;@Value&lt;/code&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="nd"&gt;@Value&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"${aws.s3.bucket}"&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;bucketName&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;Why it's a problem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scattered config makes things hard to manage&lt;/li&gt;
&lt;li&gt;No way to validate values&lt;/li&gt;
&lt;li&gt;Harder to write unit tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use &lt;code&gt;@ConfigurationProperties&lt;/code&gt; to bind entire config blocks into structured classes.&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;@ConfigurationProperties&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"aws.s3"&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;S3Properties&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;bucket&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="c1"&gt;// getters/setters&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you validation, IDE support, and cleaner wiring.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. &lt;strong&gt;Logging the Wrong Way&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I did:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Used &lt;code&gt;System.out.println()&lt;/code&gt; and vague messages like “Error occurred” or “Debug here”.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's a problem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not visible in production logs&lt;/li&gt;
&lt;li&gt;Lacks context (who, what, when)&lt;/li&gt;
&lt;li&gt;No severity levels or structured format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use SLF4J with clear, parameterized logging:&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="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="s"&gt;"User {} uploaded file {}"&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="n"&gt;fileName&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And for errors:&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="n"&gt;log&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;"Failed to process request for user {}"&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="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be intentional with log levels: &lt;code&gt;info&lt;/code&gt;, &lt;code&gt;warn&lt;/code&gt;, &lt;code&gt;error&lt;/code&gt;, and avoid logging entire stack traces unless necessary.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. &lt;strong&gt;Messy Exception Handling&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I did:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Wrapped everything in try-catch blocks, often rethrowing or printing stack traces manually.&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="k"&gt;try&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;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;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;printStackTrace&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;throw&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why it's a problem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Duplicates logic&lt;/li&gt;
&lt;li&gt;Makes error responses inconsistent&lt;/li&gt;
&lt;li&gt;Hides real issues in production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Define custom exceptions and handle them centrally using &lt;code&gt;@ControllerAdvice&lt;/code&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="nd"&gt;@ResponseStatus&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;NOT_FOUND&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;ResourceNotFoundException&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;RuntimeException&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;ResourceNotFoundException&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;msg&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;msg&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 in a global exception handler:&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;@RestControllerAdvice&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;GlobalExceptionHandler&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@ExceptionHandler&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ResourceNotFoundException&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;public&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;handleNotFound&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ResourceNotFoundException&lt;/span&gt; &lt;span class="n"&gt;ex&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;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&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;NOT_FOUND&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                             &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&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;ErrorResponse&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ex&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;Clean, consistent, and maintainable.&lt;/p&gt;




&lt;h3&gt;
  
  
  5. &lt;strong&gt;Overusing &lt;code&gt;@Autowired&lt;/code&gt; Field Injection&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I did:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Injected everything using &lt;code&gt;@Autowired&lt;/code&gt; on fields.&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;@Autowired&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&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;Why it's a problem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Makes dependencies hard to track&lt;/li&gt;
&lt;li&gt;Breaks immutability&lt;/li&gt;
&lt;li&gt;Difficult to write unit tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use constructor injection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Service&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;UserController&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;final&lt;/span&gt; &lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&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;UserController&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UserService&lt;/span&gt; &lt;span class="n"&gt;userService&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;userService&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userService&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;Bonus: With one constructor, Spring injects it automatically—no &lt;code&gt;@Autowired&lt;/code&gt; needed.&lt;/p&gt;




&lt;h3&gt;
  
  
  6. &lt;strong&gt;Forgetting API Documentation (like Swagger/OpenAPI)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I did:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Left API documentation in someone's Notion page or none at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's a problem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Frontend teams have to guess request/response formats&lt;/li&gt;
&lt;li&gt;No way to test endpoints quickly&lt;/li&gt;
&lt;li&gt;Becomes a bottleneck during integration&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Use &lt;a href="https://springdoc.org/" rel="noopener noreferrer"&gt;springdoc-openapi&lt;/a&gt; to generate live docs with minimal setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- build.gradle / pom.xml --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;dependency&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.springdoc&lt;span class="nt"&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;springdoc-openapi-ui&lt;span class="nt"&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;version&amp;gt;&lt;/span&gt;1.6.14&lt;span class="nt"&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/dependency&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then access Swagger UI at:&lt;br&gt;&lt;br&gt;
&lt;code&gt;http://localhost:8080/swagger-ui/index.html&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;It reflects your controller annotations and helps both devs and testers.&lt;/p&gt;


&lt;h3&gt;
  
  
  7. &lt;strong&gt;Mixing DTOs with Entities&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What I did:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Used JPA entities directly in request bodies and responses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it's a problem:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leaks internal persistence logic&lt;/li&gt;
&lt;li&gt;Adds accidental complexity (lazy loading, cascade issues)&lt;/li&gt;
&lt;li&gt;Makes refactoring risky&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What I do now:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Create dedicated DTO classes:&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;UserDto&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;name&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="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use mappers like MapStruct, ModelMapper, or just write a utility:&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="nc"&gt;UserDto&lt;/span&gt; &lt;span class="nf"&gt;toDto&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;UserDto&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="na"&gt;getName&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="na"&gt;getEmail&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;Entities stay clean. APIs stay stable.&lt;/p&gt;




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

&lt;p&gt;Spring Boot abstracts a lot of complexity—but with that power comes responsibility.&lt;/p&gt;

&lt;p&gt;These 7 mistakes cost me time, performance, and headaches. But fixing them made me a better engineer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What’s one mistake &lt;em&gt;you&lt;/em&gt; made in your early Spring Boot journey?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Would love to hear your thoughts below 👇&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Intern to Engineer: The Hard Lessons You Only Learn in Production</title>
      <dc:creator>Ashish Saran Shakya</dc:creator>
      <pubDate>Tue, 22 Jul 2025 13:27:28 +0000</pubDate>
      <link>https://dev.to/ashishsaranshakya/intern-to-engineer-the-hard-lessons-you-only-learn-in-production-2gfa</link>
      <guid>https://dev.to/ashishsaranshakya/intern-to-engineer-the-hard-lessons-you-only-learn-in-production-2gfa</guid>
      <description>&lt;p&gt;When I joined UBS for a 6-month internship, I thought I knew my stuff. I’d done a few projects, written some production code—but real engineering? That was still to come.&lt;/p&gt;

&lt;p&gt;Over the next six months, I worked on the Strategic Proposal Tool, a large-scale internal platform that helps financial advisors create investment proposals for HNIs and UHNIs. This is the story of what I built, what broke, and what I’ll never forget.&lt;/p&gt;




&lt;h2&gt;
  
  
  🏗 The Context: Internship + Stack
&lt;/h2&gt;

&lt;p&gt;Before this internship, I had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A basic &lt;strong&gt;Node.js internship&lt;/strong&gt; at a small startup, working on their ecommerce platform.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;summer internship&lt;/strong&gt; with the same UBS team, working on a different application migrating it from Java 8 to Java 17, also implementing some new features.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This 6-month stint gave me the opportunity to move beyond beginner-level projects and contribute to core systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tech stack I worked with:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Java (Spring Boot)&lt;/li&gt;
&lt;li&gt;React&lt;/li&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;GitLab CI/CD&lt;/li&gt;
&lt;li&gt;Azure Kubernetes&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔧 Projects I Worked On
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Admin Banners
&lt;/h3&gt;

&lt;p&gt;Dynamic notifications (like outages or feature rollouts) for FAs logging into the system. I worked on backend logic for role-based visibility and real-time display rules. Also worked on admin API to manage the banners.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Morningstar API Integration
&lt;/h3&gt;

&lt;p&gt;Integrated Morningstar’s external API to fetch live investment instrument data, including mapping, error handling, and security.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Backend from Scratch
&lt;/h3&gt;

&lt;p&gt;We were building a new system—not just patching legacy code. I helped define DB schemas, API flows, and adapted as requirements evolved over time.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ From 33 Seconds to 2.75: One Bug That Taught Me Backend Maturity
&lt;/h2&gt;

&lt;p&gt;During load testing, a &lt;code&gt;metrics&lt;/code&gt; API I had built performed well under development conditions, but under load it hit &lt;strong&gt;33 seconds&lt;/strong&gt;—far exceeding the acceptable limit of 5 seconds.&lt;/p&gt;

&lt;p&gt;I traced it to redundant queries, missing indexes, and a few architectural changes introduced after my initial implementation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fixes I applied:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Introduced hashing to reduce repeated computation&lt;/li&gt;
&lt;li&gt;Indexed key DB columns&lt;/li&gt;
&lt;li&gt;Consolidated data retrieval across endpoints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Final result? We brought it down to &lt;strong&gt;2.75 seconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That one bug forced me to revisit how I thought about system design, clean code, and performance tradeoffs. Here’s what it taught me technically…&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Key Technical Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read the System First&lt;/strong&gt;: Understanding flows end-to-end made my development faster and more accurate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Feign Clients&lt;/strong&gt;: For cleaner internal HTTP service calls use feign clients as it abstracts the HTTP call implementation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three-Layer Architecture&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Facade Layer&lt;/code&gt;: handles interactions with the UI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Business Layer&lt;/code&gt;: core business logic, interacts with other business services&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Data Layer&lt;/code&gt;: isolated DB schema responsibilities&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🤝 Communication Is Everything
&lt;/h2&gt;

&lt;p&gt;I learned quickly that technical skills aren’t enough.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Clear communication&lt;/strong&gt; avoids bugs introduced through assumptions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stakeholder questioning&lt;/strong&gt; uncovers edge cases you won’t find in GitLab tickets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Agile workflows&lt;/strong&gt; sometimes deliver magic, other times just fragments—know when to speak up and when to flex.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  😓 One Mistake I Won’t Repeat
&lt;/h2&gt;

&lt;p&gt;That performance bug? I wish I’d spent more time analyzing how the system worked and profiling early.&lt;/p&gt;

&lt;p&gt;Now, I start by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reading similar flows&lt;/li&gt;
&lt;li&gt;Understanding performance implications&lt;/li&gt;
&lt;li&gt;Testing early, not late&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Advice to Backend Interns
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Learn your fundamentals&lt;/strong&gt;: Auth flows, backend layering, and microservices communication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Explore beyond your GitLab board&lt;/strong&gt;: Use quiet sprints to pair with seniors, refactor small pieces, or research upcoming stack changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don’t code blind&lt;/strong&gt;: Read the existing APIs and logic. Learn how the system breathes before you change it.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Over to You
&lt;/h2&gt;

&lt;p&gt;Internships are bridges—between theory and practice, between coding and designing.&lt;br&gt;&lt;br&gt;
They’re also &lt;strong&gt;one of the fastest ways to level up as an engineer&lt;/strong&gt;—if you’re curious and intentional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What was your biggest lesson from your first real backend project?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
I’d love to hear it 👇&lt;/p&gt;

</description>
      <category>java</category>
      <category>career</category>
      <category>internship</category>
      <category>backend</category>
    </item>
  </channel>
</rss>
