Spring Boot ile ilk REST API projesini oluşturan hemen her geliştirici, en az bir kez "neden çalışmıyor?" sorusuyla karşı karşıya kalır. Bunun nedeni genellikle kod mantığındaki büyük bir hata değil; bağımlılık, yapılandırma, port çakışması, anotasyon eksikliği veya bean tanımlama gibi beş temel kategoriden birine giren küçük bir aksaklıktır. Bu yazı, Spring Boot hatalarını rastgele değil, sistematik bir teşhis mantığıyla ele alarak hangi hatanın hangi kategoriye ait olduğunu ve nasıl çözüleceğini gösterir.
Spring Boot Projesi Neden Çalışmıyor? Hataların Genel Haritası
Bir Spring Boot projesi genellikle beş noktadan birinde takılır: eksik veya yanlış bağımlılıklar, hatalı application.properties yapılandırması, kullanılan portun başka bir süreç tarafından işgal edilmesi, eksik veya yanlış yerleştirilmiş anotasyonlar ve son olarak Spring'in bean'leri bulamadığı durumlar. İlk projesini yazan bir geliştirici için konsola düşen kırmızı yığın izleri (stack trace) genellikle korkutucu görünür, ama gerçekte bu mesajların büyük kısmı oldukça standarttır ve aynı birkaç kalıptan birine oturur.
Burada altını çizmek gereken önemli bir nokta var: bu hatalarla karşılaşmak, kodun kötü yazıldığı anlamına gelmez. Spring Boot, arka planda çok sayıda otomatik yapılandırma (auto-configuration) işlemi yürütür ve bu otomasyonun beklediği küçük bir detay eksik kaldığında proje ayağa kalkmaz. Deneyimli geliştiriciler de aynı hatalarla karşılaşır; fark, hatayı okuma ve kaynağını hızlıca tespit etme alışkanlığındadır. Panikle rastgele kod değiştirmek yerine, hata mesajının hangi katmandan geldiğini anlamak çözüme giden en kısa yoldur.
Bu makale tam olarak bu amaçla kurgulanmıştır: bir teşhis rehberi gibi kullanılmak üzere. İlerleyen bölümlerde bağımlılık hatalarından port çakışmalarına, anotasyon eksikliklerinden bean oluşturma sorunlarına kadar her kategori ayrı ayrı ele alınacak; her biri gerçek bir hata mesajı örneğiyle somutlaştırılacaktır. Yazının sonunda yer alan hata-neden-çözüm tablosu ise, ileride benzer bir mesajla karşılaştığınızda hızlıca başvurabileceğiniz bir referans niteliği taşıyacaktır. Amaç, hatayı ezberlemek değil; Spring Boot'un neden o hatayı verdiğini anlayarak benzer durumları kendi başınıza çözebilecek bir okuma alışkanlığı kazanmaktır.
Bağımlılık Eksikliği: pom.xml ve build.gradle Hataları
Spring Boot projelerinde karşılaşılan en temel sorunlardan biri, gerekli başlangıç bağımlılıklarının (starter) proje dosyasına eklenmemiş olmasıdır. Örneğin bir REST API yazarken spring-boot-starter-web bağımlılığı pom.xml ya da build.gradle içine eklenmemişse, proje derlense bile @RestController, ResponseEntity gibi sınıflar tanınmaz ve "cannot find symbol" ya da "package does not exist" türünde derleme hataları alınır. Bu hatanın belirtisi genellikle IDE'de kırmızı alt çizgilerle kendini gösterir; kod editörü ilgili sınıfı bulamadığında classpath'te o kütüphanenin olmadığından şüphelenmek gerekir.
Maven kullanan projelerde derleme hatası genellikle mvn clean install çıktısında "dependency not found" ya da sürüm çakışmasına işaret eden mesajlarla görülür. Gradle projelerinde ise benzer durum "Could not resolve" ifadesiyle karşımıza çıkar. Bağımlılık çakışmaları ise biraz daha sinsidir: iki farklı kütüphane aynı sınıfın farklı sürümlerini projeye taşıdığında, uygulama derlenir ama çalışma anında NoSuchMethodError gibi beklenmedik hatalar fırlatabilir. Bu noktada bağımlılık ağacını (dependency tree) incelemek, çakışan sürümü tespit etmenin en güvenilir yoludur.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Bu tür hataları hızlıca teşhis edebilmek, aslında Spring Boot'a özgü bir beceri değil; Java'nın paket ve classpath mantığını sağlam kavramaktan geçer. Bir sınıfın hangi paketten geldiğini, JAR dosyalarının classpath'e nasıl dahil edildiğini ve derleyicinin bir sembolü neden "bulamadığını" anlayan bir geliştirici, framework fark etmeksizin bu tür hataları çok daha hızlı çözer. Bu nedenle Spring Boot öğrenmeye başlamadan önce sağlam bir Java temeli kurmak büyük fark yaratır; bire bir Java dersleri bu temel kavramları pratik örneklerle pekiştirmeyi hedefler.
application.properties Yapılandırma Hataları

