[Geoserver-devel] Extending WFS transaction handling for WFSV (trunk)

Hi,
I was looking at making WFS transaction element handling extensible,
since in WFSV in need to handle another element, the rollback one (and
in the future, when handling branches, I'll need to handle the merge
one).

The transaction processing is a big bad method, doing the following:
1) create gt2 transaction
2) for each element, perform basic validity checks
3) for each element, gather the name and
    namespace of involved feature types so that we can gather the
    feature type infos involved
4) build maps from feature type names to feature sources
5) check lock id, and add authorization
6) build transaction result, by looping over elements and make
    them execute their part
7) release locks
8) "complete" the result to handle issues with the spec (insert)

It seems to me it's possible to make element handling extensible
by adding a new interface, TransactionElementHandler, with the
following definition:

interface TransactionElementHandler {
   /**
    * Returns the element class this handler can proces
    */
   Class getElementClass();

   /**
    * Checks the element content is valid, throws an exception
    * otherwise
    */
   void checkValidity(Element e) throws WFSTransactionException;

   /**
    * Returns a list of feature type names needed to handle this element
    */
   QName getTypeNames(Element e) throws WFSTransactionException;

   /**
    * Executes the element against the provided feature sources
    */
   void execute(Element e, Map featureSources,
                TransactionResponseType response)
                throws WFSTransactionException;
}

We could register these handlers in the spring context or, to make
things simpler, have just a factory method that builds them
in the Transaction class, so that subclasses can handle more.

What do you think? Suggestions? I'm not stuck because of this today,
but I'll probably be tomorrow, so please be quick :slight_smile:

Cheers
Andrea

Ok, first off a big +1 to refactoring the transaction class, I was pretty sure that would need to happen.

The one thing I'm not clear on is if this is basically the same idea I had, or not. What exactly is an 'element'? You're talking like one of insert, update, delete?

Or is an element just an action that occurs when a transaction comes in?

The latter is more what I was imagining we'd need - we'd have an action for basic validity, an action for checking locks, an action for the 'validation engine' that is never really used, but which I think has good potential. And we'd have an action for 'versioning' - ie update the other tables. And down the line we might have an action to send an email based on the area being modified, to update an rss feed, to expire part of TileCache based on the area.

Or are we talking about completely different things? I believe there are many possible actions that can happen when a transaction comes in, and I'd like an interface for those actions to implement, and the transaction class just passes itself off to the list of those in the proper order. Some will be before the database commit, some will be after, I suppose some might even depend on the atomic commit if we could pull that off, pass hooks in with the transaction or something.

C

Andrea Aime wrote:

Hi,
I was looking at making WFS transaction element handling extensible,
since in WFSV in need to handle another element, the rollback one (and
in the future, when handling branches, I'll need to handle the merge
one).

The transaction processing is a big bad method, doing the following:
1) create gt2 transaction
2) for each element, perform basic validity checks
3) for each element, gather the name and
    namespace of involved feature types so that we can gather the
    feature type infos involved
4) build maps from feature type names to feature sources
5) check lock id, and add authorization
6) build transaction result, by looping over elements and make
    them execute their part
7) release locks
8) "complete" the result to handle issues with the spec (insert)

It seems to me it's possible to make element handling extensible
by adding a new interface, TransactionElementHandler, with the
following definition:

interface TransactionElementHandler {
   /**
    * Returns the element class this handler can proces
    */
   Class getElementClass();

   /**
    * Checks the element content is valid, throws an exception
    * otherwise
    */
   void checkValidity(Element e) throws WFSTransactionException;

   /**
    * Returns a list of feature type names needed to handle this element
    */
   QName getTypeNames(Element e) throws WFSTransactionException;

   /**
    * Executes the element against the provided feature sources
    */
   void execute(Element e, Map featureSources,
                TransactionResponseType response)
                throws WFSTransactionException;
}

We could register these handlers in the spring context or, to make
things simpler, have just a factory method that builds them
in the Transaction class, so that subclasses can handle more.

What do you think? Suggestions? I'm not stuck because of this today,
but I'll probably be tomorrow, so please be quick :slight_smile:

Cheers
Andrea

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

!DSPAM:1003,45f56a38137621510810322!

--
Chris Holmes
The Open Planning Project
http://topp.openplans.org

Chris Holmes ha scritto:

Ok, first off a big +1 to refactoring the transaction class, I was pretty sure that would need to happen.

The one thing I'm not clear on is if this is basically the same idea I had, or not. What exactly is an 'element'? You're talking like one of insert, update, delete?

