Move section on event wiring from misc to objects.xml

Fix tx-namespace usage in xml
This commit is contained in:
markpollack
2008-11-04 03:44:59 +00:00
parent 916103202d
commit e6307a67a5
3 changed files with 551 additions and 386 deletions

View File

@@ -1,182 +1,154 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<chapter xml:id="misc" xmlns="http://docbook.org/ns/docbook" version="5">
<title>Spring.NET miscellanea</title>
<sect1>
<title>Introduction</title>
<para>
This chapter contains miscellanea information on features, goodies, caveats
that does not belong to any paricular area.
</para>
</sect1>
<sect1>
<title>PathMatcher</title>
<para>
<emphasis>Note, Spring.Util.PathMatcher is
currently only available in CVS, not the RC3 release. If you want to use these feature
please get the code from CVS
<ulink url="http://opensource.atlassian.com/confluence/spring/display/NET/Project+Structure">(instructions)</ulink>
or from the download section of the
Spring.NET website that contains an .zip with the full CVS tree.
</emphasis>
</para>
<para>
<literal>Spring.Util.PathMatcher</literal> provides <literal>Ant/NAnt</literal>-like path name matching
features.
</para>
<para>To do the match, you use the method:
<programlisting language="csharp">static bool Match(string pattern, string path)</programlisting>
</para>
<para>If you want to decide if case is important or not use the method:
<programlisting language="csharp">static bool Match(string pattern, string path, bool ignoreCase)</programlisting>
</para>
<sect2>
<title>General rules</title>
<para>
To build your pattern, you use the <literal>*</literal>, <literal>?</literal>
and <literal>**</literal> building blocks:
<itemizedlist spacing="compact">
<listitem>
<para><literal>*</literal>: matches any number of non slash
characters;
</para>
</listitem>
<listitem>
<para><literal>?</literal>: matches exactly 1 (one) non slash/dot
character;
</para>
</listitem>
<listitem>
<para><literal>**</literal>: matches any subdirectory, without
taking care of the depth;
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
<sect2>
<title>Matching filenames</title>
<para>
A file name can be matched using the following
notation:
<programlisting>foo?bar.*</programlisting>
matches:
<programlisting>fooAbar.txt
foo1bar.txt
foo_bar.txt
foo-bar.txt</programlisting>
does not match:
<programlisting>foo.bar.txt
foo/bar.txt
foo\bar.txt</programlisting>
</para>
<para>
The classical all files pattern:
<programlisting>*.*</programlisting>
matches:
<programlisting>foo.db
.db
foo
foo.bar.db
foo.db.db
db.db.db</programlisting>
does not match:
<programlisting>c:/
c:/foo.db
c:/foo
c:/.db
c:/foo.foo.db
//server/foo</programlisting>
</para>
</sect2>
<sect2>
<title>Matching subdirectories</title>
<para>
A directory name can be matched at any depth level using the following
notation:
<programlisting>**/db/**</programlisting>
That pattern matches the following paths:
<programlisting>/db
//server/db
c:/db
c:/spring/app/db/foo.db
//Program Files/App/spaced dir/db/foo.db
/home/spring/spaced dir/db/v1/foo.db</programlisting>
but does not match these:
<programlisting>c:/spring/app/db-v1/foo.db
/home/spring/spaced dir/db-v1/foo.db</programlisting>
</para>
<para>
You can compose subdirectories to match like this:
<programlisting>**/bin/**/tmp/**</programlisting>
That pattern matches the following paths:
<programlisting>c:/spring/foo/bin/bar/tmp/a
c:/spring/foo/bin/tmp/a/b.c</programlisting>
but does not match these:
<programlisting>c:/spring/foo/bin/bar/temp/a
c:/tmp/foo/bin/bar/a/b.c</programlisting>
</para>
<para>
You can use more advanced patterns:
<programlisting>**/.spring-assemblies*/**</programlisting>
matches:
<programlisting>c:/.spring-assemblies
c:/.spring-assembliesabcd73xs
c:/app/.spring-assembliesabcd73xs
c:/app/.spring-assembliesabcd73xs/foo.dll
//server/app/.spring-assembliesabcd73xs</programlisting>
does not match:
<programlisting>c:/app/.spring-assemblie</programlisting>
</para>
</sect2>
<sect2>
<title>Case does matter, slashes don't</title>
<para>
.NET is expected to be a cross-platform development ... platform. So,
<literal>PathMatcher</literal> will match taking care of the case of the pattern
and the case of the path. For example:
<programlisting>**/db/**/*.DB</programlisting>
matches:
<programlisting>c:/spring/service/deploy/app/db/foo.DB</programlisting>
but does not match:
<programlisting>c:/spring/service/deploy/app/DB/foo.DB
c:spring/service/deploy/app/spaced dir/DB/foo.DB
//server/share/service/deploy/app/DB/backup/foo.db</programlisting>
</para>
<para>If you do not matter about case, you should explicitly tell the
<literal>Pathmatcher</literal>.</para>
<para>
Back and forward slashes, in the very same cross-platform spirit, are
not important:
<programlisting>spring/foo.bar</programlisting>
matches all the following paths:
<programlisting>c:\spring\foo.bar
c:/spring\foo.bar
c:/spring/foo.bar
/spring/foo.bar
\spring\foo.bar</programlisting>
</para>
</sect2>
</sect1>
</chapter>
<?xml version="1.0" encoding="utf-8"?>
<!--
/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-->
<chapter version="5" xml:id="misc" xmlns="http://docbook.org/ns/docbook"
xmlns:ns6="http://www.w3.org/1999/xlink"
xmlns:ns5="http://www.w3.org/1999/xhtml"
xmlns:ns4="http://www.w3.org/2000/svg"
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
xmlns:ns="http://docbook.org/ns/docbook">
<title>Spring.NET miscellanea</title>
<section xml:id="spring-net-miscellanea">
<title>Introduction</title>
<para>This chapter contains miscellanea information on features, goodies,
caveats that does not belong to any paricular area.</para>
</section>
<section xml:id="pathmatcher">
<title>PathMatcher</title>
<para><emphasis>Note, Spring.Util.PathMatcher is currently only available
in CVS, not the RC3 release. If you want to use these feature please get
the code from CVS <ulink
url="http://opensource.atlassian.com/confluence/spring/display/NET/Project+Structure">(instructions)</ulink>
or from the download section of the Spring.NET website that contains an
.zip with the full CVS tree. </emphasis></para>
<para><literal>Spring.Util.PathMatcher</literal> provides
<literal>Ant/NAnt</literal>-like path name matching features.</para>
<para>To do the match, you use the method: <programlisting
language="csharp">static bool Match(string pattern, string path)</programlisting></para>
<para>If you want to decide if case is important or not use the method:
<programlisting language="csharp">static bool Match(string pattern, string path, bool ignoreCase)</programlisting></para>
<section xml:id="pathmatcher-general-rules">
<title>General rules</title>
<para>To build your pattern, you use the <literal>*</literal>,
<literal>?</literal> and <literal>**</literal> building blocks:
<itemizedlist spacing="compact">
<listitem>
<para><literal>*</literal>: matches any number of non slash
characters;</para>
</listitem>
<listitem>
<para><literal>?</literal>: matches exactly 1 (one) non slash/dot
character;</para>
</listitem>
<listitem>
<para><literal>**</literal>: matches any subdirectory, without
taking care of the depth;</para>
</listitem>
</itemizedlist></para>
</section>
<section xml:id="pathmatcher-matching-filenames">
<title>Matching filenames</title>
<para>A file name can be matched using the following notation:
<programlisting>foo?bar.*</programlisting> matches: <programlisting>fooAbar.txt
foo1bar.txt
foo_bar.txt
foo-bar.txt</programlisting> does not match: <programlisting>foo.bar.txt
foo/bar.txt
foo\bar.txt</programlisting></para>
<para>The classical all files pattern: <programlisting>*.*</programlisting>
matches: <programlisting>foo.db
.db
foo
foo.bar.db
foo.db.db
db.db.db</programlisting> does not match: <programlisting>c:/
c:/foo.db
c:/foo
c:/.db
c:/foo.foo.db
//server/foo</programlisting></para>
</section>
<section xml:id="pathmatcher-matching-subdirectories">
<title>Matching subdirectories</title>
<para>A directory name can be matched at any depth level using the
following notation: <programlisting>**/db/**</programlisting> That
pattern matches the following paths: <programlisting>/db
//server/db
c:/db
c:/spring/app/db/foo.db
//Program Files/App/spaced dir/db/foo.db
/home/spring/spaced dir/db/v1/foo.db</programlisting> but does not match
these: <programlisting>c:/spring/app/db-v1/foo.db
/home/spring/spaced dir/db-v1/foo.db</programlisting></para>
<para>You can compose subdirectories to match like this:
<programlisting>**/bin/**/tmp/**</programlisting> That pattern matches
the following paths: <programlisting>c:/spring/foo/bin/bar/tmp/a
c:/spring/foo/bin/tmp/a/b.c</programlisting> but does not match these:
<programlisting>c:/spring/foo/bin/bar/temp/a
c:/tmp/foo/bin/bar/a/b.c</programlisting></para>
<para>You can use more advanced patterns: <programlisting>**/.spring-assemblies*/**</programlisting>
matches: <programlisting>c:/.spring-assemblies
c:/.spring-assembliesabcd73xs
c:/app/.spring-assembliesabcd73xs
c:/app/.spring-assembliesabcd73xs/foo.dll
//server/app/.spring-assembliesabcd73xs</programlisting> does not match:
<programlisting>c:/app/.spring-assemblie</programlisting></para>
</section>
<section xml:id="pathmatcher-case-matters">
<title>Case does matter, slashes don't</title>
<para>.NET is expected to be a cross-platform development ... platform.
So, <literal>PathMatcher</literal> will match taking care of the case of
the pattern and the case of the path. For example: <programlisting>**/db/**/*.DB</programlisting>
matches: <programlisting>c:/spring/service/deploy/app/db/foo.DB</programlisting>
but does not match: <programlisting>c:/spring/service/deploy/app/DB/foo.DB
c:spring/service/deploy/app/spaced dir/DB/foo.DB
//server/share/service/deploy/app/DB/backup/foo.db</programlisting></para>
<para>If you do not matter about case, you should explicitly tell the
<literal>Pathmatcher</literal>.</para>
<para>Back and forward slashes, in the very same cross-platform spirit,
are not important: <programlisting>spring/foo.bar</programlisting>
matches all the following paths: <programlisting>c:\spring\foo.bar
c:/spring\foo.bar
c:/spring/foo.bar
/spring/foo.bar
\spring\foo.bar</programlisting></para>
</section>
</section>
</chapter>

