Graham,

On May 3, 2011, at 1:46 PM, Graham Triggs wrote:

> On 3 May 2011 20:34, Mark Diggory <mdigg...@atmire.com> wrote:
> Example: Hacking Domain Model Locally
> 
> Right now, to add behavior to DSpace when Item state is altered has two 
> options:
> 
> a.) Alter the Item code
> b.) Write a consumer.
> 
> The problem with (a) is that we need to maintain differences against core 
> codebase and merge those differences over time, this is a problem when we 
> have multiple projects / addons altering the core codebase. Which wins, how 
> do we maintain both over time, altering the Domain Model is great until you 
> have a larger community with lots of unique customizations
> 
> The problem with (b) is that we can't participate in the transactional window 
> and utilize the Context /database capabilities to complete our CRUD 
> operations. We have to spawn our own transactional window after the current 
> transaction and we cannot use foreign key constraints against the dspace data 
> model tables to assure our database tables integrity, resulting in a lot of 
> extra coding to roll our own integrity checking.
> 
> Let's not confuse how the subsystems currently work, with how they have to 
> work. Right now, when an event is 'fired', it is queued for execution after 
> the current context is committed. That doesn't mean we have to restrict 
> ourselves to only having those types of events - it's feasible to rework the 
> event system to allow 'immediate' consumers... where they are executed as the 
> event is fired, and where they participate in the active context.


I think we should work to keep the Data Access Layer and the Business Logic 
Layer separate. I see the Event Manager as Business Logic layer and the DAO as 
Persistence layer.  If you need to enforce integrity for an Addon that works 
very closely with the database, then your more than likely working in the Data 
Access Layer.  If your running a secondary service that needs to be informed 
about changes in the Domain Model after their persistence has been successfully 
completed, then the EventManager / Service is appropriate.

In DSpace 2.0 these are separate as well, with the RequestService/Interceptor 
allowing in transaction work to happen while the EventService is for issuing 
events to consumers/listeners that are trying to keep in sync with the platform.

When do you need your addon to be tied to the transactional window, you need it 
when the Addons data is considered "as mission critical" as that of the core 
data model.  For instance, in the Versioning prototype I am working on, it 
needs to be closely tied to the success of the persistence of the DSpaceObject, 
 If there is a problem in the versioning, we need to roll back the whole 
transaction.  We should be looking to tie the Versioning logic into the 
Persistence tier, and, its highly likely that the versioning will be tied to 
the underlying persistence anyhow, we will implement versioning in a legacy 
dspace rdbms quite differently than we would in a Fedora repository.

 I'm very wary of adding more complexity to the EventManager, and we already 
have something in dspace-services to assist in abstracting the transactionality 
of the DSpace Context away from the Application Code, that is the 
RequestService and Request Interceptors.  My latest work in the Domain Model 
and supporting Repository/DAO classes place the org.dspace.core.Context into 
the Request and registers a RequestInterceptor responsible for completing or 
aborting it at the end of the request cycle.

For example, the following contextservice can be looked up if access to the 
current context is required, but it is not necessary for calling code to get it 
directly when executing DAO call.

http://scm.dspace.org/svn/repo/modules/dspace-core/trunk/impl/src/main/java/org/dspace/core/LegacyContextService.java

DSpace dspace = new DSpace();
CollectionService cs = dspace.getSingletonService(CollectionService.class);
Collection col = cs.find(id);
col.setName("Some text");
cs.update(col);

Behind the CollectionService, it will pickup the current Context from the 
request when necessary and provide the commit, as opposed to

Context context = new Context();
Collection col = Collection.find(context, id);
col.setName("Some text.");
col.update();
context.commit();

So if you want to introduce additional tasks that need to occur in the request 
cycle, they are added as RequestInterceptors that happen prior to Context 
Intercepter being closed.

As for the EventManager/Consumers, in DSpace 2.0 we've proposed their 
replacement by the EventService and Listeners

http://scm.dspace.org/svn/repo/modules/dspace-services/trunk/api/src/main/java/org/dspace/services/EventService.java

Which means that the Usage and Context Events would be merged into one 
infrastructure. I think its wise to clearly separate the systems that are 
within transaction (and thus need to be responsible enough to participate in 
the transaction) from those that simply monitor the application and process 
change/read events. It will be clearer to other developers to keep the two 
separate

Also, bear in mind that by making the EventManager/Consumers participate in the 
transaction, Context.commit and Context.complete get their definitions a bit 
blurred, right now they are responsible for commiting/aborting the transaction 
window, now suddenly they are for completing further persistence activities 
prior to closing the window.

