Banshun - OSGi-less modularity for Spring

53
Yet Another One.... Banshun a tiny based Modular Framework http://flic.kr/p/EWNYh

description

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.

Transcript of Banshun - OSGi-less modularity for Spring

Page 1: Banshun - OSGi-less modularity for Spring

Yet Another One....

Banshun

a tiny based Modular Framework

http://flic.kr/p/EWNYh

Page 2: Banshun - OSGi-less modularity for Spring

Agenda

●Enterprise Applications

●Banshun vs OSGi, EJB

●1, 2, 3 - BOOM!

●Features ...

Page 3: Banshun - OSGi-less modularity for Spring

Agenda - Features

● buildtime & runtime app customization

● developer friendliness

○ references validation

○ cycles resolution

○ root cause logging

○ fault-tolerance

○ dependencies graph

● Spring AOP support

Page 4: Banshun - OSGi-less modularity for Spring

Is it your app?

:TheService

+ doBusiness(param) : Result

Page 5: Banshun - OSGi-less modularity for Spring

Is it your app?

:TheService

+ doBusiness(param) : Result

RDBMS

Page 6: Banshun - OSGi-less modularity for Spring

Is it your app?

:TheService

+ doBusiness(param) : Result

Page 7: Banshun - OSGi-less modularity for Spring

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>

Page 8: Banshun - OSGi-less modularity for Spring

Don't you need to deploy it?

:TheService

+ doBusiness(param) : Result

Page 9: Banshun - OSGi-less modularity for Spring

Don't you need to deploy it?

:TheService

+ doBusiness(param) : Result

<<EAR>>

<<container>>

Page 10: Banshun - OSGi-less modularity for Spring

Don't you need to deploy it?

:TheService

+ doBusiness(param) : Result

<<WAR>>

<<container>>

Page 11: Banshun - OSGi-less modularity for Spring

The app becomes big

:FooService

:ZooService

:MooService

:FooService

:BarService

:BazService

<<WAR>>

Page 12: Banshun - OSGi-less modularity for Spring

The app becomes big

<<WAR>>:FooService

:BarService

:BazService

:FooService

:BarService

:BazService

Page 13: Banshun - OSGi-less modularity for Spring

it have to be modular

:FooService

:BarService

:BazService

:MooService

:ZooService

<<component>>

:AService

:BService

:CService

:DService

:EService

<<component>>

Page 14: Banshun - OSGi-less modularity for Spring

:FooService

:BarService

:BazService

:MooService

:ZooService

<<component>>

:FooService

:BarService

:BazService

:MooService

:ZooService

<<component>>

<<WAR>> / <<EAR>>

Page 15: Banshun - OSGi-less modularity for Spring

is not modular out-of-the-box

Page 16: Banshun - OSGi-less modularity for Spring

even

is not modular

Page 17: Banshun - OSGi-less modularity for Spring

<import resource="..."> is not modular because of

●bean name clashes ●global scopes of settings and aspects ●zero tolerance for module failure

Page 18: Banshun - OSGi-less modularity for Spring

Glue code should allow

to forge modules in isolation

Page 19: Banshun - OSGi-less modularity for Spring

and then work altogether

Page 20: Banshun - OSGi-less modularity for Spring

II. Banshun vs

OSGi, EJB

Page 23: Banshun - OSGi-less modularity for Spring

OSGi, EJBis about multiple

classloaders Single classloader

is enough!

Banshun resolves versions at build time

Page 24: Banshun - OSGi-less modularity for Spring

OSGi, EJBis about

hot partial redeploy

Page 25: Banshun - OSGi-less modularity for Spring

Never do thatat prod

it's not possible to assure that it works

http://www.newpig.com/us/caution-hot-sign/SGN550

Page 26: Banshun - OSGi-less modularity for Spring

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>

Page 27: Banshun - OSGi-less modularity for Spring

Banshun

●don't need any build facility

●a few row artefacts

Page 28: Banshun - OSGi-less modularity for Spring

OSGi, EJBhas weak runtime facilities

launch and pray

Page 29: Banshun - OSGi-less modularity for Spring

