This talk is a detailed case study about the migration of a JSF-based web application from Spring 3 to Java EE 7 and CDI. It is presented at the JavaOne 2014 conference.
At first sight this didn’t seem to be too difficult. Both technologies are based on similar concepts and provide similar mechanisms for dependency injection (DI). So migrating pure annotation based bean wiring from Spring to CDI was obvious and straight forward.
But the deeper we looked into the source code the more Spring specific code we found with no direct and easy mapping in neither of JEE7, EJB3 or CDI available. Some of the problems and challenges we were confronted with were:
- How to migrate XML based bean wirings?
- How to migrate FactoryBeans?
- How to migrate AspectJ based AOP proxies?
- How to implement Spring profiles for environment based wiring?
- How to implement custom bean scopes?
- How to implement custom Spring XML schema notations and wiring?
- How to migrate code that is built against Spring APIs?
- How to migrate unit test based on Spring Test?
To answer these questions the talk will present the patterns and strategies used to map, transform and migrate the different concepts from Spring 3 to JEE7with CDI. The talk will discuss the changes and implications of the migration on the system’s architecture.
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
Migrating a JSF-Based Web Application from Spring 3 to Java EE 7 and CDI
1. Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI
Mario-Leander Reimer
mario-leander.reimer@qaware.de
QAware
2. 2| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
This talkwill …
Give a brief overview of the system’s architecture
Try to explain the rationale behind the migration
Outline differences and similarities between both technologies
Show patternsandstrategiesused during the migration to translate the different concepts
Discuss implications on the system’s architecture
Highlight problems, challenges and lessons learned
3. 3| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
A<<Application Cluster>> AIR LoaderMechanicA<<System>> AIR CentralA<<Subsystem>> MaintenanceA<<System>> AIR RepositoryI<<Subsystem>> Apache SolrA<<Client>> AIR ClientI<<Subsystem>> .NET WPFA<<Subsystem>> Solr ExtensionsA<<Subsystem>> DefectsA<<Subsystem>> Flat RatesA<<Subsystem>> Service BulletinsServiceTechnicianA<<Ext. System>> 3rd Party ApplicationA<<Subsystem>> AIR Fork DLLA<<Subsystem>> AIR Call DLLLaunchI<<Subsystem>> Spring FrameworkI<<Subsystem>> JEE 5A<<System>> AIR ControlI<<Subsystem>> JenkinsA<<Subsystem>> DocumentsA<<Subsystem>> VehiclesA<<Subsystem>> MeasuresBackend Databasesand SystemsA<<Subsystem>> Repair OverviewA<<Subsystem>> MasterdataA<<Subsystem>> JSF Web UIA<<Subsystem>> REST APIIndependentWorkshopA<<Client>> BrowserSearch andDisplayA<<Ext. System>> 3rd Party iOS AppA<<Subsystem>> AIR iOS LibA<<Subsystem>> DefectsA<<Subsystem>> Flat RatesA<<Subsystem>> Service BulletinsI<<Subsystem>> Spring FrameworkA<<Subsystem>> DocumentsA<<Subsystem>> PartsA<<Subsystem>> WS ClientsA<<Subsystem>> File StorageA<<Subsystem>> Solr AccessA<<Subsystem>> ProtocollA<<Subsystem>> WatchlistA<<Subsystem>> MasterdataA<<Subsystem>> RetrofitsAIR DBDocumentStorageA<<Ext. System>> AIR BusI<<Ext. System>> Backend SystemsQueryA<<Subsystem>> VehiclesExecuteLoad400 GBSolr IndexA<<Subsystem>> Maintenance
4. 4| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Whywouldyouwanttomigratea stableandrunningsystem?
The shortanswer: IT governance.
The longanswer:
JEE nowprovidesthesame functionalityandisa standard
Easy andcostefficientmigrationtofutureJEE versions
Lowercostsforweb infrastructureandapplicationoperations
Easy applicationmaintenanceby*-shorecompanies
Noadditional vendorsupportrequired, noadditional costs
5. 5| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
6. 6| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Annotation basedwiringofcomponentsusingconstructorinjection
7. 7| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
UsageofcustomSpring annotationsformoreexpressiveness
8. 8| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
XML basedwiringofcomponentsforSpring specificbeansandmorecomplexcomponents
9. 9| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
FactoryBeanstobuildbeaninstanceswithregularJava code
10. 10| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Usageofpropertyplaceholdersupporttoinjectconfigurationvalues
11. 11| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Implementation ofAspectJbasedproxiesforcrosscuttingconcerns
12. 12| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
ProgrammaticbeanlookupusingtheRegistry patternandtheApplicationContext
13. 13| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
UsageofSpring beanprofilesforenvironmentspecificbeanconfigurations
14. 14| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Spring XML namespacesforsyntacticsugar
15. 15| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Unit andmoduletestsheavilyuseandrelyon theSpring Testing framework
16. 16| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Wewerefacedwithmorequestionsthanwehadanswersfor
How to migrate basic annotation based bean wiring?
How to migrate XML based bean wiring and factory beans?
How to migrate Spring property placeholder support?
How to migrate AspectJ based AOP proxies?
How to migrate programmatic bean lookups?
How to migrate Spring bean profiles?
How to migrate custom Spring XML namespaces?
How to migrate code that is built against Spring APIs?
How to migrate unit test based on Spring Test?
17. 17| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
18. 18| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
19. 19| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
All new Java EE 7 Maven Coordinates
20. 20| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Individual Mavenmodulesasmainunitofmigration
ReplaceSpring annotationsandwiringswithCDI equivalent
ReplaceXML contextdefinitionswithbeans.xml
Optional: adjustcomponentstobenefitfromCDI
Find and/orbuildsubstitutesforSpring specificfeatures
Adjustunitandintegrationtests
21. 21| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Basic Spring toCDI annotationmigrationisstraightforward, withsubtledifferences
Caution: Spring andCDI havea different defaultscope!
CDI usesclientproxiesper default(exceptfor@Dependent), in Spring youhavetodo thisexplicitly.
This mightinfluenceyourwiringstyle. Becarefulwithfinal.
Spring Annotation
CDI Annotation
@Component(„myBean“)
@Named(„myBean“)
@Scope(„singleton“)
@ApplicationScoped
@Scope(„prototype“)
@Dependent
@Scope(„request“)
@RequestScoped
@Scope(„session“)
@SessionScoped
@Autowired
@Inject
Default
Default
22. 22| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Bothtechnologiessupport@Qualifiertodistinguishvariousimplementations
Tip: do not use@Namedtoqualifyyourcomponentsin CDI, use
custom@Qualifierannotationsinstead.
23. 23| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
@Stereotype istheCDI equivalenttocustom@Componentannotations
Tip: check the@Target annotationoftheCDI stereotype, and
includeMETHODso itcanbeappliedto@Producesmethods.
24. 24| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Migrate*-components.xml tobeans.xml
Tip: useCDI 1.1 bean-discovery-mode=„annotated“
astheequivalenttoSpring‘scomponentscan.
25. 25| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
XML based bean wiring as well as factory beans are migrated to Producer methods
-Factory beanscanalso usedependencyinjection
-Support forlifecycle
-Constructorinjection
-Nestedfactorybean
26. 26| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
XML based bean wiring as well as factory beans are migrated to Producer methods
27. 27| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
ThereisnodirectequivalenttoSpring‘s@Value(„${some.property}“) annotation
28. 28| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Property injectionsupportforCDI usingtheDeltaSpikeConfigurationMechanism
Tip: havea lookat Apache DeltaSpikebeforeyoustartbuilding
yourowncustomCDI extensionsformissingfeatures.
29. 29| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Migrating Spring AOP using @Interceptor and @InterceptorBindingannotations
Activate aspectsandautoproxy
relevant beans
Pointcutforall publicmethodsin classesannotatedwith@Service
Pointcutforall publicmethodsin classesannotatedwith@Repository
30. 30| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Migrating Spring AOP using @Interceptor and @InterceptorBindingannotations
31. 31| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
The CDI way for programmatic bean lookup improved our code enormously
BeanManageristhe~ equivalenttoApplicationContext
MigratedApplicationContextAwarestaticregistryclasstousetheBeanManagerinstead
Advice: don‘tuseBeanManagerdirectly.It‘stoolowlevel. Don‘tusea staticregistryeither. Gruesometestability!
Tip: ifstaticaccesstocontextualreferencesisreallyrequired, usetheDeltaSpikeBeanProviderimplementation.
32. 32| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Are Alternatives theequivalenttoSpring‘sbeandefinitionprofiles? Almost.
Problem: Alternatives needtobeactivatedin thebean.xml
Not suitableforenvironmentspecific, dynamicactivation.
Usea CDI extensiontovetoannotatedtype ifprofileisnot active.
Alternative: UsetheDeltaSpikeProjectStagemechanism.
33. 33| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
The migrationofourcustomSpring XML namespacesseemedtobea challenge
Create instanceoftype FiniteStateMachinewithgivenID asbeanname
Enumtype definitions
Create transitioninstancewithgivenproperties
Bean lookupbynameforactioninstancetoexecute
34. 34| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Programmaticapproach: combineBuilderpatternwitha producermethod
Usedfornamedaction
beanlookup
35. 35| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Improvedapproach: usea CDI extensiontoreadXML filesandcreateFSM beans
Createsinstances, usestheBuilderfromfirstapproach
36. 36| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
DirectusageofsimplifiedJMS 2.0 API insteadofSpring‘sJmsTemplate
Sending
Receiving
37. 37| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
ReplacingSpring‘sTesting Framework was painfulanda lotofwork
SpringJUnit4ClassRunnerMockitoJUnitRunner
This workreallypaidof
Simplifiedunittestswithbetterisolation
decreasedexecutiontime
Different approachesandtestrunnersforCDI testsavailable:
JglueCDI-Unit: @RunWith(CdiRunner.class)
DeltaSpikeTest-Control: @RunWith(CdiTestRunner.class)
Arquillian: @RunWith(Arquillian.class)
Testing a CDI enabledJAR in isolationiscomplexandlaborious(orjust didn‘twork)
38. 38| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
Andtherewas a lotmorecodetomigrate
MigratedSpring taskexecutionandschedulingfuntionalityto@AsyncmethodsorJEE7 ManagedExecutorService
The JPA persistencecodemigrationwentsmoothly
Migratedpersistence.xml fromJPA 1.0 to2.1
Simple JPA unittestsusingDBUnitfortestdatasetup
The JSF web layermigrationwas quitetedious
Homogenizeannotationusage: replacedFacesbeanannotationswithCDI equivalent(e.g. @ManagedBean@Named)
RemovedRegistry basedlookupofservicefacadeinstances
Migratedandsimplifiedunittests, thisalso improvedtestquality
39. 39| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
28 daysand300K LOC later…
40. 40| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
28 daysand300K LOC later…
… wehadtheAIR Central web applicationfullymigratedandrunningon Glassfishv4.
Migration effortswereordersofmagnitudelowerthaninitiallyestimatedandanticipated!
The standaloneAIR Loaderapplicationswerenexttomigrate:
usingCDI fromJava SE,
evenmorecomplexSpring XML namespace,
comprehensiveusageofSpring JDBC.
41. 41| JavaOne2014 | Migrating a JSF-based web application from Spring 3 to Java EE 7 and CDI| M.-Leander Reimer
LessonsLearnedandResumé
JEE7 andCDI havedefinitelycaughtupon Spring
Therewas noSpring featurethatcouldnot bemigrated
Someconvenienceisstill missing, but
CDI provideslightweightandeasy touseextensionmechanisms,
thereisgrowingsupportfromtheOpen Source community.
Questionandrethinkestablishedpatternsandbestpractices
More carefulwhenusingandbindingtoa specificframework
Detailed case study about the technology migration of a current project for a major German car manufacturer
Ask audience: who uses Spring / who uses JEE?
Disclaimer: No prejudice! No bashing on either technology.
This talk is purely about technology.
Some Facts:
- Rollout since last year, by the end of this year world wide
- 17250 concurrent sessions / h
- Spring Framework with some JEE5
Glassfish v2 and JDK6
400K LOC, 200K Tests, 100K Generated, 100K Handwritten
Good quality, good performance, good acceptance
Blueprint approval required for all used open source libraries
Benefit from latest bug fixes and technology improvements
More efficient and faster development
mit einem lachenden und einem weinenden Auge == with mixed feelings
Our first reaction: no way this is possible in adequate time.
This is like taking out and replacing the spine!
But we were curious, it should definitely be possible.
Usually only @Component is enough. You can also give your beans a name.
@Scope support: singleton and prototype. Session and request also supported in combination with a webapp.
Careful with injection scoped proxies.
Visibility guarantees, strong expression of dependencies
More expressiveness:
Custom Component annotations, like @Service or @Repository
Custom Qualifiers for type safety
Good old logging aspect example.
measure execution times,
echo parameters,
start and end of invocation
Service Locator pattern also called Registry
An example: Spring DSL for a FiniteStateMachine.
Other examples: other Spring namespaces, Mule ESB, Camel
Looks fancy, but it is not really hard to implement: XSD, NamespaceHandler and BeanDefinition parser.
Absolutely essential. Test basic wiring of components using mocks.
Every Maven module has ist own integration test to test module wiring in isolation.
You get the point. The longer you develop, the more you use technology to it‘s full potential.
This is our migration agenda for the next 30 minutes.
New technology and programming wouldn‘t be so much fun if it was boring and straight forward.
It is those technically challanging projects that make live as a developer interesting and worthwhile.
It was time to learn something new.
Still unsure about the effort it would take.
JEE7 Migration: Areas of Interests a lot of congruence
Spring – CDI
Everything else CDI Extensions (Deltaspike + Custom)
Common Annotations
Interceptors for AOP
JPA Persistence
JMS for Asnyc Stuff
Enterprise Beans for Services (maybe)
Concurrency for Replacement of Executors.*
Servlets -> 3.0 with CDI
Web Fragements
New JSF + EL
JAX-RS / JAX-WS
All New Java EE 7 Maven Coordinates + 2 few more
Definitely less than all the required Spring dependencies + transitive tail deps
Every business component is usually composed of API, Core and UI module. Sometimes loader module.
We have 100+ different Maven modules, all following the same pattern.
But obviously with subtle differences in Spring API usage and wiring.
No equivalent for @Scope(„globalSession“) in CDI
No equivalent for @ConversationScoped in Spring
Subtle differences:
Default scope in Spring is Singleton, in CDI it is @Dependent
In CDI you will get a client proxy, in Spring usually not.
JSR-330: no @Required or @Lazy
Characterize your components using stereotypes. @Component can be anything.
Usually you also define the lifecycle using @Scope here also.
A producer method acts as a source of objects to be injected, where:
- the objects to be injected are not required to be instances of beans,
- the concrete type of the objects to be injected may vary at runtime or
- the objects require some custom initialization that is not performed by the bean constructor
For example, producer methods let us:
- expose a JPA entity as a bean,
- expose any JDK class as a bean,
- define multiple beans, with different scopes or initialization, for the same implementation class, or
- vary the implementation of a bean type at runtime.
A producer method acts as a source of objects to be injected, where:
- the objects to be injected are not required to be instances of beans,
- the concrete type of the objects to be injected may vary at runtime or
- the objects require some custom initialization that is not performed by the bean constructor
For example, producer methods let us:
- expose a JPA entity as a bean,
- expose any JDK class as a bean,
- define multiple beans, with different scopes or initialization, for the same implementation class, or
- vary the implementation of a bean type at runtime.
No equivalent to Spring‘s @Value annotation in JSR-330.
Tip: before you start building a CDI extension or missing feature, have a look at Apache DeltaSpike
AOP as the swiss army nife for cross-cutting concerns:
- Logging, security, transactions, …
AOP as the swiss army nife for cross-cutting concerns:
- Logging, security, transactions, …
My most favourite CDI feature: programmtic bean lookup.
The simplicity is just awesome. Provides all you need to get hold of desired instances.
Good testability.
Bean definition profiles: enhancements in Spring Framework 3.1
Don‘t forget to activate the stereotype in beans.xml
Naive approach: Alternatives and stereotype activation.
Better: use DeltaSpike ProjectStages.
Optimal: Build a custom CDI extension.
Main advantage: it‘s code. It‘s readable and testable.
Slight disadvantage: does get quite long for big FSMs. Also you need to hand code it.
Idea: reuse the existing XML definitions for the FSMs.
Parse these configurations and build bean instances.
Again, the Apache DeltaSpike project saved us a lot of work.
3h and 290 LOC, comments included.
https://github.com/rmannibucau/cdi-light-config
We often used Spring tests with injection and mocks.
Migrated towards Mockito mocks and injection. No problem.
Nothing to be scared of anymore.
CDI from Java SE DeltaSpike Core
Nothing to be scared of anymore.
CDI from Java SE DeltaSpike Core
http://realworldpatterns.com/ - Real world Java EE Patterns. Rethinking Best Practices.
You live and learn: man lernt nie aus!
Basics are easy to understand and implement. And mostly sufficient.
Basics: this also applies to building Spring based applications.