> And we can still use foreign key constraints in the 'immediate execution' 
> consumers. But, for any add ons, I would strongly argue that you should not 
> use foreign key constraints. Any add ins that start imposing database 
> integrity constraints are going to cause havoc during upgrades if we want / 
> need to make changes to the core model.

Yes and No. When the implementation its closely tied to the DAO implementation, 
you will want to be able to use the actual capabilities of the persistence 
platform to make your addon more efficient.

I think we should be focused on assuring those writing addons have a "best 
practices" from the core developers so that we can predict how constraints will 
come into the picture. an "immediate execution consumer" (or in 
dspace-services, a Request Interceptor) should be able to be delivered by an 
addon, and in such case that addon needs to participate "Responsibly" in the 
transactional window, including knowing how to rollback what it has done in the 
event the context is aborted or the request fails with an exception. If that 
addon implements this internally as a foreign key or as its own integrity check 
is its own private business.

>  
> I offer up that the benefits of the Domain Model and the Service Manager are 
> that we be able to attain the "happy medium" where Addons can participate in 
> the transactional window and contribute their own database tables into DSpace.
> 
> By utilizing the SOA approach, we create chained DAO services that can 
> participate in the transaction window.  This was Jim Rutherfords original 
> idea with the Stackable DAO.
> 
> https://github.com/DSpace/DSpace/blob/dspace-dao-prototype/dspace-api/src/main/java/org/dspace/dao/StackableDAO.java
> 
> https://github.com/DSpace/DSpace/blob/dspace-dao-prototype/dspace-api/src/main/java/org/dspace/content/dao/ItemDAOFactory.java
> 
> What James was struggling with was the means to configure the stack of DAO 
> that would participate in the transactional window. I think that with the 
> Spring Service Manager, we now have an opportunity to answer his question.
> 
> 
> I really didn't like the Stackable DAO design - I always viewed it as a 
> kludge for not having immediate / in-context consumers. My biggest complaint 
> is that it either makes or model more rigid, or it makes the add-in DAOs 
> fragile. Every change that gets made to the DAO contracts have to be 
> reflected in any add-in based off of it.

The Stackable DAO is more than an immediate in-process consumer by design, its 
specifically targeting being a member of the call stack for the DAO method in 
question (ItemDAO.delete(), CollectionDAO.update()) and as such, there's no 
need to be messing about with "extraneous mapping of Events to consumers and 
all the extra code associated with that".  Its less fragile and rigid than 
writing an extensive messaging framework to handle processing the transaction 
that has little or no specification other than its own obtuse internal business 
logic.

It is just easier to comprehend if one wired the members of the call stack 
directly in Spring 

ItemDAO.update() --> MyItemDAO.update() --> YourItemDAO.update();

ItemDAO.delete() --> MyItemDAO.delete() --> YourItemDAO.delete();

CollectionDAO.delete() --> MyCollectionDAO.delete() --> 
YourCollectionDAO.delete();

With this at least you can predict the call stack in your configuration

As opposed to 

Item.update() --> Context.addEvent(event) --> Context.commit() --> 
EventManager.dispatchEvent(event)  -->  Dispatcher.callConsumer(event)  --> 
Consumer.consume(event) --> verbose conditional switch logic to figure out what 
the hell generated the event and what to do with it now.

Which looks clearer to you?

> Compare that to the event notification mechanism - the API for passing 
> messages being consistent, and far less likely to break add-ins, even if we 
> make changes to what the DAOs do.

Bear in mind that the messaging itself originated under a proposal to introduce 
asynchronous JMS style event Queues and I haven't a clue how we'd maintain a 
transactional system across asynchronous queuing. Nor to I even want to think 
about it. The EventManagers already a complex beast, please, lets not make it 
more complex.

> A secondary issue is that a stacked DAO is as near as damn it an interceptor 
> - and as interceptors are familiar design pattern, and widely used within 
> Spring. So if you did go this route [and configured it through Spring] then 
> it would be better to keep it consistent with standard concepts.

Both the DAO and Repository DDD DesignPatterns are also fairly prevalent 
standard concepts. Call them what you want.

> But the immediate execution event mechanism is better suited to your view of 
> having reliable add-ins.

I think my points have been made above...

Mark


-- 
Mark R. Diggory
@mire - www.atmire.com
2888 Loker Avenue East - Suite 305 - Carlsbad - CA - 92010
Technologielaan 9 - 3001 Heverlee - Belgium

------------------------------------------------------------------------------
WhatsUp Gold - Download Free Network Management Software
The most intuitive, comprehensive, and cost-effective network 
management toolset available today.  Delivers lowest initial 
acquisition cost and overall TCO of any competing solution.
http://p.sf.net/sfu/whatsupgold-sd
_______________________________________________
Dspace-devel mailing list
Dspace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dspace-devel

Reply via email to