Banshun - OSGi-less modularity for Spring

752 views

Published on

If you build modular app with Spring by importing children contexts into the parent ones, you face the limitations quite soon. The next step obviously, is approaching overweight OSGi. Isn't there something between these two extremes, which powerful enough and still light yet? Sure! Meet Banshun! Easy modularity for Spring.
Banshun allows to instantiate children contexts in a proper order considering declared references between singletons across the contexts.

Published in: Technology, Education
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total views
752
On SlideShare
0
From Embeds
0
Number of Embeds
2
Actions
Shares
0
Downloads
5
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Banshun - OSGi-less modularity for Spring

  1. 1. Yet Another One.... Banshun a tiny based Modular Framework http://flic.kr/p/EWNYh
  2. 2. Agenda ●Enterprise Applications ●Banshun vs OSGi, EJB ●1, 2, 3 - BOOM! ●Features ...
  3. 3. Agenda - Features ●buildtime & runtime app customization ●developer friendliness ○references validation ○cycles resolution ○root cause logging ○fault-tolerance ○dependencies graph ●Spring AOP support
  4. 4. Is it your app? :TheService + doBusiness(param) : Result
  5. 5. Is it your app? :TheService + doBusiness(param) : Result RDBMS
  6. 6. Is it your app? :TheService + doBusiness(param) : Result
  7. 7. Is it your app? <bean id="theService" class="com.foo.TheService"> ... </bean> <bean name="/web-service" class="org.spring...HessianServiceExporter"> <property name="service" ref="theService"/> .... </bean> <bean id="/form" class="com....Controller"> </bean>
  8. 8. Don't you need to deploy it? :TheService + doBusiness(param) : Result
  9. 9. Don't you need to deploy it? :TheService + doBusiness(param) : Result <<EAR>> <<container>>
  10. 10. Don't you need to deploy it? :TheService + doBusiness(param) : Result <<WAR>> <<container>>
  11. 11. The app becomes big :FooService :ZooService :MooService :FooService :BarService :BazService <<WAR>>
  12. 12. The app becomes big <<WAR>> :FooService :BarService :BazService :FooService :BarService :BazService
  13. 13. it have to be modular :FooService :BarService :BazService :MooService :ZooService <<component>> :AService :BService :CService :DService :EService <<component>>
  14. 14. :FooService :BarService :BazService :MooService :ZooService <<component>> :FooService :BarService :BazService :MooService :ZooService <<component>> <<WAR>> / <<EAR>>
  15. 15. is not modular out-of-the-box
  16. 16. even is not modular
  17. 17. <import resource="..."> is not modular because of ●bean name clashes ●global scopes of settings and aspects ●zero tolerance for module failure
  18. 18. Glue code should allow to forge modules in isolation
  19. 19. and then work altogether
  20. 20. II. Banshun vs OSGi, EJB
  21. 21. http://docs.jboss. org/jbossas/docs/Server_Configuration_Guide/4/html/Inside_the_JBoss_Class_Loading_ rchitecture-The_Complete_Class_Loading_Model.html
  22. 22. are about multiple classloaders OSGi EJB http://docs.jboss. org/jbossas/docs/Server_Configuration_Guide/4/html/Inside_the_JBoss_Class_Loading_ rchitecture-The_Complete_Class_Loading_Model.html
  23. 23. OSGi, EJB is about multiple classloaders Single classloader is enough! Banshun resolves versions at build time
  24. 24. OSGi, EJB is about hot partial redeploy
  25. 25. Never do that at prod it's not possible to assure that it works http://www.newpig.com/us/caution-hot-sign/SGN550
  26. 26. MANIFEST.MF Manifest-Version: 1.0 Bundle-Name: Simple Service Bundle Bundle-Description: Simple Service Bundle-ManifestVersion: 2 Bundle-SymbolicName: ....sdms.message.messageService Bundle-Version: 1.1.0 Import-Library: org.aspectj, org.springframework.spring Import-Bundle: com....commons.lang;version="[2.4.0,2.4.0]" Export-Package: ....sdms.message.service;version="1.1.0" What is the value for your app? YAGNI <ejb-jar xmlns="./ns/javaee" xmlns:xsi="http://www" version="3.0" xsi:schemaLocation=""> <enterprise-beans> <session> <ejb-name>TestBean</ejb-name> <env-entry> <description>admin email</description> <env-entry-name>mail</env-entry-name> <env-entry-value>admin@</env-entry> </env-entry> </session> </enterprise-beans>
  27. 27. Banshun ●don't need any build facility ●a few row artefacts
  28. 28. OSGi, EJB has weak runtime facilities launch and pray
  29. 29. http://www.lilycli.com/lart.html Banshun has full-fledged runtime ●and for everyday development ●for production
  30. 30. III How does it work? http://blog.rinajakubowicz.com/about-boom/
  31. 31. 1. instantiate children contexts <bean id="root" class="..banshun.ContextParentBean"> <property name="configLocation" value="authenticator-context.xml datasource-context.xml ..."/> ... </bean> <<WAR>> ...
  32. 32. 2. export singleton <nested:export ref="sampleServie" interface="com.gd.sn..SampleService"/>
  33. 33. 3. import singleton <nested:import id="sampleServie" interface="com.gd.sn..SampleService"/>
  34. 34. IV Features
  35. 35. Legend
  36. 36. References Checks ●wrong interface/name ●no exports ●lack of import
  37. 37. Handling Cycles ●detect ●prohibit ●resolve
  38. 38. 12:30:55,098|**WARN**| com.macys.platform.util.caching.repository.impl.CachingDistributedOverTransactionalNamedCacheRepository | Stored object 'MAIN_IndexedCatalogIndex' is not loaded at the moment of first usage. Repository will try to perform lazy loading. |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| pageMediaDistributedCacheWorker:0 12:30:55,099|**INFO**| com.macys.platform.util.caching.repository.impl.CachingDistributedOverTransactionalNamedCacheRepository | Loading stored object: 'MAIN_IndexedCatalogIndex'. Current version is null. |Client Details{sdpGrid:,ClientName: ClientInstanceName: , ClientThreadName: }| pageMediaDistributedCacheWorker:0 12:30:55,100|**WARN**| com.macys.platform.util.caching.repository.impl.CachingDistributedOverTransactionalNamedCacheRepository | Object were not loaded because object 'MAIN_IndexedCatalogIndex' is null. Current version is null. |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| pageMediaDistributedCacheWorker:0 12:30:55,100|**WARN**| com.macys.platform.navigation.providers.catalog.domain.impl.IndexedCatalogRepositoryImpl | Failed to initialize indexed catalog. |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| pageMediaDistributedCacheWorker: 0 12:30:55,100|**ERROR**| com.tangosol.coherence.component.util.logOutput.Log4j | 2012-05-01 12:30:55.100/1208.996 Oracle Coherence EE 3.5.3/465 <Error> (thread=pageMediaDistributedCacheWorker:0, member=1): Failed to load key="PageMediaKey [pageId=519728, pageRegion=PDP_CUSTOMER_REASSURANCE, pageDomain=PRODUCT, channelMode=SITE, mediaSourceType=PRODUCT]": |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| Logger@9271941 3.5.3/465 12:30:55,101|**ERROR**| com.tangosol.coherence.component.util.logOutput.Log4j | 2012-05-01 12:30:55.100/1208.996 Oracle Coherence EE 3.5.3/465 <Error> (thread=pageMediaDistributedCacheWorker:0, member=1): com.macys.platform.navigation.providers.catalog. index.exceptions.CatalogNotReadyException: Failed to initialize indexed catalog. at com.macys.platform.navigation.providers.catalog.domain.impl.IndexedCatalogRepositoryImpl.getIndexedCatalog(IndexedCatalogRepositoryImpl.java:56) at com.macys.platform.navigation.providers.catalog.domain.impl.IndexedCatalogRepositoryImpl.getIndexedCatalogClient(IndexedCatalogRepositoryImpl.java:31) at com.macys.platform.navigation.providers.catalog.businesslogic.assembler.ProductAssembler.assemble(ProductAssembler.java:424) at com.macys.platform.navigation.providers.catalog.componentmgr.CatalogServiceComponentManager.getProducts(CatalogServiceComponentManager.java:183) at com.macys.platform.navigation.providers.catalog.componentmgr.CatalogServiceComponentManager.getProduct(CatalogServiceComponentManager.java:163) at com.macys.platform.navigation.providers.catalog.componentmgr.CatalogServiceComponentManager.getProduct(CatalogServiceComponentManager.java:159) at sun.reflect.GeneratedMethodAccessor133.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196) at $Proxy233.getProduct(Unknown Source) at com.macys.platform.navigation.providers.catalog.da.componentmgr.CatalogServiceDAComponentMgr.getAttribute(CatalogServiceDAComponentMgr.java:295) at sun.reflect.GeneratedMethodAccessor132.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:196) at $Proxy247.getAttribute(Unknown Source) at com.macys.platform.providers.media.businesslogic.mediafinder.ProductMediaFinder.getMediaKey(ProductMediaFinder.java:212) at com.macys.platform.providers.media.componentmgr.PageMediaFinderComponent.getMediaKeysForRegion(PageMediaFinderComponent.java:54) at com.macys.platform.providers.media.cache.PageMediaCacheLoader.load(PageMediaCacheLoader.java:47) at com.macys.platform.util.caching.transactional.impl.factory.util.TransactionalCacheLoader$1.call(TransactionalCacheLoader.java:59) at com.macys.platform.util.caching.transactional.impl.manager.TransactionalNamedCachesManagerImpl.invokeAs(TransactionalNamedCachesManagerImpl.java:150) at com.macys.platform.util.caching.transactional.impl.factory.util.TransactionalCacheLoader.load(TransactionalCacheLoader.java:57) at com.macys.platform.util.caching.transactional.impl.factory.util.CountingCacheLoaderWrapper.load(CountingCacheLoaderWrapper.java:22) at com.macys.platform.util.caching.factory.NamedCacheFactoryBean$Loader.load(NamedCacheFactoryBean.java:318) at com.tangosol.net.cache.ReadWriteBackingMap$CacheLoaderCacheStore.load(ReadWriteBackingMap.java:5166) at com.tangosol.net.cache.ReadWriteBackingMap$CacheStoreWrapper.load(ReadWriteBackingMap.java:4314) at com.tangosol.net.cache.ReadWriteBackingMap$CacheStoreWrapper.loadInternal(ReadWriteBackingMap.java:3987) at com.tangosol.net.cache.ReadWriteBackingMap.get(ReadWriteBackingMap.java:754) at com.tangosol.coherence.component.util.daemon.queueProcessor.service.grid.DistributedCache.onGetRequest(DistributedCache.CDB:25) at com.tangosol.coherence.component.util.daemon.queueProcessor.service.grid.DistributedCache$GetRequest.run(DistributedCache.CDB:1) at com.tangosol.coherence.component.util.DaemonPool$WrapperTask.run(DaemonPool.CDB:1) at com.tangosol.coherence.component.util.DaemonPool$WrapperTask.run(DaemonPool.CDB:32) at com.tangosol.coherence.component.util.DaemonPool$Daemon.onNotify(DaemonPool.CDB:63) at com.tangosol.coherence.component.util.Daemon.run(Daemon.CDB:42) at java.lang.Thread.run(Thread.java:662) |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| Logger@9271941 3.5.3/465 12:30:57,153|**INFO**| com.macys.platform.navigation.providers.preloader.coordinator.RefreshCoordinator | Retrieving product and reference data |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,153|**INFO**| com.macys.platform.navigation.providers.preloader.coordinator.RefreshCoordinator | loadProduct(...) is started |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,153|**INFO**| com.macys.platform.navigation.providers.preloader.loader.product.ProductLoader | Querying for products |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,329|**INFO**| com.macys.platform.navigation.providers.preloader.loader.product.ProductLoader | Loading product attributes, search attributes, loading relations |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,330|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading unary attributes |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,344|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading multi-valued attributes |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,369|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading attributes: Loading unary completed Loading multi-valued comleted Loading attributes completed, total loaded: [1] in [39] ms |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,370|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading unary attributes |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,370|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading multi-valued attributes |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,428|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading attributes: Loading unary completed Loading multi-valued comleted Loading attributes completed, total loaded: [0] in [58] ms |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:57,428|**INFO**| com.macys.platform.navigation.providers.preloader.loader.product.ProductToCategoryLoader | loadData(...) started |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:58,116|**INFO**| com.macys.platform.navigation.providers.preloader.loader.product.ProductToCategoryLoader$1 | Product-to-category load subtask completed. Retrieved data for [1] products. |Client Details{sdpGrid:,ClientName: ClientInstanceName: , ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:58,116|**INFO**| com.macys.platform.navigation.providers.preloader.loader.product.ProductToCategoryLoader | Product-to-category load data completed in [688] ms |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:8 12:30:58,229|**INFO**| com.macys.platform.navigation.providers.preloader.loader.product.ProductLoader | Load Attributes: Loading product attributes completed with [1] loaded Loading product-to-category completed with [1] loaded Loading product-to-product completed with [0] loaded logs root-cause at the bottom
  39. 39. Fault-tolerance mode failure causes skipping
  40. 40. BA A B
  41. 41. Build time Customization <bean id="root" class="..banshun.ContextParentBean"> <property name="configLocation" value=" -context.xml ..."/> ... </bean> * B A
  42. 42. Run time Customization <bean id="root" class="..banshun.ContextParentBean"> ... <property name="runOnlyServices" value="basketService profileService"> .. ... </bean> BA BA
  43. 43. skipped as not needed runOnlyServices
  44. 44. Spring AOP support <bean id="proxyCreator" class="org.springframework..... BeanNameAutoProxyCreator"> <property name="customTargetSourceCreators" > <bean class="com.....LookupTargetSourceCreator"/> </property> <property name="beanNames"> <list> <value>*_beanDef</value> </list> </property> <property name="interceptorNames"> <list> <idref bean="jamonPerformanceMonitorInterceptor" /> </list> </property> </bean>
  45. 45. http://blog.griddynamics.com/search/label/Spring http://github.com/griddynamics/banshun mkhludnev@griddynamics.com banshun@googlegroups.com http://goo.gl/RZays Whodunit Artem Kirichkov Oleg Malakhov Eugeny Morozov Alexey Olenev Vladimir Polyakov Mikhail Khludnev 2K LOC

×