seedstack, the lean development stack
TRANSCRIPT
The lean development stackAdrien LAUER
SeedStack
2 of 24
HistoryProject started late 2012
10+ years experience of frameworksCustomOpen-Source: mainly Spring
3 of 24
GoalsBuild a common development stack
Shared across all business entitiesManufacturing / logistics / finance / sales / R&D / …
Being extensible
Enabling re-use
4 of 24
OrganizationCore team at PSA Peugeot CitroënOther members at various locations
http://seedstack.orghttps://github.com/seedstackTwitter: @seedstackIRC: #seedstack on freenode
5 of 24
Get presentation code samples at
https://github.com/adrienlauer/poss-samples
6 of 24
Core valuesOpinion
A reference architecture for your apps
ModularitySingle responsibility principle
ExtensibilityOpen-Closed principle
7 of 24
FoundationJavaSet of technologies to build backends
WebSet of technologies to build Web apps
BusinessDomain-Driven Design (DDD) approach
8 of 24
FoundationJavaSet of technologies to build backends
WebSet of technologies to build Web apps
BusinessDomain-Driven Design (DDD) approach
9 of 24
Java focusKernel + plugin architecture
One plugin per concernScalable
One global Guice injector
Unified configuration
Plugin discovery
Classpath scan Initialization
10 of 24
Sample pluginpublic class MyPlugin extends AbstractPlugin { private final Set<Class<?>> annotatedClasses = new HashSet<>();
@Override public String name() { return "my-plugin"; }
@Override public Collection<ClasspathScanRequest> classpathScanRequests() { return classpathScanRequestBuilder().annotationType(Service.class).build(); }
@Override public InitState init(InitContext initContext) { annotatedClasses.addAll(initContext.scannedClassesByAnnotationClass().get(Service.class)); return InitState.INITIALIZED; }
@Override public Object nativeUnitModule() { return (Module) binder -> annotatedClasses.forEach(binder::bind); }}
11 of 24
So we built the core…Contains the kernel
Provides basic featuresLaunchingConfigurationIoCService commandsDiagnostics
12 of 24
Then we scaled up…10+ plugins
TestingSecurityTransactionsRESTMetrics / healthWeb…
Adding new technologies is quick and easy
All PSA requirements have been covered
50 satisfied projects over two years
13 of 24
FoundationJavaSet of technologies to build REST backends
WebSet of technologies to build Web apps
BusinessDomain-Driven Design (DDD) approach
14 of 24
Web focusLoader + fragments architecture
A fragment per concernComposable
Configure and initialize an SPA
Fragment download
Configuration computing Initialization
15 of 24
Sample fragment{ "id": "demo", "name": "W20 POSS demo", "modules": { "user": "{demo}/modules/user" }, "i18n": { "en": [ "{demo}/i18n/messages-en.json" ], "fr": [ "{demo}/i18n/messages-fr.json" ] }, "routes": { "hello": { "template": "<div class=\"container\"><h1>Hello World!</h1></div>", "hidden": true }, "user": { "templateUrl": "{demo}/views/user.html", "controller": "UserController" } }}
16 of 24
Main featuresBased on popular libraries
AngularJSRequireJS
Advanced enterprise features
Multi CSS frameworkBootstrapAngular material
Theming support2 Open-Source themes3 PSA proprietary themes
17 of 24
FoundationJavaSet of technologies to build REST backends
WebSet of technologies to build Web apps
BusinessDomain-Driven Design (DDD) approach
18 of 24
Level of involvement
Annotations
Interfaces
Base classes
19 of 24
Building blocks
20 of 24
Main featuresDDD semantic + injection
Easy-to-use default implementations
Smart DTO / domain mapping
Built-in identity generation strategies
21 of 24
Sampleclass SaleServiceImpl implements SaleService { private final Repository<Seller, Long> sellerRepository; private final DomainRegistry domainRegistry;
@Inject public SaleServiceImpl(Repository<Seller, Long> sellerRepository, DomainRegistry domainRegistry) { this.sellerRepository = sellerRepository; this.domainRegistry = domainRegistry; }
@Override public void updateBonus(Order order, Long sellerId) { Seller seller = sellerRepository.load(sellerId); if (seller == null) { throw new IllegalArgumentException("Seller " + sellerId + " cannot be found"); }
BonusPolicy bonusPolicy = domainRegistry .getPolicy(BonusPolicy.class, seller.getBonusPolicy());
double orderBonus = bonusPolicy.computeBonus(order); seller.addToMonthlyBonus(orderBonus);
sellerRepository.save(seller); }}
22 of 24
Extensibility20+ official add-ons
Audit, ElasticSearch, I18n, IO, JavaMail, JCache, JDBC, JMS, JPA, LDAP, MongoDB, Monitoring, Neo4J, Redis, Scheduling, Solr, Spring-bridge, Validation, W20-bridge, Web-Services, …
Open to third-partyhttp://seedstack.org/addons
PSA uses only 3 proprietary add-ons
23 of 24
DistributionGlobal packaging of all modules
Each organization can roll its own distribution
Open-Source reference distribution released 3 times per year
16.4 16.7 16.11
24 of 24
Thank you!Website: http://seedstack.orgGitHub: https://github.com/seedstackIRC: #seedstack on freenode
Contributions welcome!Pull requestsDocumentation fixesIssues