|
Monday morning, I was sipping coffee. On my desk. in my office Sarah, along with another Junior Developer, Tom, came to me. "Service works on my laptop. Crashes in staging. Same code. No idea why!" - Said Tom I checked the log. in the staging: ERROR - No qualifying bean of type 'EmailService' available
ERROR - expected at least 1 bean which qualifies as autowire candidateBut Tom's Local logs: INFO - Started Application in 8.2 seconds
INFO - EmailService initialized successfully
Same code. Same branch. Different results. 𤷠I checked Tom's code.
// Main application
package com.company.app;
ā
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The service Package com.company.services.email;
ā
@Service
public class EmailService {
public void send(String to, String message) {
// Send email
}
}
The controller package com.company.app.controllers;
ā
@RestController
public class UserController {
ā
@Autowired
private EmailService emailService; // Bean not found!
ā
@PostMapping("/register")
public String register() {
emailService.send("user@example.com", "Welcome!"); return "ok";
}
}
"What's the difference between local and staging?" Sarah asked. Tom shrugged. "Nothing. Same Dockerfile." I checked the Dockerfile. FROM openjdk:17
COPY target/app.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
Here is how Tom ran it locally: mvn spring-boot:runThere it was!!! The Problem: In the IDE, Tom ran from the project root. Maven scanned everything. In Docker, the JAR was built with: mvn clean packageI told Sarah to check the JAR contents. She did: jar tf target/app.jar | grep EmailService NOTHING The `EmailService` class wasn't in the JAR at all. WHY? She looked at the project structure project/ ā
|___src/
| |___main/ | |____java | |___com/company/app/ | |__Application.java | |__controllers/ | |__UserController.java |___services |___src/ |___main/ |___java |___com/company/services/email/ |___EmailService.java `EmailService` was in a seperate module, outside the main `src` directory! Maven's `package` goal only bundled the main module. The IDE classpath included everything. The quick fix: Move the service src/ |___main/ |____java |___com/company/app/ |__Application.java |__controllers/ | |__UserController.java |___services |___EmailService.java Rebuild mvn clean package
java -jar target/app.jar
ā
ā
INFO - Started Application in 8.2 seconds
It WORKED!!! š The better fix But Sarah noticed another issue. Even with the correct structure: package com.company.app;
ā
@SpringBootApplication // Only scans com.company.app.*
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Can you find this? It only scans the com.company.app* If someone later moves this `EmailService` to com.company.external.services It would break again. So we have to make it explicit: @SpringBootApplication
@ComponentScan(basePackages = {
"com.company.app",
"com.company.services"
})
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
The Debug Command I showed them a trick: # Check what's actually in your JAR
jar tf target/app.jar | grep -i service
ā
# Or search for any class
jar tf target/app.jar | grep EmailService
And another one: // Add this temporarily to see what Spring found
@SpringBootApplication
public class Application {
public static void main(String[] args) {
ConfigurableApplicationContext ctx =
SpringApplication.run(Application.class, args);
String[] beans = ctx.getBeanDefinitionNames();
System.out.println("=== ALL BEANS ===");
Arrays.stream(beans)
.filter(name -> name.contains("email"))
.forEach(System.out::println);
}
}
NOTE: This one is temporary. dont forget to remove it in the production. No, if `EmailService` appears in the list, Spring found it. The takeaway:"It works on my machine" usually means:
Always check:
Quick Test: # Build like prod mvn clean package
ā
# Run the JAR (not mvn spring-boot:run)
java -jar target/app.jar If it fails locally now, you found the issue. What's next: The Memory Leak That Wasn't Heap dumps point to Spring's cache. 8GB of data. But clearing the cache changes nothing.ā another word. Did you subscribe to my YouTube channel? If yes. Thank you. if not... You can try... I upload practical video related to Spring Framework. Why not try? ātake a look hereā See you next. Thank you Iftekhar Hossain |
Iām Iftekhar ā a developer sharing what I learn about Java, Spring Boot, Spring Security, and related backend technologies like Docker, Kubernetes, and Kafka.Each week, I send one practical email with code examples, mini-projects, and real-world lessons to help you grow as a backend developer.
It was 3 am. Cold night. I was in deep sleep. That's when Sarah called me. "Payment service down. It's 500 errors!!" I was terrified. Customers couldn't buy anything. My sleep... just gone. I opened my computer.... Logged on to the server to see what happened. The log showed: ERROR - BeanCreationException: Error creating bean 'paymentProcessor' ERROR - Could not resolve placeholder 'stripe.api.secret' I was exhausted. After a loooong week of development, I just wanted to take some rest. but...
Last mail was about 'How to Use Java Records to Write Better and More Efficient Code'. But Is it really Immutable? Java often receives criticism for being too formal, requiring developers to write a lot of code even for simple tasks. It has some good sides like, it making Java code more readable and at the same time helping the developer to write code that has fewer bugs. In some instances, however, it creates unnecessary overhead. The worst case scenario is when there is a need for a data...
How to Use Java Records to Write Better and More Efficient Code JAVA is one of the most popular and widely used programming languages. In many cases, it is the first choice for enterprise application development. Even now billions of devices are powered by JAVA. If you are reading this article on your Android ā you got it! This is also run by JAVA! Oracle, the company who is responsible for developing and maintaining the JAVA language itself, introduces new features on a regular basis to make...