Diese Tabelle ist der Kern der Migrationsdoku - fuer jedes EJB-/Java-EE-Konzept aus
docs/10-ejb-konzepte/ steht hier die konkrete Entsprechung im modernen Reactor, mit Verweis
auf die tatsaechliche Klasse auf beiden Seiten.
| Legacy (EJB/Java EE) | Klasse (Legacy) | Modern (Spring) | Klasse (Modern) |
|---|---|---|---|
| Stateless Session Bean | PolicyManagementBean |
@Service |
PolicyManagementService |
| Bean-Managed Transactions | PremiumCalculationBean |
TransactionTemplate/PlatformTransactionManager |
PremiumCalculationService |
| Container-Managed Transactions | @TransactionAttribute |
@Transactional (deklarativ) |
PolicyManagementService |
| MDB (Queue, Request/Reply) | ClaimIntakeMDB |
Kafka @KafkaListener |
ClaimIntakeKafkaListener |
| JMS-Request/Reply-Client | ClaimSubmissionClient |
ReplyingKafkaTemplate |
ClaimSubmissionKafkaClient (novaris-claims-modern) |
| MDB (Topic, Pub/Sub) | PolicyDocumentGenerationMDB, CustomerNotificationMDB |
zwei @KafkaListener-Consumer-Groups |
PolicyDocumentGenerationListener, CustomerNotificationListener (novaris-notification-modern) |
| JMS-Topic-Publisher | PolicyEventPublisherBean |
KafkaTemplate |
KafkaPolicyEventPublisherAdapter |
| Singleton + Timer Service | PolicyRenewalTimerBean |
@Scheduled + TaskScheduler |
PolicyRenewalScheduler |
| Annotationsbasierter Interceptor | AuditInterceptor (@Interceptors) |
Spring AOP @Aspect/@Around |
AuditAspect |
| XML-gebundener Interceptor | ejb-jar.xml-Binding auf PremiumCalculationBean |
(kein XML-Pendant - ein einziger, globaler Pointcut-Ausdruck statt zweier Bindungsarten) | AuditAspect |
Application Exception (rollback=true) |
PolicyNotFoundException (checked) |
unchecked RuntimeException, Rollback ist der @Transactional-Default |
PolicyNotFoundException |
Application Exception (rollback=false) |
UnderwritingRejectedException (checked) |
unchecked RuntimeException + @Transactional(noRollbackFor=...) |
UnderwritingRejectedException |
Repository als eigener @Stateless-Bean |
PolicyRepository |
Spring-Data-JPA-Interface (Singleton-Proxy) | PolicyJpaRepository |
JNDI-Lookup (@Resource(lookup=...)) |
JndiLookupHelper, JndiNames |
Spring-DI + application.yml |
KafkaTopics (Topic-Namen statt JNDI-Namen) |
| Local + Remote Interface | PolicyManagementLocal/Remote |
ein REST-Controller bedient beide Faelle | PolicyController |
| Stateful Session Bean | PolicyApplicationWizardBean |
persistierte, per ID adressierte Entity | PolicyApplicationDraft + PolicyApplicationDraftService |
| JAX-WS-Server (SEI) | novaris-billing-soap |
bleibt unveraendert (externer Partner) | - |
| JAX-WS-Client | BillingIntegrationBean |
JaxWsPortProxyFactoryBean |
SoapBillingIntegrationAdapter + BillingClientConfig |
| JAAS Custom Login Module + LTPA | NovarisLegacyLoginModule |
Spring Security (OAuth2 Resource Server + Keycloak, seit M6) | SecurityConfig |
| JSF-Portal | novaris-policy-web-legacy-jsf |
REST-API + eigenstaendiges React-SPA (seit M6) | PolicyController + novaris-policy-web-modern-spa |
| WebSphere Liberty + EAR-Deployment | novaris-policy-ear |
Spring-Boot-Fat-Jar + Container-Image | spring-boot-maven-plugin |
| Jenkins EAR-Kopie/Liberty-Deploy | ci/scripts/deploy.sh |
Jenkins Image-Build + oc apply/Helm |
folgt in M5 |
PolicyApplicationWizardBean hielt seinen Zustand (Quote -> Underwriting -> Bind) ueber
mehrere Aufrufe hinweg im EJB-Container, gebunden an eine Client-Session. Die naheliegende
Spring-Entsprechung waere ein @SessionScope-Bean gewesen - das wuerde aber Session-Affinity
voraussetzen (derselbe Pod muss jeden Folgeaufruf bedienen), was horizontaler Skalierung auf
OpenShift widerspricht. Umgesetzte Loesung: der Wizard-Zustand ist jetzt explizit als
Datenbank-Entity (PolicyApplicationDraft, siehe deren ausfuehrlichen Javadoc) persistiert und
per generierter ID adressiert statt im Server-Speicher gehalten - jeder Request kann von jedem
Pod bedient werden. Das ist ein bewusster Architekturwechsel (nicht nur eine
Technologie-Uebersetzung), verifiziert per echtem End-to-End-Lauf des kompletten
Wizard-Ablaufs (siehe novaris-policy-core-modern/README.md).
PolicyRepository musste im Legacy-Original selbst ein @Stateless-Bean sein, ausschliesslich
damit der Container einen @PersistenceContext-EntityManager injizieren konnte - "Repository
als EJB" ist ein reines Artefakt des Programmiermodells, keine fachliche Notwendigkeit. Spring
Data JPA generiert PolicyJpaRepository zur Laufzeit aus einem reinen Interface heraus, als
Singleton-Proxy - kein manuelles EntityManager-Handling, keine JPQL-Strings fuer die simplen
Faelle (Methodennamen wie findByPolicyNumber werden automatisch in eine Query uebersetzt).