Naar de inhoud

Blog

Legacy Java moderniseren: wat moet blijven en wat moet veranderen

Pieter Vercammen
Pieter Vercammen
Geschreven op 12 nov 2026
8 min leestijd
A transparent figure restoring a vintage steam locomotive with modern parts
Architectuur Back-End Java Modernisering

Java is niet het probleem in je legacy-applicatie. Ontdek wat je moet behouden, wat je moet veranderen en waar modernisering echt begint.

In veel directiekamers leeft hetzelfde beeld: Java is technologie van gisteren, iets waar je vroeg of laat vanaf moet.

Dat beeld klopt niet. Sinds 2017 verschijnt er elk halfjaar een nieuwe versie van Java. Java 21 en Java 25 zijn moderne LTS-releases. Wie in 2005 een enterprise-applicatie bouwde, deed dat vaak in Java. Ook vandaag blijft Java een logische keuze voor nieuwe bedrijfskritische toepassingen.

Dat betekent niet dat er niets moet gebeuren. Het systeem dat al vijftien jaar je transacties verwerkt, wordt steeds moeilijker om veilig aan te passen. Een release duurt weken. Kennis over de WebSphere-configuratie zit nog bij één ervaren developer, die binnen enkele jaren met pensioen gaat.

Er is dus wel degelijk reden om te moderniseren. Alleen ligt die zelden bij Java zelf.

In discussies over legacy Java lopen drie dingen voortdurend door elkaar: de taal en het platform, de enterprise-API’s en de architectuurstijl. Pas als je die uit elkaar haalt, wordt duidelijk wat verouderd is, wat nog perfect bruikbaar is en waar de modernisering echt moet beginnen.

De taal en het platform

Java als taal en runtime evolueert sneller dan ooit. Records, sealed classes, pattern matching en virtual threads hebben het platform de voorbije jaren grondig vernieuwd.

Virtual threads, standaard sinds Java 21, maken het bijvoorbeeld mogelijk om het vertrouwde thread-per-requestmodel te gebruiken voor grote aantallen gelijktijdige taken, zonder meteen complexe asynchrone code te moeten schrijven. Ze maken niet elke applicatie automatisch sneller, maar nemen wel een belangrijke drempel weg bij het bouwen van schaalbare toepassingen.

De taal en het platform zijn dus niet het legacyprobleem.

De enterprise-API’s

De specificaties die vroeger J2EE en Java EE heetten, leven verder als Jakarta EE onder de vleugels van de Eclipse Foundation. Jakarta EE 11 verscheen in juni 2025 en bracht onder meer Jakarta Data, ondersteuning voor records en verbeteringen voor het gebruik van virtual threads.

De namen en namespaces zijn veranderd, maar veel van de onderliggende standaarden en programmeerconcepten blijven relevant binnen moderne enterprise Java. Frameworks zoals Quarkus bouwen nog altijd voort op Jakarta-specificaties. Ook Spring gebruikt verschillende API’s uit dat ecosysteem.

De technologie is dus verder geëvolueerd. Het knelpunt zit meestal ergens anders.

De architectuurstijl

Daar ligt doorgaans het echte probleem: één sterk gekoppelde applicatie, verpakt als EAR-bestand en uitgerold op een zware applicatieserver, met slechts enkele releases per jaar.

Dat model is ontwikkeld voor een ander tijdperk. Het sluit moeilijk aan bij continuous delivery, containers en infrastructuur die snel moet kunnen schalen. Kleine wijzigingen worden daardoor al snel grote releaseprojecten.

Niet de taal is verouderd, maar de manier waarop de applicatie is opgebouwd, uitgerold en beheerd.

Bij legacy Java wordt het probleem vaak meteen bij de monoliet gelegd. Maar één deployable hoeft op zich geen slechte architectuur te zijn. Een modulaire monoliet is voor veel organisaties zelfs een verstandige doelarchitectuur, zolang de onderdelen duidelijke verantwoordelijkheden en grenzen hebben.

Het echte probleem is te veel coupling en te weinig cohesion.

Modules weten te veel van elkaar en verantwoordelijkheden liggen verspreid over verschillende delen van het systeem. Daardoor kun je een onderdeel niet afzonderlijk wijzigen, testen of deployen.