Bağımlılıklar doğru eklendiğinde bile proje çoğu zaman ikinci bir engelde takılır: yapılandırma dosyası. application.properties içindeki sunucu portu, veritabanı bağlantı adresi, kullanıcı adı veya şifre gibi değerlerden biri yanlış girildiğinde uygulama ya hiç açılmaz ya da açılır ama veritabanına bağlanamadığı için istekleri işleyemez. Örneğin spring.datasource.url satırındaki bağlantı adresinde bir karakter hatası, konsola "Communications link failure" ya da "Access denied" gibi bir hata mesajı olarak yansır.
Bu dosyada en sık yapılan hatalar aslında çok küçük ayrıntılardır: bir anahtar (key) isminde fazladan boşluk, yanlış yazılmış bir özellik adı (örneğin server.port yerine server.Port yazmak) veya satır sonunda kalan görünmez bir karakter, Spring Boot'un o ayarı hiç okumamasına yol açabilir. application.yml formatını tercih edenler için ise girinti (indentation) hataları en büyük tuzaktır; YAML boşluk hassasiyeti yüksek bir formattır ve yanlış girintilenmiş bir satır, o özelliğin tamamen farklı bir hiyerarşiye ait sanılmasına neden olur.
İki format arasındaki fark da sık karıştırılan bir konudur: .properties dosyasında her satır anahtar=değer şeklinde düz yazılırken, .yml dosyasında aynı ayarlar iç içe geçmiş bloklar halinde ve girintiyle ifade edilir. Bir projede aynı ayarı hem .properties hem .yml formatında yanlışlıkla iki kez tanımlamak da beklenmedik davranışlara yol açabilir. Son olarak, yapılandırma dosyasının src/main/resources klasöründe, yani classpath'in kök dizininde bulunup bulunmadığını kontrol etmek gerekir; dosya yanlış bir klasöre konduğunda Spring Boot onu hiç bulamaz ve tüm ayarlar varsayılan değerleriyle çalışır, bu da genellikle "neden ayarlarım hiç etkili olmuyor?" sorusunun cevabıdır.
Port Çakışması: "Port Already In Use" Hatası
Bir Spring Boot uygulamasını çalıştırdığınızda karşınıza çıkabilecek en can sıkıcı ama aslında en kolay çözülen hatalardan biri port çakışmasıdır. Uygulama başlarken sunucu genellikle 8080 gibi varsayılan bir portu dinlemeye çalışır; eğer bu port başka bir process tarafından zaten kullanılıyorsa Spring Boot uygulamayı ayağa kaldıramaz ve hemen kapanır. Konsolda genellikle şuna benzer bir mesaj görürsünüz:
***************************
APPLICATION FAILED TO START
***************************
Description:
Web server failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
Bu hatanın nedeni çoğu zaman iki şeyden biridir: aynı portu dinleyen tamamen farklı bir uygulama (örneğin başka bir Java servisi, bir veritabanı yönetim aracı ya da geliştirme sırasında açık kalmış bir sunucu) ya da bir önceki Spring Boot oturumunun düzgün kapanmamış olmasıdır. Özellikle IDE üzerinden "Stop" tuşuna basmadan pencereyi kapatmak, arka planda process'in canlı kalmasına ve portu bırakmamasına yol açabilir. Panik yapmadan, sırayla şu adımları izlemek sorunu net biçimde çözer:
- Portu kullanan process'i tespit edin. İşletim sisteminize göre terminal veya komut satırından ilgili port numarasını dinleyen process'in kimliğini (PID) bulun.
- Process'i sonlandırın. Bulduğunuz PID'yi kullanarak process'i güvenli şekilde durdurun; eğer bu process başka önemli bir uygulamaysa onu kapatmak yerine bir sonraki adıma geçin.
- Gerekirse server.port değerini değiştirin. application.properties dosyasına
server.port=8081gibi farklı bir değer yazarak uygulamanın başka bir portta çalışmasını sağlayın. - Uygulamayı yeniden başlatın. Değişikliği kaydettikten sonra projeyi tekrar çalıştırın ve konsolda "Tomcat started on port" mesajını görene kadar bekleyin.
Bu dört adımı bir kez elle uyguladıktan sonra port çakışmasının mantığı kalıcı olarak oturur; bir daha aynı hatayla karşılaştığınızda hangi komutu çalıştıracağınızı düşünmeden bilirsiniz.
Anotasyon ve 404 Hataları: @RestController, @Service, @Repository Eksiklikleri

