https://github.com/BottegaIT/ddd-leaven-v2
This time our goal was to present more advanced modeling techniques.
(but still You can learn some technical tricks, for example bullet proof locking: https://github.com/BottegaIT/ddd-leaven-v2/blob/master/src/main/java/pl/com/bottega/ddd/support/infrastructure/repository/jpa/GenericJpaRepository.java)
You can find some linguistic modeling tricks we have learned during IDDD Tour. I'll describe it in the wiki in spare time.
Wiki is still under construction, but this map should help:
http://prezi.com/akrfq7jyau8w/ddd-cqrs-leaven-v20/
Rafał Jamróz is working on more advanced testing (both Unit and jBehave) samples.
We are waiting for your comments:)
DDD and CqRS Leaven
Domain Driven Design and CqRS sample project. More than just sample, but not another framework... leaven - something You start when making a good bread.
Friday, December 6, 2013
Monday, August 20, 2012
.NET Version - alpha is out
We are proud to announce the .NET Verion of the Leaven Project.
You can check it here http://cqrssample.codeplex.com/.
//======================
Comments and contribution are welcome.
You can check it here http://cqrssample.codeplex.com/.
//======================
Comments and contribution are welcome.
Monday, February 6, 2012
Fork us at github
We have moved the source code and now the project is officially licensed using Apache 2.0 license. Check out our github project site . Remember it's a "leaven" and not another framework ;) so feel free to use it as a playground for learning about DDD and CQRS or even a starting point for your new project. If you decide to do so, we will be happy to hear from you.
Thursday, February 2, 2012
Monday, December 12, 2011
Alternative implementation in JEE
The main goal of DDD-CQRS Leaven Project was to present some concepts of system architecture together with domain modeling. In order to avoid high entry threshold, project leaders decided to create one maven project and implement with well-known Spring framework.
The JEE-based implementation emerged as an idea of providing that Spring is only a supporting framework that can be easily replaced by any other. This would make the leaven even strong and convincing. During development of the JEE-branch I ran into some interesting challenges, some of them are still unresolved. Here's a summary of what has been achieved so far.
All the command handlers were adnotated with custom @CommandHandlerAnnotation and here I met the first obstacle. In the original implementation, this annotation has following definition:
If this branch becomes more stable and the database will stay unchanged, I will try to rewrite the product finder with Native SQL.
CDIEventsInitializer: Scans the CDI BeansManager and registers listeners (as names) for events basing on annotations
CDIEventHandler: A wrapper class for instantiating appropriate real handler from the BeanManager
CDIEventPublisher: implementation of ApplicationEventPublisher and DomainEventPublisher that orchestrates handling.
As you can see, nothing new here, just the same idea as in Spring-based implementation rewritten with the BeanManager. Solution re-uses current @EventListener and @EventListeners annotations without adding anything to existing code. Asynchronous event handling is not yet available, but it should not be difficult, probably we could use the EJB 3.1 @Asynchronous annotation.
ProductOrderingIT: Known as ProductsOrderingFunctionalTest in trunk
SagaIT: Known as SagaIntegrationTest in trunk
JpqlProductFinderIT: Tests different criterias of the finder against some test data
CDIEventsIT: Tests if the CDI Event dispatching/handling engine works as expected
Let me explain a few details about test names. An integration test verifies some scenario in environment of collaborating objects. Sometimes it checks whole flow between layers, soetimes only cooperation of few elements (like the CDIEventsIT). Another thing is an end-to-end test. Its scope is wider, it verifies application behavior simulating actions of end-users (for example with Selenium). This subject will be explored later after I finish some work with the UI.
The Arquillian runner is an interesting tool that certainly adds a lot of comfort, but there are two disadvantages worth mentioning:
1. The Glassfish-embedded server startup time is significant. If you want to run your test many times with continous refactoring and checking, it's probably slower than deploying the Spring solution on jetty.
2. Deployment must be described by list of classes or packages. I could not find an easy method to deploy "just the whole thing", so I was forced to redeploy many many times before my tests stopped showing the ClassNotFoundException. If you have a tip how to do it (there must be a way...), please let me know.
Last thing to complete is preparing other entry points for the application: remote, web services, maybe REST? Anyway these subjects are a little bit beyond proving flexibility of framework running the CQRS/DDD architecture of the Leaven.
CQRS
Command Handlers
The Spring-based HandlersProvider was based on the BeanFactory which is being processed during context refresh. In this process the BeanFactory is scanned for any implementation of CommandHandler interface. Next, these definitions are stored in a registry to map command to handler bean name. CDIHandlersProvider does exactly the same but using the CDI BeanManager. I could not find any reasonable substitute for the 'context refresh' event handler, hence whole process is initialized in the @PostConstruct method.All the command handlers were adnotated with custom @CommandHandlerAnnotation and here I met the first obstacle. In the original implementation, this annotation has following definition:
@Component
@Transactional
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface CommandHandlerAnnotation {
}
I wanted to add @Stateless in order to make all annotated command handlers transactional EJBs. That doesn't work, because EJB specification allows putting this annotation on classes only. Similar problem with @Named. The only quick solution was just adding additional annotations to command handlers and polluting them with framework-related stuff. If you know any workaround (excpt xml deployment descriptors) don't hasitate to share.Finders
In original solution finders were implemented using JPQL (JpaOrderFinder) or JDBC (SqlProductFinder). First approach is fine since it uses a part of JEE, the second one had to be removed due to its coupling with Spring's NamedParameterJdbcOperations. I decidded to rewrite it with Jpql to keep it simple and consistent, but there is absolutely nothing wrong in writing pure SQL-based implementation even if it's strongly related to particular DB engine. For many purposes such solution is even a better choice. This subject is well covered by the CQRS Query Tier philosophy.If this branch becomes more stable and the database will stay unchanged, I will try to rewrite the product finder with Native SQL.
Events Engine
When I first started to prepare the events engine, I was really glad that JEE6 offered cool and simple API to deal with such matters. If you're not familiar with it, let me give a quick example: @Inject
private Event<SomeDomainEvent> event;
public void doSomeBusiness()
{
// business code here
event.fire(new SomeDomainEvent(someArguments));
}
In some other bean:
public void handle(@Observes SomeDomainEvent event)
{
// reaction
}
This is all, fire and forget. Of course, there are some additional mechanisms, for example possibility of adding qualifiers, but I do not want to cover it all here. Just google "cdi events" and you will find plenty of tutorials.
Now, if we want to cover this engine with one common EventPublisher implementation, we will end up discovering that this framework is just not sufficient for our needs. There is no possibility to create one dispatcher that receiver any (undefined) kind of event and multiple concrete listeners. After many experiments with tricks like on this thread, I decided to give up and implement the engine just like with the HandlersProvider. As a result we have three classes:CDIEventsInitializer: Scans the CDI BeansManager and registers listeners (as names) for events basing on annotations
CDIEventHandler: A wrapper class for instantiating appropriate real handler from the BeanManager
CDIEventPublisher: implementation of ApplicationEventPublisher and DomainEventPublisher that orchestrates handling.
As you can see, nothing new here, just the same idea as in Spring-based implementation rewritten with the BeanManager. Solution re-uses current @EventListener and @EventListeners annotations without adding anything to existing code. Asynchronous event handling is not yet available, but it should not be difficult, probably we could use the EJB 3.1 @Asynchronous annotation.
DDD
Repositories
Due to some experimental purposes the repositories were somewhat modified, but in fact there should be no need to do that. I will try to revert changes in order to bring all the JPA-based repos back to their initial form. To achieve JTA without Spring I added OpenJPA + Derby initialized by TestDBInitializer. There were some problems with Embedded in-memory database, so instead a standard network server was used (data is wiped on startup, refer to persistence.xml).Sagas
Since no changes were needed in event handling API, the SimpleSagaEngine could be left untouched as well. The only thing to do was writing new SagaRegistry implementation, the... yes, CDISagaRegistry. Again, if you take a closer look you will see that it is almost a copy of SpringSagaRegistry using BeanManager instead of BeanFactory.Integration Tests
I must admit that it was my first experiment with Arquillian. I had to learn how to set it up quickly due to very limited free time, so correct me if I made some dumb mistakes in my tests. This runner combined with Glassfish-embedded lets us create a fully functionable JEE sandbox environment where we can deploy our tests and run them automatically. Four tests were prepared:ProductOrderingIT: Known as ProductsOrderingFunctionalTest in trunk
SagaIT: Known as SagaIntegrationTest in trunk
JpqlProductFinderIT: Tests different criterias of the finder against some test data
CDIEventsIT: Tests if the CDI Event dispatching/handling engine works as expected
Let me explain a few details about test names. An integration test verifies some scenario in environment of collaborating objects. Sometimes it checks whole flow between layers, soetimes only cooperation of few elements (like the CDIEventsIT). Another thing is an end-to-end test. Its scope is wider, it verifies application behavior simulating actions of end-users (for example with Selenium). This subject will be explored later after I finish some work with the UI.
The Arquillian runner is an interesting tool that certainly adds a lot of comfort, but there are two disadvantages worth mentioning:
1. The Glassfish-embedded server startup time is significant. If you want to run your test many times with continous refactoring and checking, it's probably slower than deploying the Spring solution on jetty.
2. Deployment must be described by list of classes or packages. I could not find an easy method to deploy "just the whole thing", so I was forced to redeploy many many times before my tests stopped showing the ClassNotFoundException. If you have a tip how to do it (there must be a way...), please let me know.
User Interface
I am not a big fan of tinkering with presentation, styles and all that stuff. With JSF 2.0 + JRebel creating UI is pretty simple and painless. First I spent some time struggling with Resin just to discover that its own JSF implementation is not supported by JRebel. Everything works fine on Glassfish 3.1 Web Profile, so currently I am developing the view layer. You can see first effects committed in the repository, but please remember that it's still just a draft.Coming next
After finishing the application will be re-integrated with JBehave without using Spring. Simultaneously I am thinging about how to decouple @Named and @Stateless bean definitions from classes. As I mentioned before on the discussion board, it is hard to imagine how this branch can be merged into trunk to keep one project and still maintain its simplicity. Probably it will just stay as a fork in a role of proof of concept.Last thing to complete is preparing other entry points for the application: remote, web services, maybe REST? Anyway these subjects are a little bit beyond proving flexibility of framework running the CQRS/DDD architecture of the Leaven.
Summary
The main concepts of DDD and CQRS are not related to particular technology and we can implement them with different frameworks without messing with API and domain model. You could leverage the Leaven as a base for your new project with your favourite toolset and environment. Comparing the Spring-based trunk and the JEE fork can help to understand boundaries between mental model, patterns and technical details. Feel free to dig in, any comments are most welcome.Wednesday, November 30, 2011
Workshop #3
Last week, during the second day of the Java Developers' Days conference we gave another Leaven Workshop.
This time Greg Young made this harder being master of the vodka ceremony on previous night at afterparty:)
This time Greg Young made this harder being master of the vodka ceremony on previous night at afterparty:)
Monday, October 17, 2011
Workshop #2
Last Saturday (15.10.2011) we have had a second workshop dedicated to the DDD-CqRS Leaven Project.
This time workshop was part of the Warsjawa conference so we managed to gather 60 passionate software engineers:)
Here are Prezi presentations used during workshop based on our source code:
Here are some photos:
This time workshop was part of the Warsjawa conference so we managed to gather 60 passionate software engineers:)
Here are Prezi presentations used during workshop based on our source code:
Here are some photos:
Subscribe to:
Posts (Atom)