Dat maakt een systeem legacy: niet de leeftijd van de code, maar de mate waarin alles aan elkaar vasthangt.

Eén kortingsregel, twee architecturen.

Een illustratief voorbeeld:

Neem een orderplatform uit 2009. De business vraagt een nieuwe kortingsregel in de catalogus. Op papier is dat een dag werk.

In de praktijk schrijft de catalogusmodule rechtstreeks in de tabellen van facturatie. De rapporteringsmodule leest diezelfde tabellen mee en een deel van de kortingslogica zit in een JSF-scherm. Eén kleine wijziging vraagt daardoor regressietests over het hele systeem, een volledige release en een nachtelijk deploymentvenster.

Java maakt die wijziging niet complex. De rechtstreekse koppelingen en verspreide logica doen dat. Hetzelfde probleem kun je in eender welke taal bouwen.

Om het huidige landschap te begrijpen, helpt het om drie generaties te onderscheiden. In het Belgische IT-landschap kom je ze vandaag alle drie nog tegen.

Drie generaties, nog altijd naast elkaar

  1. 1. De applicatieservergeneratie Eén EAR op WebSphere, WebLogic of JBoss
    , vandaag nog in productie
  2. 2. De Spring-generatie Zelfstandige applicatie met ingebedde webserver Vandaag de mainstream van enterprise Java
    , vandaag nog in productie
  3. 3. Cloud-native by design Container-image, eventueel een native executable Frameworks zoals Quarkus
    , vandaag nog in productie

Vandaag: alle drie in productie

Mijlpalen uit het artikel

  • 2014 Spring Boot verschijnt
  • 2017 Elk halfjaar een nieuwe Java-release
  • Java 21 LTS: virtual threads worden standaard
  • Juni 2025 Jakarta EE 11
  • Java 25 LTS
Drie generaties enterprise Java, nog altijd naast elkaar.

Generatie 1: de applicatieservergeneratie

J2EE en Java EE met EJB’s, servlets, JSP of JSF, als één EAR gedeployed op WebSphere, WebLogic of JBoss.

Deze systemen zijn vaak robuust en transactieveilig, maar zwaar in beheer en traag om te veranderen. Veel ervan draaien al vijftien jaar of langer en doen nog altijd wat ze moeten doen. Alleen wordt het onderhoud elk jaar duurder en riskanter.

Generatie 2: de Spring-generatie

Applicaties die het zware EJB-model inruilden voor Spring en sinds 2014 vooral voor Spring Boot.

De winst zat niet alleen in het framework, maar vooral in de architectuur die het mogelijk maakte: zelfstandig draaiende applicaties met een ingebedde webserver, expliciete afhankelijkheden en code die buiten een applicatieserver kan worden getest.

Dit is vandaag de mainstream van enterprise Java.

Generatie 3: cloud-native by design

Architecturen die vertrekken vanuit containers, snelle opstart en elastische schaal, met frameworks zoals Quarkus die daarvoor ontworpen zijn.

Quarkus verschuift een deel van het werk van runtime naar buildtijd. In combinatie met native executables kan dat zorgen voor zeer snelle opstarttijden en een lager geheugengebruik. Dat maakt het interessant voor bepaalde cloud- en serverlessworkloads, maar niet automatisch de beste keuze voor elke applicatie.

De drie generaties bestaan vandaag naast elkaar.

Moderniseren betekent dus niet dat je Java achterlaat. Je beweegt bewust van het ene model naar het andere, op het tempo en tot het niveau dat bij je organisatie past.

De volgorde telt daarbij: eerst bepaal je welke architectuur je nodig hebt. Daarna kies je het framework dat die keuze het best ondersteunt. Niet omgekeerd.

Welk framework bij je context past, lees je in Spring Boot of Quarkus.

Als Java zelf niet het probleem is, kun je de modernisering dan niet gewoon uitstellen?

Omdat twee risico’s toenemen naarmate je langer wacht:

De talentklok

Developers die EJB 2, JSF of een specifieke WebSphere-configuratie grondig kennen, worden schaarser. Tegelijk komen er weinig nieuwe developers bij die bewust voor zo’n stack kiezen.

Hoe langer je wacht, hoe kleiner het venster waarin de mensen die het systeem nog kennen de modernisering kunnen begeleiden. Vertrekt die kennis eerst, dan moet een volgend team niet alleen de technologie vernieuwen, maar ook reconstrueren waarom het systeem werkt zoals het werkt.