Spring Boot'ta bir endpoint'e istek attığınızda 404 Not Found almak, çoğu yeni başlayanın ilk şaşırdığı durumlardan biridir; çünkü kod "doğru" görünür ama sunucu isteği hiç tanımıyor gibi davranır. Bu hatanın en sık nedeni @RestController yerine yanlışlıkla @Controller anotasyonunun kullanılmasıdır. @Controller, dönüş değerini bir view (sayfa) adı olarak yorumlar; JSON döndürmek istediğinizde @ResponseBody eklenmediği sürece istemci beklediği veriyi alamaz ve genellikle 404 ya da boş içerikle karşılaşır. Doğru çalışan bir örnek şöyledir:
@RestController
@RequestMapping("/api/kitaplar")
public class KitapController {
private final KitapService kitapService;
public KitapController(KitapService kitapService) {
this.kitapService = kitapService;
}
@GetMapping("/{id}")
public Kitap getirById(@PathVariable Long id) {
return kitapService.bul(id);
}
}
Buradaki @RestController hem @Controller hem @ResponseBody anlamına geldiği için metottan dönen nesne otomatik olarak JSON'a çevrilir. Eğer bu anotasyon tamamen unutulursa Spring, sınıfı bir web bileşeni olarak tanımaz ve endpoint hiç oluşmaz; istek attığınızda 404 almanız kaçınılmazdır. Aynı mantık katman anotasyonları için de geçerlidir. @Service iş mantığı sınıflarını, @Repository ise veri erişim sınıflarını Spring'in bean konteynerine kaydeder. Bu anotasyonlardan biri unutulursa, ilgili sınıf konteynerde hiç oluşmaz ve o sınıfı bağımlılık olarak bekleyen başka bir bileşen (örneğin controller) uygulama başlarken hata verir. Bu noktada temel anotasyonların ne işe yaradığını pratik örneklerle pekiştirmek isteyenler Java bilgi seviyesini ölçen kısa test ile hangi konularda eksik olduklarını hızlıca görebilir.
Bean Oluşturma Hataları: "No Qualifying Bean" ve NoSuchBeanDefinitionException
Spring Boot'un bağımlılık enjeksiyonu (dependency injection) mekanizması, doğru kurulduğunda sihir gibi çalışır; ama bir bean bulunamadığında hata mesajı ilk bakışta karmaşık görünebilir. En sık karşılaşılan iki mesaj şöyledir:
NoSuchBeanDefinitionException: No qualifying bean of type
'com.ornek.KitapRepository' available: expected at least 1 bean
which qualifies as autowire candidate.
Bu hatanın kök nedeni genellikle üç durumdan biridir: ilgili sınıfın @Component, @Service veya @Repository ile işaretlenmemiş olması; sınıfın component scan kapsamının tamamen dışında bir pakette bulunması; ya da bir interface'in birden fazla implementasyonu olduğunda Spring'in hangisini enjekte edeceğini karar verememesidir. Özellikle constructor injection kullanılan projelerde, constructor'ın beklediği bağımlılık konteynerde hiç oluşmamışsa uygulama başlamadan hemen çöker; bu, hatayı çalışma zamanında değil başlangıçta yakalamanın bir avantajıdır.
@Autowired kullanırken yapılan en yaygın hatalardan biri, bir interface'in iki veya daha fazla sınıf tarafından implement edildiği durumlarda hiçbir ayrım belirtmeden enjeksiyon yapmaya çalışmaktır; Spring bu durumda hangi implementasyonu vereceğini bilemez ve "No qualifying bean" yerine bu sefer birden fazla aday bulunduğu için farklı bir çakışma hatası fırlatır. Çözüm için izlenebilecek adımlar nettir:
- @Qualifier kullanın: Birden fazla implementasyon varsa, hangisinin enjekte edileceğini @Qualifier ile açıkça belirtin.
- Bean tanımını kontrol edin: İlgili sınıfın üzerinde @Component, @Service veya @Repository anotasyonlarından birinin gerçekten bulunduğundan emin olun.
- Interface-implementation ilişkisini doğrulayın: Enjekte etmeye çalıştığınız tipin interface mi somut sınıf mı olduğunu ve implementasyonun doğru şekilde bu interface'i uyguladığını gözden geçirin.
Bu tür bean hataları, kodun mantığından çok Spring'in konteyner yönetimini anlamakla ilgilidir; kavram tek başına soyut kaldığında kafa karıştırabilir. Bu yüzden gerçek projeler üzerinde birebir ilerlemek isteyenler için Java özel ders seçeneği, bu tarz hataları canlı bir ortamda adım adım çözme fırsatı sunar.
Component Scan Kapsamı Dışında Kalan Sınıflar ve Paket Yapısı Hataları
Bağımlılıklar doğru, application.properties eksiksiz, port da boş; buna rağmen bir servis veya repository sınıfı hâlâ tanınmıyorsa sorun genellikle kod içeriğinde değil, paket yapısında saklanır. Spring Boot, uygulamayı hangi sınıfların oluşturduğunu anlamak için component scan adı verilen bir tarama mekanizması kullanır ve bu tarama, rastgele bir yerden değil, ana uygulama sınıfının bulunduğu paketten başlar.
@SpringBootApplication anotasyonunu taşıyan sınıf hangi pakette duruyorsa, Spring o paketi ve onun alt paketlerini otomatik olarak tarar. Örneğin ana sınıf com.ornek.proje paketindeyse, com.ornek.proje.servis veya com.ornek.proje.repository gibi alt paketler sorunsuz taranır. Ancak bir geliştirici elindeki sınıfı hızlıca com.baska.paket altına koyarsa, o sınıf ana paketin dışında kaldığı için Spring tarafından hiç görülmez; ne bean olarak kaydedilir ne de bağımlılık enjeksiyonuna dahil edilir. Sonuç genellikle bir önceki bölümde ele alınan "no qualifying bean" hatasıdır, ama kök neden burada, paket hizasında gizlidir.
Bu tür bir hatayı teşhis etmenin en pratik yolu, projedeki paket ağacını ana sınıfın konumuyla karşılaştırmaktır. Eğer bir sınıf gerçekten farklı bir pakette durmak zorundaysa, Spring'e bunu açıkça söylemek gerekir. Bunun için @ComponentScan anotasyonu, ana uygulama sınıfına eklenerek taranacak ek paketler manuel olarak belirtilebilir:
@SpringBootApplication
@ComponentScan(basePackages = {"com.ornek.proje", "com.baska.paket"})
public class Uygulama {
public static void main(String[] args) {
SpringApplication.run(Uygulama.class, args);
}
}
Bu çözüm işe yarasa da, çoğu zaman gerçek ihtiyaç manuel tarama tanımlamak değil, paket hiyerarşisini baştan doğru kurmaktır. Sınıfları ana paketin altında mantıklı alt paketlere (controller, service, repository, model gibi) yerleştirmek hem bu hatayı tamamen önler hem de proje büyüdükçe okunabilirliği korur. Bu noktada Java'nın paket ve import mekanizmasını, sınıf erişim belirleyicilerini ve proje organizasyonunu sağlam bir şekilde kavramış olmak fark yaratır; bu temeller Java video eğitim içerikleri gibi kaynaklarla düzenli tekrar edildiğinde, ileride çok daha karmaşık Spring Boot projelerinde paket kaynaklı hatalarla neredeyse hiç karşılaşılmaz.
Hata Mesajı, Neden ve Çözüm Eşleştirme Tablosu
Buraya kadar ele alınan hataların ortak noktası, her birinin kendine özgü bir mesaj kalıbıyla ortaya çıkması ve bu kalıbın doğru okunduğunda çözümün oldukça net olmasıdır. Aşağıdaki tablo, sık karşılaşılan hata mesajlarını olası nedenleri ve pratik çözümleriyle bir arada özetler; bir hata aldığınızda önce bu tabloya bakmak, gereksiz yere kod satırlarını tek tek silip eklemekten çok daha hızlı sonuç verir.
| Hata Mesajı | Olası Neden | Çözüm |
|---|---|---|
| Whitelabel Error Page / 404 | Controller sınıfı eksik veya @RestController anotasyonu unutulmuş | Anotasyonu ve endpoint eşleşmesini kontrol edin |
| Port already in use | Aynı portta başka bir Spring Boot süreci çalışıyor | Süreci sonlandırın veya server.port ile farklı port atayın |
| NoSuchBeanDefinitionException | İlgili sınıf hiç bean olarak taranmamış | Anotasyonu ve paket konumunu doğrulayın |
| No qualifying bean of type | Birden fazla veya sıfır uygun implementasyon bulunuyor | @Qualifier kullanın veya implementasyon sayısını netleştirin |
| Cannot resolve dependency (Maven/Gradle) | Bağımlılık sürümü veya kapsamı hatalı tanımlanmış | pom.xml/build.gradle içeriğini ve yerel repository önbelleğini kontrol edin |
Bu beş kalıbın arkasında yatan mantığı özetlemek gerekirse, Spring Boot projelerinde karşılaşılan sorunların büyük kısmı şu beş başlıkta toplanır:
- Bağımlılık hataları: pom.xml veya build.gradle dosyasına eklenen kütüphanenin eksik, yanlış sürümde veya yanlış kapsamda tanımlanması.
- Yapılandırma hataları: application.properties dosyasındaki anahtar isimlerinin yanlış yazılması veya değerlerin uyumsuz olması.
- Port çakışması: aynı portu kullanan başka bir sürecin arka planda açık kalması.
- Anotasyon eksiklikleri: @RestController, @Service veya @Repository gibi anotasyonların unutulması ya da yanlış katmana konulması.
- Bean ve component scan hataları: sınıfın tarama kapsamı dışında kalması veya birden fazla implementasyonun hangisinin kullanılacağının belirtilmemesi.
Bu beş başlığı tanıyan bir geliştirici, hata mesajını gördüğü anda paniğe kapılmadan doğru yere bakmayı öğrenir; bu da zamanla bir refleks hâline gelir. Elbette bazı hatalar, özellikle birden fazla nedenin iç içe geçtiği durumlarda, yazılı kaynaklardan takip etmek yerine birebir gözden geçirilmeyi gerektirir; böyle anlarda Java özel ders desteği almak, hatanın kök nedenini saatler yerine dakikalar içinde bulmayı sağlayabilir. Asıl kalıcı kazanım ise şudur: hata mesajını okumadan tahmin yürütmek yerine, mesajı satır satır çözümleyip nedeni doğrulayarak ilerleme alışkanlığı, yalnızca Spring Boot'ta değil ileride çalışılacak her Java projesinde işe yarayan bir teşhis becerisine dönüşür.
Sık Sorulan Sorular
Spring Boot projemi çalıştırdığımda tarayıcıda "Whitelabel Error Page" görüyorum, ne yapmalıyım?
Bu sayfa genellikle uygulamanın çalıştığını ama istenen adrese karşılık gelen bir endpoint bulunamadığını gösterir. Önce ilgili sınıfın @RestController ile işaretlendiğini, ardından @GetMapping veya @RequestMapping içindeki adresin tarayıcıda yazdığınız adresle birebir eşleştiğini kontrol edin.
Port already in use hatasını almadan uygulamaya farklı bir port nasıl atarım?
application.properties dosyasına server.port=8081 gibi bir satır ekleyerek varsayılan port yerine boş olan başka bir portu kullanabilirsiniz. Ayrıca aynı portu kullanan eski bir sürecin işletim sisteminde hâlâ açık olup olmadığını kontrol etmek de kalıcı çözüm için önemlidir.
No qualifying bean ile NoSuchBeanDefinitionException hataları arasındaki fark nedir?
NoSuchBeanDefinitionException, Spring'in ilgili tipte hiçbir bean bulamadığı durumda ortaya çıkar; genellikle sınıf hiç taranmamış veya anotasyon eksiktir. No qualifying bean hatası ise sınıfın var olduğu ama birden fazla veya belirsiz implementasyon yüzünden Spring'in hangisini seçeceğine karar verememesi durumunda görülür.
@Component ve @Service anotasyonları arasındaki fark nedir, hangisini kullanmalıyım?
İkisi de sınıfı Spring bean'i olarak işaretler ve teknik olarak birbirinin yerine geçebilir, ancak @Service iş mantığı katmanındaki sınıfları anlamsal olarak ayırt etmek için kullanılır. Kodun okunabilirliği açısından, iş mantığı sınıflarında @Service, daha genel amaçlı bileşenlerde @Component tercih edilmesi önerilir.
pom.xml dosyasına bağımlılığı ekledim ama hata almaya devam ediyorum, neden olabilir?
En sık nedenlerden biri, IDE'nin veya build aracının değişikliği henüz algılamamış olmasıdır; bu durumda projeyi yeniden derlemek veya bağımlılıkları yeniden indirmek sorunu çözer. Bir diğer olasılık, eklenen bağımlılığın sürümünün projenin diğer bağımlılıklarıyla uyumsuz olmasıdır.
Component scan hangi paketleri tarar, bunu nasıl kontrol edebilirim?
Component scan, varsayılan olarak @SpringBootApplication anotasyonunu taşıyan ana sınıfın bulunduğu paketi ve bu paketin tüm alt paketlerini tarar. Bir sınıfın taranıp taranmadığını görmek için o sınıfın paket yolunu ana sınıfın paket yoluyla karşılaştırmak yeterlidir; farklı bir kök pakette ise @ComponentScan ile ek paket belirtmek gerekir.
Spring Boot'a başlamadan önce Java bilgim yeterli mi, nasıl anlarım?
Spring Boot; sınıflar, arayüzler, kalıtım, anotasyonlar ve bağımlılık yönetimi gibi Java temellerinin üzerine kurulur, bu yüzden bu kavramlarda rahat olmak öğrenme sürecini büyük ölçüde kolaylaştırır. Mevcut seviyenizi objektif biçimde görmek isterseniz Java bilgi testi ile hızlıca bir öz değerlendirme yapabilirsiniz.
Spring Boot'ta karşılaşılan hataların neredeyse tamamı, aslında birkaç tekrar eden kalıbın farklı görünümleridir; bu kalıpları tanımak, hata mesajlarını korku kaynağı olmaktan çıkarıp birer ipucuna dönüştürür. Bu süreçte sağlam bir Java temeli kurmak isteyenler, 1-1 Java kursu ile hem dil temellerini hem de bu tür pratik proje hatalarını sistemli biçimde ilerleyerek öğrenebilir.