Apache Struts ile geliştirilen eski uygulamaları Spring Boot/Spring MVC veya modern mikroservis mimarilerine güvenli ve adım adım nasıl taşırsınız; örnek kod, riskler ve test stratejileri.
Apache Struts'tan Modern Java Web Mimarilerine Geçiş: Strateji ve Örnekler
Apache Struts, 2000'lerin ilk on yılında Java web uygulamaları için yaygın kullanılan bir MVC çatısıydı. Ancak güvenlik, bakım ve modern geliştirme deneyimi konularında günümüz gereksinimlerini karşılamıyor. Bu makalede Struts tabanlı projelerinizi neden ve nasıl modern bir Java web çatısına (ör. Spring Boot / Spring MVC, Jakarta EE, Micronaut, Quarkus) taşıyabileceğinizi, gerekli adımları, örnek kod dönüşümlerini ve test/dağıtım stratejilerini ele alacağım.
Struts'un Kısa Değerlendirmesi: Neden Geçiş Düşünmelisiniz?
Struts (özellikle Struts 1) mimarisi sınıf tabanlı Action'lar, XML konfigürasyonları ve JSP/Taglib kullanımına dayanır. Yıllar içinde ortaya çıkan güvenlik açıkları (örneğin OGNL/remote code execution tarzı sorunlar) ve bakım zorlukları, pek çok ekip için risk oluşturmuştur. Struts 2'de iyileştirmeler olsa da modern araç zincirleri ve bulut-dostu yaklaşımlar daha caziptir.
Geçiş nedenleri özetle şunlardır:
- Daha iyi topluluk desteği ve güncel güvenlik yamaları
- Bağımlılık yönetimi ve otomasyon için Spring Boot, Maven/Gradle entegrasyonu
- Mikroservis, konteyner ve bulut ortamlarına uygunluk
- Daha test edilebilir, DI tabanlı bileşen mimarileri
Modern Alternatifler: Hangisi Size Uygun?
Her proje farklıdır; monolitik bir iç yönetim uygulaması ile yüz milyon kullanıcıya hizmet veren bir portali aynı şekilde taşıyamazsınız. En yaygın alternatifler ve kullanım alanları:
- Spring Boot / Spring MVC: Mevcut monolitleri hızlı modernizasyona uygun, geniş ekosistem ve modül desteği.
- Jakarta EE (veya daha hafif Jakarta REST): Kurumsal standartlara uygun, uygulama sunucusu odaklı projeler için uygun.
- Micronaut / Quarkus: Başlangıç maliyeti düşük, hızlı başlatma ve düşük bellek tüketimiyle mikroservisler için tercih.
Karar verirken ekip yetkinliği, hedef mimari (monolit vs mikroservis), operasyon gereksinimleri ve üçüncü taraf entegrasyonlarını değerlendirin.
Geçiş Stratejileri: Saf Kopyalama mı, İnkremental Modernizasyon mu?
Genelde iki ana yaklaşım vardır: "Big Bang" (tam yeniden yazım) veya inkremental geçiş. Tam yeniden yazım kısa vadede riskli olabilir; ekipler, zaman çizelgeleri ve işlevsellik kaybı ihtimali göz önünde bulundurulmalıdır. İnkremenal geçiş çoğunlukla tercih edilir.
İnkremenal geçiş örnek adımları:
- Mevcut uygulamayı modüllere ayırın (ör. auth, user, billing)
- Her bir modülü bağımsız olarak teste tabi tutun ve kontratları (API, mesaj formatları) sabitleyin
- Edge-case'leri, uçtan uca testleri ve performans metriklerini izleyerek bir modülü modern bir çatıda yeniden yazın
- Eski ve yeni sistemi aynı anda çalıştırarak (strangler pattern) trafiği kademeli devredin
Pratik Dönüşüm: Struts Action'dan Spring MVC Controller'a Örnek
Aşağıda basit bir Struts Action örneği ve eşdeğer Spring MVC Controller örneğini göreceksiniz. Amaç, iskeleti ve veri akışını göstermek.
Struts 1.x Action örneği:
<!-- Struts action mapping in struts-config.xml -->
<action path="/login" type="com.example.action.LoginAction" name="loginForm" scope="request" validate="true" input="/login.jsp"/>
// LoginAction.java
public class LoginAction extends Action {
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response) throws Exception {
LoginForm lf = (LoginForm) form;
if (AuthService.login(lf.getUsername(), lf.getPassword())) {
return mapping.findForward("success");
}
request.setAttribute("error", "Hatalı kullanıcı");
return mapping.findForward("failure");
}
}
Eşdeğer Spring MVC Controller:
// LoginController.java
@RestController
@RequestMapping("/api")
public class LoginController {
private final AuthService authService;
public LoginController(AuthService authService) {
this.authService = authService;
}
@PostMapping("/login")
public ResponseEntity<Map<String, Object>> login(@RequestBody LoginDto dto) {
boolean ok = authService.login(dto.getUsername(), dto.getPassword());
if (ok) {
Map<String,Object> body = Map.of("status","ok");
return ResponseEntity.ok(body);
}
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Map.of("error","Hatalı kullanıcı"));
}
}
Bu dönüşümde dikkat edilmesi gerekenler:
- Form binding ve validasyon: Struts'taki form nesneleri yerine DTO + Bean Validation (javax.validation / jakarta.validation) kullanın.
- View katmanını ayrıştırın: JSP'leri modern frontend (React/Angular/Vue) ile ya da server-side templating ile değiştirin.
- Session yönetimi ve güvenlik: Spring Security gibi paketlerle oturum, CSRF ve kimlik doğrulamayı merkezi hale getirin.
Veri Geçişi, Konfigürasyon ve Bağımlılıklar
Struts projelerinde konfigürasyon genellikle XML tabanlı ve dağıtım paketine gömülüdür. Spring Boot ile dışa taşınabilir konfigürasyon (application.properties/yaml), merkezi konfigürasyon sunucuları ve profil bazlı ayarlar kullanabilirsiniz.
Bağımlılık yönetimi için Maven veya Gradle kullanın. Eski JAR'ların güvenlik açıklarını ve uyumluluk problemlerini tespit etmek için dependency-check, OWASP araçları ve SCA çözümleri uygulayın.
Test, CI/CD ve İzleme
Geçiş sırasında test kapsamınızı genişletin. Struts Action'lar genelde statik, zor test edilebilen kısımlardı; yeni mimaride birim testleri, entegrasyon testleri ve kontrat testleri (ör. Spring MockMvc, WireMock) ile hata riskini azaltın.
CI/CD boru hattı kurun: derleme, paketleme, statik analiz, güvenlik taramaları ve otomatik testler. Canary dağıtım veya blue-green stratejileri, canlı sistemlerde değişiklik riskini azaltır. İzleme için uygulama metrikleri (Prometheus, Micrometer) ve merkezi loglama (ELK/EFK) kullanın.
Migrasyon Riskleri ve Yönetim Takti̇kleri
Birkaç yaygın risk ve önlemler:
- Fonksiyon kaybı: Küçük, iyi tanımlanmış kullanıcı hikâyeleriyle ilerleyin ve E2E testlerle doğrulayın.
- Performans regresyonu: Yük testleri yapın, resource usage ölçün, gerektiğinde caching ve optimizasyon uygulayın.
- Güvenlik açıkları: Bağımlılıkların güncel olduğundan emin olun; güvenlik taramalarını otomatikleştirin.
Ayrıca ekip içi bilgi transferi planlayın: kod gözden geçirme, pair programming ve dokümantasyon kritik önemdedir.
Sık Sorulan Sorular
1) Struts uygulamasını tamamen yeniden yazmak mı yoksa kademeli geçirmek mi daha hızlıdır?
Kademeli (inkremental) geçiş genellikle daha az risklidir. Strangler pattern ile bağımsız modüller birer birer taşınabilir. Tam yeniden yazım bazı durumlarda tercih edilebilir fakat zaman, maliyet ve kayıp işlevsellik riski yüksektir.
2) Mevcut JSP tabanlı view'ları korumak mümkün mü?
Evet mümkün; Spring MVC JSP ile uyumludur. Ancak modern frontend framework'leri (React, Vue, Angular) ile API-first mimariye geçiş uzun vadede daha sürdürülebilir olur. Mevcut JSP'leri geçici olarak koruyup frontend'i kademeli olarak değiştirebilirsiniz.
3) Güvenlik için en kritik öncelik nedir?
En kritik öncelikler: güncel bağımlılıklar, giriş doğrulama/escape, CSRF koruması, session yönetimi ve merkezi kimlik doğrulama (ör. OAuth2/OpenID Connect). Ayrıca otomatik güvenlik taramaları ve kod incelemeleri düzenleyin.
İlgili Eğitim
Sonuç
Struts ile geliştirilen uygulamalar hâlâ çalışıyor olabilir ancak sürdürülebilirlik, güvenlik ve bulut uyumluluğu açısından modern bir çatıya geçiş uzun vadede kazanım sağlar. İnkremenal bir yaklaşım, kapsamlı test ve otomasyon ile riski azaltır. Spring Boot / Spring MVC genelde ilk tercih olurken, mikroservis gereksinimleri varsa Micronaut veya Quarkus değerlendirilebilir. Planlama, modülerizasyon ve otomatik testler başarılı bir geçişin anahtarıdır.