De securitydruk

Bijblijven met versies is in de eerste plaats een securityzaak.

Wie met de runtime, server en bibliotheken binnen de supported range blijft, kan doorgaans snel reageren op een ernstige kwetsbaarheid. Wie jaren achterloopt, moet vaak eerst meerdere upgrades uitvoeren voordat een patch toepasbaar is. Daardoor wordt een dringend beveiligingsprobleem plots ook een omvangrijk migratietraject.

Volgens het State of the Java Ecosystem-rapport van New Relic uit 2024 draaide toen nog bijna 29% van de gemonitorde Java-applicaties op Java 8, een versie uit 2014. Tegelijk maken ISO 27001, NIS2 en strengere eisen van klanten het steeds moeilijker om een niet-ondersteunde of onvoldoende gepatchte stack te verantwoorden.

De talentklok en de securitydruk versterken elkaar. Net wanneer een upgrade dringender wordt, zijn er steeds minder mensen die de bestaande omgeving goed genoeg kennen om ze veilig uit te voeren.

Een modernisering hoeft niet meteen te beginnen met een nieuw framework of een andere architectuur. De overstap naar een ondersteunde JDK kan op zichzelf al veel opleveren.

Java zet sterk in op backwards compatibility. Code die alleen ondersteunde Java-API’s gebruikt, komt vaak verrassend goed door een upgrade. Toch is de sprong van Java 8 naar Java 21 niet altijd een kwestie van opnieuw compileren.

Verouderde dependencies, reflectie, interne JDK-API’s, verwijderde componenten en wijzigingen in standaardgedrag kunnen wel degelijk problemen veroorzaken. Zo’n upgrade is dus geen herschrijving, maar wel een traject dat je bewust moet voorbereiden, testen en meten.

Hoe ver je runtime van een ondersteunde LTS zit.

Daar staat duidelijke winst tegenover: een ondersteunde runtime, recente securityupdates en toegang tot nieuwe taal- en platformfeatures. Nog voor je één framework vervangt.

“Weg van Java” kan onnodig veel waarde vernietigen: jaren aan investeringen, opgebouwde domeinkennis en een volwassen ecosysteem.

Een betere richting is vaak: weg van het oude deploymentmodel.

Organisaties die verstandig moderniseren, behouden hun taal en grote delen van hun bedrijfslogica. Ze vervangen gericht wat knelt: een niet-ondersteunde runtime, sterke koppelingen, onduidelijke modulegrenzen en een releaseproces dat elke wijziging groter maakt dan nodig.

Dat begint met eerlijk kijken naar wat je vandaag hebt. Wat kost stilstand, in cijfers en niet alleen in gevoel? Daarover gaat wat stilstand écht kost.

Soms blijkt uit die oefening dat je beter nog even wacht. Lees dan wanneer je (nog) niet moet migreren.

Wil je weten waar in jullie landschap de grootste knelpunten zitten, dan is een objectieve second opinion op je architectuur vaak zinvoller dan meteen een migratiebudget vast te leggen.

Dit artikel is het eerste in een reeks bij het e-book Evolueer, herschrijf niet.

Het boek gaat verder waar dit artikel stopt: de businesscase, het beslissingskader voor Spring Boot en Quarkus, het strangler fig-patroon, tooling, de rol van AI en een roadmap in vier fasen. Inclusief een hoofdstuk over wanneer je beter nog niet migreert.

Pieter Vercammen is Managing Partner en Tech Lead bij CraftCode.

< Keep reading />

More from our team

Meer inzichten, tips en verdiepingen van het CraftCode-team.

De verborgen lessen van Spring: één framework, drie perspectieven
Blog </> · 5 min leestijd

De verborgen lessen van Spring: één framework, drie perspectieven

Blog </> · 3 min leestijd

De Debugging-Detective: JProfiler vs. IntelliJ Profiler

Blog </> · 3 min leestijd

TDD voor leesbare code

Blog </> · 2 min leestijd

End-to-end tracing: krijg grip op de chaos van microservices!

Aan de slag!

Klaar om jouw visie werkelijkheid te maken?
Laten we iets bouwen waar je bedrijf écht mee verder kan.