SeedStack is a comprehensive full development stack. Learn about its features and their benefits for building enterprise software applications.
These slides have been shown at Ippon technologies, the 11th of July 2016, in Paris.
4. What is SeedStack?
A full-stack development solution
– Java backend
– Web frontend
A scalable architecture for enterprise software
An extensible ecosystem of add-ons
6. Modularity
Modularity at every level of the stack
– Clear separation of APIs from impl.
– One module per concern
– Powerful extension mechanisms (plugins,
fragments, API/SPI)
Automatic integration of modules
– Auto-discovery
– Every module just works without effort
7. Distribution
Global packaging of all modules
Archetypes for quick project creation
Each organization can roll its own custom distribution
16.4 16.7 16.11
11. Kernel + plugin architecture
A concern per plugin
Each plugin is responsible for:
1. Submitting classpath scan requests to the kernel
2. Providing initialization, startup and shutdown code
3. Building a Guice module
The kernel orchestrates all plugins:
– Resolve dependencies between plugins
– Invoke init, startup and shutdown code
12. Sample plugin
public 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);
}
}
13. Dependency injection
Each plugin provides a Guice module
– Define injection bindings
– Is dynamically created by the plugin
All modules are aggregated and used to produce
a global injector
Only javax.inject API is used in application code
14. Modular configuration
Configuration files go in META-INF/configuration
– They are scanned upon startup
– They are merged into one unique configuration
Configuration values can be accessed from
anywhere in the application
Feature-rich: profiles, macros, environment
variables, system properties, override, converters,
…
16. Exceptions and diagnostic
Readable, content-rich technical exceptions:
– Templatable message and fix advice
– Concise list of causes
– Online reference if relevant
When an unexpected exception occurs:
– Extensive diagnostic info is collected
– A JSON diagnostic report is dumped to the filesystem if possible
Custom diagnostic collectors and reporters can be plugged in
Great support tool
17. Sample exception trace
org.seedstack.seed.SeedException: (CORE) Unexpected exception
Causes
------
1. java.lang.RuntimeException: (JPA) No persisted classes in unit
2. (JPA) No classes were found belonging to JPA unit "my-unit".
Fix
---
Verify that the classes are correctly scanned and they are configured to belong to the
JPA unit "my-unit".
Online information
------------------
http://seedstack.org/addons/jpa#configuration
Stacktrace
----------
...
18. Security
Based on Apache Shiro
Modular permission-based security model
Built-in and pluggable security realms:
– Static configuration
– LDAP
– X509 certificate
Fine-grained data obfuscation
19. REST
JAX-RS 2.0 through Jersey 2
Hypermedia capable:
– JSON-HOME for discovering entry resources
– Registry of rels
– Builder of HAL representations and links
Swagger generator via add-on
20. More…
Fully injectable Servlet and Filters
WebSockets
Command-line parsing
Transactions
Metrics collection and reporting
Applicative SSH shell
21. Benefits
Lays ground for software componentization at
the enterprise scale:
– Provides and promotes modularity
– Enables quick integration of components without
effort
Solves common technical challenges once for
the whole organization
25. Entities
public class Customer extends BaseEntity<String> {
private String email;
private Address address;
public Customer (String email) {
this.email = email;
}
@Override
public String getEntityId() {
return this.email;
}
// … more
}
26. Value Objects
public class Address extends BaseValueObject {
private final String street;
private final String city;
private final ZipCode zipCode;
public Address(String street, String city, ZipCode zipCode) {
this.street = street;
this.city = city;
this.zipCode = zipCode;
}
// … more
}
27. Aggregates
public class Order extends BaseAggregateRoot<OrderId> {
private OrderId orderId;
private Date checkoutDate;
private double totalPrice;
public Order(OrderId orderId) {
this.orderId = orderId;
}
@Override
public OrderId getEntityId() {
return this.orderId ;
}
// … more
}
28. Services
Define an interface:
@Service
public interface CheckoutService {
public Invoice checkout(Order order);
}
And one or more implementation(s):
@Named(“creditCard")
public class CreditCardCheckoutService implements CheckoutService {
@Override
public Invoice checkout(Order order) {
...
}
}
Qualifies implementation if there are multiple ones
29. Repositories
Basic repositories without effort:
@Inject @Jpa
private Repository<Customer, String> customerRepository;
Can be extended with custom methods:
public interface CustomerRepository extends GenericRepository<Customer, String> {
List<Customer> findByName(String firstName, String lastName);
}
@Jpa
public class CustomerJpaRepository extends BaseJpaRepository<Customer, String>
implements CustomerRepository {
@Override
public List<Customer> findByName (String firstName, String lastName) {
...
}
}
Also available with other technologies
Qualifies implementation if there are multiple ones
30. Factories
Constructor-based factories without effort:
@Inject
private Factory<Customer> customerFactory;
Can be extended with custom methods:
public interface CustomerFactory extends GenericFactory<Customer> {
Customer createCustomer(String email, String firstName, String lastName);
}
public class CustomerFactoryImpl extends BaseFactory<Customer>
implements CustomerFactory {
@Override
public Customer createCustomer(String email, String firstName, String lastName) {
...
}
}
Can be plugged in with identity generators (provided or custom)
32. Benefits
Proven approach to produce quality and
maintainable software
Promotes software industry best-practices
Homogenize business code accross projects
Design for reuse
34. Loader + fragment architecture
Allows composability of Web frontends
Each fragment contains:
– A manifest describing its contents
– Static assets like modules, stylesheets, templates, …
The W20 loader aggregates all fragments and
orchestrate the initialization of the Single-Page
Application
36. Sample fragment
{
"id": "my-fragment",
"name": "My awesome fragment",
"modules": {
"module1": "{my-fragment}/modules/module1"
},
"...": {
…
},
"...": {
…
}
}
Identity
1. Modules are loaded by the W20 loader first
2. Then each loaded module can process
fragment sections to further initialize the
application
Paths can be relative to the fragment manifest
Additional abitrary section
38. Features
AngularJS integration
Culture and internationalization
Integration with backend security
Navigation and menu management
Hypermedia
Pluggable CSS frameworks
Theming
42. Benefits
Provides a component architecture for Web
frontends
Provides useful services for Web enterprise
applications (security, i18n, navigation …)
Provides theming support
Solves common technical challenges once for the
whole organization
44. Features
Seamless Java/Web integration:
– Auto-detects W20 fragments in classpath
– Implements REST API required by frontend
– Dynamically generates the W20 configuration and the
masterpage
Can be extended through an SPI
Enables activation of a front/back feature simply by
adding a dependency
46. SeedStack tools
Maven plugin:
– Generate: generate projects from scratch
– Run: run a project from command-line
– Package: creates a runnable unique JAR
Yeoman generator for pure-frontend modules
Grunt plugin for bundling and minification