View File

@@ -2111,6 +2111,163 @@ public class MixedIocObject
</sect3>
</sect2>
<sect2>
<title>Declarative Event Listener Registration</title>
<para>In C# events are built right into the language thanks to the
<literal>event</literal> keyword. Under the scenes, events are
essentially a shorthand notation for delegates with some additional
guidelines as to what the parameters to an event handler method should
be (i.e. a sender <literal>System.Object</literal> and an
<literal>System.EventArgs</literal> object).</para>
<para><programlisting language="csharp">public class EventSource
public event EventHandler Click;</programlisting></para>
<para>In use, .NET events are combined with one or more event handler
methods. Each handler method is programmatically added, or removed, from
the event and corresponds to an object's method that should be invoked
when a particular event occurs. When more than one handler method is
added to an event, then each of the registered methods will be invoked
in turn when an event occurs.</para>
<para><programlisting language="csharp">TestObject source = new TestObject();
TestEventHandler eventListener1 = new TestEventHandler();
TestEventHandler eventListener2 = new TestEventHandler();
source.Click += eventListener1.HandleEvent; // Adding the first event handler method to the event
source.Click += eventListener2.HandleEvent; // Adding a second event handler method to the event
source.OnClick(); // First eventListener1.HandleEvent is invoked, then eventListener2.HandleEvent</programlisting></para>
<para>When OnClick() is invoked, the event is fired.</para>
<para><programlisting language="csharp">public void OnClick()
{
if (Click != null)
{
Click(this, EventArgs.Empty); // Fire the event off to the registered handler methods
}
}</programlisting></para>
<para>One of the not so nice things about using events is that, without
employing late binding, you declare the objects that are registered with
a particular event programmatically. Spring .NET offers a way to
declaratively register your handler methods with particular events using
the <literal>&lt;listener&gt;</literal> element inside your
<literal>&lt;object&gt;</literal> elements.</para>
<sect3>
<title>Declarative event handlers</title>
<para>Rather than having to specifically declare in your code that you
are adding a method to be invoked on an event, using the
<literal>&lt;listener&gt;</literal> element you can register a plain
object's methods with the corresponding event declaratively in your
application configuration.</para>
<para>Using the <literal>listener</literal> element you can:
<itemizedlist>
<listitem>
<link linkend="objects-simple-event-configuration">Configure a
method to be invoked when an event is fired.</link>
</listitem>
<listitem>
<link linkend="objects-handler-reg-ex-configuration">Register a
collection of handler methods based on a regular
expression.</link>
</listitem>
<listitem>
<link linkend="objects-event-name-reg-ex-configuration">Register
a handler method against an event name that contains a regular
expression.</link>
</listitem>
</itemizedlist></para>
</sect3>
<sect3 xml:id="objects-simple-event-configuration">
<title>Configuring a method to be invoked when an event is
fired</title>
<para>The same event registration in the example above can be achieved
using configuration using the <literal>&lt;listener&gt;</literal>
element.</para>
<para><programlisting language="myxml">&lt;object id="eventListener1" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;!-- wired up to an event exposed on an instance --&gt;
&lt;listener event="Click" method="HandleEvent"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;
&lt;object id="eventListener2" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;!-- wired up to an event exposed on an instance --&gt;
&lt;listener event="Click" method="HandleEvent"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;</programlisting></para>
<para>In this case the two different objects will have their
<literal>HandleEvent</literal> method invoked, as indicated explicitly
using the <literal>method</literal> attribute, when a
<literal>Click</literal> event, as specified by the
<literal>event</literal> attribute, is triggered on the object
referred to by the <literal>ref</literal> element.</para>
</sect3>
<sect3 xml:id="objects-handler-reg-ex-configuration">
<title>Registering a collection of handler methods based on a regular
expression</title>
<para>Regular expressions can be employed to wire up more than one
handler method to an object that contains one or more events.</para>
<para><programlisting language="myxml">&lt;object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;listener method="Handle.+"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;</programlisting></para>
<para>Here all the <literal>eventListener</literal>'s handler methods
that begin with 'Handle', and that have the corresponding two
parameters of a <literal>System.Object</literal> and a
<literal>System.EventArgs</literal>, will be registered against all
events exposed by the <literal>source</literal> object.</para>
<para>You can also use the name of the event in regular expression to
filter your handler methods based on the type of event
triggered.</para>
<para><programlisting language="myxml">&lt;object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;!-- For the Click event, the HandleClick handler method will be invoked. --&gt;
&lt;listener method="Handle${event}"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;</programlisting></para>
</sect3>
<sect3 xml:id="objects-event-name-reg-ex-configuration">
<title>Registering a handler method against an event name that
contains a regular expression</title>
<para>Finally, you can register an object's handler methods against a
selection of events, filtering based on their name using a regular
expression.</para>
<para><programlisting language="myxml">&lt;object id="eventListener" type="SpringdotNETEventsExample.TestEventHandler, SpringdotNETEventsExample"&gt;
&lt;listener method="HandleEvent" event="Cl.+"&gt;
&lt;ref object="source"/&gt;
&lt;/listener&gt;
&lt;/object&gt;</programlisting></para>
<para>In this example the <literal>eventListener</literal>'s
<literal>HandleEvent</literal> handler method will be invoked for any
event that begins with 'Cl'.</para>
</sect3>
</sect2>
<sect2 xml:id="objects-factory-dependson">
<title>Using <literal>depends-on</literal></title>