http://www.lilycli.com/lart.html

Banshunhas full-fledged runtime

●and for everyday development

●for production

Page 30: Banshun - OSGi-less modularity for Spring
Page 31: Banshun - OSGi-less modularity for Spring

III How does it work?

http://blog.rinajakubowicz.com/about-boom/

Page 32: Banshun - OSGi-less modularity for Spring

1. instantiate children contexts

<bean id="root" class="..banshun.ContextParentBean"> <property name="configLocation" value="authenticator-context.xml datasource-context.xml ..."/> ... </bean>

<<WAR>>

...

Page 33: Banshun - OSGi-less modularity for Spring

2. export singleton

<nested:export ref="sampleServie" interface="com.gd.sn..SampleService"/>

Page 34: Banshun - OSGi-less modularity for Spring

3. import singleton

<nested:import id="sampleServie" interface="com.gd.sn..SampleService"/>

Page 35: Banshun - OSGi-less modularity for Spring
Page 36: Banshun - OSGi-less modularity for Spring

IV Features

Page 37: Banshun - OSGi-less modularity for Spring

Legend

Page 38: Banshun - OSGi-less modularity for Spring
Page 39: Banshun - OSGi-less modularity for Spring
Page 40: Banshun - OSGi-less modularity for Spring
Page 41: Banshun - OSGi-less modularity for Spring
Page 42: Banshun - OSGi-less modularity for Spring

References Checks

●wrong interface/name

●no exports

● lack of import

Page 43: Banshun - OSGi-less modularity for Spring

Handling Cycles●detect ●prohibit ●resolve

Page 44: Banshun - OSGi-less modularity for Spring

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:012: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:012: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:012: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:012: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/46512: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/46512:30:57,153|**INFO**| com.macys.platform.navigation.providers.preloader.coordinator.RefreshCoordinator | Retrieving product and reference data |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:812:30:57,153|**INFO**| com.macys.platform.navigation.providers.preloader.coordinator.RefreshCoordinator | loadProduct(...) is started |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:812:30:57,153|**INFO**| com.macys.platform.navigation.providers.preloader.loader.product.ProductLoader | Querying for products |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:812: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:812:30:57,330|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading unary attributes |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:812:30:57,344|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading multi-valued attributes |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:812: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:812:30:57,370|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading unary attributes |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:812:30:57,370|**INFO**| com.macys.platform.navigation.providers.preloader.loader.attribute.AttributeLoader | Loading multi-valued attributes |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:812: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:812:30:57,428|**INFO**| com.macys.platform.navigation.providers.preloader.loader.product.ProductToCategoryLoader | loadData(...) started |Client Details{sdpGrid:,ClientName: ClientInstanceName: ,ClientThreadName: }| ProductDistributedCacheWorker:812: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:812: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:812: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

Page 45: Banshun - OSGi-less modularity for Spring

Fault-tolerance mode

failurecauses skipping

Page 46: Banshun - OSGi-less modularity for Spring

BA

A

B

Page 47: Banshun - OSGi-less modularity for Spring

Build time Customization

<bean id="root" class="..banshun.ContextParentBean"> <property name="configLocation"

value=" -context.xml ..."/> ... </bean>

*

B A

Page 48: Banshun - OSGi-less modularity for Spring

Run time Customization

<bean id="root" class="..banshun.ContextParentBean"> ... <property name="runOnlyServices" value="basketService profileService"> .. ... </bean>

BA BA

Page 49: Banshun - OSGi-less modularity for Spring

skipped as not needed

runOnlyServices

Page 50: Banshun - OSGi-less modularity for Spring
Page 51: Banshun - OSGi-less modularity for Spring

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>

Page 52: Banshun - OSGi-less modularity for Spring

http://blog.griddynamics.com/search/label/Springhttp://github.com/griddynamics/[email protected]@googlegroups.com

http://goo.gl/RZays

Whodunit

Artem KirichkovOleg MalakhovEugeny MorozovAlexey OlenevVladimir PolyakovMikhail Khludnev

2K LOC

Page 53: Banshun - OSGi-less modularity for Spring