It's been a while since I made a blog posting so this one might be a little lengthy. Let's chat up Event Sourcing...
What is Event Sourcing and why do I care?
First off, Event Sourcing is not new. It has been around a long time, but the buzz around Command Query Responsibility Separation and DDD has pushed it back into the nerdy mainstream. The basic concept behind event sourcing is that we record state changes in the form of events, instead of the entire state of the object each time.
Using this technique adds a few nice benefits too; First, a reliable audit log becomes a first class citizen in your architecture, and not an after-thought. Second the persistence code becomes remarkably simpler. Third, your event storage can be implemented by as many options as you can imagine (RDBMS, flat file, xml, Object DB, BigTable, CouchDB, etc). Finally, you can replay these events to create the state of an object at any point in time...which kicks up the cool many, many notches.
Let's cover a little bit about one way you could implement event sourcing to persist and recreate a domain object. Before I begin, a little proviso to keep the bliki piranha at bay: this code is taken from a Contact Manager sample app I am in the process of writing in java to demonstrate the CQRS architecture. It is definitely a work in progress. Before you say it, yes I am well aware that implementing a contact manager in CQRS is crazy over-architected ;}
The code can be found on BitBucket here if you are interested in following along.
With that out of the way, the first thing we should discuss is how to develop your domain objects to take advantage of Event Sourcing. This snippet comes from my Contact object, which is an aggregate root in my domain. Each of the methods that modify the state of my object, translate that state change into an Event. For example,
The HomeAddressChanged object represents an Event. It is representative of the fact that the state of the address changed in my domain. Notice also that it is a past tense verb. This is important if you are trying to create DDD type UL. That said, DDD is out of scope for this posting, so let's move on.
After you've made all of your state changes, it's time to save the entity. The Contacts object, which is an implementation of the Repository pattern, will pull the events generated by state changes from the Contact aggregate (1 to *), and store them in the event store. Finally, the markChangesCommitted() method clears the event cache in my contact object.
The last part of persistence is saving these events in the event store. My example is *extra* simple because I am simply using an InMemoryEventStore, but your event store can literally be just about anything. I may do a separate post on the event store to delve into that topic a bit more.
A couple of key points. First, we ONLY ever insert into the event store, never update or delete. This is to preserve the lifecycle of the aggregate and build a solid audit trail. Second, it is very helpful if your aggregate has a identity that is unique throughout your enterprise. I chose a UUID for simplicity, but it isn't the only way to generate uniqueness.
Ok, now we have a series of events in the event store, lets talk a bit about replaying events to recreate an aggregate. First step is to get the events for a given id. In my case, I just grab them out of the event store:
Then I loop through this collection of events and in order, invoke the replay method of the aggregate to rebuild its state.
Notice the vanilla replay(Event event) method which uses Reflection to invoke the correct replay method for the type of event it is. This is not the most efficient way to build this functionality, but it is pretty darn simple to maintain, so I'm sticking with it for now. I'd be interested in hearing about other ways java folks have implemented this same piece without Reflection..perhaps an AOP implementation?
So when this loop finishes, you have the aggregate back in the exact state it was in when you stored it last. Here's an example of testing the storage and then the replay:
That concludes this little ditty about Event Sourcing. In a future post, I will demonstrate different types EventStore implementations. When I am satisfied with my CQRS Demo I will also do a series of posts about that topic.
If you are interested in CQRS, here are two great presentations by Greg Young and Udi Dahan.
That's it for now, I am interested to hear your experiences with Event Sourcing and ways I can tweak my code to make it more efficient or amp up the cool.
Tuesday, October 19, 2010
Thursday, July 8, 2010
How to URL Rewrite in Spring MVC
I am in the process of writing a Groovy based web app with Spring MVC and I wanted to use URL Rewriting. I scoured the boards for HOWTO's and from all my research Tuckey.org's URLRewrite is the best one out there. Here's a quick tutorial on how to set it up.
First, you need to add the dependency to your pom:
Next you need to map the URL Rewrite filter and your Spring Dispatcher servlet in your web.xml:
Then in src/main/webapp/WEB-INF you need to define a urlrewrite.xml. This file defines the filters for your webapp. For my app, I keep all JSP files under WEB-INF/jsp and use Spring's InternalResourceViewResolver to forward to them. This is great, except since my filter takes all request, I have to supply rules for the static files like html, javascript, css, images etc.
Here's how you do that. In urlrewrite.xml add the following:
That's it, URL rewriting is enabled on your app. Now anytime someone hits a URL in your app like http://[server]:[port]/[context-root]/[controller]/[action] (depending on which HandlerMapping you use) the filter will forward the request to the dispatcher servlet and your appropriate controller. For anything that goes to /images /js /css or /html, they will be forwarded to those resources.
I hope this is helpful.
First, you need to add the dependency to your pom:
Next you need to map the URL Rewrite filter and your Spring Dispatcher servlet in your web.xml:
Then in src/main/webapp/WEB-INF you need to define a urlrewrite.xml. This file defines the filters for your webapp. For my app, I keep all JSP files under WEB-INF/jsp and use Spring's InternalResourceViewResolver to forward to them. This is great, except since my filter takes all request, I have to supply rules for the static files like html, javascript, css, images etc.
Here's how you do that. In urlrewrite.xml add the following:
That's it, URL rewriting is enabled on your app. Now anytime someone hits a URL in your app like http://[server]:[port]/[context-root]/[controller]/[action] (depending on which HandlerMapping you use) the filter will forward the request to the dispatcher servlet and your appropriate controller. For anything that goes to /images /js /css or /html, they will be forwarded to those resources.
I hope this is helpful.
Subscribe to:
Posts (Atom)