View File

@@ -16,7 +16,13 @@
* limitations under the License.
*/
-->
<chapter xml:id="transaction" xmlns="http://docbook.org/ns/docbook" version="5">
<chapter version="5" xml:id="transaction"
xmlns="http://docbook.org/ns/docbook"
xmlns:ns6="http://www.w3.org/1999/xlink"
xmlns:ns5="http://www.w3.org/2000/svg"
xmlns:ns4="http://www.w3.org/1999/xhtml"
xmlns:ns3="http://www.w3.org/1998/Math/MathML"
xmlns:ns="http://docbook.org/ns/docbook">
<title>Transaction management</title>
<sect1 xml:id="tx-introduction">
@@ -40,7 +46,8 @@
<listitem>
<para>Provides a simple API for <link
linkend="transaction-programmatic">programmatic</link> transaction management</para>
linkend="transaction-programmatic">programmatic</link> transaction
management</para>
</listitem>
<listitem>
@@ -76,9 +83,10 @@
</listitem>
<listitem>
<para>The fourth section, entitled <link linkend="transaction-programmatic">Programmatic
transaction management</link>, covers support for programmatic
transaction management.</para>
<para>The fourth section, entitled <link
linkend="transaction-programmatic">Programmatic transaction
management</link>, covers support for programmatic transaction
management.</para>
</listitem>
</itemizedlist>
</sect1>
@@ -215,16 +223,16 @@
<para>This is primarily a 'SPI' (Service Provider Interface), although it
can be used Programatically. Note that in keeping with the Spring
Framework's philosophy, <literal>IPlatformTransactionManager</literal>
is an interface, and can thus be easily mocked or stubbed as necessary.
<literal>IPlatformTransactionManager</literal> implementations
are defined like any other object in the IoC container. The following
implementations are provided</para>
Framework's philosophy, <literal>IPlatformTransactionManager</literal> is
an interface, and can thus be easily mocked or stubbed as necessary.
<literal>IPlatformTransactionManager</literal> implementations are defined
like any other object in the IoC container. The following implementations
are provided</para>
<itemizedlist>
<listitem>
<para><literal>AdoPlatformTransactionManager</literal> - local
ADO.NET based transactions</para>
<para><literal>AdoPlatformTransactionManager</literal> - local ADO.NET
based transactions</para>
</listitem>
<listitem>
@@ -238,8 +246,8 @@
</listitem>
<listitem>
<para><literal>HibernatePlatformTransactionManager</literal> -
local transaction manager for use with NHibernate or mixed
<para><literal>HibernatePlatformTransactionManager</literal> - local
transaction manager for use with NHibernate or mixed
ADO.NET/NHibernate data access operations.</para>
</listitem>
</itemizedlist>
@@ -261,11 +269,10 @@
<para>The <literal>GetTransaction(..)</literal> method returns a
<literal>ITransactionStatus</literal> object, depending on a
<literal>ITransactionDefinition</literal> parameters. The returned
<literal>ITransactionStatus</literal> might represent a new or
existing transaction (if there was a matching transaction in the current
call stack - with the implication being that a
<literal>ITransactionStatus</literal> is associated with a logical
thread of execution.</para>
<literal>ITransactionStatus</literal> might represent a new or existing
transaction (if there was a matching transaction in the current call stack
- with the implication being that a <literal>ITransactionStatus</literal>
is associated with a logical thread of execution.</para>
<para>The <literal>ITransactionDefinition</literal> interface
specified</para>
@@ -305,28 +312,25 @@
concepts is essential to using the Spring Framework or indeed any other
transaction management solution.</para>
<para>The <literal>ITransactionStatus</literal> interface
provides a simple way for transactional code to control transaction
execution and query transaction status.</para>
<para>The <literal>ITransactionStatus</literal> interface provides a
simple way for transactional code to control transaction execution and
query transaction status.</para>
<para>Regardless of whether you opt for declarative or programmatic
transaction management in Spring, defining the correct
<literal>IPlatformTransactionManager</literal> implementation
is absolutely essential. In good Spring fashion, this important definition
<literal>IPlatformTransactionManager</literal> implementation is
absolutely essential. In good Spring fashion, this important definition
typically is made using via Dependency Injection.</para>
<para><literal>IPlatformTransactionManager</literal>
implementations normally require knowledge of the environment in which
they work, ADO.NET, NHibernate, etc. The following example shows how a
standard ADO.NET based
<literal>IPlatformTransactionManager</literal> can be
defined.</para>
<para><literal>IPlatformTransactionManager</literal> implementations
normally require knowledge of the environment in which they work, ADO.NET,
NHibernate, etc. The following example shows how a standard ADO.NET based
<literal>IPlatformTransactionManager</literal> can be defined.</para>
<para>We must define a Spring <literal>IDbProvider</literal>
and then use Spring's
<literal>AdoPlatformTransactionManager</literal>, giving it a
reference to the <literal>IDbProvider</literal>. For more information
on the <literal>IDbProvider</literal> abstraction refer to the next
<para>We must define a Spring <literal>IDbProvider</literal> and then use
Spring's <literal>AdoPlatformTransactionManager</literal>, giving it a
reference to the <literal>IDbProvider</literal>. For more information on
the <literal>IDbProvider</literal> abstraction refer to the next
chapter.</para>
<programlisting language="myxml">&lt;objects xmlns='http://www.springframework.net'
@@ -463,9 +467,9 @@
specify which exceptions should cause automatic roll back. We specify this
declaratively, in configuration, not in code. So, while we can still set
<literal>RollbackOnly</literal> on the
<literal>ITransactionStatus</literal> object to roll the
current transaction back Programatically, most often we can specify a rule
that MyApplicationException must always result in rollback. This has the
<literal>ITransactionStatus</literal> object to roll the current
transaction back Programatically, most often we can specify a rule that
MyApplicationException must always result in rollback. This has the
significant advantage that business objects don't need to depend on the
transaction infrastructure. For example, they typically don't need to
import any Spring APIs, transaction or other. If you would like to
@@ -481,8 +485,8 @@
</note>
<sect2 xml:id="tx-understandingimpl">
<title>Understanding
Spring's declarative transaction implementation</title>
<title>Understanding Spring's declarative transaction
implementation</title>
<para>The aim of this section is to dispel the mystique that is
sometimes associated with the use of declarative transactions. It is all
@@ -522,7 +526,7 @@
<mediaobject>
<imageobject>
<imagedata fileref="images/tx.png" />
<imagedata fileref="images/tx.png"></imagedata>
</imageobject>
</mediaobject>
@@ -534,9 +538,9 @@
<itemizedlist>
<listitem>
<para><literal>ProxyFactoryObject</literal>. The common
properties to set are the reference to the object to proxy (the
target object) and a reference to the transaction advice. See <xref
<para><literal>ProxyFactoryObject</literal>. The common properties
to set are the reference to the object to proxy (the target object)
and a reference to the transaction advice. See <xref
linkend="aop-proxyfactoryobject" /> for more details.</para>
</listitem>
@@ -555,10 +559,10 @@
</listitem>
<listitem>
<para><literal>DefaultAdvisorAutoProxyCreator</literal>
which specifies one or more "advisors" i.e an object
representing an aspect, including both an advice and a pointcut
targeting it to specific joinpoints. See <xref
<para><literal>DefaultAdvisorAutoProxyCreator</literal> which
specifies one or more "advisors" i.e an object representing an
aspect, including both an advice and a pointcut targeting it to
specific joinpoints. See <xref
linkend="aop-advisorautoproxy" /></para>
</listitem>
</itemizedlist>
@@ -567,8 +571,8 @@
<para>There is also a convenience subclass of
<literal>ProxyFactoryObject</literal>, namely
<literal>TransactionProxyFactoryObject</literal>, that sets some
common default values for the specific case of applying transactional
<literal>TransactionProxyFactoryObject</literal>, that sets some common
default values for the specific case of applying transactional
advice.</para>
<para>The <literal>DefaultAdvisorAutoProxyCreator</literal> is very
@@ -610,11 +614,11 @@
<para>Consider the following interface. The intent is to convey the
concepts to you so you can concentrate on the transaction usage and not
have to worry about domain specific details. The
<literal>ITestObjectManager</literal> is a poor-mans
business service layer - the implementation of which will make two DAO
calls. Clearly this example is overly simplistic from the service layer
perspective as there isn't any business logic at all!. The 'service'
interface is shown below.</para>
<literal>ITestObjectManager</literal> is a poor-mans business service
layer - the implementation of which will make two DAO calls. Clearly
this example is overly simplistic from the service layer perspective as
there isn't any business logic at all!. The 'service' interface is shown
below.</para>
<programlisting language="csharp">public interface ITestObjectManager
{
@@ -623,8 +627,8 @@
void DeleteTwoTestObjects(string name1, string name2);
}</programlisting>
<para>The implementation of
<literal>ITestObjectManager</literal> is shown below</para>
<para>The implementation of <literal>ITestObjectManager</literal> is
shown below</para>
<programlisting language="csharp">public class TestObjectManager : ITestObjectManager
{
@@ -669,8 +673,8 @@
}</programlisting>
<para>The Create and Delete method implementation is shown below. Note
that this uses the <literal>AdoTemplate</literal> class discussed in
the following chapter. Refer to <xref linkend="resource-sync" /> for
that this uses the <literal>AdoTemplate</literal> class discussed in the
following chapter. Refer to <xref linkend="resource-sync" /> for
information on the interaction between Spring's high level persistence
integration APIs and transaction management features.</para>
@@ -691,15 +695,14 @@
}
}</programlisting>
<para>The <literal>TestObjectManager</literal> is configured with
the DAO objects by standard dependency injection techniques. The client
<para>The <literal>TestObjectManager</literal> is configured with the
DAO objects by standard dependency injection techniques. The client
code, which in this case directly asks the Spring IoC container for an
instance of <literal>ITestObjectManager</literal>, will
receive a transaction proxy with transaction options based on the
attribute metadata. Note that typically the
<literal>ITestObjectManager</literal> would be set on yet
another higher level object via dependency injection, for example a web
service.</para>
instance of <literal>ITestObjectManager</literal>, will receive a
transaction proxy with transaction options based on the attribute
metadata. Note that typically the <literal>ITestObjectManager</literal>
would be set on yet another higher level object via dependency
injection, for example a web service.</para>
<para>The client calling code is shown below</para>
@@ -807,26 +810,26 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<itemizedlist>
<listitem>
<para><literal>TransactionInterceptor</literal> is the AOP
advice responsible for performing transaction management
<para><literal>TransactionInterceptor</literal> is the AOP advice
responsible for performing transaction management
functionality.</para>
</listitem>
<listitem>
<para><literal>TransactionAttributeSourceAdvisor</literal> is an
AOP Advisor that holds the TransactionInterceptor, which is the
advice, and a pointcut (where to apply the advice), in the form of a
<para><literal>TransactionAttributeSourceAdvisor</literal> is an AOP
Advisor that holds the TransactionInterceptor, which is the advice,
and a pointcut (where to apply the advice), in the form of a
TransactionAttributeSource.</para>
</listitem>
<listitem>
<para><literal>AttributesTransactionAttributeSource</literal> is
an implementation of the
<literal>ITransactionAttributeSource</literal> interface that
defines where to get the transaction metadata defining the
transaction semantics (isolation level, propagation behavior, etc)
that should be applied to specific methods of specific classes. The
transaction metadata is specified via implementations of the
<para><literal>AttributesTransactionAttributeSource</literal> is an
implementation of the <literal>ITransactionAttributeSource</literal>
interface that defines where to get the transaction metadata
defining the transaction semantics (isolation level, propagation
behavior, etc) that should be applied to specific methods of
specific classes. The transaction metadata is specified via
implementations of the
<literal>ITransactionAttributeSource</literal> interface. This
example shows the use of the implementation
<literal>Spring.Transaction.Interceptor.AttributesTransactionAttributeSource</literal>
@@ -848,8 +851,8 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</listitem>
<listitem>
<para><literal>AttributesTransactionAttributeSource</literal>
: Use a standard. .NET attributes to specify the transactional
<para><literal>AttributesTransactionAttributeSource</literal> :
Use a standard. .NET attributes to specify the transactional
information. See <literal>TransactionAttribute</literal> class
for more information.</para>
</listitem>
@@ -877,8 +880,8 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</listitem>
<listitem>
<para><literal>MethodMapTransactionAttributeSource</literal>
: Similar to NameMatchTransactionAttributeSource but specifies
<para><literal>MethodMapTransactionAttributeSource</literal> :
Similar to NameMatchTransactionAttributeSource but specifies
that only fully qualified method names (i.e. type.method,
assembly) and wildcards can be used at the start or end of the
method name for matching multiple methods.</para>
@@ -887,8 +890,8 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</listitem>
<listitem>
<para><literal>DefaultAdvisorAutoProxyCreator</literal>: looks
for Advisors in the context, and automatically creates proxy objects
<para><literal>DefaultAdvisorAutoProxyCreator</literal>: looks for
Advisors in the context, and automatically creates proxy objects
which are the transactional wrappers</para>
</listitem>
</itemizedlist>
@@ -944,7 +947,7 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
xmlns:db="http://www.springframework.net/database"
xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/schema/objects/spring-objects.xsd
http://www.springframework.net/schema/tx http://www.springframework.net/schema/tx/spring-tx-1.1.xsd"
http://www.springframework.net/schema/tx http://www.springframework.net/schema/tx/spring-database.xsd"&gt;
http://www.springframework.net/schema/db http://www.springframework.net/schema/db/spring-database.xsd"&gt;
&lt;db:provider id="DbProvider"
provider="SqlServer-1.1"
@@ -980,13 +983,12 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<para>You can actually omit the
<literal>'transaction-manager'</literal> attribute in the
<literal>&lt;tx:attribute-driven/&gt;</literal> tag if the object
name of the
<literal>IPlatformTransactionManager</literal> that you
name of the <literal>IPlatformTransactionManager</literal> that you
want to wire in has the name
<literal>'transactionManager'</literal>. If the
<literal>PlatformTransactionManager</literal> object
that you want to dependency inject has any other name, then you have
to be explicit and use the <literal>'transaction-manager'</literal>
<literal>PlatformTransactionManager</literal> object that you want
to dependency inject has any other name, then you have to be
explicit and use the <literal>'transaction-manager'</literal>
attribute as in the example above.</para>
</tip>The various optional elements of the
&lt;tx:attribute-driven/&gt; tag are summarised in the following
@@ -1011,57 +1013,68 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<tbody>
<row>
<entry><literal>transaction-manager</literal></entry>
<entry>
<literal>transaction-manager</literal>
</entry>
<entry>No</entry>
<entry>transactionManager</entry>
<entry><para>The name of transaction manager to use. Only
required if the name of the transaction manager is not
<literal>transactionManager</literal>, as in the example
above.</para></entry>
<entry>
<para>The name of transaction manager to use. Only required
if the name of the transaction manager is not
<literal>transactionManager</literal>, as in the example
above.</para>
</entry>
</row>
<row>
<entry><literal>proxy-target-type</literal></entry>
<entry>
<literal>proxy-target-type</literal>
</entry>
<entry>No</entry>
<entry></entry>
<entry />
<entry><para>Controls what type of transactional proxies are
created for classes annotated with the
<literal>[Transaction]</literal> attribute. If
"<literal>proxy-target-type</literal>" attribute is set to
"<literal>true</literal>", then class-based proxies will be
created (proxy inherits from target class, however calls are
still delegated to target object via composition. This allows
for casting to base class. If
"<literal>proxy-target-type</literal>" is
"<literal>false</literal>" or if the attribute is omitted,
then a pure composition based proxy is created and you can
only cast the proxy to implemented interfaces. (See the
section entitled <xref linkend="aop-proxy-mechanism" /> for a
detailed examination of the different proxy
types.)</para></entry>
<entry>
<para>Controls what type of transactional proxies are
created for classes annotated with the
<literal>[Transaction]</literal> attribute. If
"<literal>proxy-target-type</literal>" attribute is set to
"<literal>true</literal>", then class-based proxies will be
created (proxy inherits from target class, however calls are
still delegated to target object via composition. This
allows for casting to base class. If
"<literal>proxy-target-type</literal>" is
"<literal>false</literal>" or if the attribute is omitted,
then a pure composition based proxy is created and you can
only cast the proxy to implemented interfaces. (See the
section entitled <xref linkend="aop-proxy-mechanism" /> for
a detailed examination of the different proxy types.)</para>
</entry>
</row>
<row>
<entry><literal>order</literal></entry>
<entry>
<literal>order</literal>
</entry>
<entry>No</entry>
<entry></entry>
<entry />
<entry><para>Defines the order of the transaction advice that
will be applied to objects annotated with
<code>[Transaction]</code>. More on the rules related to
ordering of AOP advice can be found in the AOP chapter (see
section <xref lang="" linkend="aop-advice-ordering" />). Note
that not specifying any ordering will leave the decision as to
what order advice is run in to the AOP
subsystem.</para></entry>
<entry>
<para>Defines the order of the transaction advice that will
be applied to objects annotated with
<code>[Transaction]</code>. More on the rules related to
ordering of AOP advice can be found in the AOP chapter (see
section <xref lang="" linkend="aop-advice-ordering" />).
Note that not specifying any ordering will leave the
decision as to what order advice is run in to the AOP
subsystem.</para>
</entry>
</row>
</tbody>
</tgroup>
@@ -1214,23 +1227,29 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<tbody>
<row>
<entry><literal>name</literal></entry>
<entry>
<literal>name</literal>
</entry>
<entry>Yes</entry>
<entry></entry>
<entry />
<entry><para>The method name(s) with which the transaction
attributes are to be associated. The wildcard (*) character
can be used to associate the same transaction attribute
settings with a number of methods; for example,
<literal>'Get*'</literal>,
<literal>'Handle*'</literal>,<literal> 'On*Event'</literal>,
and so forth.</para></entry>
<entry>
<para>The method name(s) with which the transaction
attributes are to be associated. The wildcard (*) character
can be used to associate the same transaction attribute
settings with a number of methods; for example,
<literal>'Get*'</literal>,
<literal>'Handle*'</literal>,<literal> 'On*Event'</literal>,
and so forth.</para>
</entry>
</row>
<row>
<entry><literal>propagation</literal></entry>
<entry>
<literal>propagation</literal>
</entry>
<entry>No</entry>
@@ -1240,7 +1259,9 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</row>
<row>
<entry><literal>isolation</literal></entry>
<entry>
<literal>isolation</literal>
</entry>
<entry>No</entry>
@@ -1250,7 +1271,9 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</row>
<row>
<entry><literal>timeout</literal></entry>
<entry>
<literal>timeout</literal>
</entry>
<entry>No</entry>
@@ -1260,7 +1283,9 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</row>
<row>
<entry><literal>read-only</literal></entry>
<entry>
<literal>read-only</literal>
</entry>
<entry>No</entry>
@@ -1270,7 +1295,9 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</row>
<row>
<entry><literal>EnterpriseServicesInteropOption</literal></entry>
<entry>
<literal>EnterpriseServicesInteropOption</literal>
</entry>
<entry>No</entry>
@@ -1281,28 +1308,36 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</row>
<row>
<entry><literal>rollback-for</literal></entry>
<entry>
<literal>rollback-for</literal>
</entry>
<entry>No</entry>
<entry></entry>
<entry />
<entry><para>The <literal>Exception(s)</literal> that will
trigger rollback; comma-delimited. For example,
<literal>'MyProduct.MyBusinessException,ValidationException'</literal></para></entry>
<entry>
<para>The <literal>Exception(s)</literal> that will trigger
rollback; comma-delimited. For example,
<literal>'MyProduct.MyBusinessException,ValidationException'</literal></para>
</entry>
</row>
<row>
<entry><literal>no-rollback-for</literal></entry>
<entry>
<literal>no-rollback-for</literal>
</entry>
<entry>No</entry>
<entry></entry>
<entry />
<entry><para>The <literal>Exception(s)</literal> that will
<emphasis>not</emphasis> trigger rollback; comma-delimited.
For example,
<literal>'MyProduct.MyBusinessException,ValidationException'</literal></para></entry>
<entry>
<para>The <literal>Exception(s)</literal> that will
<emphasis>not</emphasis> trigger rollback; comma-delimited.
For example,
<literal>'MyProduct.MyBusinessException,ValidationException'</literal></para>
</entry>
</row>
</tbody>
</tgroup>
@@ -1365,14 +1400,17 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<tbody>
<row>
<entry align="center"><emphasis
role="bold">Property</emphasis></entry>
<entry align="center">
<emphasis role="bold">Property</emphasis>
</entry>
<entry align="center"><emphasis
role="bold">Type</emphasis></entry>
<entry align="center">
<emphasis role="bold">Type</emphasis>
</entry>
<entry align="center"><emphasis
role="bold">Description</emphasis></entry>
<entry align="center">
<emphasis role="bold">Description</emphasis>
</entry>
</row>
<row>
@@ -1388,7 +1426,9 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<row>
<entry>Isolation</entry>
<entry><literal>System.Data.IsolationLevel</literal></entry>
<entry>
<literal>System.Data.IsolationLevel</literal>
</entry>
<entry>optional isolation level</entry>
</row>
@@ -1496,9 +1536,8 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<link linkend="tx-firstexample">first example</link>. The use of
Spring's autoproxy functionality defines criteria to select a collection
of objects to create a transactional AOP proxy. There are two AutoProxy
classes that you can use,
<literal>ObjectNameAutoProxyCreator</literal> and
<literal>DefaultAdvisorAutoProxyCreator</literal>. If you are using
classes that you can use, <literal>ObjectNameAutoProxyCreator</literal>
and <literal>DefaultAdvisorAutoProxyCreator</literal>. If you are using
the new transaction namespace support you do not need to configure these
objects as a DefaultAdvisorAutoProxyCreator is created 'under the
covers' while parsing the transaction namespace elements</para>
@@ -1759,8 +1798,7 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</listitem>
<listitem>
<para>Using a
<literal>IPlatformTransactionManager</literal>
<para>Using a <literal>IPlatformTransactionManager</literal>
implementation directly</para>
</listitem>
</itemizedlist>
@@ -1775,16 +1813,16 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<para>The TransactionTemplate adopts the same approach as other Spring
templates such as <literal>AdoTemplate</literal> and
<literal>HibernateTemplate</literal>. It uses a callback approach,
to free application code from having to do the boilerplate acquisition
and release of resources, and results in code that is intention driven,
in that the code that is written focuses solely on what the developer
wants to do. Granted that the using construct of System.Transaction
alleviates much of this. One key difference with the approach taken with
the TransactionTemplate is that a commit is assumed - throwing an
exception triggers a rollback instead of using the TransactionScope API
to commit or rollback. This also allows for the use of rollback rules,
that is a commit can still occur for exceptions of certain types. <note>
<literal>HibernateTemplate</literal>. It uses a callback approach, to
free application code from having to do the boilerplate acquisition and
release of resources, and results in code that is intention driven, in
that the code that is written focuses solely on what the developer wants
to do. Granted that the using construct of System.Transaction alleviates
much of this. One key difference with the approach taken with the
TransactionTemplate is that a commit is assumed - throwing an exception
triggers a rollback instead of using the TransactionScope API to commit
or rollback. This also allows for the use of rollback rules, that is a
commit can still occur for exceptions of certain types. <note>
<para>As you will immediately see in the examples that follow, using
the <literal>TransactionTemplate</literal> absolutely couples you to
Spring's transaction infrastructure and APIs. Whether or not
@@ -1799,8 +1837,8 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
execute in the context of a transaction. You will then pass an instance
of your custom ITransactionCallback to the Execute(..) method exposed on
the TransactionTemplate. Note that the
<literal>ITransactionCallback</literal> can be used to
return a value:</para>
<literal>ITransactionCallback</literal> can be used to return a
value:</para>
<programlisting language="csharp">public class SimpleService : IService
{
@@ -1826,11 +1864,10 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
delegates, which provides a particularly elegant means to invoke a
callback function as local variables can be referred to inside the
delegate, i.e. userId. In this case the
<literal>ITransactionStatus</literal> was not exposed in the
delegate (delegate can infer the signature to use), but one could also
obtain a reference to the
<literal>ITransactionStatus</literal> instance and set the
<literal>RollbackOnly</literal> property to trigger a rollback - or
<literal>ITransactionStatus</literal> was not exposed in the delegate
(delegate can infer the signature to use), but one could also obtain a
reference to the <literal>ITransactionStatus</literal> instance and set
the <literal>RollbackOnly</literal> property to trigger a rollback - or
alternatively throw an exception. This is shown below</para>
<programlisting language="csharp">tt.Execute(delegate(ITransactionStatus status)
@@ -1846,8 +1883,8 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<para>If you are using .NET 1.1 then you should provide a normal
delegate reference or an instance of a class that implements the
<literal>ITransactionCallback</literal> interface. This is
shown below</para>
<literal>ITransactionCallback</literal> interface. This is shown
below</para>
<programlisting language="csharp">tt.Execute(new TransactionRollbackTxCallback(amount));
@@ -1872,9 +1909,9 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<para>Application classes wishing to use the
<literal>TransactionTemplate</literal> must have access to a
<literal>IPlatformTransactionManager</literal> (which will
typically be supplied to the class via dependency injection). It is easy
to unit test such classes with a mock or stub
<literal>IPlatformTransactionManager</literal> (which will typically be
supplied to the class via dependency injection). It is easy to unit test
such classes with a mock or stub
<literal>IPlatformTransactionManager</literal>.</para>
<sect3>
@@ -1882,11 +1919,11 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
<para>Transaction settings such as the propagation mode, the isolation
level, the timeout, and so forth can be set on the
<literal>TransactionTemplate</literal> either programmatically or
in configuration. <literal>TransactionTemplate</literal> instances
by default have the default transactional settings. Find below an
example of programmatically customizing the transactional settings for
a specific <literal>TransactionTemplate</literal>.</para>
<literal>TransactionTemplate</literal> either programmatically or in
configuration. <literal>TransactionTemplate</literal> instances by
default have the default transactional settings. Find below an example
of programmatically customizing the transactional settings for a
specific <literal>TransactionTemplate</literal>.</para>
<programlisting language="csharp">public class SimpleService : IService
{
@@ -1912,8 +1949,8 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
</programlisting>
<para>Find below an example of defining a
<literal>TransactionTemplate</literal> with some custom
transactional settings, using Spring XML configuration. The
<literal>TransactionTemplate</literal> with some custom transactional
settings, using Spring XML configuration. The
'<literal>sharedTransactionTemplate</literal>' can then be injected
into as many services as are required.</para>
@@ -1923,15 +1960,14 @@ mgr.DeleteTwoTestObjects("Jack", "Jill");
&lt;property name="TransactionTimeout" value="30"/&gt;
&lt;/object&gt;</programlisting>
<para>Finally, instances of the
<literal>TransactionTemplate</literal> class are threadsafe, in
that instances do not maintain any conversational state.
<literal>TransactionTemplate</literal> instances do however
maintain configuration state, so while a number of classes may choose
to share a single instance of a
<para>Finally, instances of the <literal>TransactionTemplate</literal>
class are threadsafe, in that instances do not maintain any
conversational state. <literal>TransactionTemplate</literal> instances
do however maintain configuration state, so while a number of classes
may choose to share a single instance of a
<literal>TransactionTemplate</literal>, if a class needed to use a
<literal>TransactionTemplate</literal> with different settings
(for example, a different isolation level), then two distinct
<literal>TransactionTemplate</literal> with different settings (for
example, a different isolation level), then two distinct
<literal>TransactionTemplate</literal> instances would need to be
created and used.</para>
</sect3>
@@ -1991,10 +2027,10 @@ transactionManager.Commit(status);</programlisting>
Typical application code should not need to rely on using this class but
in some cases it is convenient to receive events around the lifecycle of
the transaction, i.e. before committing, after committing.
<literal>TransactionSynchronizationManager</literal> provides a method
to register a callback object that is informed on all significant stages
in the transaction lifecycle. Note that you can register for lifecycle
call back information for any of the transaction managers you use, be it
<literal>TransactionSynchronizationManager</literal> provides a method to
register a callback object that is informed on all significant stages in
the transaction lifecycle. Note that you can register for lifecycle call
back information for any of the transaction managers you use, be it
NHibernate or local ADO.NET transactions.</para>
<para>The method to register a callback with the
@@ -2023,7 +2059,7 @@ transactionManager.Commit(status);</programlisting>
void AfterCompletion( TransactionSynchronizationStatus status );
}</programlisting>
<para>The <literal>TransactionSynchronizationStatus</literal> is an
enum with the values Committed, Rolledback, and Unknown.</para>
<para>The <literal>TransactionSynchronizationStatus</literal> is an enum
with the values Committed, Rolledback, and Unknown.</para>
</sect1>
</chapter>
</chapter>