Yeah, I talk about these.

Or is an element just an action that occurs when a transaction comes in?

Nope.

The latter is more what I was imagining we'd need - we'd have an action for basic validity, an action for checking locks, an action for the 'validation engine' that is never really used, but which I think has good potential. And we'd have an action for 'versioning' - ie update the other tables.

No no, that's the datastore work.

And down the line we might have an action to send an email based on the area being modified, to update an rss feed, to expire part of TileCache based on the area.

Or are we talking about completely different things? I believe there are many possible actions that can happen when a transaction comes in, and I'd like an interface for those actions to implement, and the transaction class just passes itself off to the list of those in the proper order. Some will be before the database commit, some will be after, I suppose some might even depend on the atomic commit if we could pull that off, pass hooks in with the transaction or something.

I hear you, and yes, validation, authorization, transformation, notification are all things that can occur during transaction processing.
But these are different that the actual transaction imho.

We could have a framework that allows to register actions that should
be performed before and after the transaction elements run, that
may stop the processing, or alter the transaction elements that are
coming in. These would be TransactionAspect (as in AOP), and may
follow an interface like:

interfance TransactionAspect {
   TransactionType beforeTransaction(TransactionType t) throws WFSExceptoin;

   FeatureCollection duringTransaction(null, FeatureCollection collections) throws WFSExceptoin;

   void beforeCommit() throws WFSEXception

   int getPriority();

}

well, certainly incomplete and a big ugly, but I think you
get the idea: a way to alter/check the request, a way to alter
the feature collections and attach listeners, a way to
say the last word before commit goes on, and a way to state
your priority in the evaluation chain.

Cheers
Andrea

Ok, sounds great. Oh right, now I remember the transaction code better, we just have three huge blocks for insert, update and delete, and you're just wanting to split those in to classes. +1. In the future we can play with the TransactionAspect stuff a bit, I like that approach.

C

Andrea Aime wrote:

Chris Holmes ha scritto:

Ok, first off a big +1 to refactoring the transaction class, I was pretty sure that would need to happen.

The one thing I'm not clear on is if this is basically the same idea I had, or not. What exactly is an 'element'? You're talking like one of insert, update, delete?

Yeah, I talk about these.

Or is an element just an action that occurs when a transaction comes in?

Nope.

The latter is more what I was imagining we'd need - we'd have an action for basic validity, an action for checking locks, an action for the 'validation engine' that is never really used, but which I think has good potential. And we'd have an action for 'versioning' - ie update the other tables.

No no, that's the datastore work.

And down the line we might have an action to send an email based on the area being modified, to update an rss feed, to expire part of TileCache based on the area.

Or are we talking about completely different things? I believe there are many possible actions that can happen when a transaction comes in, and I'd like an interface for those actions to implement, and the transaction class just passes itself off to the list of those in the proper order. Some will be before the database commit, some will be after, I suppose some might even depend on the atomic commit if we could pull that off, pass hooks in with the transaction or something.

I hear you, and yes, validation, authorization, transformation, notification are all things that can occur during transaction processing.
But these are different that the actual transaction imho.

We could have a framework that allows to register actions that should
be performed before and after the transaction elements run, that
may stop the processing, or alter the transaction elements that are
coming in. These would be TransactionAspect (as in AOP), and may
follow an interface like:

interfance TransactionAspect {
  TransactionType beforeTransaction(TransactionType t) throws WFSExceptoin;

  FeatureCollection duringTransaction(null, FeatureCollection collections) throws WFSExceptoin;

  void beforeCommit() throws WFSEXception

  int getPriority();

}

well, certainly incomplete and a big ugly, but I think you
get the idea: a way to alter/check the request, a way to alter
the feature collections and attach listeners, a way to
say the last word before commit goes on, and a way to state
your priority in the evaluation chain.

Cheers
Andrea

!DSPAM:1003,45f59f64190621116498154!

--
Chris Holmes
The Open Planning Project
http://topp.openplans.org

I think replicating all the little bits of that big bad transaction
method will be tricky, but definitely doable. In the methods defense it
may be a single unbelievably long method, but it is pretty well
documented and if you spend some time you can eventually figure out what
it is doing. It also has the benefit that everything is defined in a
single place. Breaking things apart often has the negative side effect
of important details being spread across classes.

That being said I would be for it. I also like the extension point. But
what about the extension point that the validation stuff uses. Are the
two compatible?

-Justin

Chris Holmes wrote:

Ok, sounds great. Oh right, now I remember the transaction code better,
we just have three huge blocks for insert, update and delete, and you're
just wanting to split those in to classes. +1. In the future we can
play with the TransactionAspect stuff a bit, I like that approach.

C

Andrea Aime wrote:

Chris Holmes ha scritto:

Ok, first off a big +1 to refactoring the transaction class, I was
pretty sure that would need to happen.

The one thing I'm not clear on is if this is basically the same idea
I had, or not. What exactly is an 'element'? You're talking like
one of insert, update, delete?

Yeah, I talk about these.

Or is an element just an action that occurs when a transaction comes in?

Nope.

The latter is more what I was imagining we'd need - we'd have an
action for basic validity, an action for checking locks, an action
for the 'validation engine' that is never really used, but which I
think has good potential. And we'd have an action for 'versioning' -
ie update the other tables.

No no, that's the datastore work.

And down the line we might have an action to send an email based on
the area being modified, to update an rss feed, to expire part of
TileCache based on the area.

Or are we talking about completely different things? I believe there
are many possible actions that can happen when a transaction comes
in, and I'd like an interface for those actions to implement, and the
transaction class just passes itself off to the list of those in the
proper order. Some will be before the database commit, some will be
after, I suppose some might even depend on the atomic commit if we
could pull that off, pass hooks in with the transaction or something.

I hear you, and yes, validation, authorization, transformation,
notification are all things that can occur during transaction processing.
But these are different that the actual transaction imho.

We could have a framework that allows to register actions that should
be performed before and after the transaction elements run, that
may stop the processing, or alter the transaction elements that are
coming in. These would be TransactionAspect (as in AOP), and may
follow an interface like:

interfance TransactionAspect {
  TransactionType beforeTransaction(TransactionType t) throws
WFSExceptoin;

  FeatureCollection duringTransaction(null, FeatureCollection
collections) throws WFSExceptoin;

  void beforeCommit() throws WFSEXception

  int getPriority();

}

well, certainly incomplete and a big ugly, but I think you
get the idea: a way to alter/check the request, a way to alter
the feature collections and attach listeners, a way to
say the last word before commit goes on, and a way to state
your priority in the evaluation chain.

Cheers
Andrea

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV

!DSPAM:1004,45f5a0b0192381362196140!

------------------------------------------------------------------------

_______________________________________________
Geoserver-devel mailing list
Geoserver-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/geoserver-devel

!DSPAM:1004,45f5a0b0192381362196140!

--
Justin Deoliveira
The Open Planning Project
http://topp.openplans.org

Justin Deoliveira ha scritto:

I think replicating all the little bits of that big bad transaction
method will be tricky, but definitely doable. In the methods defense it
may be a single unbelievably long method, but it is pretty well
documented and if you spend some time you can eventually figure out what
it is doing. It also has the benefit that everything is defined in a
single place. Breaking things apart often has the negative side effect
of important details being spread across classes.

That being said I would be for it. I also like the extension point. But
what about the extension point that the validation stuff uses. Are the
two compatible?

I don't know. My initial proposal was just to break the current
element transaction in separate classes and forget about the rest.
If I use inner classes I'm pretty sure I can replicate the full
behavior of the current one.

Please remember my current motivation is to be able and handle a
new "rollback" element without having to rewrite the whole big
method.

Cheers
Andrea

Andrea Aime wrote:

I don't know. My initial proposal was just to break the current
element transaction in separate classes and forget about the rest.
If I use inner classes I'm pretty sure I can replicate the full
behavior of the current one.

Please remember my current motivation is to be able and handle a
new "rollback" element without having to rewrite the whole big
method.

Right, well regardless which you choose I think it will be a step up
from before, So I guess the "wfs:Native" transaction element does not
work for you here? I guess not since you are actually extending the spec
itself.

Cheers
Andrea

!DSPAM:1004,45f5b7e5217287731818748!

--
Justin Deoliveira
The Open Planning Project
http://topp.openplans.org

Justin Deoliveira ha scritto:

Andrea Aime wrote:

I don't know. My initial proposal was just to break the current
element transaction in separate classes and forget about the rest.
If I use inner classes I'm pretty sure I can replicate the full
behavior of the current one.

Please remember my current motivation is to be able and handle a
new "rollback" element without having to rewrite the whole big
method.

Right, well regardless which you choose I think it will be a step up
from before, So I guess the "wfs:Native" transaction element does not
work for you here? I guess not since you are actually extending the spec
itself.

Yeah. Plus, the current method does not allow to add custom processing
for native methods.

Cheers
Andrea