andrew.asa
5 years ago
450 changed files with 51143 additions and 0 deletions
Binary file not shown.
Binary file not shown.
@ -0,0 +1,685 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" |
||||||
|
xmlns:ldap="http://www.springframework.org/schema/ldap" |
||||||
|
xmlns:repository="http://www.springframework.org/schema/data/repository" |
||||||
|
elementFormDefault="qualified" |
||||||
|
targetNamespace="http://www.springframework.org/schema/ldap"> |
||||||
|
|
||||||
|
<xs:import namespace="http://www.springframework.org/schema/data/repository" |
||||||
|
schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd" /> |
||||||
|
|
||||||
|
<xs:attributeGroup name="context-source.attlist"> |
||||||
|
<xs:attribute name="id" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
A bean identifier, used for referring to the bean elsewhere in the context. |
||||||
|
"contextSource". |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="anonymous-read-only" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Defines whether read-only operations will be performed using an anonymous (unauthenticated) context. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="authentication-source-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the AuthenticationSource instance to use. If not specified, a SimpleAuthenticationSource will |
||||||
|
be used. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="authentication-strategy-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the DirContextAuthenticationStrategy instance to use. If not specified, a SimpleDirContextAuthenticationStrategy |
||||||
|
will be used. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="base" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The base DN. If configured, all LDAP operations on contexts retrieved from this ContextSource will |
||||||
|
be relative to this DN. Default is an empty distinguished name (i.e. all operations will be |
||||||
|
relative to the directory root). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="password" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The password to use for authentication. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="native-pooling" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Specify whether native Java LDAP connection pooling should be used. Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="referral"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Defines the strategy to handle referrals, as described on http://docs.oracle.com/javase/jndi/tutorial/ldap/referral/jndi.html. |
||||||
|
Default is null. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:simpleType> |
||||||
|
<xs:restriction base="xs:token"> |
||||||
|
<xs:enumeration value="ignore" /> |
||||||
|
<xs:enumeration value="follow" /> |
||||||
|
<xs:enumeration value="throw" /> |
||||||
|
</xs:restriction> |
||||||
|
</xs:simpleType> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="url" type="xs:string" use="required"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
URL of the LDAP server to use. If fail-over functionality is desired, more than one URL can |
||||||
|
be specified, separated using comma (,). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="username" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The username (principal) to use for authentication. This will normally be the distinguished name |
||||||
|
of an admin user. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="base-env-props-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Reference to a Map of custom environment properties that should supplied with the environment |
||||||
|
sent to the DirContext on construction. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
</xs:attributeGroup> |
||||||
|
|
||||||
|
<xs:attributeGroup name="pooling.attlist"> |
||||||
|
<xs:attribute name="max-active" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The maximum number of active connections of each type (read-only|read-write) |
||||||
|
that can be allocated from the pool at the same time, or non-positive for no limit. |
||||||
|
Default is 8. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="max-total" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The overall maximum number of active connections (for all types) that can be allocated from |
||||||
|
this pool at the same time, or non-positive for no limit. Default is -1 (no limit). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="max-idle" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The maximum number of active connections of each type (read-only|read-write) that can remain idle in the pool, |
||||||
|
without extra ones being released, or non-positive for no limit. Default is 8. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="min-idle" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The minimum number of active connections of each type (read-only|read-write) that can remain |
||||||
|
idle in the pool, without extra ones being created, or zero to create none. Default is 0. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="max-wait" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The maximum number of milliseconds that the pool will wait (when there are no available connections) |
||||||
|
for a connection to be returned before throwing an exception, or non-positive to wait indefinitely. |
||||||
|
Default is -1. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="when-exhausted"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Specifies the behaviour when the pool is exhausted. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:simpleType> |
||||||
|
<xs:restriction base="xs:token"> |
||||||
|
<xs:enumeration value="FAIL"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Throw a NoSuchElementException when the pool is exhausted |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:enumeration> |
||||||
|
<xs:enumeration value="BLOCK"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Wait until a new object is available. If max-wait is positive a NoSuchElementException |
||||||
|
is thrown if no new object is available after the maxWait time expires. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:enumeration> |
||||||
|
<xs:enumeration value="GROW"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Create and return a new object (essentially making maxActive meaningless). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:enumeration> |
||||||
|
</xs:restriction> |
||||||
|
</xs:simpleType> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="test-on-borrow" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The indication of whether objects will be validated before being borrowed from the pool. |
||||||
|
If the object fails to validate, it will be dropped from the pool, and an attempt to borrow another will be made. |
||||||
|
Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="test-on-return" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The indication of whether objects will be validated before being returned to the pool. |
||||||
|
Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="test-while-idle" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The indication of whether objects will be validated by the idle object evictor (if any). |
||||||
|
If an object fails to validate, it will be dropped from the pool. |
||||||
|
Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="eviction-run-interval-millis" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, |
||||||
|
no idle object evictor thread will be run. Default is -1. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="tests-per-eviction-run" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The number of objects to examine during each run of the idle object evictor thread (if any). |
||||||
|
Default is 3. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="min-evictable-time-millis" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The minimum amount of time an object may sit idle in the pool before it is eligible |
||||||
|
for eviction by the idle object evictor (if any). Default is 1000 * 60 * 30. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="validation-query-base" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The base dn to use for validation searches. Default is LdapUtils.emptyPath(). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="validation-query-filter" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The filter to use for validation queries. Default is (objectclass=*). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="validation-query-search-controls-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the SearchControls instance to use for searches. Default is searchScope=OBJECT_SCOPE; |
||||||
|
countLimit: 1; timeLimit: 500; returningAttributes: [objectclass]. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="non-transient-exceptions" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the SearchControls instance to use for searches. Default is searchScope=OBJECT_SCOPE; |
||||||
|
countLimit: 1; timeLimit: 500; returningAttributes: [objectclass]. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
</xs:attributeGroup> |
||||||
|
|
||||||
|
<xs:attributeGroup name="pooling2.attlist"> |
||||||
|
<xs:attribute name="max-total" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The overall maximum number of active connections (for all types) that can be allocated from |
||||||
|
this pool at the same time, or non-positive for no limit. Default is -1 (no limit). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="max-total-per-key" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The limit on the number of object instances allocated by the pool (checked out or idle), |
||||||
|
per key. When the limit is reached, the sub-pool is said to be exhausted. A negative value |
||||||
|
indicates no limit. Default is 8. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="max-idle-per-key" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The maximum number of active connections per type (read-only|read-write) that can remain idle in the pool, |
||||||
|
without extra ones being released, or non-positive for no limit. Default is 8. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="min-idle-per-key" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The minimum number of active connections per type (read-only|read-write) that can remain |
||||||
|
idle in the pool, without extra ones being created, or zero to create none. Default is 0. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="max-wait" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The maximum number of milliseconds that the pool will wait (when there are no available connections) |
||||||
|
for a connection to be returned before throwing an exception, or non-positive to wait indefinitely. |
||||||
|
Default is -1. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="block-when-exhausted" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Sets to wait until a new object is available. If max-wait is positive a NoSuchElementException |
||||||
|
is thrown if no new object is available after the maxWait time expires.. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="test-on-create" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Sets whether objects created for the pool will be validated before borrowing. If the object |
||||||
|
fails to validate, then borrowing will fail. Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="test-on-borrow" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The indication of whether objects will be validated before being borrowed from the pool. |
||||||
|
If the object fails to validate, it will be dropped from the pool, and an attempt to borrow another will be made. |
||||||
|
Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="test-on-return" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The indication of whether objects will be validated before being returned to the pool. |
||||||
|
Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="test-while-idle" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The indication of whether objects will be validated by the idle object evictor (if any). |
||||||
|
If an object fails to validate, it will be dropped from the pool. |
||||||
|
Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="eviction-run-interval-millis" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The number of milliseconds to sleep between runs of the idle object evictor thread. When non-positive, |
||||||
|
no idle object evictor thread will be run. Default is -1. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="tests-per-eviction-run" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The number of objects to examine during each run of the idle object evictor thread (if any). |
||||||
|
Default is 3. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="min-evictable-time-millis" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The minimum amount of time an object may sit idle in the pool before it is eligible |
||||||
|
for eviction by the idle object evictor (if any). Default is 1000 * 60 * 30. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="soft-min-evictable-idle-time-millis" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The minimum amount of time an object may sit idle in the pool before it is eligible for |
||||||
|
eviction by the idle object evictor, with the extra condition that at least minimum number |
||||||
|
of object instances per key remain in the pool. This settings is overridden by min-evictable-time-millis if |
||||||
|
it is set to a positive value. Default is -1. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="eviction-policy-class" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The name of the eviction policy implementation that is used by this pool. The Pool will |
||||||
|
attempt to load the class using the thread context class loader. If that fails, the Pool |
||||||
|
will attempt to load the class using the class loader that loaded this class. Default is |
||||||
|
com.fr.third.org.apache.commons.pool2.impl.DefaultEvictionPolicy. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="fairness" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Sets whether or not the pool serves threads waiting to borrow connections fairly. |
||||||
|
True means that waiting threads are served as if waiting in a FIFO queue. Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="jmx-enable" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Sets whether JMX will be enabled with the platform MBean server for the pool. Default |
||||||
|
is true. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="jmx-name-base" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The value of the JMX name base that will be used as part of the name assigned |
||||||
|
to JMX enabled pools. Default is null. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="jmx-name-prefix" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The value of the JMX name prefix that will be used as part of the name assigned |
||||||
|
to JMX enabled pools. Default value is pool. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="lifo" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Sets whether the pool has LIFO (last in, first out) behaviour with |
||||||
|
respect to idle objects - always returning the most recently used object |
||||||
|
from the pool, or as a FIFO (first in, first out) queue, where the pool |
||||||
|
always returns the oldest object in the idle object pool. Default is true. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="validation-query-base" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The base dn to use for validation searches. Default is LdapUtils.emptyPath(). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="validation-query-filter" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The filter to use for validation queries. Default is (objectclass=*). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="validation-query-search-controls-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the SearchControls instance to use for searches. Default is searchScope=OBJECT_SCOPE; |
||||||
|
countLimit: 1; timeLimit: 500; returningAttributes: [objectclass]. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="non-transient-exceptions" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the SearchControls instance to use for searches. Default is searchScope=OBJECT_SCOPE; |
||||||
|
countLimit: 1; timeLimit: 500; returningAttributes: [objectclass]. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
</xs:attributeGroup> |
||||||
|
|
||||||
|
<xs:element name="context-source"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Creates a ContextSource instance to be used to get LdapContexts for communicating with an LDAP server. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:complexType> |
||||||
|
<xs:choice minOccurs="0" maxOccurs="1"> |
||||||
|
<xs:sequence> |
||||||
|
<xs:element name="pooling"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Defines the settings to use for the Spring LDAP connection pooling support. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:complexType> |
||||||
|
<xs:attributeGroup ref="ldap:pooling.attlist" /> |
||||||
|
</xs:complexType> |
||||||
|
</xs:element> |
||||||
|
</xs:sequence> |
||||||
|
<xs:sequence> |
||||||
|
<xs:element name="pooling2"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Defines the settings to use for the Spring LDAP connection pooling support based on commons-pool2 library. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:complexType> |
||||||
|
<xs:attributeGroup ref="ldap:pooling2.attlist" /> |
||||||
|
</xs:complexType> |
||||||
|
</xs:element> |
||||||
|
</xs:sequence> |
||||||
|
</xs:choice> |
||||||
|
<xs:attributeGroup ref="ldap:context-source.attlist" /> |
||||||
|
</xs:complexType> |
||||||
|
</xs:element> |
||||||
|
|
||||||
|
<xs:attributeGroup name="ldap-template.attlist"> |
||||||
|
<xs:attribute name="id" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
A bean identifier, used for referring to the bean elsewhere in the context. |
||||||
|
Default is "ldapTemplate". |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="context-source-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the ContextSource instance to use. Default is "contextSource". |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="count-limit" type="xs:integer"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The default count limit for searches. Default is 0 (no limit). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="time-limit" type="xs:integer"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The default time limit for searches. Default is 0 (no limit). |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="search-scope"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The default search scope for searches. Default is SUBTREE. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:simpleType> |
||||||
|
<xs:restriction base="xs:token"> |
||||||
|
<xs:enumeration value="OBJECT" /> |
||||||
|
<xs:enumeration value="ONELEVEL" /> |
||||||
|
<xs:enumeration value="SUBTREE" /> |
||||||
|
</xs:restriction> |
||||||
|
</xs:simpleType> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="ignore-name-not-found" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Specifies whether NameNotFoundException should be ignored in searches. Setting this |
||||||
|
attribute to true will cause errors caused by invalid search base to be silently swallowed. |
||||||
|
Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="ignore-partial-result" type="xs:boolean"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Specifies whether PartialResultException should be ignored in searches. Some LDAP servers |
||||||
|
have problems with referrals; these should normally be followed automatically, but if this |
||||||
|
doesn't work it will manifest itself with a PartialResultException. Setting this attribute |
||||||
|
to true presents a work-around to this problem. Default is false. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="odm-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the ObjectDirectoryMapper instance to use. Default is a default-configured DefaultObjectDirectoryMapper. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
</xs:attributeGroup> |
||||||
|
|
||||||
|
<xs:element name="ldap-template"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Creates an LdapTemplate instance. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:complexType> |
||||||
|
<xs:attributeGroup ref="ldap:ldap-template.attlist" /> |
||||||
|
</xs:complexType> |
||||||
|
</xs:element> |
||||||
|
|
||||||
|
<xs:attributeGroup name="transaction-manager.attlist"> |
||||||
|
<xs:attribute name="id" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of this instance. Default is "transactionManager". |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="context-source-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the ContextSource instance to use. "contextSource". |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="data-source-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the DataSource instance to use. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
<xs:attribute name="session-factory-ref" type="xs:token"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Id of the Hibernate SessionFactory instance to use. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
</xs:attributeGroup> |
||||||
|
|
||||||
|
<xs:element name="transaction-manager"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
Creates an ContextSourceTransactionManager. If data-source-ref or session-factory-ref is specified, |
||||||
|
a DataSourceAndContextSourceTransactionManager/HibernateAndContextSourceTransactionManager will be |
||||||
|
created. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:complexType> |
||||||
|
<xs:choice minOccurs="1" maxOccurs="1"> |
||||||
|
<xs:element name="default-renaming-strategy"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The default (simplistic) TempEntryRenamingStrategy. Please note that this |
||||||
|
strategy will not work for more advanced scenarios. See reference documentation |
||||||
|
for details. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:complexType> |
||||||
|
<xs:attribute name="temp-suffix" type="xs:string"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The default suffix that will be added to modified entries. |
||||||
|
Default is "_temp". |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
</xs:complexType> |
||||||
|
</xs:element> |
||||||
|
<xs:element name="different-subtree-renaming-strategy"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
TempEntryRenamingStrategy that moves the entry to a different subtree than |
||||||
|
the original entry. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
<xs:complexType> |
||||||
|
<xs:attribute name="subtree-node" type="xs:string" use="required"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The subtree base where changed entries should be moved. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
</xs:complexType> |
||||||
|
</xs:element> |
||||||
|
</xs:choice> |
||||||
|
<xs:attributeGroup ref="ldap:transaction-manager.attlist" /> |
||||||
|
</xs:complexType> |
||||||
|
</xs:element> |
||||||
|
|
||||||
|
<xs:element name="repositories"> |
||||||
|
<xs:complexType> |
||||||
|
<xs:complexContent> |
||||||
|
<xs:extension base="repository:repositories"> |
||||||
|
<xs:attribute name="ldap-template-ref"> |
||||||
|
<xs:annotation> |
||||||
|
<xs:documentation> |
||||||
|
The reference to an LdapTemplate. Will default to 'ldapTemplate'. |
||||||
|
</xs:documentation> |
||||||
|
</xs:annotation> |
||||||
|
</xs:attribute> |
||||||
|
</xs:extension> |
||||||
|
</xs:complexContent> |
||||||
|
</xs:complexType> |
||||||
|
</xs:element> |
||||||
|
</xs:schema> |
@ -0,0 +1,198 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
|
||||||
|
<xsd:schema xmlns="http://www.springframework.org/schema/tx" |
||||||
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
||||||
|
xmlns:beans="http://www.springframework.org/schema/beans" |
||||||
|
xmlns:tool="http://www.springframework.org/schema/tool" |
||||||
|
targetNamespace="http://www.springframework.org/schema/tx" |
||||||
|
elementFormDefault="qualified" |
||||||
|
attributeFormDefault="unqualified"> |
||||||
|
|
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"/> |
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-2.0.xsd"/> |
||||||
|
|
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Defines the elements used in the Spring Framework's declarative |
||||||
|
transaction management infrastructure. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
|
||||||
|
<xsd:element name="advice"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[ |
||||||
|
Defines the transactional semantics of the AOP advice that is to be |
||||||
|
executed. |
||||||
|
|
||||||
|
That is, this advice element is where the transactional semantics of |
||||||
|
any number of methods are defined (where transactional semantics |
||||||
|
includes the propagation settings, the isolation level, the rollback |
||||||
|
rules, and suchlike). |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:complexContent> |
||||||
|
<xsd:extension base="beans:identifiedType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/> |
||||||
|
</xsd:sequence> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:extension> |
||||||
|
</xsd:complexContent> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="annotation-driven"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[ |
||||||
|
Indicates that transaction configuration is defined by Java 5 |
||||||
|
annotations on bean classes, and that proxies are automatically |
||||||
|
to be created for the relevant annotated beans. |
||||||
|
|
||||||
|
The default annotation supported is Spring's @Transactional. |
||||||
|
Transaction semantics such as propagation settings, the isolation level, |
||||||
|
the rollback rules, etc are all defined in the annotation metadata. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Are class-based (CGLIB) proxies to be created? By default, standard |
||||||
|
Java interface-based proxies are created. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="order" type="xsd:int"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[ |
||||||
|
Controls the ordering of the execution of the transaction advisor |
||||||
|
when multiple advice executes at a specific joinpoint. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:complexType name="attributesType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
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, 'get*', 'handle*', '*Order', etc. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="propagation" default="REQUIRED"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[ |
||||||
|
The transaction propagation behavior. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="REQUIRED"/> |
||||||
|
<xsd:enumeration value="SUPPORTS"/> |
||||||
|
<xsd:enumeration value="MANDATORY"/> |
||||||
|
<xsd:enumeration value="REQUIRES_NEW"/> |
||||||
|
<xsd:enumeration value="NOT_SUPPORTED"/> |
||||||
|
<xsd:enumeration value="NEVER"/> |
||||||
|
<xsd:enumeration value="NESTED"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="isolation" default="DEFAULT"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[ |
||||||
|
The transaction isolation level. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="DEFAULT"/> |
||||||
|
<xsd:enumeration value="READ_UNCOMMITTED"/> |
||||||
|
<xsd:enumeration value="READ_COMMITTED"/> |
||||||
|
<xsd:enumeration value="REPEATABLE_READ"/> |
||||||
|
<xsd:enumeration value="SERIALIZABLE"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="timeout" type="xsd:integer" default="-1"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The transaction timeout value (in seconds). |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="read-only" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Is this transaction read-only? |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="no-rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will *not* trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
</xsd:sequence> |
||||||
|
</xsd:complexType> |
||||||
|
|
||||||
|
</xsd:schema> |
@ -0,0 +1,244 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
|
||||||
|
<xsd:schema xmlns="http://www.springframework.org/schema/tx" |
||||||
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
||||||
|
xmlns:beans="http://www.springframework.org/schema/beans" |
||||||
|
xmlns:tool="http://www.springframework.org/schema/tool" |
||||||
|
targetNamespace="http://www.springframework.org/schema/tx" |
||||||
|
elementFormDefault="qualified" |
||||||
|
attributeFormDefault="unqualified"> |
||||||
|
|
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"/> |
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-2.5.xsd"/> |
||||||
|
|
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Defines the elements used in the Spring Framework's declarative |
||||||
|
transaction management infrastructure. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
|
||||||
|
<xsd:element name="advice"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[ |
||||||
|
Defines the transactional semantics of the AOP advice that is to be |
||||||
|
executed. |
||||||
|
|
||||||
|
That is, this advice element is where the transactional semantics of |
||||||
|
any number of methods are defined (where transactional semantics |
||||||
|
includes the propagation settings, the isolation level, the rollback |
||||||
|
rules, and suchlike). |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:complexContent> |
||||||
|
<xsd:extension base="beans:identifiedType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/> |
||||||
|
</xsd:sequence> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:extension> |
||||||
|
</xsd:complexContent> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="annotation-driven"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[ |
||||||
|
Indicates that transaction configuration is defined by Java 5 |
||||||
|
annotations on bean classes, and that proxies are automatically |
||||||
|
to be created for the relevant annotated beans. |
||||||
|
|
||||||
|
The default annotations supported are Spring's @Transactional |
||||||
|
and EJB3's @TransactionAttribute (if available). |
||||||
|
|
||||||
|
Transaction semantics such as propagation settings, the isolation level, |
||||||
|
the rollback rules, etc are all defined in the annotation metadata. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="mode" default="proxy"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Should annotated beans be proxied using Spring's AOP framework, |
||||||
|
or should they rather be weaved with an AspectJ transaction aspect? |
||||||
|
|
||||||
|
AspectJ weaving requires spring-aspects.jar on the classpath, |
||||||
|
as well as load-time weaving (or compile-time weaving) enabled. |
||||||
|
|
||||||
|
Note: The weaving-based aspect requires the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="proxy"/> |
||||||
|
<xsd:enumeration value="aspectj"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Are class-based (CGLIB) proxies to be created? By default, standard |
||||||
|
Java interface-based proxies are created. |
||||||
|
|
||||||
|
Note: Class-based proxies require the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="order" type="xsd:int"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[ |
||||||
|
Controls the ordering of the execution of the transaction advisor |
||||||
|
when multiple advice executes at a specific joinpoint. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="jta-transaction-manager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Creates a default JtaTransactionManager bean with name "transactionManager", |
||||||
|
matching the default bean name expected by the "annotation-driven" tag. |
||||||
|
Automatically detects WebLogic, WebSphere and OC4J: creating a WebLogicJtaTransactionManager, |
||||||
|
WebSphereUowTransactionManager or OC4JJtaTransactionManager, respectively. |
||||||
|
|
||||||
|
For customization needs, consider defining a JtaTransactionManager bean as a regular |
||||||
|
Spring bean definition with name "transactionManager", replacing this element. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:complexType name="attributesType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
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, 'get*', 'handle*', '*Order', 'on*Event', etc. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="propagation" default="REQUIRED"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[ |
||||||
|
The transaction propagation behavior. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="REQUIRED"/> |
||||||
|
<xsd:enumeration value="SUPPORTS"/> |
||||||
|
<xsd:enumeration value="MANDATORY"/> |
||||||
|
<xsd:enumeration value="REQUIRES_NEW"/> |
||||||
|
<xsd:enumeration value="NOT_SUPPORTED"/> |
||||||
|
<xsd:enumeration value="NEVER"/> |
||||||
|
<xsd:enumeration value="NESTED"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="isolation" default="DEFAULT"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[ |
||||||
|
The transaction isolation level. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="DEFAULT"/> |
||||||
|
<xsd:enumeration value="READ_UNCOMMITTED"/> |
||||||
|
<xsd:enumeration value="READ_COMMITTED"/> |
||||||
|
<xsd:enumeration value="REPEATABLE_READ"/> |
||||||
|
<xsd:enumeration value="SERIALIZABLE"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="timeout" type="xsd:integer" default="-1"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The transaction timeout value (in seconds). |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="read-only" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Is this transaction read-only? |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="no-rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will *not* trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
</xsd:sequence> |
||||||
|
</xsd:complexType> |
||||||
|
|
||||||
|
</xsd:schema> |
@ -0,0 +1,244 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
|
||||||
|
<xsd:schema xmlns="http://www.springframework.org/schema/tx" |
||||||
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
||||||
|
xmlns:beans="http://www.springframework.org/schema/beans" |
||||||
|
xmlns:tool="http://www.springframework.org/schema/tool" |
||||||
|
targetNamespace="http://www.springframework.org/schema/tx" |
||||||
|
elementFormDefault="qualified" |
||||||
|
attributeFormDefault="unqualified"> |
||||||
|
|
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"/> |
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.0.xsd"/> |
||||||
|
|
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Defines the elements used in the Spring Framework's declarative |
||||||
|
transaction management infrastructure. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
|
||||||
|
<xsd:element name="advice"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[ |
||||||
|
Defines the transactional semantics of the AOP advice that is to be |
||||||
|
executed. |
||||||
|
|
||||||
|
That is, this advice element is where the transactional semantics of |
||||||
|
any number of methods are defined (where transactional semantics |
||||||
|
includes the propagation settings, the isolation level, the rollback |
||||||
|
rules, and suchlike). |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:complexContent> |
||||||
|
<xsd:extension base="beans:identifiedType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/> |
||||||
|
</xsd:sequence> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:extension> |
||||||
|
</xsd:complexContent> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="annotation-driven"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[ |
||||||
|
Indicates that transaction configuration is defined by Java 5 |
||||||
|
annotations on bean classes, and that proxies are automatically |
||||||
|
to be created for the relevant annotated beans. |
||||||
|
|
||||||
|
The default annotations supported are Spring's @Transactional |
||||||
|
and EJB3's @TransactionAttribute (if available). |
||||||
|
|
||||||
|
Transaction semantics such as propagation settings, the isolation level, |
||||||
|
the rollback rules, etc are all defined in the annotation metadata. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="mode" default="proxy"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Should annotated beans be proxied using Spring's AOP framework, |
||||||
|
or should they rather be weaved with an AspectJ transaction aspect? |
||||||
|
|
||||||
|
AspectJ weaving requires spring-aspects.jar on the classpath, |
||||||
|
as well as load-time weaving (or compile-time weaving) enabled. |
||||||
|
|
||||||
|
Note: The weaving-based aspect requires the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="proxy"/> |
||||||
|
<xsd:enumeration value="aspectj"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Are class-based (CGLIB) proxies to be created? By default, standard |
||||||
|
Java interface-based proxies are created. |
||||||
|
|
||||||
|
Note: Class-based proxies require the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="order" type="xsd:int"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[ |
||||||
|
Controls the ordering of the execution of the transaction advisor |
||||||
|
when multiple advice executes at a specific joinpoint. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="jta-transaction-manager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Creates a default JtaTransactionManager bean with name "transactionManager", |
||||||
|
matching the default bean name expected by the "annotation-driven" tag. |
||||||
|
Automatically detects WebLogic, WebSphere and OC4J: creating a WebLogicJtaTransactionManager, |
||||||
|
WebSphereUowTransactionManager or OC4JJtaTransactionManager, respectively. |
||||||
|
|
||||||
|
For customization needs, consider defining a JtaTransactionManager bean as a regular |
||||||
|
Spring bean definition with name "transactionManager", replacing this element. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:complexType name="attributesType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
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, 'get*', 'handle*', '*Order', 'on*Event', etc. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="propagation" default="REQUIRED"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[ |
||||||
|
The transaction propagation behavior. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="REQUIRED"/> |
||||||
|
<xsd:enumeration value="SUPPORTS"/> |
||||||
|
<xsd:enumeration value="MANDATORY"/> |
||||||
|
<xsd:enumeration value="REQUIRES_NEW"/> |
||||||
|
<xsd:enumeration value="NOT_SUPPORTED"/> |
||||||
|
<xsd:enumeration value="NEVER"/> |
||||||
|
<xsd:enumeration value="NESTED"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="isolation" default="DEFAULT"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[ |
||||||
|
The transaction isolation level. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="DEFAULT"/> |
||||||
|
<xsd:enumeration value="READ_UNCOMMITTED"/> |
||||||
|
<xsd:enumeration value="READ_COMMITTED"/> |
||||||
|
<xsd:enumeration value="REPEATABLE_READ"/> |
||||||
|
<xsd:enumeration value="SERIALIZABLE"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="timeout" type="xsd:integer" default="-1"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The transaction timeout value (in seconds). |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="read-only" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Is this transaction read-only? |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="no-rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will *not* trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
</xsd:sequence> |
||||||
|
</xsd:complexType> |
||||||
|
|
||||||
|
</xsd:schema> |
@ -0,0 +1,247 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
|
||||||
|
<xsd:schema xmlns="http://www.springframework.org/schema/tx" |
||||||
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
||||||
|
xmlns:beans="http://www.springframework.org/schema/beans" |
||||||
|
xmlns:tool="http://www.springframework.org/schema/tool" |
||||||
|
targetNamespace="http://www.springframework.org/schema/tx" |
||||||
|
elementFormDefault="qualified" |
||||||
|
attributeFormDefault="unqualified"> |
||||||
|
|
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"/> |
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.1.xsd"/> |
||||||
|
|
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Defines the elements used in the Spring Framework's declarative |
||||||
|
transaction management infrastructure. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
|
||||||
|
<xsd:element name="advice"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[ |
||||||
|
Defines the transactional semantics of the AOP advice that is to be |
||||||
|
executed. |
||||||
|
|
||||||
|
That is, this advice element is where the transactional semantics of |
||||||
|
any number of methods are defined (where transactional semantics |
||||||
|
includes the propagation settings, the isolation level, the rollback |
||||||
|
rules, and suchlike). |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:complexContent> |
||||||
|
<xsd:extension base="beans:identifiedType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/> |
||||||
|
</xsd:sequence> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:extension> |
||||||
|
</xsd:complexContent> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="annotation-driven"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[ |
||||||
|
Indicates that transaction configuration is defined by Java 5 |
||||||
|
annotations on bean classes, and that proxies are automatically |
||||||
|
to be created for the relevant annotated beans. |
||||||
|
|
||||||
|
The default annotations supported are Spring's @Transactional |
||||||
|
and EJB3's @TransactionAttribute (if available). |
||||||
|
|
||||||
|
Transaction semantics such as propagation settings, the isolation level, |
||||||
|
the rollback rules, etc are all defined in the annotation metadata. |
||||||
|
|
||||||
|
See com.fr.third.springframework.transaction.annotation.EnableTransactionManagement Javadoc |
||||||
|
for information on code-based alternatives to this XML element. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="mode" default="proxy"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Should annotated beans be proxied using Spring's AOP framework, |
||||||
|
or should they rather be weaved with an AspectJ transaction aspect? |
||||||
|
|
||||||
|
AspectJ weaving requires spring-aspects.jar on the classpath, |
||||||
|
as well as load-time weaving (or compile-time weaving) enabled. |
||||||
|
|
||||||
|
Note: The weaving-based aspect requires the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="proxy"/> |
||||||
|
<xsd:enumeration value="aspectj"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Are class-based (CGLIB) proxies to be created? By default, standard |
||||||
|
Java interface-based proxies are created. |
||||||
|
|
||||||
|
Note: Class-based proxies require the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="order" type="xsd:int"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[ |
||||||
|
Controls the ordering of the execution of the transaction advisor |
||||||
|
when multiple advice executes at a specific joinpoint. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="jta-transaction-manager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Creates a default JtaTransactionManager bean with name "transactionManager", |
||||||
|
matching the default bean name expected by the "annotation-driven" tag. |
||||||
|
Automatically detects WebLogic, WebSphere and OC4J: creating a WebLogicJtaTransactionManager, |
||||||
|
WebSphereUowTransactionManager or OC4JJtaTransactionManager, respectively. |
||||||
|
|
||||||
|
For customization needs, consider defining a JtaTransactionManager bean as a regular |
||||||
|
Spring bean definition with name "transactionManager", replacing this element. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:complexType name="attributesType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
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, 'get*', 'handle*', '*Order', 'on*Event', etc. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="propagation" default="REQUIRED"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[ |
||||||
|
The transaction propagation behavior. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="REQUIRED"/> |
||||||
|
<xsd:enumeration value="SUPPORTS"/> |
||||||
|
<xsd:enumeration value="MANDATORY"/> |
||||||
|
<xsd:enumeration value="REQUIRES_NEW"/> |
||||||
|
<xsd:enumeration value="NOT_SUPPORTED"/> |
||||||
|
<xsd:enumeration value="NEVER"/> |
||||||
|
<xsd:enumeration value="NESTED"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="isolation" default="DEFAULT"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[ |
||||||
|
The transaction isolation level. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="DEFAULT"/> |
||||||
|
<xsd:enumeration value="READ_UNCOMMITTED"/> |
||||||
|
<xsd:enumeration value="READ_COMMITTED"/> |
||||||
|
<xsd:enumeration value="REPEATABLE_READ"/> |
||||||
|
<xsd:enumeration value="SERIALIZABLE"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="timeout" type="xsd:integer" default="-1"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The transaction timeout value (in seconds). |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="read-only" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Is this transaction read-only? |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="no-rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will *not* trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
</xsd:sequence> |
||||||
|
</xsd:complexType> |
||||||
|
|
||||||
|
</xsd:schema> |
@ -0,0 +1,247 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
|
||||||
|
<xsd:schema xmlns="http://www.springframework.org/schema/tx" |
||||||
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
||||||
|
xmlns:beans="http://www.springframework.org/schema/beans" |
||||||
|
xmlns:tool="http://www.springframework.org/schema/tool" |
||||||
|
targetNamespace="http://www.springframework.org/schema/tx" |
||||||
|
elementFormDefault="qualified" |
||||||
|
attributeFormDefault="unqualified"> |
||||||
|
|
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-3.2.xsd"/> |
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-3.2.xsd"/> |
||||||
|
|
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Defines the elements used in the Spring Framework's declarative |
||||||
|
transaction management infrastructure. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
|
||||||
|
<xsd:element name="advice"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[ |
||||||
|
Defines the transactional semantics of the AOP advice that is to be |
||||||
|
executed. |
||||||
|
|
||||||
|
That is, this advice element is where the transactional semantics of |
||||||
|
any number of methods are defined (where transactional semantics |
||||||
|
includes the propagation settings, the isolation level, the rollback |
||||||
|
rules, and suchlike). |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:complexContent> |
||||||
|
<xsd:extension base="beans:identifiedType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/> |
||||||
|
</xsd:sequence> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:extension> |
||||||
|
</xsd:complexContent> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="annotation-driven"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[ |
||||||
|
Indicates that transaction configuration is defined by Java 5 |
||||||
|
annotations on bean classes, and that proxies are automatically |
||||||
|
to be created for the relevant annotated beans. |
||||||
|
|
||||||
|
The default annotations supported are Spring's @Transactional |
||||||
|
and EJB3's @TransactionAttribute (if available). |
||||||
|
|
||||||
|
Transaction semantics such as propagation settings, the isolation level, |
||||||
|
the rollback rules, etc are all defined in the annotation metadata. |
||||||
|
|
||||||
|
See com.fr.third.springframework.transaction.annotation.EnableTransactionManagement Javadoc |
||||||
|
for information on code-based alternatives to this XML element. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="mode" default="proxy"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Should annotated beans be proxied using Spring's AOP framework, |
||||||
|
or should they rather be weaved with an AspectJ transaction aspect? |
||||||
|
|
||||||
|
AspectJ weaving requires spring-aspects.jar on the classpath, |
||||||
|
as well as load-time weaving (or compile-time weaving) enabled. |
||||||
|
|
||||||
|
Note: The weaving-based aspect requires the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="proxy"/> |
||||||
|
<xsd:enumeration value="aspectj"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Are class-based (CGLIB) proxies to be created? By default, standard |
||||||
|
Java interface-based proxies are created. |
||||||
|
|
||||||
|
Note: Class-based proxies require the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="order" type="xsd:int"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[ |
||||||
|
Controls the ordering of the execution of the transaction advisor |
||||||
|
when multiple advice executes at a specific joinpoint. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="jta-transaction-manager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Creates a default JtaTransactionManager bean with name "transactionManager", |
||||||
|
matching the default bean name expected by the "annotation-driven" tag. |
||||||
|
Automatically detects WebLogic, WebSphere and OC4J: creating a WebLogicJtaTransactionManager, |
||||||
|
WebSphereUowTransactionManager or OC4JJtaTransactionManager, respectively. |
||||||
|
|
||||||
|
For customization needs, consider defining a JtaTransactionManager bean as a regular |
||||||
|
Spring bean definition with name "transactionManager", replacing this element. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:complexType name="attributesType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
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, 'get*', 'handle*', '*Order', 'on*Event', etc. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="propagation" default="REQUIRED"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[ |
||||||
|
The transaction propagation behavior. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="REQUIRED"/> |
||||||
|
<xsd:enumeration value="SUPPORTS"/> |
||||||
|
<xsd:enumeration value="MANDATORY"/> |
||||||
|
<xsd:enumeration value="REQUIRES_NEW"/> |
||||||
|
<xsd:enumeration value="NOT_SUPPORTED"/> |
||||||
|
<xsd:enumeration value="NEVER"/> |
||||||
|
<xsd:enumeration value="NESTED"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="isolation" default="DEFAULT"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[ |
||||||
|
The transaction isolation level. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="DEFAULT"/> |
||||||
|
<xsd:enumeration value="READ_UNCOMMITTED"/> |
||||||
|
<xsd:enumeration value="READ_COMMITTED"/> |
||||||
|
<xsd:enumeration value="REPEATABLE_READ"/> |
||||||
|
<xsd:enumeration value="SERIALIZABLE"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="timeout" type="xsd:integer" default="-1"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The transaction timeout value (in seconds). |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="read-only" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Is this transaction read-only? |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="no-rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will *not* trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
</xsd:sequence> |
||||||
|
</xsd:complexType> |
||||||
|
|
||||||
|
</xsd:schema> |
@ -0,0 +1,247 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
||||||
|
|
||||||
|
<xsd:schema xmlns="http://www.springframework.org/schema/tx" |
||||||
|
xmlns:xsd="http://www.w3.org/2001/XMLSchema" |
||||||
|
xmlns:beans="http://www.springframework.org/schema/beans" |
||||||
|
xmlns:tool="http://www.springframework.org/schema/tool" |
||||||
|
targetNamespace="http://www.springframework.org/schema/tx" |
||||||
|
elementFormDefault="qualified" |
||||||
|
attributeFormDefault="unqualified"> |
||||||
|
|
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"/> |
||||||
|
<xsd:import namespace="http://www.springframework.org/schema/tool" schemaLocation="http://www.springframework.org/schema/tool/spring-tool-4.0.xsd"/> |
||||||
|
|
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Defines the elements used in the Spring Framework's declarative |
||||||
|
transaction management infrastructure. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
|
||||||
|
<xsd:element name="advice"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"><![CDATA[ |
||||||
|
Defines the transactional semantics of the AOP advice that is to be |
||||||
|
executed. |
||||||
|
|
||||||
|
That is, this advice element is where the transactional semantics of |
||||||
|
any number of methods are defined (where transactional semantics |
||||||
|
includes the propagation settings, the isolation level, the rollback |
||||||
|
rules, and suchlike). |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.interceptor.TransactionInterceptor"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:complexContent> |
||||||
|
<xsd:extension base="beans:identifiedType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="attributes" type="attributesType" minOccurs="0" maxOccurs="1"/> |
||||||
|
</xsd:sequence> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:extension> |
||||||
|
</xsd:complexContent> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="annotation-driven"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.AnnotationTransactionAttributeSource"><![CDATA[ |
||||||
|
Indicates that transaction configuration is defined by Java 5 |
||||||
|
annotations on bean classes, and that proxies are automatically |
||||||
|
to be created for the relevant annotated beans. |
||||||
|
|
||||||
|
The default annotations supported are Spring's @Transactional |
||||||
|
and EJB3's @TransactionAttribute (if available). |
||||||
|
|
||||||
|
Transaction semantics such as propagation settings, the isolation level, |
||||||
|
the rollback rules, etc are all defined in the annotation metadata. |
||||||
|
|
||||||
|
See com.fr.third.springframework.transaction.annotation.EnableTransactionManagement Javadoc |
||||||
|
for information on code-based alternatives to this XML element. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:attribute name="transaction-manager" type="xsd:string" default="transactionManager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.PlatformTransactionManager"><![CDATA[ |
||||||
|
The bean name of the PlatformTransactionManager that is to be used |
||||||
|
to drive transactions. |
||||||
|
|
||||||
|
This attribute is not required, and only needs to be specified |
||||||
|
explicitly if the bean name of the desired PlatformTransactionManager |
||||||
|
is not 'transactionManager'. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation kind="ref"> |
||||||
|
<tool:expected-type type="com.fr.third.springframework.transaction.PlatformTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="mode" default="proxy"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Should annotated beans be proxied using Spring's AOP framework, |
||||||
|
or should they rather be weaved with an AspectJ transaction aspect? |
||||||
|
|
||||||
|
AspectJ weaving requires spring-aspects.jar on the classpath, |
||||||
|
as well as load-time weaving (or compile-time weaving) enabled. |
||||||
|
|
||||||
|
Note: The weaving-based aspect requires the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="proxy"/> |
||||||
|
<xsd:enumeration value="aspectj"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Are class-based (CGLIB) proxies to be created? By default, standard |
||||||
|
Java interface-based proxies are created. |
||||||
|
|
||||||
|
Note: Class-based proxies require the @Transactional annotation to be |
||||||
|
defined on the concrete class. Annotations in interfaces will not work |
||||||
|
in that case (they will rather only work with interface-based proxies)! |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="order" type="xsd:token"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.core.Ordered"><![CDATA[ |
||||||
|
Controls the ordering of the execution of the transaction advisor |
||||||
|
when multiple advice executes at a specific joinpoint. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:element name="jta-transaction-manager"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Creates a default JtaTransactionManager bean with name "transactionManager", |
||||||
|
matching the default bean name expected by the "annotation-driven" tag. |
||||||
|
Automatically detects WebLogic and WebSphere: creating a WebLogicJtaTransactionManager |
||||||
|
or WebSphereUowTransactionManager, respectively. |
||||||
|
|
||||||
|
For customization needs, consider defining a JtaTransactionManager bean as a regular |
||||||
|
Spring bean definition with name "transactionManager", replacing this element. |
||||||
|
]]></xsd:documentation> |
||||||
|
<xsd:appinfo> |
||||||
|
<tool:annotation> |
||||||
|
<tool:exports type="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/> |
||||||
|
</tool:annotation> |
||||||
|
</xsd:appinfo> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:element> |
||||||
|
|
||||||
|
<xsd:complexType name="attributesType"> |
||||||
|
<xsd:sequence> |
||||||
|
<xsd:element name="method" minOccurs="1" maxOccurs="unbounded"> |
||||||
|
<xsd:complexType> |
||||||
|
<xsd:attribute name="name" type="xsd:string" use="required"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
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, 'get*', 'handle*', '*Order', 'on*Event', etc. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="propagation" default="REQUIRED"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Propagation"><![CDATA[ |
||||||
|
The transaction propagation behavior. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="REQUIRED"/> |
||||||
|
<xsd:enumeration value="SUPPORTS"/> |
||||||
|
<xsd:enumeration value="MANDATORY"/> |
||||||
|
<xsd:enumeration value="REQUIRES_NEW"/> |
||||||
|
<xsd:enumeration value="NOT_SUPPORTED"/> |
||||||
|
<xsd:enumeration value="NEVER"/> |
||||||
|
<xsd:enumeration value="NESTED"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="isolation" default="DEFAULT"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation source="java:com.fr.third.springframework.transaction.annotation.Isolation"><![CDATA[ |
||||||
|
The transaction isolation level. |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
<xsd:simpleType> |
||||||
|
<xsd:restriction base="xsd:string"> |
||||||
|
<xsd:enumeration value="DEFAULT"/> |
||||||
|
<xsd:enumeration value="READ_UNCOMMITTED"/> |
||||||
|
<xsd:enumeration value="READ_COMMITTED"/> |
||||||
|
<xsd:enumeration value="REPEATABLE_READ"/> |
||||||
|
<xsd:enumeration value="SERIALIZABLE"/> |
||||||
|
</xsd:restriction> |
||||||
|
</xsd:simpleType> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="timeout" type="xsd:int" default="-1"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The transaction timeout value (in seconds). |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="read-only" type="xsd:boolean" default="false"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
Is this transaction read-only? |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
<xsd:attribute name="no-rollback-for" type="xsd:string"> |
||||||
|
<xsd:annotation> |
||||||
|
<xsd:documentation><![CDATA[ |
||||||
|
The Exception(s) that will *not* trigger rollback; comma-delimited. |
||||||
|
For example, 'com.foo.MyBusinessException,ServletException' |
||||||
|
]]></xsd:documentation> |
||||||
|
</xsd:annotation> |
||||||
|
</xsd:attribute> |
||||||
|
</xsd:complexType> |
||||||
|
</xsd:element> |
||||||
|
</xsd:sequence> |
||||||
|
</xsd:complexType> |
||||||
|
|
||||||
|
</xsd:schema> |
After Width: | Height: | Size: 581 B |
@ -0,0 +1,212 @@ |
|||||||
|
package com.fr.third.springframework; |
||||||
|
|
||||||
|
import javax.naming.Name; |
||||||
|
import javax.naming.directory.Attributes; |
||||||
|
import java.util.SortedSet; |
||||||
|
|
||||||
|
/** |
||||||
|
* Common data access methods for entries in an LDAP tree. |
||||||
|
* |
||||||
|
* @author Mattias Hellborg Arthursson |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public interface LdapDataEntry { |
||||||
|
/** |
||||||
|
* Get the value of a String attribute. If more than one attribute value |
||||||
|
* exists for the specified attribute, only the first one will be returned. |
||||||
|
* If an attribute has no value, <code>null</code> will be returned. |
||||||
|
* |
||||||
|
* @param name name of the attribute. |
||||||
|
* @return the value of the attribute if it exists, or <code>null</code> if |
||||||
|
* the attribute doesn't exist or if it exists but with no value. |
||||||
|
* @throws ClassCastException if the value of the entry is not a String. |
||||||
|
*/ |
||||||
|
String getStringAttribute(String name); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get the value of an Object attribute. If more than one attribute value |
||||||
|
* exists for the specified attribute, only the first one will be returned. |
||||||
|
* If an attribute has no value, <code>null</code> will be returned. |
||||||
|
* |
||||||
|
* @param name name of the attribute. |
||||||
|
* @return the attribute value as an object if it exists, or |
||||||
|
* <code>null</code> if the attribute doesn't exist or if it exists but with |
||||||
|
* no value. |
||||||
|
*/ |
||||||
|
Object getObjectAttribute(String name); |
||||||
|
|
||||||
|
/** |
||||||
|
* Check if an Object attribute exists, regardless of whether it has a value |
||||||
|
* or not. |
||||||
|
* |
||||||
|
* @param name name of the attribute |
||||||
|
* @return <code>true</code> if the attribute exists, <code>false</code> |
||||||
|
* otherwise |
||||||
|
*/ |
||||||
|
boolean attributeExists(String name); |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the with the name <code>name</code> to the <code>value</code>. |
||||||
|
* If the value is a {@link Name} instance, equality for Distinguished |
||||||
|
* Names will be used for calculating attribute modifications. |
||||||
|
* |
||||||
|
* @param name name of the attribute. |
||||||
|
* @param value value to set the attribute to. |
||||||
|
* @throws IllegalArgumentException if the value is a {@link Name} instance |
||||||
|
* and one or several of the currently present attribute values is <strong>not</strong> |
||||||
|
* {@link Name} instances or Strings representing valid Distinguished Names. |
||||||
|
*/ |
||||||
|
void setAttributeValue(String name, Object value); |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets a multivalue attribute, disregarding the order of the values. |
||||||
|
* |
||||||
|
* If value is null or value.length == 0 then the attribute will be removed. |
||||||
|
* |
||||||
|
* If update mode, changes will be made only if the array has more or less |
||||||
|
* objects or if one or more object has changed. Reordering the objects will |
||||||
|
* not cause an update. |
||||||
|
* |
||||||
|
* If the values are {@link Name} instances, equality for Distinguished |
||||||
|
* Names will be used for calculating attribute modifications. |
||||||
|
* |
||||||
|
* @param name The id of the attribute. |
||||||
|
* @param values Attribute values. |
||||||
|
* @throws IllegalArgumentException if value is a {@link Name} instance |
||||||
|
* and one or several of the currently present attribute values is <strong>not</strong> |
||||||
|
* {@link Name} instances or Strings representing valid Distinguished Names. |
||||||
|
*/ |
||||||
|
void setAttributeValues(String name, Object[] values); |
||||||
|
|
||||||
|
/** |
||||||
|
* Sets a multivalue attribute. |
||||||
|
* |
||||||
|
* If value is null or value.length == 0 then the attribute will be removed. |
||||||
|
* |
||||||
|
* If update mode, changes will be made if the array has more or less |
||||||
|
* objects or if one or more string has changed. |
||||||
|
* |
||||||
|
* Reordering the objects will only cause an update if orderMatters is set |
||||||
|
* to true. |
||||||
|
* |
||||||
|
* If the values are {@link Name} instances, equality for Distinguished |
||||||
|
* Names will be used for calculating attribute modifications. |
||||||
|
* @param name The id of the attribute. |
||||||
|
* @param values Attribute values. |
||||||
|
* @param orderMatters If <code>true</code>, it will be changed even if data |
||||||
|
* was just reordered. |
||||||
|
* @throws IllegalArgumentException if value is a {@link Name} instance |
||||||
|
* and one or several of the currently present attribute values is <strong>not</strong> |
||||||
|
* {@link Name} instances or Strings representing valid Distinguished Names. |
||||||
|
*/ |
||||||
|
void setAttributeValues(String name, Object[] values, boolean orderMatters); |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a value to the Attribute with the specified name. If the Attribute |
||||||
|
* doesn't exist it will be created. This method makes sure that the there |
||||||
|
* will be no duplicates of an added value - it the value exists it will not |
||||||
|
* be added again. |
||||||
|
* |
||||||
|
* If the value is a {@link Name} instance, equality for Distinguished |
||||||
|
* Names will be used for calculating attribute modifications. |
||||||
|
* |
||||||
|
* @param name the name of the Attribute to which the specified value should |
||||||
|
* be added. |
||||||
|
* @param value the Attribute value to add. |
||||||
|
* @throws IllegalArgumentException if value is a {@link Name} instance |
||||||
|
* and one or several of the currently present attribute values is <strong>not</strong> |
||||||
|
* {@link Name} instances or Strings representing valid Distinguished Names. |
||||||
|
*/ |
||||||
|
void addAttributeValue(String name, Object value); |
||||||
|
|
||||||
|
/** |
||||||
|
* Add a value to the Attribute with the specified name. If the Attribute |
||||||
|
* doesn't exist it will be created. The <code>addIfDuplicateExists</code> |
||||||
|
* parameter controls the handling of duplicates. It <code>false</code>, |
||||||
|
* this method makes sure that the there will be no duplicates of an added |
||||||
|
* value - it the value exists it will not be added again. |
||||||
|
* |
||||||
|
* If the value is a {@link Name} instance, equality for Distinguished |
||||||
|
* Names will be used for calculating attribute modifications. |
||||||
|
* |
||||||
|
* @param name the name of the Attribute to which the specified value should |
||||||
|
* be added. |
||||||
|
* @param value the Attribute value to add. |
||||||
|
* @param addIfDuplicateExists <code>true</code> will add the value |
||||||
|
* regardless of whether there is an identical value already, allowing for |
||||||
|
* duplicate attribute values; <code>false</code> will not add the value if |
||||||
|
* it already exists. |
||||||
|
* @throws IllegalArgumentException if value is a {@link Name} instance |
||||||
|
* and one or several of the currently present attribute values is <strong>not</strong> |
||||||
|
* {@link Name} instances or Strings representing valid Distinguished Names. |
||||||
|
*/ |
||||||
|
void addAttributeValue(String name, Object value, |
||||||
|
boolean addIfDuplicateExists); |
||||||
|
|
||||||
|
/** |
||||||
|
* Remove a value from the Attribute with the specified name. If the |
||||||
|
* Attribute doesn't exist, do nothing. |
||||||
|
* |
||||||
|
* If the value is a {@link Name} instance, equality for Distinguished |
||||||
|
* Names will be used for calculating attribute modifications. |
||||||
|
* |
||||||
|
* @param name the name of the Attribute from which the specified value |
||||||
|
* should be removed. |
||||||
|
* @param value the value to remove. |
||||||
|
* @throws IllegalArgumentException if value is a {@link Name} instance |
||||||
|
* and one or several of the currently present attribute values is <strong>not</strong> |
||||||
|
* {@link Name} instances or Strings representing valid Distinguished Names. |
||||||
|
*/ |
||||||
|
void removeAttributeValue(String name, Object value); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get all values of a String attribute. |
||||||
|
* |
||||||
|
* @param name name of the attribute. |
||||||
|
* @return a (possibly empty) array containing all registered values of the |
||||||
|
* attribute as Strings if the attribute is defined or <code>null</code> |
||||||
|
* otherwise. |
||||||
|
* @throws IllegalArgumentException if any of the attribute values is not a |
||||||
|
* String. |
||||||
|
*/ |
||||||
|
String[] getStringAttributes(String name); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get all values of an Object attribute. |
||||||
|
* |
||||||
|
* @param name name of the attribute. |
||||||
|
* @return a (possibly empty) array containing all registered values of the |
||||||
|
* attribute if the attribute is defined or <code>null</code> otherwise. |
||||||
|
* @since 1.3 |
||||||
|
*/ |
||||||
|
Object[] getObjectAttributes(String name); |
||||||
|
|
||||||
|
/** |
||||||
|
* Get all String values of the attribute as a <code>SortedSet</code>. |
||||||
|
* |
||||||
|
* @param name name of the attribute. |
||||||
|
* @return a <code>SortedSet</code> containing all values of the attribute, |
||||||
|
* or <code>null</code> if the attribute does not exist. |
||||||
|
* @throws IllegalArgumentException if one of the found attribute values cannot be cast to a String. |
||||||
|
*/ |
||||||
|
SortedSet<String> getAttributeSortedStringSet(String name); |
||||||
|
|
||||||
|
/** |
||||||
|
* Returns the DN relative to the base path. |
||||||
|
* <b>NB</b>: as of version 2.0 the returned name will be an LdapName instance. |
||||||
|
* |
||||||
|
* @return The distinguished name of the current context. |
||||||
|
* |
||||||
|
* @see com.fr.third.springframework.ldap.core.DirContextAdapter#getNameInNamespace() |
||||||
|
*/ |
||||||
|
Name getDn(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Get all the Attributes. |
||||||
|
* |
||||||
|
* @return all the Attributes. |
||||||
|
* @since 1.3 |
||||||
|
*/ |
||||||
|
Attributes getAttributes(); |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown on failure to aquire a lock during an update, |
||||||
|
* for example during a "select for update" statement. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class CannotAcquireLockException extends PessimisticLockingFailureException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for CannotAcquireLockException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public CannotAcquireLockException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for CannotAcquireLockException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public CannotAcquireLockException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown on failure to complete a transaction in serialized mode |
||||||
|
* due to update conflicts. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class CannotSerializeTransactionException extends PessimisticLockingFailureException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for CannotSerializeTransactionException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public CannotSerializeTransactionException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for CannotSerializeTransactionException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public CannotSerializeTransactionException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown when we couldn't cleanup after a data access operation, |
||||||
|
* but the actual operation went OK. |
||||||
|
* |
||||||
|
* <p>For example, this exception or a subclass might be thrown if a JDBC |
||||||
|
* Connection couldn't be closed after it had been used successfully. |
||||||
|
* |
||||||
|
* <p>Note that data access code might perform resources cleanup in a |
||||||
|
* finally block and therefore log cleanup failure rather than rethrow it, |
||||||
|
* to keep the original data access exception, if any. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class CleanupFailureDataAccessException extends NonTransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for CleanupFailureDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the underlying data access API, |
||||||
|
* such as JDBC |
||||||
|
*/ |
||||||
|
public CleanupFailureDataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,52 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown on concurrency failure. |
||||||
|
* |
||||||
|
* <p>This exception should be subclassed to indicate the type of failure: |
||||||
|
* optimistic locking, failure to acquire lock, etc. |
||||||
|
* |
||||||
|
* @author Thomas Risberg |
||||||
|
* @since 1.1 |
||||||
|
* @see OptimisticLockingFailureException |
||||||
|
* @see PessimisticLockingFailureException |
||||||
|
* @see CannotAcquireLockException |
||||||
|
* @see DeadlockLoserDataAccessException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class ConcurrencyFailureException extends TransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for ConcurrencyFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public ConcurrencyFailureException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for ConcurrencyFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public ConcurrencyFailureException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,59 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
import com.fr.third.springframework.core.NestedRuntimeException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Root of the hierarchy of data access exceptions discussed in |
||||||
|
* <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0764543857/">Expert One-On-One J2EE Design and Development</a>. |
||||||
|
* Please see Chapter 9 of this book for detailed discussion of the |
||||||
|
* motivation for this package. |
||||||
|
* |
||||||
|
* <p>This exception hierarchy aims to let user code find and handle the |
||||||
|
* kind of error encountered without knowing the details of the particular |
||||||
|
* data access API in use (e.g. JDBC). Thus it is possible to react to an |
||||||
|
* optimistic locking failure without knowing that JDBC is being used. |
||||||
|
* |
||||||
|
* <p>As this class is a runtime exception, there is no need for user code |
||||||
|
* to catch it or subclasses if any error is to be considered fatal |
||||||
|
* (the usual case). |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public abstract class DataAccessException extends NestedRuntimeException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public DataAccessException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause (usually from using a underlying |
||||||
|
* data access API such as JDBC) |
||||||
|
*/ |
||||||
|
public DataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Data access exception thrown when a resource fails completely: |
||||||
|
* for example, if we can't connect to a database using JDBC. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Thomas Risberg |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class DataAccessResourceFailureException extends NonTransientDataAccessResourceException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DataAccessResourceFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public DataAccessResourceFailureException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DataAccessResourceFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public DataAccessResourceFailureException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown when an attempt to insert or update data |
||||||
|
* results in violation of an integrity constraint. Note that this |
||||||
|
* is not purely a relational concept; unique primary keys are |
||||||
|
* required by most database types. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class DataIntegrityViolationException extends NonTransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DataIntegrityViolationException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public DataIntegrityViolationException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DataIntegrityViolationException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public DataIntegrityViolationException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown if certain expected data could not be retrieved, e.g. |
||||||
|
* when looking up specific data via a known identifier. This exception |
||||||
|
* will be thrown either by O/R mapping tools or by DAO implementations. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 13.10.2003 |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class DataRetrievalFailureException extends NonTransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DataRetrievalFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public DataRetrievalFailureException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DataRetrievalFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public DataRetrievalFailureException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,37 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Generic exception thrown when the current process was |
||||||
|
* a deadlock loser, and its transaction rolled back. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class DeadlockLoserDataAccessException extends PessimisticLockingFailureException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DeadlockLoserDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public DeadlockLoserDataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown when an attempt to insert or update data |
||||||
|
* results in violation of an primary key or unique constraint. |
||||||
|
* Note that this is not necessarily a purely relational concept; |
||||||
|
* unique primary keys are required by most database types. |
||||||
|
* |
||||||
|
* @author Thomas Risberg |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class DuplicateKeyException extends DataIntegrityViolationException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DuplicateKeyException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public DuplicateKeyException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for DuplicateKeyException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public DuplicateKeyException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Data access exception thrown when a result was expected to have at least |
||||||
|
* one row (or element) but zero rows (or elements) were actually returned. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
* @see IncorrectResultSizeDataAccessException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class EmptyResultDataAccessException extends IncorrectResultSizeDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for EmptyResultDataAccessException. |
||||||
|
* @param expectedSize the expected result size |
||||||
|
*/ |
||||||
|
public EmptyResultDataAccessException(int expectedSize) { |
||||||
|
super(expectedSize, 0); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for EmptyResultDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param expectedSize the expected result size |
||||||
|
*/ |
||||||
|
public EmptyResultDataAccessException(String msg, int expectedSize) { |
||||||
|
super(msg, expectedSize, 0); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for EmptyResultDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param expectedSize the expected result size |
||||||
|
* @param ex the wrapped exception |
||||||
|
*/ |
||||||
|
public EmptyResultDataAccessException(String msg, int expectedSize, Throwable ex) { |
||||||
|
super(msg, expectedSize, 0, ex); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,120 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Data access exception thrown when a result was not of the expected size, |
||||||
|
* for example when expecting a single row but getting 0 or more than 1 rows. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @author Chris Beams |
||||||
|
* @since 1.0.2 |
||||||
|
* @see EmptyResultDataAccessException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class IncorrectResultSizeDataAccessException extends DataRetrievalFailureException { |
||||||
|
|
||||||
|
private int expectedSize; |
||||||
|
|
||||||
|
private int actualSize; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for IncorrectResultSizeDataAccessException. |
||||||
|
* @param expectedSize the expected result size |
||||||
|
*/ |
||||||
|
public IncorrectResultSizeDataAccessException(int expectedSize) { |
||||||
|
super("Incorrect result size: expected " + expectedSize); |
||||||
|
this.expectedSize = expectedSize; |
||||||
|
this.actualSize = -1; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for IncorrectResultSizeDataAccessException. |
||||||
|
* @param expectedSize the expected result size |
||||||
|
* @param actualSize the actual result size (or -1 if unknown) |
||||||
|
*/ |
||||||
|
public IncorrectResultSizeDataAccessException(int expectedSize, int actualSize) { |
||||||
|
super("Incorrect result size: expected " + expectedSize + ", actual " + actualSize); |
||||||
|
this.expectedSize = expectedSize; |
||||||
|
this.actualSize = actualSize; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for IncorrectResultSizeDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param expectedSize the expected result size |
||||||
|
*/ |
||||||
|
public IncorrectResultSizeDataAccessException(String msg, int expectedSize) { |
||||||
|
super(msg); |
||||||
|
this.expectedSize = expectedSize; |
||||||
|
this.actualSize = -1; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for IncorrectResultSizeDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param expectedSize the expected result size |
||||||
|
* @param ex the wrapped exception |
||||||
|
*/ |
||||||
|
public IncorrectResultSizeDataAccessException(String msg, int expectedSize, Throwable ex) { |
||||||
|
super(msg, ex); |
||||||
|
this.expectedSize = expectedSize; |
||||||
|
this.actualSize = -1; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for IncorrectResultSizeDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param expectedSize the expected result size |
||||||
|
* @param actualSize the actual result size (or -1 if unknown) |
||||||
|
*/ |
||||||
|
public IncorrectResultSizeDataAccessException(String msg, int expectedSize, int actualSize) { |
||||||
|
super(msg); |
||||||
|
this.expectedSize = expectedSize; |
||||||
|
this.actualSize = actualSize; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for IncorrectResultSizeDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param expectedSize the expected result size |
||||||
|
* @param actualSize the actual result size (or -1 if unknown) |
||||||
|
* @param ex the wrapped exception |
||||||
|
*/ |
||||||
|
public IncorrectResultSizeDataAccessException(String msg, int expectedSize, int actualSize, Throwable ex) { |
||||||
|
super(msg, ex); |
||||||
|
this.expectedSize = expectedSize; |
||||||
|
this.actualSize = actualSize; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Return the expected result size. |
||||||
|
*/ |
||||||
|
public int getExpectedSize() { |
||||||
|
return this.expectedSize; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the actual result size (or -1 if unknown). |
||||||
|
*/ |
||||||
|
public int getActualSize() { |
||||||
|
return this.actualSize; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,57 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Data access exception thrown when something unintended appears to have |
||||||
|
* happened with an update, but the transaction hasn't already been rolled back. |
||||||
|
* Thrown, for example, when we wanted to update 1 row in an RDBMS but actually |
||||||
|
* updated 3. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class IncorrectUpdateSemanticsDataAccessException extends InvalidDataAccessResourceUsageException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for IncorrectUpdateSemanticsDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public IncorrectUpdateSemanticsDataAccessException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for IncorrectUpdateSemanticsDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the underlying API, such as JDBC |
||||||
|
*/ |
||||||
|
public IncorrectUpdateSemanticsDataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return whether data was updated. |
||||||
|
* If this method returns false, there's nothing to roll back. |
||||||
|
* <p>The default implementation always returns true. |
||||||
|
* This can be overridden in subclasses. |
||||||
|
*/ |
||||||
|
public boolean wasDataUpdated() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,48 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown on incorrect usage of the API, such as failing to |
||||||
|
* "compile" a query object that needed compilation before execution. |
||||||
|
* |
||||||
|
* <p>This represents a problem in our Java data access framework, |
||||||
|
* not the underlying data access infrastructure. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class InvalidDataAccessApiUsageException extends NonTransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for InvalidDataAccessApiUsageException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public InvalidDataAccessApiUsageException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for InvalidDataAccessApiUsageException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public InvalidDataAccessApiUsageException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Root for exceptions thrown when we use a data access resource incorrectly. |
||||||
|
* Thrown for example on specifying bad SQL when using a RDBMS. |
||||||
|
* Resource-specific subclasses are supplied by concrete data access packages. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class InvalidDataAccessResourceUsageException extends NonTransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for InvalidDataAccessResourceUsageException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public InvalidDataAccessResourceUsageException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for InvalidDataAccessResourceUsageException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public InvalidDataAccessResourceUsageException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Root of the hierarchy of data access exceptions that are considered non-transient - |
||||||
|
* where a retry of the same operation would fail unless the cause of the Exception |
||||||
|
* is corrected. |
||||||
|
* |
||||||
|
* @author Thomas Risberg |
||||||
|
* @since 2.5 |
||||||
|
* @see java.sql.SQLNonTransientException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public abstract class NonTransientDataAccessException extends DataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for NonTransientDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public NonTransientDataAccessException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for NonTransientDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause (usually from using a underlying |
||||||
|
* data access API such as JDBC) |
||||||
|
*/ |
||||||
|
public NonTransientDataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Data access exception thrown when a resource fails completely and the failure is permanent. |
||||||
|
* |
||||||
|
* @author Thomas Risberg |
||||||
|
* @since 2.5 |
||||||
|
* @see java.sql.SQLNonTransientConnectionException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class NonTransientDataAccessResourceException extends NonTransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for NonTransientDataAccessResourceException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public NonTransientDataAccessResourceException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for NonTransientDataAccessResourceException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public NonTransientDataAccessResourceException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown on an optimistic locking violation. |
||||||
|
* |
||||||
|
* <p>This exception will be thrown either by O/R mapping tools |
||||||
|
* or by custom DAO implementations. Optimistic locking failure |
||||||
|
* is typically <i>not</i> detected by the database itself. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @see PessimisticLockingFailureException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class OptimisticLockingFailureException extends ConcurrencyFailureException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for OptimisticLockingFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public OptimisticLockingFailureException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for OptimisticLockingFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public OptimisticLockingFailureException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,39 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown when the underlying resource denied a permission |
||||||
|
* to access a specific element, such as a specific database table. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class PermissionDeniedDataAccessException extends NonTransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for PermissionDeniedDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the underlying data access API, |
||||||
|
* such as JDBC |
||||||
|
*/ |
||||||
|
public PermissionDeniedDataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,53 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown on a pessimistic locking violation. |
||||||
|
* Thrown by Spring's SQLException translation mechanism |
||||||
|
* if a corresponding database error is encountered. |
||||||
|
* |
||||||
|
* <p>Serves as superclass for more specific exceptions, like |
||||||
|
* CannotAcquireLockException and DeadlockLoserDataAccessException. |
||||||
|
* |
||||||
|
* @author Thomas Risberg |
||||||
|
* @since 1.2 |
||||||
|
* @see CannotAcquireLockException |
||||||
|
* @see DeadlockLoserDataAccessException |
||||||
|
* @see OptimisticLockingFailureException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class PessimisticLockingFailureException extends ConcurrencyFailureException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for PessimisticLockingFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public PessimisticLockingFailureException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for PessimisticLockingFailureException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public PessimisticLockingFailureException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,50 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception to be thrown on a query timeout. This could have different causes depending on |
||||||
|
* the database API in use but most likely thrown after the database interrupts or stops |
||||||
|
* the processing of a query before it has completed. |
||||||
|
* |
||||||
|
* <p>This exception can be thrown by user code trapping the native database exception or |
||||||
|
* by exception translation. |
||||||
|
* |
||||||
|
* @author Thomas Risberg |
||||||
|
* @since 3.1 |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class QueryTimeoutException extends TransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for QueryTimeoutException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public QueryTimeoutException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for QueryTimeoutException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public QueryTimeoutException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,51 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Data access exception thrown when a previously failed operation might be able |
||||||
|
* to succeed if the application performs some recovery steps and retries the entire |
||||||
|
* transaction or in the case of a distributed transaction, the transaction branch. |
||||||
|
* At a minimum, the recovery operation must include closing the current connection |
||||||
|
* and getting a new connection. |
||||||
|
* |
||||||
|
* @author Thomas Risberg |
||||||
|
* @since 2.5 |
||||||
|
* @see java.sql.SQLRecoverableException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class RecoverableDataAccessException extends DataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for RecoverableDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public RecoverableDataAccessException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for RecoverableDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause (usually from using a underlying |
||||||
|
* data access API such as JDBC) |
||||||
|
*/ |
||||||
|
public RecoverableDataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Root of the hierarchy of data access exceptions that are considered transient - |
||||||
|
* where a previously failed operation might be able to succeed when the operation |
||||||
|
* is retried without any intervention by application-level functionality. |
||||||
|
* |
||||||
|
* @author Thomas Risberg |
||||||
|
* @since 2.5 |
||||||
|
* @see java.sql.SQLTransientException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public abstract class TransientDataAccessException extends DataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for TransientDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public TransientDataAccessException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for TransientDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause (usually from using a underlying |
||||||
|
* data access API such as JDBC) |
||||||
|
*/ |
||||||
|
public TransientDataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Data access exception thrown when a resource fails temporarily |
||||||
|
* and the operation can be retried. |
||||||
|
* |
||||||
|
* @author Thomas Risberg |
||||||
|
* @since 2.5 |
||||||
|
* @see java.sql.SQLTransientConnectionException |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class TransientDataAccessResourceException extends TransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for TransientDataAccessResourceException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public TransientDataAccessResourceException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for TransientDataAccessResourceException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public TransientDataAccessResourceException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown on mismatch between Java type and database type: |
||||||
|
* for example on an attempt to set an object of the wrong type |
||||||
|
* in an RDBMS column. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class TypeMismatchDataAccessException extends InvalidDataAccessResourceUsageException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for TypeMismatchDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
*/ |
||||||
|
public TypeMismatchDataAccessException(String msg) { |
||||||
|
super(msg); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for TypeMismatchDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the root cause from the data access API in use |
||||||
|
*/ |
||||||
|
public TypeMismatchDataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,38 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
||||||
|
/** |
||||||
|
* Normal superclass when we can't distinguish anything more specific |
||||||
|
* than "something went wrong with the underlying resource": for example, |
||||||
|
* a SQLException from JDBC we can't pinpoint more precisely. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public abstract class UncategorizedDataAccessException extends NonTransientDataAccessException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for UncategorizedDataAccessException. |
||||||
|
* @param msg the detail message |
||||||
|
* @param cause the exception thrown by underlying data access API |
||||||
|
*/ |
||||||
|
public UncategorizedDataAccessException(String msg, Throwable cause) { |
||||||
|
super(msg, cause); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,86 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao.annotation; |
||||||
|
|
||||||
|
import java.lang.annotation.Annotation; |
||||||
|
|
||||||
|
import org.aopalliance.aop.Advice; |
||||||
|
|
||||||
|
import com.fr.third.springframework.aop.Pointcut; |
||||||
|
import com.fr.third.springframework.aop.support.AbstractPointcutAdvisor; |
||||||
|
import com.fr.third.springframework.aop.support.annotation.AnnotationMatchingPointcut; |
||||||
|
import com.fr.third.springframework.beans.factory.ListableBeanFactory; |
||||||
|
import com.fr.third.springframework.dao.support.PersistenceExceptionTranslationInterceptor; |
||||||
|
import com.fr.third.springframework.dao.support.PersistenceExceptionTranslator; |
||||||
|
|
||||||
|
/** |
||||||
|
* Spring AOP exception translation aspect for use at Repository or DAO layer level. |
||||||
|
* Translates native persistence exceptions into Spring's DataAccessException hierarchy, |
||||||
|
* based on a given PersistenceExceptionTranslator. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
* @see com.fr.third.springframework.dao.DataAccessException |
||||||
|
* @see com.fr.third.springframework.dao.support.PersistenceExceptionTranslator |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class PersistenceExceptionTranslationAdvisor extends AbstractPointcutAdvisor { |
||||||
|
|
||||||
|
private final PersistenceExceptionTranslationInterceptor advice; |
||||||
|
|
||||||
|
private final AnnotationMatchingPointcut pointcut; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new PersistenceExceptionTranslationAdvisor. |
||||||
|
* @param persistenceExceptionTranslator the PersistenceExceptionTranslator to use |
||||||
|
* @param repositoryAnnotationType the annotation type to check for |
||||||
|
*/ |
||||||
|
public PersistenceExceptionTranslationAdvisor( |
||||||
|
PersistenceExceptionTranslator persistenceExceptionTranslator, |
||||||
|
Class<? extends Annotation> repositoryAnnotationType) { |
||||||
|
|
||||||
|
this.advice = new PersistenceExceptionTranslationInterceptor(persistenceExceptionTranslator); |
||||||
|
this.pointcut = new AnnotationMatchingPointcut(repositoryAnnotationType, true); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new PersistenceExceptionTranslationAdvisor. |
||||||
|
* @param beanFactory the ListableBeanFactory to obtaining all |
||||||
|
* PersistenceExceptionTranslators from |
||||||
|
* @param repositoryAnnotationType the annotation type to check for |
||||||
|
*/ |
||||||
|
PersistenceExceptionTranslationAdvisor( |
||||||
|
ListableBeanFactory beanFactory, Class<? extends Annotation> repositoryAnnotationType) { |
||||||
|
|
||||||
|
this.advice = new PersistenceExceptionTranslationInterceptor(beanFactory); |
||||||
|
this.pointcut = new AnnotationMatchingPointcut(repositoryAnnotationType, true); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Advice getAdvice() { |
||||||
|
return this.advice; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Pointcut getPointcut() { |
||||||
|
return this.pointcut; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,89 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2014 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao.annotation; |
||||||
|
|
||||||
|
import java.lang.annotation.Annotation; |
||||||
|
|
||||||
|
import com.fr.third.springframework.aop.framework.AbstractAdvisingBeanPostProcessor; |
||||||
|
import com.fr.third.springframework.beans.factory.BeanFactory; |
||||||
|
import com.fr.third.springframework.beans.factory.BeanFactoryAware; |
||||||
|
import com.fr.third.springframework.beans.factory.ListableBeanFactory; |
||||||
|
import com.fr.third.springframework.stereotype.Repository; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Bean post-processor that automatically applies persistence exception translation to any |
||||||
|
* bean marked with Spring's @{@link com.fr.third.springframework.stereotype.Repository Repository} |
||||||
|
* annotation, adding a corresponding {@link PersistenceExceptionTranslationAdvisor} to |
||||||
|
* the exposed proxy (either an existing AOP proxy or a newly generated proxy that |
||||||
|
* implements all of the target's interfaces). |
||||||
|
* |
||||||
|
* <p>Translates native resource exceptions to Spring's |
||||||
|
* {@link com.fr.third.springframework.dao.DataAccessException DataAccessException} hierarchy. |
||||||
|
* Autodetects beans that implement the |
||||||
|
* {@link com.fr.third.springframework.dao.support.PersistenceExceptionTranslator |
||||||
|
* PersistenceExceptionTranslator} interface, which are subsequently asked to translate |
||||||
|
* candidate exceptions. |
||||||
|
* |
||||||
|
|
||||||
|
* <p>All of Spring's applicable resource factories (e.g. |
||||||
|
* {@link com.fr.third.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean}) |
||||||
|
* implement the {@code PersistenceExceptionTranslator} interface out of the box. |
||||||
|
* As a consequence, all that is usually needed to enable automatic exception |
||||||
|
* translation is marking all affected beans (such as Repositories or DAOs) |
||||||
|
* with the {@code @Repository} annotation, along with defining this post-processor |
||||||
|
* as a bean in the application context. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
* @see PersistenceExceptionTranslationAdvisor |
||||||
|
* @see com.fr.third.springframework.stereotype.Repository |
||||||
|
* @see com.fr.third.springframework.dao.DataAccessException |
||||||
|
* @see com.fr.third.springframework.dao.support.PersistenceExceptionTranslator |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class PersistenceExceptionTranslationPostProcessor extends AbstractAdvisingBeanPostProcessor |
||||||
|
implements BeanFactoryAware { |
||||||
|
|
||||||
|
private Class<? extends Annotation> repositoryAnnotationType = Repository.class; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the 'repository' annotation type. |
||||||
|
* The default repository annotation type is the {@link Repository} annotation. |
||||||
|
* <p>This setter property exists so that developers can provide their own |
||||||
|
* (non-Spring-specific) annotation type to indicate that a class has a |
||||||
|
* repository role. |
||||||
|
* @param repositoryAnnotationType the desired annotation type |
||||||
|
*/ |
||||||
|
public void setRepositoryAnnotationType(Class<? extends Annotation> repositoryAnnotationType) { |
||||||
|
Assert.notNull(repositoryAnnotationType, "'repositoryAnnotationType' must not be null"); |
||||||
|
this.repositoryAnnotationType = repositoryAnnotationType; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setBeanFactory(BeanFactory beanFactory) { |
||||||
|
if (!(beanFactory instanceof ListableBeanFactory)) { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory"); |
||||||
|
} |
||||||
|
this.advisor = new PersistenceExceptionTranslationAdvisor( |
||||||
|
(ListableBeanFactory) beanFactory, this.repositoryAnnotationType); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Annotation support for DAOs. Contains a bean post-processor for translating |
||||||
|
* persistence exceptions based on a repository stereotype annotation. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.dao.annotation; |
||||||
|
|
@ -0,0 +1,20 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Exception hierarchy enabling sophisticated error handling independent |
||||||
|
* of the data access approach in use. For example, when DAOs and data |
||||||
|
* access frameworks use the exceptions in this package (and custom |
||||||
|
* subclasses), calling code can detect and handle common problems such |
||||||
|
* as deadlocks without being tied to a particular data access strategy, |
||||||
|
* such as JDBC. |
||||||
|
* |
||||||
|
* <p>All these exceptions are unchecked, meaning that calling code can |
||||||
|
* leave them uncaught and treat all data access exceptions as fatal. |
||||||
|
* |
||||||
|
* <p>The classes in this package are discussed in Chapter 9 of |
||||||
|
* <a href="http://www.amazon.com/exec/obidos/tg/detail/-/0764543857/">Expert One-On-One J2EE Design and Development</a> |
||||||
|
* by Rod Johnson (Wrox, 2002). |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.dao; |
||||||
|
|
@ -0,0 +1,67 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao.support; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Implementation of {@link PersistenceExceptionTranslator} that supports chaining, |
||||||
|
* allowing the addition of PersistenceExceptionTranslator instances in order. |
||||||
|
* Returns {@code non-null} on the first (if any) match. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public class ChainedPersistenceExceptionTranslator implements PersistenceExceptionTranslator { |
||||||
|
|
||||||
|
/** List of PersistenceExceptionTranslators */ |
||||||
|
private final List<PersistenceExceptionTranslator> delegates = new ArrayList<PersistenceExceptionTranslator>(4); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Add a PersistenceExceptionTranslator to the chained delegate list. |
||||||
|
*/ |
||||||
|
public final void addDelegate(PersistenceExceptionTranslator pet) { |
||||||
|
Assert.notNull(pet, "PersistenceExceptionTranslator must not be null"); |
||||||
|
this.delegates.add(pet); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return all registered PersistenceExceptionTranslator delegates (as array). |
||||||
|
*/ |
||||||
|
public final PersistenceExceptionTranslator[] getDelegates() { |
||||||
|
return this.delegates.toArray(new PersistenceExceptionTranslator[this.delegates.size()]); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public DataAccessException translateExceptionIfPossible(RuntimeException ex) { |
||||||
|
for (PersistenceExceptionTranslator pet : this.delegates) { |
||||||
|
DataAccessException translatedDex = pet.translateExceptionIfPossible(ex); |
||||||
|
if (translatedDex != null) { |
||||||
|
return translatedDex; |
||||||
|
} |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,73 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao.support; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.BeanInitializationException; |
||||||
|
import com.fr.third.springframework.beans.factory.InitializingBean; |
||||||
|
|
||||||
|
/** |
||||||
|
* Generic base class for DAOs, defining template methods for DAO initialization. |
||||||
|
* |
||||||
|
* <p>Extended by Spring's specific DAO support classes, such as: |
||||||
|
* JdbcDaoSupport, JdoDaoSupport, etc. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2.2 |
||||||
|
* @see com.fr.third.springframework.jdbc.core.support.JdbcDaoSupport |
||||||
|
*/ |
||||||
|
public abstract class DaoSupport implements InitializingBean { |
||||||
|
|
||||||
|
/** Logger available to subclasses */ |
||||||
|
protected final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException { |
||||||
|
// Let abstract subclasses check their configuration.
|
||||||
|
checkDaoConfig(); |
||||||
|
|
||||||
|
// Let concrete implementations initialize themselves.
|
||||||
|
try { |
||||||
|
initDao(); |
||||||
|
} |
||||||
|
catch (Exception ex) { |
||||||
|
throw new BeanInitializationException("Initialization of DAO failed", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Abstract subclasses must override this to check their configuration. |
||||||
|
* <p>Implementors should be marked as {@code final} if concrete subclasses |
||||||
|
* are not supposed to override this template method themselves. |
||||||
|
* @throws IllegalArgumentException in case of illegal configuration |
||||||
|
*/ |
||||||
|
protected abstract void checkDaoConfig() throws IllegalArgumentException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Concrete subclasses can override this for custom initialization behavior. |
||||||
|
* Gets called after population of this instance's bean properties. |
||||||
|
* @throws Exception if DAO initialization fails |
||||||
|
* (will be rethrown as a BeanInitializationException) |
||||||
|
* @see com.fr.third.springframework.beans.factory.BeanInitializationException |
||||||
|
*/ |
||||||
|
protected void initDao() throws Exception { |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,217 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao.support; |
||||||
|
|
||||||
|
import java.util.Collection; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
import com.fr.third.springframework.dao.EmptyResultDataAccessException; |
||||||
|
import com.fr.third.springframework.dao.IncorrectResultSizeDataAccessException; |
||||||
|
import com.fr.third.springframework.dao.TypeMismatchDataAccessException; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
import com.fr.third.springframework.util.CollectionUtils; |
||||||
|
import com.fr.third.springframework.util.NumberUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Miscellaneous utility methods for DAO implementations. |
||||||
|
* Useful with any data access technology. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.0.2 |
||||||
|
*/ |
||||||
|
public abstract class DataAccessUtils { |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a single result object from the given Collection. |
||||||
|
* <p>Returns {@code null} if 0 result objects found; |
||||||
|
* throws an exception if more than 1 element found. |
||||||
|
* @param results the result Collection (can be {@code null}) |
||||||
|
* @return the single result object, or {@code null} if none |
||||||
|
* @throws IncorrectResultSizeDataAccessException if more than one |
||||||
|
* element has been found in the given Collection |
||||||
|
*/ |
||||||
|
public static <T> T singleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException { |
||||||
|
int size = (results != null ? results.size() : 0); |
||||||
|
if (size == 0) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
if (results.size() > 1) { |
||||||
|
throw new IncorrectResultSizeDataAccessException(1, size); |
||||||
|
} |
||||||
|
return results.iterator().next(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a single result object from the given Collection. |
||||||
|
* <p>Throws an exception if 0 or more than 1 element found. |
||||||
|
* @param results the result Collection (can be {@code null}) |
||||||
|
* @return the single result object |
||||||
|
* @throws IncorrectResultSizeDataAccessException if more than one |
||||||
|
* element has been found in the given Collection |
||||||
|
* @throws EmptyResultDataAccessException if no element at all |
||||||
|
* has been found in the given Collection |
||||||
|
*/ |
||||||
|
public static <T> T requiredSingleResult(Collection<T> results) throws IncorrectResultSizeDataAccessException { |
||||||
|
int size = (results != null ? results.size() : 0); |
||||||
|
if (size == 0) { |
||||||
|
throw new EmptyResultDataAccessException(1); |
||||||
|
} |
||||||
|
if (results.size() > 1) { |
||||||
|
throw new IncorrectResultSizeDataAccessException(1, size); |
||||||
|
} |
||||||
|
return results.iterator().next(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a unique result object from the given Collection. |
||||||
|
* <p>Returns {@code null} if 0 result objects found; |
||||||
|
* throws an exception if more than 1 instance found. |
||||||
|
* @param results the result Collection (can be {@code null}) |
||||||
|
* @return the unique result object, or {@code null} if none |
||||||
|
* @throws IncorrectResultSizeDataAccessException if more than one |
||||||
|
* result object has been found in the given Collection |
||||||
|
* @see com.fr.third.springframework.util.CollectionUtils#hasUniqueObject |
||||||
|
*/ |
||||||
|
public static <T> T uniqueResult(Collection<T> results) throws IncorrectResultSizeDataAccessException { |
||||||
|
int size = (results != null ? results.size() : 0); |
||||||
|
if (size == 0) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
if (!CollectionUtils.hasUniqueObject(results)) { |
||||||
|
throw new IncorrectResultSizeDataAccessException(1, size); |
||||||
|
} |
||||||
|
return results.iterator().next(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a unique result object from the given Collection. |
||||||
|
* <p>Throws an exception if 0 or more than 1 instance found. |
||||||
|
* @param results the result Collection (can be {@code null}) |
||||||
|
* @return the unique result object |
||||||
|
* @throws IncorrectResultSizeDataAccessException if more than one |
||||||
|
* result object has been found in the given Collection |
||||||
|
* @throws EmptyResultDataAccessException if no result object at all |
||||||
|
* has been found in the given Collection |
||||||
|
* @see com.fr.third.springframework.util.CollectionUtils#hasUniqueObject |
||||||
|
*/ |
||||||
|
public static <T> T requiredUniqueResult(Collection<T> results) throws IncorrectResultSizeDataAccessException { |
||||||
|
int size = (results != null ? results.size() : 0); |
||||||
|
if (size == 0) { |
||||||
|
throw new EmptyResultDataAccessException(1); |
||||||
|
} |
||||||
|
if (!CollectionUtils.hasUniqueObject(results)) { |
||||||
|
throw new IncorrectResultSizeDataAccessException(1, size); |
||||||
|
} |
||||||
|
return results.iterator().next(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a unique result object from the given Collection. |
||||||
|
* Throws an exception if 0 or more than 1 result objects found, |
||||||
|
* of if the unique result object is not convertable to the |
||||||
|
* specified required type. |
||||||
|
* @param results the result Collection (can be {@code null}) |
||||||
|
* @return the unique result object |
||||||
|
* @throws IncorrectResultSizeDataAccessException if more than one |
||||||
|
* result object has been found in the given Collection |
||||||
|
* @throws EmptyResultDataAccessException if no result object |
||||||
|
* at all has been found in the given Collection |
||||||
|
* @throws TypeMismatchDataAccessException if the unique object does |
||||||
|
* not match the specified required type |
||||||
|
*/ |
||||||
|
@SuppressWarnings("unchecked") |
||||||
|
public static <T> T objectResult(Collection<?> results, Class<T> requiredType) |
||||||
|
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException { |
||||||
|
|
||||||
|
Object result = requiredUniqueResult(results); |
||||||
|
if (requiredType != null && !requiredType.isInstance(result)) { |
||||||
|
if (String.class.equals(requiredType)) { |
||||||
|
result = result.toString(); |
||||||
|
} |
||||||
|
else if (Number.class.isAssignableFrom(requiredType) && Number.class.isInstance(result)) { |
||||||
|
try { |
||||||
|
result = NumberUtils.convertNumberToTargetClass(((Number) result), (Class<? extends Number>) requiredType); |
||||||
|
} |
||||||
|
catch (IllegalArgumentException ex) { |
||||||
|
throw new TypeMismatchDataAccessException(ex.getMessage()); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new TypeMismatchDataAccessException( |
||||||
|
"Result object is of type [" + result.getClass().getName() + |
||||||
|
"] and could not be converted to required type [" + requiredType.getName() + "]"); |
||||||
|
} |
||||||
|
} |
||||||
|
return (T) result; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a unique int result from the given Collection. |
||||||
|
* Throws an exception if 0 or more than 1 result objects found, |
||||||
|
* of if the unique result object is not convertable to an int. |
||||||
|
* @param results the result Collection (can be {@code null}) |
||||||
|
* @return the unique int result |
||||||
|
* @throws IncorrectResultSizeDataAccessException if more than one |
||||||
|
* result object has been found in the given Collection |
||||||
|
* @throws EmptyResultDataAccessException if no result object |
||||||
|
* at all has been found in the given Collection |
||||||
|
* @throws TypeMismatchDataAccessException if the unique object |
||||||
|
* in the collection is not convertable to an int |
||||||
|
*/ |
||||||
|
public static int intResult(Collection<?> results) |
||||||
|
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException { |
||||||
|
|
||||||
|
return objectResult(results, Number.class).intValue(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a unique long result from the given Collection. |
||||||
|
* Throws an exception if 0 or more than 1 result objects found, |
||||||
|
* of if the unique result object is not convertable to a long. |
||||||
|
* @param results the result Collection (can be {@code null}) |
||||||
|
* @return the unique long result |
||||||
|
* @throws IncorrectResultSizeDataAccessException if more than one |
||||||
|
* result object has been found in the given Collection |
||||||
|
* @throws EmptyResultDataAccessException if no result object |
||||||
|
* at all has been found in the given Collection |
||||||
|
* @throws TypeMismatchDataAccessException if the unique object |
||||||
|
* in the collection is not convertable to a long |
||||||
|
*/ |
||||||
|
public static long longResult(Collection<?> results) |
||||||
|
throws IncorrectResultSizeDataAccessException, TypeMismatchDataAccessException { |
||||||
|
|
||||||
|
return objectResult(results, Number.class).longValue(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Return a translated exception if this is appropriate, |
||||||
|
* otherwise return the input exception. |
||||||
|
* @param rawException exception we may wish to translate |
||||||
|
* @param pet PersistenceExceptionTranslator to use to perform the translation |
||||||
|
* @return a translated exception if translation is possible, or |
||||||
|
* the raw exception if it is not |
||||||
|
*/ |
||||||
|
public static RuntimeException translateIfNecessary( |
||||||
|
RuntimeException rawException, PersistenceExceptionTranslator pet) { |
||||||
|
|
||||||
|
Assert.notNull(pet, "PersistenceExceptionTranslator must not be null"); |
||||||
|
DataAccessException dex = pet.translateExceptionIfPossible(rawException); |
||||||
|
return (dex != null ? dex : rawException); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,171 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2013 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao.support; |
||||||
|
|
||||||
|
import java.util.Map; |
||||||
|
|
||||||
|
import org.aopalliance.intercept.MethodInterceptor; |
||||||
|
import org.aopalliance.intercept.MethodInvocation; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.BeansException; |
||||||
|
import com.fr.third.springframework.beans.factory.BeanFactory; |
||||||
|
import com.fr.third.springframework.beans.factory.BeanFactoryAware; |
||||||
|
import com.fr.third.springframework.beans.factory.BeanFactoryUtils; |
||||||
|
import com.fr.third.springframework.beans.factory.InitializingBean; |
||||||
|
import com.fr.third.springframework.beans.factory.ListableBeanFactory; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
import com.fr.third.springframework.util.ReflectionUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* AOP Alliance MethodInterceptor that provides persistence exception translation |
||||||
|
* based on a given PersistenceExceptionTranslator. |
||||||
|
* |
||||||
|
* <p>Delegates to the given {@link PersistenceExceptionTranslator} to translate |
||||||
|
* a RuntimeException thrown into Spring's DataAccessException hierarchy |
||||||
|
* (if appropriate). If the RuntimeException in question is declared on the |
||||||
|
* target method, it is always propagated as-is (with no translation applied). |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
* @see PersistenceExceptionTranslator |
||||||
|
*/ |
||||||
|
public class PersistenceExceptionTranslationInterceptor |
||||||
|
implements MethodInterceptor, BeanFactoryAware, InitializingBean { |
||||||
|
|
||||||
|
private volatile PersistenceExceptionTranslator persistenceExceptionTranslator; |
||||||
|
|
||||||
|
private boolean alwaysTranslate = false; |
||||||
|
|
||||||
|
private ListableBeanFactory beanFactory; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new PersistenceExceptionTranslationInterceptor. |
||||||
|
* Needs to be configured with a PersistenceExceptionTranslator afterwards. |
||||||
|
* @see #setPersistenceExceptionTranslator |
||||||
|
*/ |
||||||
|
public PersistenceExceptionTranslationInterceptor() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new PersistenceExceptionTranslationInterceptor |
||||||
|
* for the given PersistenceExceptionTranslator. |
||||||
|
* @param pet the PersistenceExceptionTranslator to use |
||||||
|
*/ |
||||||
|
public PersistenceExceptionTranslationInterceptor(PersistenceExceptionTranslator pet) { |
||||||
|
Assert.notNull(pet, "PersistenceExceptionTranslator must not be null"); |
||||||
|
this.persistenceExceptionTranslator = pet; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new PersistenceExceptionTranslationInterceptor, autodetecting |
||||||
|
* PersistenceExceptionTranslators in the given BeanFactory. |
||||||
|
* @param beanFactory the ListableBeanFactory to obtaining all |
||||||
|
* PersistenceExceptionTranslators from |
||||||
|
*/ |
||||||
|
public PersistenceExceptionTranslationInterceptor(ListableBeanFactory beanFactory) { |
||||||
|
Assert.notNull(beanFactory, "ListableBeanFactory must not be null"); |
||||||
|
this.beanFactory = beanFactory; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the PersistenceExceptionTranslator to use. |
||||||
|
* <p>Default is to autodetect all PersistenceExceptionTranslators |
||||||
|
* in the containing BeanFactory, using them in a chain. |
||||||
|
* @see #detectPersistenceExceptionTranslators |
||||||
|
*/ |
||||||
|
public void setPersistenceExceptionTranslator(PersistenceExceptionTranslator pet) { |
||||||
|
this.persistenceExceptionTranslator = pet; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify whether to always translate the exception ("true"), or whether throw the |
||||||
|
* raw exception when declared, i.e. when the originating method signature's exception |
||||||
|
* declarations allow for the raw exception to be thrown ("false"). |
||||||
|
* <p>Default is "false". Switch this flag to "true" in order to always translate |
||||||
|
* applicable exceptions, independent from the originating method signature. |
||||||
|
* <p>Note that the originating method does not have to declare the specific exception. |
||||||
|
* Any base class will do as well, even {@code throws Exception}: As long as the |
||||||
|
* originating method does explicitly declare compatible exceptions, the raw exception |
||||||
|
* will be rethrown. If you would like to avoid throwing raw exceptions in any case, |
||||||
|
* switch this flag to "true". |
||||||
|
*/ |
||||||
|
public void setAlwaysTranslate(boolean alwaysTranslate) { |
||||||
|
this.alwaysTranslate = alwaysTranslate; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setBeanFactory(BeanFactory beanFactory) throws BeansException { |
||||||
|
if (this.persistenceExceptionTranslator == null) { |
||||||
|
// No explicit exception translator specified - perform autodetection.
|
||||||
|
if (!(beanFactory instanceof ListableBeanFactory)) { |
||||||
|
throw new IllegalArgumentException( |
||||||
|
"Cannot use PersistenceExceptionTranslator autodetection without ListableBeanFactory"); |
||||||
|
} |
||||||
|
this.beanFactory = (ListableBeanFactory) beanFactory; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() { |
||||||
|
if (this.persistenceExceptionTranslator == null && this.beanFactory == null) { |
||||||
|
throw new IllegalArgumentException("Property 'persistenceExceptionTranslator' is required"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Object invoke(MethodInvocation mi) throws Throwable { |
||||||
|
try { |
||||||
|
return mi.proceed(); |
||||||
|
} |
||||||
|
catch (RuntimeException ex) { |
||||||
|
// Let it throw raw if the type of the exception is on the throws clause of the method.
|
||||||
|
if (!this.alwaysTranslate && ReflectionUtils.declaresException(mi.getMethod(), ex.getClass())) { |
||||||
|
throw ex; |
||||||
|
} |
||||||
|
else { |
||||||
|
if (this.persistenceExceptionTranslator == null) { |
||||||
|
this.persistenceExceptionTranslator = detectPersistenceExceptionTranslators(this.beanFactory); |
||||||
|
} |
||||||
|
throw DataAccessUtils.translateIfNecessary(ex, this.persistenceExceptionTranslator); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Detect all PersistenceExceptionTranslators in the given BeanFactory. |
||||||
|
* @param beanFactory the ListableBeanFactory to obtaining all |
||||||
|
* PersistenceExceptionTranslators from |
||||||
|
* @return a chained PersistenceExceptionTranslator, combining all |
||||||
|
* PersistenceExceptionTranslators found in the factory |
||||||
|
* @see ChainedPersistenceExceptionTranslator |
||||||
|
*/ |
||||||
|
protected PersistenceExceptionTranslator detectPersistenceExceptionTranslators(ListableBeanFactory beanFactory) { |
||||||
|
// Find all translators, being careful not to activate FactoryBeans.
|
||||||
|
Map<String, PersistenceExceptionTranslator> pets = BeanFactoryUtils.beansOfTypeIncludingAncestors( |
||||||
|
beanFactory, PersistenceExceptionTranslator.class, false, false); |
||||||
|
ChainedPersistenceExceptionTranslator cpet = new ChainedPersistenceExceptionTranslator(); |
||||||
|
for (PersistenceExceptionTranslator pet : pets.values()) { |
||||||
|
cpet.addDelegate(pet); |
||||||
|
} |
||||||
|
return cpet; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,55 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.dao.support; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Interface implemented by Spring integrations with data access technologies |
||||||
|
* that throw runtime exceptions, such as JPA, TopLink, JDO and Hibernate. |
||||||
|
* |
||||||
|
* <p>This allows consistent usage of combined exception translation functionality, |
||||||
|
* without forcing a single translator to understand every single possible type |
||||||
|
* of exception. |
||||||
|
* |
||||||
|
* @author Rod Johnson |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0 |
||||||
|
*/ |
||||||
|
public interface PersistenceExceptionTranslator { |
||||||
|
|
||||||
|
/** |
||||||
|
* Translate the given runtime exception thrown by a persistence framework to a |
||||||
|
* corresponding exception from Spring's generic DataAccessException hierarchy, |
||||||
|
* if possible. |
||||||
|
* <p>Do not translate exceptions that are not understand by this translator: |
||||||
|
* for example, if coming from another persistence framework, or resulting |
||||||
|
* from user code and unrelated to persistence. |
||||||
|
* <p>Of particular importance is the correct translation to |
||||||
|
* DataIntegrityViolationException, for example on constraint violation. |
||||||
|
* Implementations may use Spring JDBC's sophisticated exception translation |
||||||
|
* to provide further information in the event of SQLException as a root cause. |
||||||
|
* @param ex a RuntimeException thrown |
||||||
|
* @return the corresponding DataAccessException (or {@code null} if the |
||||||
|
* exception could not be translated, as in this case it may result from |
||||||
|
* user code rather than an actual persistence problem) |
||||||
|
* @see com.fr.third.springframework.dao.DataIntegrityViolationException |
||||||
|
* @see com.fr.third.springframework.jdbc.support.SQLExceptionTranslator |
||||||
|
*/ |
||||||
|
DataAccessException translateExceptionIfPossible(RuntimeException ex); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Support classes for DAO implementations, |
||||||
|
* providing miscellaneous utility methods. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.dao.support; |
||||||
|
|
@ -0,0 +1,42 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessResourceFailureException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown when the creating of a CCI Record failed |
||||||
|
* for connector-internal reasons. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class CannotCreateRecordException extends DataAccessResourceFailureException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for CannotCreateRecordException. |
||||||
|
* @param msg message |
||||||
|
* @param ex ResourceException root cause |
||||||
|
*/ |
||||||
|
public CannotCreateRecordException(String msg, ResourceException ex) { |
||||||
|
super(msg, ex); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessResourceFailureException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Fatal exception thrown when we can't connect to an EIS using CCI. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class CannotGetCciConnectionException extends DataAccessResourceFailureException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for CannotGetCciConnectionException. |
||||||
|
* @param msg message |
||||||
|
* @param ex ResourceException root cause |
||||||
|
*/ |
||||||
|
public CannotGetCciConnectionException(String msg, ResourceException ex) { |
||||||
|
super(msg, ex); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,41 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.InvalidDataAccessResourceUsageException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown when the connector doesn't support a specific CCI operation. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class CciOperationNotSupportedException extends InvalidDataAccessResourceUsageException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for CciOperationNotSupportedException. |
||||||
|
* @param msg message |
||||||
|
* @param ex ResourceException root cause |
||||||
|
*/ |
||||||
|
public CciOperationNotSupportedException(String msg, ResourceException ex) { |
||||||
|
super(msg, ex); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,46 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci; |
||||||
|
|
||||||
|
import java.sql.SQLException; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.InvalidDataAccessResourceUsageException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown when a ResultSet has been accessed in an invalid fashion. |
||||||
|
* Such exceptions always have a {@code java.sql.SQLException} root cause. |
||||||
|
* |
||||||
|
* <p>This typically happens when an invalid ResultSet column index or name |
||||||
|
* has been specified. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see javax.resource.cci.ResultSet |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class InvalidResultSetAccessException extends InvalidDataAccessResourceUsageException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for InvalidResultSetAccessException. |
||||||
|
* @param msg message |
||||||
|
* @param ex the root cause |
||||||
|
*/ |
||||||
|
public InvalidResultSetAccessException(String msg, SQLException ex) { |
||||||
|
super(ex.getMessage(), ex); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,42 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.InvalidDataAccessResourceUsageException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Exception thrown when the creating of a CCI Record failed because |
||||||
|
* the connector doesn't support the desired CCI Record type. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class RecordTypeNotSupportedException extends InvalidDataAccessResourceUsageException { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor for RecordTypeNotSupportedException. |
||||||
|
* @param msg message |
||||||
|
* @param ex ResourceException root cause |
||||||
|
*/ |
||||||
|
public RecordTypeNotSupportedException(String msg, ResourceException ex) { |
||||||
|
super(msg, ex); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,274 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2014 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.connection; |
||||||
|
|
||||||
|
import javax.resource.NotSupportedException; |
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Connection; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.spi.LocalTransactionException; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.InitializingBean; |
||||||
|
import com.fr.third.springframework.transaction.CannotCreateTransactionException; |
||||||
|
import com.fr.third.springframework.transaction.TransactionDefinition; |
||||||
|
import com.fr.third.springframework.transaction.TransactionException; |
||||||
|
import com.fr.third.springframework.transaction.TransactionSystemException; |
||||||
|
import com.fr.third.springframework.transaction.support.AbstractPlatformTransactionManager; |
||||||
|
import com.fr.third.springframework.transaction.support.DefaultTransactionStatus; |
||||||
|
import com.fr.third.springframework.transaction.support.ResourceTransactionManager; |
||||||
|
import com.fr.third.springframework.transaction.support.TransactionSynchronizationManager; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link com.fr.third.springframework.transaction.PlatformTransactionManager} implementation |
||||||
|
* that manages local transactions for a single CCI ConnectionFactory. |
||||||
|
* Binds a CCI Connection from the specified ConnectionFactory to the thread, |
||||||
|
* potentially allowing for one thread-bound Connection per ConnectionFactory. |
||||||
|
* |
||||||
|
* <p>Application code is required to retrieve the CCI Connection via |
||||||
|
* {@link ConnectionFactoryUtils#getConnection(ConnectionFactory)} instead of a standard |
||||||
|
* J2EE-style {@link ConnectionFactory#getConnection()} call. Spring classes such as |
||||||
|
* {@link com.fr.third.springframework.jca.cci.core.CciTemplate} use this strategy implicitly. |
||||||
|
* If not used in combination with this transaction manager, the |
||||||
|
* {@link ConnectionFactoryUtils} lookup strategy behaves exactly like the native |
||||||
|
* DataSource lookup; it can thus be used in a portable fashion. |
||||||
|
* |
||||||
|
* <p>Alternatively, you can allow application code to work with the standard |
||||||
|
* J2EE lookup pattern {@link ConnectionFactory#getConnection()}, for example |
||||||
|
* for legacy code that is not aware of Spring at all. In that case, define a |
||||||
|
* {@link TransactionAwareConnectionFactoryProxy} for your target ConnectionFactory, |
||||||
|
* which will automatically participate in Spring-managed transactions. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see ConnectionFactoryUtils#getConnection(javax.resource.cci.ConnectionFactory) |
||||||
|
* @see ConnectionFactoryUtils#releaseConnection |
||||||
|
* @see TransactionAwareConnectionFactoryProxy |
||||||
|
* @see com.fr.third.springframework.jca.cci.core.CciTemplate |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class CciLocalTransactionManager extends AbstractPlatformTransactionManager |
||||||
|
implements ResourceTransactionManager, InitializingBean { |
||||||
|
|
||||||
|
private ConnectionFactory connectionFactory; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new CciLocalTransactionManager instance. |
||||||
|
* A ConnectionFactory has to be set to be able to use it. |
||||||
|
* @see #setConnectionFactory |
||||||
|
*/ |
||||||
|
public CciLocalTransactionManager() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new CciLocalTransactionManager instance. |
||||||
|
* @param connectionFactory CCI ConnectionFactory to manage local transactions for |
||||||
|
*/ |
||||||
|
public CciLocalTransactionManager(ConnectionFactory connectionFactory) { |
||||||
|
setConnectionFactory(connectionFactory); |
||||||
|
afterPropertiesSet(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the CCI ConnectionFactory that this instance should manage local |
||||||
|
* transactions for. |
||||||
|
*/ |
||||||
|
public void setConnectionFactory(ConnectionFactory cf) { |
||||||
|
if (cf instanceof TransactionAwareConnectionFactoryProxy) { |
||||||
|
// If we got a TransactionAwareConnectionFactoryProxy, we need to perform transactions
|
||||||
|
// for its underlying target ConnectionFactory, else JMS access code won't see
|
||||||
|
// properly exposed transactions (i.e. transactions for the target ConnectionFactory).
|
||||||
|
this.connectionFactory = ((TransactionAwareConnectionFactoryProxy) cf).getTargetConnectionFactory(); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.connectionFactory = cf; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the CCI ConnectionFactory that this instance manages local |
||||||
|
* transactions for. |
||||||
|
*/ |
||||||
|
public ConnectionFactory getConnectionFactory() { |
||||||
|
return this.connectionFactory; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() { |
||||||
|
if (getConnectionFactory() == null) { |
||||||
|
throw new IllegalArgumentException("Property 'connectionFactory' is required"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getResourceFactory() { |
||||||
|
return getConnectionFactory(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Object doGetTransaction() { |
||||||
|
CciLocalTransactionObject txObject = new CciLocalTransactionObject(); |
||||||
|
ConnectionHolder conHolder = |
||||||
|
(ConnectionHolder) TransactionSynchronizationManager.getResource(getConnectionFactory()); |
||||||
|
txObject.setConnectionHolder(conHolder); |
||||||
|
return txObject; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected boolean isExistingTransaction(Object transaction) { |
||||||
|
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction; |
||||||
|
// Consider a pre-bound connection as transaction.
|
||||||
|
return (txObject.getConnectionHolder() != null); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doBegin(Object transaction, TransactionDefinition definition) { |
||||||
|
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction; |
||||||
|
Connection con = null; |
||||||
|
|
||||||
|
try { |
||||||
|
con = getConnectionFactory().getConnection(); |
||||||
|
if (logger.isDebugEnabled()) { |
||||||
|
logger.debug("Acquired Connection [" + con + "] for local CCI transaction"); |
||||||
|
} |
||||||
|
|
||||||
|
txObject.setConnectionHolder(new ConnectionHolder(con)); |
||||||
|
txObject.getConnectionHolder().setSynchronizedWithTransaction(true); |
||||||
|
|
||||||
|
con.getLocalTransaction().begin(); |
||||||
|
int timeout = determineTimeout(definition); |
||||||
|
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { |
||||||
|
txObject.getConnectionHolder().setTimeoutInSeconds(timeout); |
||||||
|
} |
||||||
|
TransactionSynchronizationManager.bindResource(getConnectionFactory(), txObject.getConnectionHolder()); |
||||||
|
} |
||||||
|
catch (NotSupportedException ex) { |
||||||
|
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory()); |
||||||
|
throw new CannotCreateTransactionException("CCI Connection does not support local transactions", ex); |
||||||
|
} |
||||||
|
catch (LocalTransactionException ex) { |
||||||
|
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory()); |
||||||
|
throw new CannotCreateTransactionException("Could not begin local CCI transaction", ex); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory()); |
||||||
|
throw new TransactionSystemException("Unexpected failure on begin of CCI local transaction", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected Object doSuspend(Object transaction) { |
||||||
|
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction; |
||||||
|
txObject.setConnectionHolder(null); |
||||||
|
return TransactionSynchronizationManager.unbindResource(getConnectionFactory()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doResume(Object transaction, Object suspendedResources) { |
||||||
|
ConnectionHolder conHolder = (ConnectionHolder) suspendedResources; |
||||||
|
TransactionSynchronizationManager.bindResource(getConnectionFactory(), conHolder); |
||||||
|
} |
||||||
|
|
||||||
|
protected boolean isRollbackOnly(Object transaction) throws TransactionException { |
||||||
|
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction; |
||||||
|
return txObject.getConnectionHolder().isRollbackOnly(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doCommit(DefaultTransactionStatus status) { |
||||||
|
CciLocalTransactionObject txObject = (CciLocalTransactionObject) status.getTransaction(); |
||||||
|
Connection con = txObject.getConnectionHolder().getConnection(); |
||||||
|
if (status.isDebug()) { |
||||||
|
logger.debug("Committing CCI local transaction on Connection [" + con + "]"); |
||||||
|
} |
||||||
|
try { |
||||||
|
con.getLocalTransaction().commit(); |
||||||
|
} |
||||||
|
catch (LocalTransactionException ex) { |
||||||
|
throw new TransactionSystemException("Could not commit CCI local transaction", ex); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
throw new TransactionSystemException("Unexpected failure on commit of CCI local transaction", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doRollback(DefaultTransactionStatus status) { |
||||||
|
CciLocalTransactionObject txObject = (CciLocalTransactionObject) status.getTransaction(); |
||||||
|
Connection con = txObject.getConnectionHolder().getConnection(); |
||||||
|
if (status.isDebug()) { |
||||||
|
logger.debug("Rolling back CCI local transaction on Connection [" + con + "]"); |
||||||
|
} |
||||||
|
try { |
||||||
|
con.getLocalTransaction().rollback(); |
||||||
|
} |
||||||
|
catch (LocalTransactionException ex) { |
||||||
|
throw new TransactionSystemException("Could not roll back CCI local transaction", ex); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
throw new TransactionSystemException("Unexpected failure on rollback of CCI local transaction", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doSetRollbackOnly(DefaultTransactionStatus status) { |
||||||
|
CciLocalTransactionObject txObject = (CciLocalTransactionObject) status.getTransaction(); |
||||||
|
if (status.isDebug()) { |
||||||
|
logger.debug("Setting CCI local transaction [" + txObject.getConnectionHolder().getConnection() + |
||||||
|
"] rollback-only"); |
||||||
|
} |
||||||
|
txObject.getConnectionHolder().setRollbackOnly(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void doCleanupAfterCompletion(Object transaction) { |
||||||
|
CciLocalTransactionObject txObject = (CciLocalTransactionObject) transaction; |
||||||
|
|
||||||
|
// Remove the connection holder from the thread.
|
||||||
|
TransactionSynchronizationManager.unbindResource(getConnectionFactory()); |
||||||
|
txObject.getConnectionHolder().clear(); |
||||||
|
|
||||||
|
Connection con = txObject.getConnectionHolder().getConnection(); |
||||||
|
if (logger.isDebugEnabled()) { |
||||||
|
logger.debug("Releasing CCI Connection [" + con + "] after transaction"); |
||||||
|
} |
||||||
|
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* CCI local transaction object, representing a ConnectionHolder. |
||||||
|
* Used as transaction object by CciLocalTransactionManager. |
||||||
|
* @see ConnectionHolder |
||||||
|
*/ |
||||||
|
private static class CciLocalTransactionObject { |
||||||
|
|
||||||
|
private ConnectionHolder connectionHolder; |
||||||
|
|
||||||
|
public void setConnectionHolder(ConnectionHolder connectionHolder) { |
||||||
|
this.connectionHolder = connectionHolder; |
||||||
|
} |
||||||
|
|
||||||
|
public ConnectionHolder getConnectionHolder() { |
||||||
|
return this.connectionHolder; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,214 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.connection; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Connection; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.ConnectionSpec; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.jca.cci.CannotGetCciConnectionException; |
||||||
|
import com.fr.third.springframework.transaction.support.ResourceHolderSynchronization; |
||||||
|
import com.fr.third.springframework.transaction.support.TransactionSynchronizationManager; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Helper class that provides static methods for obtaining CCI Connections |
||||||
|
* from a {@link javax.resource.cci.ConnectionFactory}. Includes special |
||||||
|
* support for Spring-managed transactional Connections, e.g. managed |
||||||
|
* by {@link CciLocalTransactionManager} or |
||||||
|
* {@link com.fr.third.springframework.transaction.jta.JtaTransactionManager}. |
||||||
|
* |
||||||
|
* <p>Used internally by {@link com.fr.third.springframework.jca.cci.core.CciTemplate}, |
||||||
|
* Spring's CCI operation objects and the {@link CciLocalTransactionManager}. |
||||||
|
* Can also be used directly in application code. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see #getConnection |
||||||
|
* @see #releaseConnection |
||||||
|
* @see CciLocalTransactionManager |
||||||
|
* @see com.fr.third.springframework.transaction.jta.JtaTransactionManager |
||||||
|
* @see com.fr.third.springframework.transaction.support.TransactionSynchronizationManager |
||||||
|
*/ |
||||||
|
public abstract class ConnectionFactoryUtils { |
||||||
|
|
||||||
|
private static final Log logger = LogFactory.getLog(ConnectionFactoryUtils.class); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Obtain a Connection from the given ConnectionFactory. Translates ResourceExceptions |
||||||
|
* into the Spring hierarchy of unchecked generic data access exceptions, simplifying |
||||||
|
* calling code and making any exception that is thrown more meaningful. |
||||||
|
* <p>Is aware of a corresponding Connection bound to the current thread, for example |
||||||
|
* when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread |
||||||
|
* if transaction synchronization is active (e.g. if in a JTA transaction). |
||||||
|
* @param cf the ConnectionFactory to obtain Connection from |
||||||
|
* @return a CCI Connection from the given ConnectionFactory |
||||||
|
* @throws com.fr.third.springframework.jca.cci.CannotGetCciConnectionException |
||||||
|
* if the attempt to get a Connection failed |
||||||
|
* @see #releaseConnection |
||||||
|
*/ |
||||||
|
public static Connection getConnection(ConnectionFactory cf) throws CannotGetCciConnectionException { |
||||||
|
return getConnection(cf, null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Obtain a Connection from the given ConnectionFactory. Translates ResourceExceptions |
||||||
|
* into the Spring hierarchy of unchecked generic data access exceptions, simplifying |
||||||
|
* calling code and making any exception that is thrown more meaningful. |
||||||
|
* <p>Is aware of a corresponding Connection bound to the current thread, for example |
||||||
|
* when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread |
||||||
|
* if transaction synchronization is active (e.g. if in a JTA transaction). |
||||||
|
* @param cf the ConnectionFactory to obtain Connection from |
||||||
|
* @param spec the ConnectionSpec for the desired Connection (may be {@code null}). |
||||||
|
* Note: If this is specified, a new Connection will be obtained for every call, |
||||||
|
* without participating in a shared transactional Connection. |
||||||
|
* @return a CCI Connection from the given ConnectionFactory |
||||||
|
* @throws com.fr.third.springframework.jca.cci.CannotGetCciConnectionException |
||||||
|
* if the attempt to get a Connection failed |
||||||
|
* @see #releaseConnection |
||||||
|
*/ |
||||||
|
public static Connection getConnection(ConnectionFactory cf, ConnectionSpec spec) |
||||||
|
throws CannotGetCciConnectionException { |
||||||
|
try { |
||||||
|
if (spec != null) { |
||||||
|
Assert.notNull(cf, "No ConnectionFactory specified"); |
||||||
|
return cf.getConnection(spec); |
||||||
|
} |
||||||
|
else { |
||||||
|
return doGetConnection(cf); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
throw new CannotGetCciConnectionException("Could not get CCI Connection", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Actually obtain a CCI Connection from the given ConnectionFactory. |
||||||
|
* Same as {@link #getConnection}, but throwing the original ResourceException. |
||||||
|
* <p>Is aware of a corresponding Connection bound to the current thread, for example |
||||||
|
* when using {@link CciLocalTransactionManager}. Will bind a Connection to the thread |
||||||
|
* if transaction synchronization is active (e.g. if in a JTA transaction). |
||||||
|
* <p>Directly accessed by {@link TransactionAwareConnectionFactoryProxy}. |
||||||
|
* @param cf the ConnectionFactory to obtain Connection from |
||||||
|
* @return a CCI Connection from the given ConnectionFactory |
||||||
|
* @throws ResourceException if thrown by CCI API methods |
||||||
|
* @see #doReleaseConnection |
||||||
|
*/ |
||||||
|
public static Connection doGetConnection(ConnectionFactory cf) throws ResourceException { |
||||||
|
Assert.notNull(cf, "No ConnectionFactory specified"); |
||||||
|
|
||||||
|
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(cf); |
||||||
|
if (conHolder != null) { |
||||||
|
return conHolder.getConnection(); |
||||||
|
} |
||||||
|
|
||||||
|
logger.debug("Opening CCI Connection"); |
||||||
|
Connection con = cf.getConnection(); |
||||||
|
|
||||||
|
if (TransactionSynchronizationManager.isSynchronizationActive()) { |
||||||
|
logger.debug("Registering transaction synchronization for CCI Connection"); |
||||||
|
conHolder = new ConnectionHolder(con); |
||||||
|
conHolder.setSynchronizedWithTransaction(true); |
||||||
|
TransactionSynchronizationManager.registerSynchronization(new ConnectionSynchronization(conHolder, cf)); |
||||||
|
TransactionSynchronizationManager.bindResource(cf, conHolder); |
||||||
|
} |
||||||
|
|
||||||
|
return con; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Determine whether the given JCA CCI Connection is transactional, that is, |
||||||
|
* bound to the current thread by Spring's transaction facilities. |
||||||
|
* @param con the Connection to check |
||||||
|
* @param cf the ConnectionFactory that the Connection was obtained from |
||||||
|
* (may be {@code null}) |
||||||
|
* @return whether the Connection is transactional |
||||||
|
*/ |
||||||
|
public static boolean isConnectionTransactional(Connection con, ConnectionFactory cf) { |
||||||
|
if (cf == null) { |
||||||
|
return false; |
||||||
|
} |
||||||
|
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(cf); |
||||||
|
return (conHolder != null && conHolder.getConnection() == con); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Close the given Connection, obtained from the given ConnectionFactory, |
||||||
|
* if it is not managed externally (that is, not bound to the thread). |
||||||
|
* @param con the Connection to close if necessary |
||||||
|
* (if this is {@code null}, the call will be ignored) |
||||||
|
* @param cf the ConnectionFactory that the Connection was obtained from |
||||||
|
* (can be {@code null}) |
||||||
|
* @see #getConnection |
||||||
|
*/ |
||||||
|
public static void releaseConnection(Connection con, ConnectionFactory cf) { |
||||||
|
try { |
||||||
|
doReleaseConnection(con, cf); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
logger.debug("Could not close CCI Connection", ex); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
// We don't trust the CCI driver: It might throw RuntimeException or Error.
|
||||||
|
logger.debug("Unexpected exception on closing CCI Connection", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Actually close the given Connection, obtained from the given ConnectionFactory. |
||||||
|
* Same as {@link #releaseConnection}, but throwing the original ResourceException. |
||||||
|
* <p>Directly accessed by {@link TransactionAwareConnectionFactoryProxy}. |
||||||
|
* @param con the Connection to close if necessary |
||||||
|
* (if this is {@code null}, the call will be ignored) |
||||||
|
* @param cf the ConnectionFactory that the Connection was obtained from |
||||||
|
* (can be {@code null}) |
||||||
|
* @throws ResourceException if thrown by JCA CCI methods |
||||||
|
* @see #doGetConnection |
||||||
|
*/ |
||||||
|
public static void doReleaseConnection(Connection con, ConnectionFactory cf) throws ResourceException { |
||||||
|
if (con == null || isConnectionTransactional(con, cf)) { |
||||||
|
return; |
||||||
|
} |
||||||
|
con.close(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Callback for resource cleanup at the end of a non-native CCI transaction |
||||||
|
* (e.g. when participating in a JTA transaction). |
||||||
|
*/ |
||||||
|
private static class ConnectionSynchronization |
||||||
|
extends ResourceHolderSynchronization<ConnectionHolder, ConnectionFactory> { |
||||||
|
|
||||||
|
public ConnectionSynchronization(ConnectionHolder connectionHolder, ConnectionFactory connectionFactory) { |
||||||
|
super(connectionHolder, connectionFactory); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected void releaseResource(ConnectionHolder resourceHolder, ConnectionFactory resourceKey) { |
||||||
|
releaseConnection(resourceHolder.getConnection(), resourceKey); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,49 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.connection; |
||||||
|
|
||||||
|
import javax.resource.cci.Connection; |
||||||
|
|
||||||
|
import com.fr.third.springframework.transaction.support.ResourceHolderSupport; |
||||||
|
|
||||||
|
/** |
||||||
|
* Connection holder, wrapping a CCI Connection. |
||||||
|
* |
||||||
|
* <p>CciLocalTransactionManager binds instances of this class
|
||||||
|
* to the thread, for a given ConnectionFactory. |
||||||
|
* |
||||||
|
* <p>Note: This is an SPI class, not intended to be used by applications. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see CciLocalTransactionManager |
||||||
|
* @see ConnectionFactoryUtils |
||||||
|
*/ |
||||||
|
public class ConnectionHolder extends ResourceHolderSupport { |
||||||
|
|
||||||
|
private final Connection connection; |
||||||
|
|
||||||
|
public ConnectionHolder(Connection connection) { |
||||||
|
this.connection = connection; |
||||||
|
} |
||||||
|
|
||||||
|
public Connection getConnection() { |
||||||
|
return this.connection; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,143 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.connection; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Connection; |
||||||
|
import javax.resource.cci.ConnectionSpec; |
||||||
|
|
||||||
|
import com.fr.third.springframework.core.NamedThreadLocal; |
||||||
|
|
||||||
|
/** |
||||||
|
* An adapter for a target CCI {@link javax.resource.cci.ConnectionFactory}, |
||||||
|
* applying the given ConnectionSpec to every standard {@code getConnection()} |
||||||
|
* call, that is, implicitly invoking {@code getConnection(ConnectionSpec)} |
||||||
|
* on the target. All other methods simply delegate to the corresponding methods |
||||||
|
* of the target ConnectionFactory. |
||||||
|
* |
||||||
|
* <p>Can be used to proxy a target JNDI ConnectionFactory that does not have a |
||||||
|
* ConnectionSpec configured. Client code can work with the ConnectionFactory |
||||||
|
* without passing in a ConnectionSpec on every {@code getConnection()} call. |
||||||
|
* |
||||||
|
* <p>In the following example, client code can simply transparently work with |
||||||
|
* the preconfigured "myConnectionFactory", implicitly accessing |
||||||
|
* "myTargetConnectionFactory" with the specified user credentials. |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* <bean id="myTargetConnectionFactory" class="com.fr.third.springframework.jndi.JndiObjectFactoryBean"> |
||||||
|
* <property name="jndiName" value="java:comp/env/cci/mycf"/> |
||||||
|
* </bean> |
||||||
|
* |
||||||
|
* <bean id="myConnectionFactory" class="com.fr.third.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter"> |
||||||
|
* <property name="targetConnectionFactory" ref="myTargetConnectionFactory"/> |
||||||
|
* <property name="connectionSpec"> |
||||||
|
* <bean class="your.resource.adapter.ConnectionSpecImpl"> |
||||||
|
* <property name="username" value="myusername"/> |
||||||
|
* <property name="password" value="mypassword"/> |
||||||
|
* </bean> |
||||||
|
* </property> |
||||||
|
* </bean></pre> |
||||||
|
* |
||||||
|
* <p>If the "connectionSpec" is empty, this proxy will simply delegate to the |
||||||
|
* standard {@code getConnection()} method of the target ConnectionFactory. |
||||||
|
* This can be used to keep a UserCredentialsConnectionFactoryAdapter bean definition |
||||||
|
* just for the <i>option</i> of implicitly passing in a ConnectionSpec if the |
||||||
|
* particular target ConnectionFactory requires it. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see #getConnection |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class ConnectionSpecConnectionFactoryAdapter extends DelegatingConnectionFactory { |
||||||
|
|
||||||
|
private ConnectionSpec connectionSpec; |
||||||
|
|
||||||
|
private final ThreadLocal<ConnectionSpec> threadBoundSpec = |
||||||
|
new NamedThreadLocal<ConnectionSpec>("Current CCI ConnectionSpec"); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the ConnectionSpec that this adapter should use for retrieving Connections. |
||||||
|
* Default is none. |
||||||
|
*/ |
||||||
|
public void setConnectionSpec(ConnectionSpec connectionSpec) { |
||||||
|
this.connectionSpec = connectionSpec; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set a ConnectionSpec for this proxy and the current thread. |
||||||
|
* The given ConnectionSpec will be applied to all subsequent |
||||||
|
* {@code getConnection()} calls on this ConnectionFactory proxy. |
||||||
|
* <p>This will override any statically specified "connectionSpec" property. |
||||||
|
* @param spec the ConnectionSpec to apply |
||||||
|
* @see #removeConnectionSpecFromCurrentThread |
||||||
|
*/ |
||||||
|
public void setConnectionSpecForCurrentThread(ConnectionSpec spec) { |
||||||
|
this.threadBoundSpec.set(spec); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Remove any ConnectionSpec for this proxy from the current thread. |
||||||
|
* A statically specified ConnectionSpec applies again afterwards. |
||||||
|
* @see #setConnectionSpecForCurrentThread |
||||||
|
*/ |
||||||
|
public void removeConnectionSpecFromCurrentThread() { |
||||||
|
this.threadBoundSpec.remove(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Determine whether there is currently a thread-bound ConnectionSpec, |
||||||
|
* using it if available, falling back to the statically specified |
||||||
|
* "connectionSpec" property else. |
||||||
|
* @see #doGetConnection |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public final Connection getConnection() throws ResourceException { |
||||||
|
ConnectionSpec threadSpec = this.threadBoundSpec.get(); |
||||||
|
if (threadSpec != null) { |
||||||
|
return doGetConnection(threadSpec); |
||||||
|
} |
||||||
|
else { |
||||||
|
return doGetConnection(this.connectionSpec); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This implementation delegates to the {@code getConnection(ConnectionSpec)} |
||||||
|
* method of the target ConnectionFactory, passing in the specified user credentials. |
||||||
|
* If the specified username is empty, it will simply delegate to the standard |
||||||
|
* {@code getConnection()} method of the target ConnectionFactory. |
||||||
|
* @param spec the ConnectionSpec to apply |
||||||
|
* @return the Connection |
||||||
|
* @see javax.resource.cci.ConnectionFactory#getConnection(javax.resource.cci.ConnectionSpec) |
||||||
|
* @see javax.resource.cci.ConnectionFactory#getConnection() |
||||||
|
*/ |
||||||
|
protected Connection doGetConnection(ConnectionSpec spec) throws ResourceException { |
||||||
|
if (getTargetConnectionFactory() == null) { |
||||||
|
throw new IllegalStateException("targetConnectionFactory is required"); |
||||||
|
} |
||||||
|
if (spec != null) { |
||||||
|
return getTargetConnectionFactory().getConnection(spec); |
||||||
|
} |
||||||
|
else { |
||||||
|
return getTargetConnectionFactory().getConnection(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,101 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.connection; |
||||||
|
|
||||||
|
import javax.naming.NamingException; |
||||||
|
import javax.naming.Reference; |
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Connection; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.ConnectionSpec; |
||||||
|
import javax.resource.cci.RecordFactory; |
||||||
|
import javax.resource.cci.ResourceAdapterMetaData; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.InitializingBean; |
||||||
|
|
||||||
|
/** |
||||||
|
* CCI {@link ConnectionFactory} implementation that delegates all calls |
||||||
|
* to a given target {@link ConnectionFactory}. |
||||||
|
* |
||||||
|
* <p>This class is meant to be subclassed, with subclasses overriding only |
||||||
|
* those methods (such as {@link #getConnection()}) that should not simply |
||||||
|
* delegate to the target {@link ConnectionFactory}. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see #getConnection |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class DelegatingConnectionFactory implements ConnectionFactory, InitializingBean { |
||||||
|
|
||||||
|
private ConnectionFactory targetConnectionFactory; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the target ConnectionFactory that this ConnectionFactory should delegate to. |
||||||
|
*/ |
||||||
|
public void setTargetConnectionFactory(ConnectionFactory targetConnectionFactory) { |
||||||
|
this.targetConnectionFactory = targetConnectionFactory; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the target ConnectionFactory that this ConnectionFactory should delegate to. |
||||||
|
*/ |
||||||
|
public ConnectionFactory getTargetConnectionFactory() { |
||||||
|
return this.targetConnectionFactory; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() { |
||||||
|
if (getTargetConnectionFactory() == null) { |
||||||
|
throw new IllegalArgumentException("Property 'targetConnectionFactory' is required"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Connection getConnection() throws ResourceException { |
||||||
|
return getTargetConnectionFactory().getConnection(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException { |
||||||
|
return getTargetConnectionFactory().getConnection(connectionSpec); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public RecordFactory getRecordFactory() throws ResourceException { |
||||||
|
return getTargetConnectionFactory().getRecordFactory(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ResourceAdapterMetaData getMetaData() throws ResourceException { |
||||||
|
return getTargetConnectionFactory().getMetaData(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Reference getReference() throws NamingException { |
||||||
|
return getTargetConnectionFactory().getReference(); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setReference(Reference reference) { |
||||||
|
getTargetConnectionFactory().setReference(reference); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,54 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.connection; |
||||||
|
|
||||||
|
import javax.resource.NotSupportedException; |
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.IndexedRecord; |
||||||
|
import javax.resource.cci.MappedRecord; |
||||||
|
import javax.resource.cci.RecordFactory; |
||||||
|
|
||||||
|
/** |
||||||
|
* Implementation of the CCI RecordFactory interface that always throws |
||||||
|
* NotSupportedException. |
||||||
|
* |
||||||
|
* <p>Useful as a placeholder for a RecordFactory argument (for example as |
||||||
|
* defined by the RecordCreator callback), in particular when the connector's |
||||||
|
* {@code ConnectionFactory.getRecordFactory()} implementation happens to |
||||||
|
* throw NotSupportedException early rather than throwing the exception from |
||||||
|
* RecordFactory's methods. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2.4 |
||||||
|
* @see com.fr.third.springframework.jca.cci.core.RecordCreator#createRecord(javax.resource.cci.RecordFactory) |
||||||
|
* @see com.fr.third.springframework.jca.cci.core.CciTemplate#getRecordFactory(javax.resource.cci.ConnectionFactory) |
||||||
|
* @see javax.resource.cci.ConnectionFactory#getRecordFactory() |
||||||
|
* @see javax.resource.NotSupportedException |
||||||
|
*/ |
||||||
|
public class NotSupportedRecordFactory implements RecordFactory { |
||||||
|
|
||||||
|
@Override |
||||||
|
public MappedRecord createMappedRecord(String name) throws ResourceException { |
||||||
|
throw new NotSupportedException("The RecordFactory facility is not supported by the connector"); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public IndexedRecord createIndexedRecord(String name) throws ResourceException { |
||||||
|
throw new NotSupportedException("The RecordFactory facility is not supported by the connector"); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,255 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.connection; |
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler; |
||||||
|
import java.lang.reflect.InvocationTargetException; |
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.lang.reflect.Proxy; |
||||||
|
|
||||||
|
import javax.resource.NotSupportedException; |
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Connection; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.ConnectionSpec; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.DisposableBean; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* A CCI ConnectionFactory adapter that returns the same Connection on all |
||||||
|
* {@code getConnection} calls, and ignores calls to |
||||||
|
* {@code Connection.close()}. |
||||||
|
* |
||||||
|
* <p>Useful for testing and standalone environments, to keep using the same |
||||||
|
* Connection for multiple CciTemplate calls, without having a pooling |
||||||
|
* ConnectionFactory, also spanning any number of transactions. |
||||||
|
* |
||||||
|
* <p>You can either pass in a CCI Connection directly, or let this |
||||||
|
* factory lazily create a Connection via a given target ConnectionFactory. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see #getConnection() |
||||||
|
* @see javax.resource.cci.Connection#close() |
||||||
|
* @see com.fr.third.springframework.jca.cci.core.CciTemplate |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class SingleConnectionFactory extends DelegatingConnectionFactory implements DisposableBean { |
||||||
|
|
||||||
|
protected final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
/** Wrapped Connection */ |
||||||
|
private Connection target; |
||||||
|
|
||||||
|
/** Proxy Connection */ |
||||||
|
private Connection connection; |
||||||
|
|
||||||
|
/** Synchronization monitor for the shared Connection */ |
||||||
|
private final Object connectionMonitor = new Object(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new SingleConnectionFactory for bean-style usage. |
||||||
|
* @see #setTargetConnectionFactory |
||||||
|
*/ |
||||||
|
public SingleConnectionFactory() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new SingleConnectionFactory that always returns the |
||||||
|
* given Connection. |
||||||
|
* @param target the single Connection |
||||||
|
*/ |
||||||
|
public SingleConnectionFactory(Connection target) { |
||||||
|
Assert.notNull(target, "Target Connection must not be null"); |
||||||
|
this.target = target; |
||||||
|
this.connection = getCloseSuppressingConnectionProxy(target); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new SingleConnectionFactory that always returns a single |
||||||
|
* Connection which it will lazily create via the given target |
||||||
|
* ConnectionFactory. |
||||||
|
* @param targetConnectionFactory the target ConnectionFactory |
||||||
|
*/ |
||||||
|
public SingleConnectionFactory(ConnectionFactory targetConnectionFactory) { |
||||||
|
Assert.notNull(targetConnectionFactory, "Target ConnectionFactory must not be null"); |
||||||
|
setTargetConnectionFactory(targetConnectionFactory); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Make sure a Connection or ConnectionFactory has been set. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() { |
||||||
|
if (this.connection == null && getTargetConnectionFactory() == null) { |
||||||
|
throw new IllegalArgumentException("Connection or 'targetConnectionFactory' is required"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Connection getConnection() throws ResourceException { |
||||||
|
synchronized (this.connectionMonitor) { |
||||||
|
if (this.connection == null) { |
||||||
|
initConnection(); |
||||||
|
} |
||||||
|
return this.connection; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException { |
||||||
|
throw new NotSupportedException( |
||||||
|
"SingleConnectionFactory does not support custom ConnectionSpec"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Close the underlying Connection. |
||||||
|
* The provider of this ConnectionFactory needs to care for proper shutdown. |
||||||
|
* <p>As this bean implements DisposableBean, a bean factory will |
||||||
|
* automatically invoke this on destruction of its cached singletons. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void destroy() { |
||||||
|
resetConnection(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Initialize the single underlying Connection. |
||||||
|
* <p>Closes and reinitializes the Connection if an underlying |
||||||
|
* Connection is present already. |
||||||
|
* @throws javax.resource.ResourceException if thrown by CCI API methods |
||||||
|
*/ |
||||||
|
public void initConnection() throws ResourceException { |
||||||
|
if (getTargetConnectionFactory() == null) { |
||||||
|
throw new IllegalStateException( |
||||||
|
"'targetConnectionFactory' is required for lazily initializing a Connection"); |
||||||
|
} |
||||||
|
synchronized (this.connectionMonitor) { |
||||||
|
if (this.target != null) { |
||||||
|
closeConnection(this.target); |
||||||
|
} |
||||||
|
this.target = doCreateConnection(); |
||||||
|
prepareConnection(this.target); |
||||||
|
if (logger.isInfoEnabled()) { |
||||||
|
logger.info("Established shared CCI Connection: " + this.target); |
||||||
|
} |
||||||
|
this.connection = getCloseSuppressingConnectionProxy(this.target); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Reset the underlying shared Connection, to be reinitialized on next access. |
||||||
|
*/ |
||||||
|
public void resetConnection() { |
||||||
|
synchronized (this.connectionMonitor) { |
||||||
|
if (this.target != null) { |
||||||
|
closeConnection(this.target); |
||||||
|
} |
||||||
|
this.target = null; |
||||||
|
this.connection = null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a CCI Connection via this template's ConnectionFactory. |
||||||
|
* @return the new CCI Connection |
||||||
|
* @throws javax.resource.ResourceException if thrown by CCI API methods |
||||||
|
*/ |
||||||
|
protected Connection doCreateConnection() throws ResourceException { |
||||||
|
return getTargetConnectionFactory().getConnection(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Prepare the given Connection before it is exposed. |
||||||
|
* <p>The default implementation is empty. Can be overridden in subclasses. |
||||||
|
* @param con the Connection to prepare |
||||||
|
*/ |
||||||
|
protected void prepareConnection(Connection con) throws ResourceException { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Close the given Connection. |
||||||
|
* @param con the Connection to close |
||||||
|
*/ |
||||||
|
protected void closeConnection(Connection con) { |
||||||
|
try { |
||||||
|
con.close(); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
logger.warn("Could not close shared CCI Connection", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Wrap the given Connection with a proxy that delegates every method call to it |
||||||
|
* but suppresses close calls. This is useful for allowing application code to |
||||||
|
* handle a special framework Connection just like an ordinary Connection from a |
||||||
|
* CCI ConnectionFactory. |
||||||
|
* @param target the original Connection to wrap |
||||||
|
* @return the wrapped Connection |
||||||
|
*/ |
||||||
|
protected Connection getCloseSuppressingConnectionProxy(Connection target) { |
||||||
|
return (Connection) Proxy.newProxyInstance( |
||||||
|
Connection.class.getClassLoader(), |
||||||
|
new Class<?>[] {Connection.class}, |
||||||
|
new CloseSuppressingInvocationHandler(target)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Invocation handler that suppresses close calls on CCI Connections. |
||||||
|
*/ |
||||||
|
private static class CloseSuppressingInvocationHandler implements InvocationHandler { |
||||||
|
|
||||||
|
private final Connection target; |
||||||
|
|
||||||
|
private CloseSuppressingInvocationHandler(Connection target) { |
||||||
|
this.target = target; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
||||||
|
if (method.getName().equals("equals")) { |
||||||
|
// Only consider equal when proxies are identical.
|
||||||
|
return (proxy == args[0]); |
||||||
|
} |
||||||
|
else if (method.getName().equals("hashCode")) { |
||||||
|
// Use hashCode of Connection proxy.
|
||||||
|
return System.identityHashCode(proxy); |
||||||
|
} |
||||||
|
else if (method.getName().equals("close")) { |
||||||
|
// Handle close method: don't pass the call on.
|
||||||
|
return null; |
||||||
|
} |
||||||
|
try { |
||||||
|
return method.invoke(this.target, args); |
||||||
|
} |
||||||
|
catch (InvocationTargetException ex) { |
||||||
|
throw ex.getTargetException(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,165 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.connection; |
||||||
|
|
||||||
|
import java.lang.reflect.InvocationHandler; |
||||||
|
import java.lang.reflect.InvocationTargetException; |
||||||
|
import java.lang.reflect.Method; |
||||||
|
import java.lang.reflect.Proxy; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Connection; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
|
||||||
|
/** |
||||||
|
* Proxy for a target CCI {@link javax.resource.cci.ConnectionFactory}, adding |
||||||
|
* awareness of Spring-managed transactions. Similar to a transactional JNDI |
||||||
|
* ConnectionFactory as provided by a J2EE server. |
||||||
|
* |
||||||
|
* <p>Data access code that should remain unaware of Spring's data access support |
||||||
|
* can work with this proxy to seamlessly participate in Spring-managed transactions. |
||||||
|
* Note that the transaction manager, for example the {@link CciLocalTransactionManager}, |
||||||
|
* still needs to work with underlying ConnectionFactory, <i>not</i> with this proxy. |
||||||
|
* |
||||||
|
* <p><b>Make sure that TransactionAwareConnectionFactoryProxy is the outermost |
||||||
|
* ConnectionFactory of a chain of ConnectionFactory proxies/adapters.</b> |
||||||
|
* TransactionAwareConnectionFactoryProxy can delegate either directly to the |
||||||
|
* target connection pool or to some intermediate proxy/adapter like |
||||||
|
* {@link ConnectionSpecConnectionFactoryAdapter}. |
||||||
|
* |
||||||
|
* <p>Delegates to {@link ConnectionFactoryUtils} for automatically participating in |
||||||
|
* thread-bound transactions, for example managed by {@link CciLocalTransactionManager}. |
||||||
|
* {@code getConnection} calls and {@code close} calls on returned Connections |
||||||
|
* will behave properly within a transaction, i.e. always operate on the transactional |
||||||
|
* Connection. If not within a transaction, normal ConnectionFactory behavior applies. |
||||||
|
* |
||||||
|
* <p>This proxy allows data access code to work with the plain JCA CCI API and still |
||||||
|
* participate in Spring-managed transactions, similar to CCI code in a J2EE/JTA |
||||||
|
* environment. However, if possible, use Spring's ConnectionFactoryUtils, CciTemplate or |
||||||
|
* CCI operation objects to get transaction participation even without a proxy for |
||||||
|
* the target ConnectionFactory, avoiding the need to define such a proxy in the first place. |
||||||
|
* |
||||||
|
* <p><b>NOTE:</b> This ConnectionFactory proxy needs to return wrapped Connections |
||||||
|
* in order to handle close calls properly. Therefore, the returned Connections cannot |
||||||
|
* be cast to a native CCI Connection type or to a connection pool implementation type. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see javax.resource.cci.ConnectionFactory#getConnection |
||||||
|
* @see javax.resource.cci.Connection#close |
||||||
|
* @see ConnectionFactoryUtils#doGetConnection |
||||||
|
* @see ConnectionFactoryUtils#doReleaseConnection |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class TransactionAwareConnectionFactoryProxy extends DelegatingConnectionFactory { |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new TransactionAwareConnectionFactoryProxy. |
||||||
|
* @see #setTargetConnectionFactory |
||||||
|
*/ |
||||||
|
public TransactionAwareConnectionFactoryProxy() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new TransactionAwareConnectionFactoryProxy. |
||||||
|
* @param targetConnectionFactory the target ConnectionFactory |
||||||
|
*/ |
||||||
|
public TransactionAwareConnectionFactoryProxy(ConnectionFactory targetConnectionFactory) { |
||||||
|
setTargetConnectionFactory(targetConnectionFactory); |
||||||
|
afterPropertiesSet(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Delegate to ConnectionFactoryUtils for automatically participating in Spring-managed |
||||||
|
* transactions. Throws the original ResourceException, if any. |
||||||
|
* @return a transactional Connection if any, a new one else |
||||||
|
* @see com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils#doGetConnection |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public Connection getConnection() throws ResourceException { |
||||||
|
Connection con = ConnectionFactoryUtils.doGetConnection(getTargetConnectionFactory()); |
||||||
|
return getTransactionAwareConnectionProxy(con, getTargetConnectionFactory()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Wrap the given Connection with a proxy that delegates every method call to it |
||||||
|
* but delegates {@code close} calls to ConnectionFactoryUtils. |
||||||
|
* @param target the original Connection to wrap |
||||||
|
* @param cf ConnectionFactory that the Connection came from |
||||||
|
* @return the wrapped Connection |
||||||
|
* @see javax.resource.cci.Connection#close() |
||||||
|
* @see ConnectionFactoryUtils#doReleaseConnection |
||||||
|
*/ |
||||||
|
protected Connection getTransactionAwareConnectionProxy(Connection target, ConnectionFactory cf) { |
||||||
|
return (Connection) Proxy.newProxyInstance( |
||||||
|
Connection.class.getClassLoader(), |
||||||
|
new Class<?>[] {Connection.class}, |
||||||
|
new TransactionAwareInvocationHandler(target, cf)); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Invocation handler that delegates close calls on CCI Connections |
||||||
|
* to ConnectionFactoryUtils for being aware of thread-bound transactions. |
||||||
|
*/ |
||||||
|
private static class TransactionAwareInvocationHandler implements InvocationHandler { |
||||||
|
|
||||||
|
private final Connection target; |
||||||
|
|
||||||
|
private final ConnectionFactory connectionFactory; |
||||||
|
|
||||||
|
public TransactionAwareInvocationHandler(Connection target, ConnectionFactory cf) { |
||||||
|
this.target = target; |
||||||
|
this.connectionFactory = cf; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
||||||
|
// Invocation on Connection interface coming in...
|
||||||
|
|
||||||
|
if (method.getName().equals("equals")) { |
||||||
|
// Only consider equal when proxies are identical.
|
||||||
|
return (proxy == args[0]); |
||||||
|
} |
||||||
|
else if (method.getName().equals("hashCode")) { |
||||||
|
// Use hashCode of Connection proxy.
|
||||||
|
return System.identityHashCode(proxy); |
||||||
|
} |
||||||
|
else if (method.getName().equals("getLocalTransaction")) { |
||||||
|
if (ConnectionFactoryUtils.isConnectionTransactional(this.target, this.connectionFactory)) { |
||||||
|
throw new javax.resource.spi.IllegalStateException( |
||||||
|
"Local transaction handling not allowed within a managed transaction"); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (method.getName().equals("close")) { |
||||||
|
// Handle close method: only close if not within a transaction.
|
||||||
|
ConnectionFactoryUtils.doReleaseConnection(this.target, this.connectionFactory); |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
// Invoke method on target Connection.
|
||||||
|
try { |
||||||
|
return method.invoke(this.target, args); |
||||||
|
} |
||||||
|
catch (InvocationTargetException ex) { |
||||||
|
throw ex.getTargetException(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,10 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Provides a utility class for easy ConnectionFactory access, |
||||||
|
* a PlatformTransactionManager for local CCI transactions, |
||||||
|
* and various simple ConnectionFactory proxies/adapters. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.jca.cci.connection; |
||||||
|
|
@ -0,0 +1,121 @@ |
|||||||
|
/* |
||||||
|
* 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.core; |
||||||
|
|
||||||
|
import javax.resource.cci.InteractionSpec; |
||||||
|
import javax.resource.cci.Record; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Interface that specifies a basic set of CCI operations on an EIS. |
||||||
|
* Implemented by CciTemplate. Not often used, but a useful option |
||||||
|
* to enhance testability, as it can easily be mocked or stubbed. |
||||||
|
* |
||||||
|
* <p>Alternatively, the standard CCI infrastructure can be mocked. |
||||||
|
* However, mocking this interface constitutes significantly less work. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see CciTemplate |
||||||
|
*/ |
||||||
|
public interface CciOperations { |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute a request on an EIS with CCI, implemented as callback action |
||||||
|
* working on a CCI Connection. This allows for implementing arbitrary |
||||||
|
* data access operations, within Spring's managed CCI environment: |
||||||
|
* that is, participating in Spring-managed transactions and converting |
||||||
|
* JCA ResourceExceptions into Spring's DataAccessException hierarchy. |
||||||
|
* <p>The callback action can return a result object, for example a |
||||||
|
* domain object or a collection of domain objects. |
||||||
|
* @param action the callback object that specifies the action |
||||||
|
* @return the result object returned by the action, if any |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
*/ |
||||||
|
<T> T execute(ConnectionCallback<T> action) throws DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute a request on an EIS with CCI, implemented as callback action |
||||||
|
* working on a CCI Interaction. This allows for implementing arbitrary |
||||||
|
* data access operations on a single Interaction, within Spring's managed |
||||||
|
* CCI environment: that is, participating in Spring-managed transactions |
||||||
|
* and converting JCA ResourceExceptions into Spring's DataAccessException |
||||||
|
* hierarchy. |
||||||
|
* <p>The callback action can return a result object, for example a |
||||||
|
* domain object or a collection of domain objects. |
||||||
|
* @param action the callback object that specifies the action |
||||||
|
* @return the result object returned by the action, if any |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
*/ |
||||||
|
<T> T execute(InteractionCallback<T> action) throws DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the specified interaction on an EIS with CCI. |
||||||
|
* @param spec the CCI InteractionSpec instance that defines |
||||||
|
* the interaction (connector-specific) |
||||||
|
* @param inputRecord the input record |
||||||
|
* @return the output record |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
*/ |
||||||
|
Record execute(InteractionSpec spec, Record inputRecord) throws DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the specified interaction on an EIS with CCI. |
||||||
|
* @param spec the CCI InteractionSpec instance that defines |
||||||
|
* the interaction (connector-specific) |
||||||
|
* @param inputRecord the input record |
||||||
|
* @param outputRecord the output record |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
*/ |
||||||
|
void execute(InteractionSpec spec, Record inputRecord, Record outputRecord) throws DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the specified interaction on an EIS with CCI. |
||||||
|
* @param spec the CCI InteractionSpec instance that defines |
||||||
|
* the interaction (connector-specific) |
||||||
|
* @param inputCreator object that creates the input record to use |
||||||
|
* @return the output record |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
*/ |
||||||
|
Record execute(InteractionSpec spec, RecordCreator inputCreator) throws DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the specified interaction on an EIS with CCI. |
||||||
|
* @param spec the CCI InteractionSpec instance that defines |
||||||
|
* the interaction (connector-specific) |
||||||
|
* @param inputRecord the input record |
||||||
|
* @param outputExtractor object to convert the output record to a result object |
||||||
|
* @return the output data extracted with the RecordExtractor object |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
*/ |
||||||
|
<T> T execute(InteractionSpec spec, Record inputRecord, RecordExtractor<T> outputExtractor) |
||||||
|
throws DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the specified interaction on an EIS with CCI. |
||||||
|
* @param spec the CCI InteractionSpec instance that defines |
||||||
|
* the interaction (connector-specific) |
||||||
|
* @param inputCreator object that creates the input record to use |
||||||
|
* @param outputExtractor object to convert the output record to a result object |
||||||
|
* @return the output data extracted with the RecordExtractor object |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
*/ |
||||||
|
<T> T execute(InteractionSpec spec, RecordCreator inputCreator, RecordExtractor<T> outputExtractor) |
||||||
|
throws DataAccessException; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,439 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.core; |
||||||
|
|
||||||
|
import java.sql.SQLException; |
||||||
|
import javax.resource.NotSupportedException; |
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Connection; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.ConnectionSpec; |
||||||
|
import javax.resource.cci.IndexedRecord; |
||||||
|
import javax.resource.cci.Interaction; |
||||||
|
import javax.resource.cci.InteractionSpec; |
||||||
|
import javax.resource.cci.MappedRecord; |
||||||
|
import javax.resource.cci.Record; |
||||||
|
import javax.resource.cci.RecordFactory; |
||||||
|
import javax.resource.cci.ResultSet; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
import com.fr.third.springframework.dao.DataAccessResourceFailureException; |
||||||
|
import com.fr.third.springframework.jca.cci.CannotCreateRecordException; |
||||||
|
import com.fr.third.springframework.jca.cci.CciOperationNotSupportedException; |
||||||
|
import com.fr.third.springframework.jca.cci.InvalidResultSetAccessException; |
||||||
|
import com.fr.third.springframework.jca.cci.RecordTypeNotSupportedException; |
||||||
|
import com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils; |
||||||
|
import com.fr.third.springframework.jca.cci.connection.NotSupportedRecordFactory; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* <b>This is the central class in the CCI core package.</b> |
||||||
|
* It simplifies the use of CCI and helps to avoid common errors. |
||||||
|
* It executes core CCI workflow, leaving application code to provide parameters |
||||||
|
* to CCI and extract results. This class executes EIS queries or updates, |
||||||
|
* catching ResourceExceptions and translating them to the generic exception |
||||||
|
* hierarchy defined in the {@code com.fr.third.springframework.dao} package. |
||||||
|
* |
||||||
|
* <p>Code using this class can pass in and receive {@link javax.resource.cci.Record} |
||||||
|
* instances, or alternatively implement callback interfaces for creating input |
||||||
|
* Records and extracting result objects from output Records (or CCI ResultSets). |
||||||
|
* |
||||||
|
* <p>Can be used within a service implementation via direct instantiation |
||||||
|
* with a ConnectionFactory reference, or get prepared in an application context |
||||||
|
* and given to services as bean reference. Note: The ConnectionFactory should |
||||||
|
* always be configured as a bean in the application context, in the first case |
||||||
|
* given to the service directly, in the second case to the prepared template. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see RecordCreator |
||||||
|
* @see RecordExtractor |
||||||
|
*/ |
||||||
|
public class CciTemplate implements CciOperations { |
||||||
|
|
||||||
|
private final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
private ConnectionFactory connectionFactory; |
||||||
|
|
||||||
|
private ConnectionSpec connectionSpec; |
||||||
|
|
||||||
|
private RecordCreator outputRecordCreator; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Construct a new CciTemplate for bean usage. |
||||||
|
* <p>Note: The ConnectionFactory has to be set before using the instance. |
||||||
|
* @see #setConnectionFactory |
||||||
|
*/ |
||||||
|
public CciTemplate() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Construct a new CciTemplate, given a ConnectionFactory to obtain Connections from. |
||||||
|
* Note: This will trigger eager initialization of the exception translator. |
||||||
|
* @param connectionFactory JCA ConnectionFactory to obtain Connections from |
||||||
|
*/ |
||||||
|
public CciTemplate(ConnectionFactory connectionFactory) { |
||||||
|
setConnectionFactory(connectionFactory); |
||||||
|
afterPropertiesSet(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Construct a new CciTemplate, given a ConnectionFactory to obtain Connections from. |
||||||
|
* Note: This will trigger eager initialization of the exception translator. |
||||||
|
* @param connectionFactory JCA ConnectionFactory to obtain Connections from |
||||||
|
* @param connectionSpec the CCI ConnectionSpec to obtain Connections for |
||||||
|
* (may be {@code null}) |
||||||
|
*/ |
||||||
|
public CciTemplate(ConnectionFactory connectionFactory, ConnectionSpec connectionSpec) { |
||||||
|
setConnectionFactory(connectionFactory); |
||||||
|
setConnectionSpec(connectionSpec); |
||||||
|
afterPropertiesSet(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the CCI ConnectionFactory to obtain Connections from. |
||||||
|
*/ |
||||||
|
public void setConnectionFactory(ConnectionFactory connectionFactory) { |
||||||
|
this.connectionFactory = connectionFactory; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the CCI ConnectionFactory used by this template. |
||||||
|
*/ |
||||||
|
public ConnectionFactory getConnectionFactory() { |
||||||
|
return this.connectionFactory; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the CCI ConnectionSpec that this template instance is |
||||||
|
* supposed to obtain Connections for. |
||||||
|
*/ |
||||||
|
public void setConnectionSpec(ConnectionSpec connectionSpec) { |
||||||
|
this.connectionSpec = connectionSpec; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the CCI ConnectionSpec used by this template, if any. |
||||||
|
*/ |
||||||
|
public ConnectionSpec getConnectionSpec() { |
||||||
|
return this.connectionSpec; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set a RecordCreator that should be used for creating default output Records. |
||||||
|
* <p>Default is none: When no explicit output Record gets passed into an |
||||||
|
* {@code execute} method, CCI's {@code Interaction.execute} variant |
||||||
|
* that returns an output Record will be called. |
||||||
|
* <p>Specify a RecordCreator here if you always need to call CCI's |
||||||
|
* {@code Interaction.execute} variant with a passed-in output Record. |
||||||
|
* Unless there is an explicitly specified output Record, CciTemplate will |
||||||
|
* then invoke this RecordCreator to create a default output Record instance. |
||||||
|
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record) |
||||||
|
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record) |
||||||
|
*/ |
||||||
|
public void setOutputRecordCreator(RecordCreator creator) { |
||||||
|
this.outputRecordCreator = creator; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a RecordCreator that should be used for creating default output Records. |
||||||
|
*/ |
||||||
|
public RecordCreator getOutputRecordCreator() { |
||||||
|
return this.outputRecordCreator; |
||||||
|
} |
||||||
|
|
||||||
|
public void afterPropertiesSet() { |
||||||
|
if (getConnectionFactory() == null) { |
||||||
|
throw new IllegalArgumentException("Property 'connectionFactory' is required"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a template derived from this template instance, |
||||||
|
* inheriting the ConnectionFactory and other settings but |
||||||
|
* overriding the ConnectionSpec used for obtaining Connections. |
||||||
|
* @param connectionSpec the CCI ConnectionSpec that the derived template |
||||||
|
* instance is supposed to obtain Connections for |
||||||
|
* @return the derived template instance |
||||||
|
* @see #setConnectionSpec |
||||||
|
*/ |
||||||
|
public CciTemplate getDerivedTemplate(ConnectionSpec connectionSpec) { |
||||||
|
CciTemplate derived = new CciTemplate(); |
||||||
|
derived.setConnectionFactory(getConnectionFactory()); |
||||||
|
derived.setConnectionSpec(connectionSpec); |
||||||
|
derived.setOutputRecordCreator(getOutputRecordCreator()); |
||||||
|
return derived; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> T execute(ConnectionCallback<T> action) throws DataAccessException { |
||||||
|
Assert.notNull(action, "Callback object must not be null"); |
||||||
|
Connection con = ConnectionFactoryUtils.getConnection(getConnectionFactory(), getConnectionSpec()); |
||||||
|
try { |
||||||
|
return action.doInConnection(con, getConnectionFactory()); |
||||||
|
} |
||||||
|
catch (NotSupportedException ex) { |
||||||
|
throw new CciOperationNotSupportedException("CCI operation not supported by connector", ex); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
throw new DataAccessResourceFailureException("CCI operation failed", ex); |
||||||
|
} |
||||||
|
catch (SQLException ex) { |
||||||
|
throw new InvalidResultSetAccessException("Parsing of CCI ResultSet failed", ex); |
||||||
|
} |
||||||
|
finally { |
||||||
|
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> T execute(final InteractionCallback<T> action) throws DataAccessException { |
||||||
|
Assert.notNull(action, "Callback object must not be null"); |
||||||
|
return execute(new ConnectionCallback<T>() { |
||||||
|
@Override |
||||||
|
public T doInConnection(Connection connection, ConnectionFactory connectionFactory) |
||||||
|
throws ResourceException, SQLException, DataAccessException { |
||||||
|
Interaction interaction = connection.createInteraction(); |
||||||
|
try { |
||||||
|
return action.doInInteraction(interaction, connectionFactory); |
||||||
|
} |
||||||
|
finally { |
||||||
|
closeInteraction(interaction); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Record execute(InteractionSpec spec, Record inputRecord) throws DataAccessException { |
||||||
|
return doExecute(spec, inputRecord, null, new SimpleRecordExtractor()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void execute(InteractionSpec spec, Record inputRecord, Record outputRecord) throws DataAccessException { |
||||||
|
doExecute(spec, inputRecord, outputRecord, null); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Record execute(InteractionSpec spec, RecordCreator inputCreator) throws DataAccessException { |
||||||
|
return doExecute(spec, createRecord(inputCreator), null, new SimpleRecordExtractor()); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> T execute(InteractionSpec spec, Record inputRecord, RecordExtractor<T> outputExtractor) |
||||||
|
throws DataAccessException { |
||||||
|
|
||||||
|
return doExecute(spec, inputRecord, null, outputExtractor); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> T execute(InteractionSpec spec, RecordCreator inputCreator, RecordExtractor<T> outputExtractor) |
||||||
|
throws DataAccessException { |
||||||
|
|
||||||
|
return doExecute(spec, createRecord(inputCreator), null, outputExtractor); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the specified interaction on an EIS with CCI. |
||||||
|
* All other interaction execution methods go through this. |
||||||
|
* @param spec the CCI InteractionSpec instance that defines |
||||||
|
* the interaction (connector-specific) |
||||||
|
* @param inputRecord the input record |
||||||
|
* @param outputRecord output record (can be {@code null}) |
||||||
|
* @param outputExtractor object to convert the output record to a result object |
||||||
|
* @return the output data extracted with the RecordExtractor object |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
*/ |
||||||
|
protected <T> T doExecute( |
||||||
|
final InteractionSpec spec, final Record inputRecord, final Record outputRecord, |
||||||
|
final RecordExtractor<T> outputExtractor) throws DataAccessException { |
||||||
|
|
||||||
|
return execute(new InteractionCallback<T>() { |
||||||
|
@Override |
||||||
|
public T doInInteraction(Interaction interaction, ConnectionFactory connectionFactory) |
||||||
|
throws ResourceException, SQLException, DataAccessException { |
||||||
|
Record outputRecordToUse = outputRecord; |
||||||
|
try { |
||||||
|
if (outputRecord != null || getOutputRecordCreator() != null) { |
||||||
|
// Use the CCI execute method with output record as parameter.
|
||||||
|
if (outputRecord == null) { |
||||||
|
RecordFactory recordFactory = getRecordFactory(connectionFactory); |
||||||
|
outputRecordToUse = getOutputRecordCreator().createRecord(recordFactory); |
||||||
|
} |
||||||
|
interaction.execute(spec, inputRecord, outputRecordToUse); |
||||||
|
} |
||||||
|
else { |
||||||
|
outputRecordToUse = interaction.execute(spec, inputRecord); |
||||||
|
} |
||||||
|
return (outputExtractor != null ? outputExtractor.extractData(outputRecordToUse) : null); |
||||||
|
} |
||||||
|
finally { |
||||||
|
if (outputRecordToUse instanceof ResultSet) { |
||||||
|
closeResultSet((ResultSet) outputRecordToUse); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create an indexed Record through the ConnectionFactory's RecordFactory. |
||||||
|
* @param name the name of the record |
||||||
|
* @return the Record |
||||||
|
* @throws DataAccessException if creation of the Record failed |
||||||
|
* @see #getRecordFactory(javax.resource.cci.ConnectionFactory) |
||||||
|
* @see javax.resource.cci.RecordFactory#createIndexedRecord(String) |
||||||
|
*/ |
||||||
|
public IndexedRecord createIndexedRecord(String name) throws DataAccessException { |
||||||
|
try { |
||||||
|
RecordFactory recordFactory = getRecordFactory(getConnectionFactory()); |
||||||
|
return recordFactory.createIndexedRecord(name); |
||||||
|
} |
||||||
|
catch (NotSupportedException ex) { |
||||||
|
throw new RecordTypeNotSupportedException("Creation of indexed Record not supported by connector", ex); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
throw new CannotCreateRecordException("Creation of indexed Record failed", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a mapped Record from the ConnectionFactory's RecordFactory. |
||||||
|
* @param name record name |
||||||
|
* @return the Record |
||||||
|
* @throws DataAccessException if creation of the Record failed |
||||||
|
* @see #getRecordFactory(javax.resource.cci.ConnectionFactory) |
||||||
|
* @see javax.resource.cci.RecordFactory#createMappedRecord(String) |
||||||
|
*/ |
||||||
|
public MappedRecord createMappedRecord(String name) throws DataAccessException { |
||||||
|
try { |
||||||
|
RecordFactory recordFactory = getRecordFactory(getConnectionFactory()); |
||||||
|
return recordFactory.createMappedRecord(name); |
||||||
|
} |
||||||
|
catch (NotSupportedException ex) { |
||||||
|
throw new RecordTypeNotSupportedException("Creation of mapped Record not supported by connector", ex); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
throw new CannotCreateRecordException("Creation of mapped Record failed", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Invoke the given RecordCreator, converting JCA ResourceExceptions |
||||||
|
* to Spring's DataAccessException hierarchy. |
||||||
|
* @param recordCreator the RecordCreator to invoke |
||||||
|
* @return the created Record |
||||||
|
* @throws DataAccessException if creation of the Record failed |
||||||
|
* @see #getRecordFactory(javax.resource.cci.ConnectionFactory) |
||||||
|
* @see RecordCreator#createRecord(javax.resource.cci.RecordFactory) |
||||||
|
*/ |
||||||
|
protected Record createRecord(RecordCreator recordCreator) throws DataAccessException { |
||||||
|
try { |
||||||
|
RecordFactory recordFactory = getRecordFactory(getConnectionFactory()); |
||||||
|
return recordCreator.createRecord(recordFactory); |
||||||
|
} |
||||||
|
catch (NotSupportedException ex) { |
||||||
|
throw new RecordTypeNotSupportedException( |
||||||
|
"Creation of the desired Record type not supported by connector", ex); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
throw new CannotCreateRecordException("Creation of the desired Record failed", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a RecordFactory for the given ConnectionFactory. |
||||||
|
* <p>Default implementation returns the connector's RecordFactory if |
||||||
|
* available, falling back to a NotSupportedRecordFactory placeholder. |
||||||
|
* This allows to invoke a RecordCreator callback with a non-null |
||||||
|
* RecordFactory reference in any case. |
||||||
|
* @param connectionFactory the CCI ConnectionFactory |
||||||
|
* @return the CCI RecordFactory for the ConnectionFactory |
||||||
|
* @throws ResourceException if thrown by CCI methods |
||||||
|
* @see com.fr.third.springframework.jca.cci.connection.NotSupportedRecordFactory |
||||||
|
*/ |
||||||
|
protected RecordFactory getRecordFactory(ConnectionFactory connectionFactory) throws ResourceException { |
||||||
|
try { |
||||||
|
return connectionFactory.getRecordFactory(); |
||||||
|
} |
||||||
|
catch (NotSupportedException ex) { |
||||||
|
return new NotSupportedRecordFactory(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Close the given CCI Interaction and ignore any thrown exception. |
||||||
|
* This is useful for typical finally blocks in manual CCI code. |
||||||
|
* @param interaction the CCI Interaction to close |
||||||
|
* @see javax.resource.cci.Interaction#close() |
||||||
|
*/ |
||||||
|
private void closeInteraction(Interaction interaction) { |
||||||
|
if (interaction != null) { |
||||||
|
try { |
||||||
|
interaction.close(); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
logger.trace("Could not close CCI Interaction", ex); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
// We don't trust the CCI driver: It might throw RuntimeException or Error.
|
||||||
|
logger.trace("Unexpected exception on closing CCI Interaction", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Close the given CCI ResultSet and ignore any thrown exception. |
||||||
|
* This is useful for typical finally blocks in manual CCI code. |
||||||
|
* @param resultSet the CCI ResultSet to close |
||||||
|
* @see javax.resource.cci.ResultSet#close() |
||||||
|
*/ |
||||||
|
private void closeResultSet(ResultSet resultSet) { |
||||||
|
if (resultSet != null) { |
||||||
|
try { |
||||||
|
resultSet.close(); |
||||||
|
} |
||||||
|
catch (SQLException ex) { |
||||||
|
logger.trace("Could not close CCI ResultSet", ex); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
// We don't trust the CCI driver: It might throw RuntimeException or Error.
|
||||||
|
logger.trace("Unexpected exception on closing CCI ResultSet", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
private static class SimpleRecordExtractor implements RecordExtractor<Record> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public Record extractData(Record record) { |
||||||
|
return record; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,79 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.core; |
||||||
|
|
||||||
|
import java.sql.SQLException; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Connection; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Generic callback interface for code that operates on a CCI Connection. |
||||||
|
* Allows to execute any number of operations on a single Connection, |
||||||
|
* using any type and number of Interaction. |
||||||
|
* |
||||||
|
* <p>This is particularly useful for delegating to existing data access code |
||||||
|
* that expects a Connection to work on and throws ResourceException. For newly |
||||||
|
* written code, it is strongly recommended to use CciTemplate's more specific |
||||||
|
* {@code execute} variants. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see CciTemplate#execute(ConnectionCallback) |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, javax.resource.cci.Record) |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor) |
||||||
|
*/ |
||||||
|
public interface ConnectionCallback<T> { |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets called by {@code CciTemplate.execute} with an active CCI Connection. |
||||||
|
* Does not need to care about activating or closing the Connection, or handling |
||||||
|
* transactions. |
||||||
|
* |
||||||
|
* <p>If called without a thread-bound CCI transaction (initiated by |
||||||
|
* CciLocalTransactionManager), the code will simply get executed on the CCI |
||||||
|
* Connection with its transactional semantics. If CciTemplate is configured |
||||||
|
* to use a JTA-aware ConnectionFactory, the CCI Connection and thus the callback |
||||||
|
* code will be transactional if a JTA transaction is active. |
||||||
|
* |
||||||
|
* <p>Allows for returning a result object created within the callback, i.e. |
||||||
|
* a domain object or a collection of domain objects. Note that there's special |
||||||
|
* support for single step actions: see the {@code CciTemplate.execute} |
||||||
|
* variants. A thrown RuntimeException is treated as application exception: |
||||||
|
* it gets propagated to the caller of the template. |
||||||
|
* |
||||||
|
* @param connection active CCI Connection |
||||||
|
* @param connectionFactory the CCI ConnectionFactory that the Connection was |
||||||
|
* created with (gives access to RecordFactory and ResourceAdapterMetaData) |
||||||
|
* @return a result object, or {@code null} if none |
||||||
|
* @throws ResourceException if thrown by a CCI method, to be auto-converted |
||||||
|
* to a DataAccessException |
||||||
|
* @throws SQLException if thrown by a ResultSet method, to be auto-converted |
||||||
|
* to a DataAccessException |
||||||
|
* @throws DataAccessException in case of custom exceptions |
||||||
|
* @see javax.resource.cci.ConnectionFactory#getRecordFactory() |
||||||
|
* @see javax.resource.cci.ConnectionFactory#getMetaData() |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor) |
||||||
|
*/ |
||||||
|
T doInConnection(Connection connection, ConnectionFactory connectionFactory) |
||||||
|
throws ResourceException, SQLException, DataAccessException; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,80 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.core; |
||||||
|
|
||||||
|
import java.sql.SQLException; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.Interaction; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Generic callback interface for code that operates on a CCI Interaction. |
||||||
|
* Allows to execute any number of operations on a single Interaction, for |
||||||
|
* example a single execute call or repeated execute calls with varying |
||||||
|
* parameters. |
||||||
|
* |
||||||
|
* <p>This is particularly useful for delegating to existing data access code |
||||||
|
* that expects an Interaction to work on and throws ResourceException. For newly |
||||||
|
* written code, it is strongly recommended to use CciTemplate's more specific |
||||||
|
* {@code execute} variants. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see CciTemplate#execute(InteractionCallback) |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, javax.resource.cci.Record) |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor) |
||||||
|
*/ |
||||||
|
public interface InteractionCallback<T> { |
||||||
|
|
||||||
|
/** |
||||||
|
* Gets called by {@code CciTemplate.execute} with an active CCI Interaction. |
||||||
|
* Does not need to care about activating or closing the Interaction, or |
||||||
|
* handling transactions. |
||||||
|
* |
||||||
|
* <p>If called without a thread-bound CCI transaction (initiated by |
||||||
|
* CciLocalTransactionManager), the code will simply get executed on the CCI |
||||||
|
* Interaction with its transactional semantics. If CciTemplate is configured |
||||||
|
* to use a JTA-aware ConnectionFactory, the CCI Interaction and thus the callback |
||||||
|
* code will be transactional if a JTA transaction is active. |
||||||
|
* |
||||||
|
* <p>Allows for returning a result object created within the callback, i.e. |
||||||
|
* a domain object or a collection of domain objects. Note that there's special |
||||||
|
* support for single step actions: see the {@code CciTemplate.execute} |
||||||
|
* variants. A thrown RuntimeException is treated as application exception: |
||||||
|
* it gets propagated to the caller of the template. |
||||||
|
* |
||||||
|
* @param interaction active CCI Interaction |
||||||
|
* @param connectionFactory the CCI ConnectionFactory that the Connection was |
||||||
|
* created with (gives access to RecordFactory and ResourceAdapterMetaData) |
||||||
|
* @return a result object, or {@code null} if none |
||||||
|
* @throws ResourceException if thrown by a CCI method, to be auto-converted |
||||||
|
* to a DataAccessException |
||||||
|
* @throws SQLException if thrown by a ResultSet method, to be auto-converted |
||||||
|
* to a DataAccessException |
||||||
|
* @throws DataAccessException in case of custom exceptions |
||||||
|
* @see javax.resource.cci.ConnectionFactory#getRecordFactory() |
||||||
|
* @see javax.resource.cci.ConnectionFactory#getMetaData() |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor) |
||||||
|
*/ |
||||||
|
T doInInteraction(Interaction interaction, ConnectionFactory connectionFactory) |
||||||
|
throws ResourceException, SQLException, DataAccessException; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,64 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.core; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Record; |
||||||
|
import javax.resource.cci.RecordFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Callback interface for creating a CCI Record instance, |
||||||
|
* usually based on the passed-in CCI RecordFactory. |
||||||
|
* |
||||||
|
* <p>Used for input Record creation in CciTemplate. Alternatively, |
||||||
|
* Record instances can be passed into CciTemplate's corresponding |
||||||
|
* {@code execute} methods directly, either instantiated manually |
||||||
|
* or created through CciTemplate's Record factory methods. |
||||||
|
* |
||||||
|
* <P>Also used for creating default output Records in CciTemplate. |
||||||
|
* This is useful when the JCA connector needs an explicit output Record |
||||||
|
* instance, but no output Records should be passed into CciTemplate's |
||||||
|
* {@code execute} methods. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator) |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor) |
||||||
|
* @see CciTemplate#createIndexedRecord(String) |
||||||
|
* @see CciTemplate#createMappedRecord(String) |
||||||
|
* @see CciTemplate#setOutputRecordCreator(RecordCreator) |
||||||
|
*/ |
||||||
|
public interface RecordCreator { |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a CCI Record instance, usually based on the passed-in CCI RecordFactory. |
||||||
|
* <p>For use as <i>input</i> creator with CciTemplate's {@code execute} methods, |
||||||
|
* this method should create a <i>populated</i> Record instance. For use as |
||||||
|
* <i>output</i> Record creator, it should return an <i>empty</i> Record instance. |
||||||
|
* @param recordFactory the CCI RecordFactory (never {@code null}, but not guaranteed to be |
||||||
|
* supported by the connector: its create methods might throw NotSupportedException) |
||||||
|
* @return the Record instance |
||||||
|
* @throws ResourceException if thrown by a CCI method, to be auto-converted |
||||||
|
* to a DataAccessException |
||||||
|
* @throws DataAccessException in case of custom exceptions |
||||||
|
*/ |
||||||
|
Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,63 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.core; |
||||||
|
|
||||||
|
import java.sql.SQLException; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.Record; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Callback interface for extracting a result object from a CCI Record instance. |
||||||
|
* |
||||||
|
* <p>Used for output object creation in CciTemplate. Alternatively, output |
||||||
|
* Records can also be returned to client code as-is. In case of a CCI ResultSet |
||||||
|
* as execution result, you will almost always want to implement a RecordExtractor, |
||||||
|
* to be able to read the ResultSet in a managed fashion, with the CCI Connection |
||||||
|
* still open while reading the ResultSet. |
||||||
|
* |
||||||
|
* <p>Implementations of this interface perform the actual work of extracting |
||||||
|
* results, but don't need to worry about exception handling. ResourceExceptions |
||||||
|
* will be caught and handled correctly by the CciTemplate class. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, Record, RecordExtractor) |
||||||
|
* @see CciTemplate#execute(javax.resource.cci.InteractionSpec, RecordCreator, RecordExtractor) |
||||||
|
* @see javax.resource.cci.ResultSet |
||||||
|
*/ |
||||||
|
public interface RecordExtractor<T> { |
||||||
|
|
||||||
|
/** |
||||||
|
* Process the data in the given Record, creating a corresponding result object. |
||||||
|
* @param record the Record to extract data from |
||||||
|
* (possibly a CCI ResultSet) |
||||||
|
* @return an arbitrary result object, or {@code null} if none |
||||||
|
* (the extractor will typically be stateful in the latter case) |
||||||
|
* @throws ResourceException if thrown by a CCI method, to be auto-converted |
||||||
|
* to a DataAccessException |
||||||
|
* @throws SQLException if thrown by a ResultSet method, to be auto-converted |
||||||
|
* to a DataAccessException |
||||||
|
* @throws DataAccessException in case of custom exceptions |
||||||
|
* @see javax.resource.cci.ResultSet |
||||||
|
*/ |
||||||
|
T extractData(Record record) throws ResourceException, SQLException, DataAccessException; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Provides the core JCA CCI support, based on CciTemplate |
||||||
|
* and its associated callback interfaces. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.jca.cci.core; |
||||||
|
|
@ -0,0 +1,138 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.core.support; |
||||||
|
|
||||||
|
import javax.resource.cci.Connection; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.ConnectionSpec; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.support.DaoSupport; |
||||||
|
import com.fr.third.springframework.jca.cci.CannotGetCciConnectionException; |
||||||
|
import com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils; |
||||||
|
import com.fr.third.springframework.jca.cci.core.CciTemplate; |
||||||
|
|
||||||
|
/** |
||||||
|
* Convenient super class for CCI-based data access objects. |
||||||
|
* |
||||||
|
* <p>Requires a {@link javax.resource.cci.ConnectionFactory} to be set, |
||||||
|
* providing a {@link com.fr.third.springframework.jca.cci.core.CciTemplate} based |
||||||
|
* on it to subclasses through the {@link #getCciTemplate()} method. |
||||||
|
* |
||||||
|
* <p>This base class is mainly intended for CciTemplate usage but can |
||||||
|
* also be used when working with a Connection directly or when using |
||||||
|
* {@code com.fr.third.springframework.jca.cci.object} classes. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see #setConnectionFactory |
||||||
|
* @see #getCciTemplate |
||||||
|
* @see com.fr.third.springframework.jca.cci.core.CciTemplate |
||||||
|
*/ |
||||||
|
public abstract class CciDaoSupport extends DaoSupport { |
||||||
|
|
||||||
|
private CciTemplate cciTemplate; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the ConnectionFactory to be used by this DAO. |
||||||
|
*/ |
||||||
|
public final void setConnectionFactory(ConnectionFactory connectionFactory) { |
||||||
|
if (this.cciTemplate == null || connectionFactory != this.cciTemplate.getConnectionFactory()) { |
||||||
|
this.cciTemplate = createCciTemplate(connectionFactory); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a CciTemplate for the given ConnectionFactory. |
||||||
|
* Only invoked if populating the DAO with a ConnectionFactory reference! |
||||||
|
* <p>Can be overridden in subclasses to provide a CciTemplate instance |
||||||
|
* with different configuration, or a custom CciTemplate subclass. |
||||||
|
* @param connectionFactory the CCI ConnectionFactory to create a CciTemplate for |
||||||
|
* @return the new CciTemplate instance |
||||||
|
* @see #setConnectionFactory(javax.resource.cci.ConnectionFactory) |
||||||
|
*/ |
||||||
|
protected CciTemplate createCciTemplate(ConnectionFactory connectionFactory) { |
||||||
|
return new CciTemplate(connectionFactory); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the ConnectionFactory used by this DAO. |
||||||
|
*/ |
||||||
|
public final ConnectionFactory getConnectionFactory() { |
||||||
|
return this.cciTemplate.getConnectionFactory(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the CciTemplate for this DAO explicitly, |
||||||
|
* as an alternative to specifying a ConnectionFactory. |
||||||
|
*/ |
||||||
|
public final void setCciTemplate(CciTemplate cciTemplate) { |
||||||
|
this.cciTemplate = cciTemplate; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the CciTemplate for this DAO, |
||||||
|
* pre-initialized with the ConnectionFactory or set explicitly. |
||||||
|
*/ |
||||||
|
public final CciTemplate getCciTemplate() { |
||||||
|
return this.cciTemplate; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected final void checkDaoConfig() { |
||||||
|
if (this.cciTemplate == null) { |
||||||
|
throw new IllegalArgumentException("'connectionFactory' or 'cciTemplate' is required"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Obtain a CciTemplate derived from the main template instance, |
||||||
|
* inheriting the ConnectionFactory and other settings but |
||||||
|
* overriding the ConnectionSpec used for obtaining Connections. |
||||||
|
* @param connectionSpec the CCI ConnectionSpec that the returned |
||||||
|
* template instance is supposed to obtain Connections for |
||||||
|
* @return the derived template instance |
||||||
|
* @see com.fr.third.springframework.jca.cci.core.CciTemplate#getDerivedTemplate(javax.resource.cci.ConnectionSpec) |
||||||
|
*/ |
||||||
|
protected final CciTemplate getCciTemplate(ConnectionSpec connectionSpec) { |
||||||
|
return getCciTemplate().getDerivedTemplate(connectionSpec); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Get a CCI Connection, either from the current transaction or a new one. |
||||||
|
* @return the CCI Connection |
||||||
|
* @throws com.fr.third.springframework.jca.cci.CannotGetCciConnectionException |
||||||
|
* if the attempt to get a Connection failed |
||||||
|
* @see com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils#getConnection(javax.resource.cci.ConnectionFactory) |
||||||
|
*/ |
||||||
|
protected final Connection getConnection() throws CannotGetCciConnectionException { |
||||||
|
return ConnectionFactoryUtils.getConnection(getConnectionFactory()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Close the given CCI Connection, created via this bean's ConnectionFactory, |
||||||
|
* if it isn't bound to the thread. |
||||||
|
* @param con Connection to close |
||||||
|
* @see com.fr.third.springframework.jca.cci.connection.ConnectionFactoryUtils#releaseConnection |
||||||
|
*/ |
||||||
|
protected final void releaseConnection(Connection con) { |
||||||
|
ConnectionFactoryUtils.releaseConnection(con, getConnectionFactory()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,104 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.core.support; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
import java.io.InputStream; |
||||||
|
import java.io.OutputStream; |
||||||
|
|
||||||
|
import javax.resource.cci.Record; |
||||||
|
import javax.resource.cci.Streamable; |
||||||
|
|
||||||
|
import com.fr.third.springframework.util.FileCopyUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* CCI Record implementation for a COMMAREA, holding a byte array. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see com.fr.third.springframework.jca.cci.object.MappingCommAreaOperation |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public class CommAreaRecord implements Record, Streamable { |
||||||
|
|
||||||
|
private byte[] bytes; |
||||||
|
|
||||||
|
private String recordName; |
||||||
|
|
||||||
|
private String recordShortDescription; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new CommAreaRecord. |
||||||
|
* @see #read(java.io.InputStream) |
||||||
|
*/ |
||||||
|
public CommAreaRecord() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new CommAreaRecord. |
||||||
|
* @param bytes the bytes to fill the record with |
||||||
|
*/ |
||||||
|
public CommAreaRecord(byte[] bytes) { |
||||||
|
this.bytes = bytes; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void setRecordName(String recordName) { |
||||||
|
this.recordName=recordName; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getRecordName() { |
||||||
|
return recordName; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void setRecordShortDescription(String recordShortDescription) { |
||||||
|
this.recordShortDescription=recordShortDescription; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public String getRecordShortDescription() { |
||||||
|
return recordShortDescription; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void read(InputStream in) throws IOException { |
||||||
|
this.bytes = FileCopyUtils.copyToByteArray(in); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void write(OutputStream out) throws IOException { |
||||||
|
out.write(this.bytes); |
||||||
|
out.flush(); |
||||||
|
} |
||||||
|
|
||||||
|
public byte[] toByteArray() { |
||||||
|
return this.bytes; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Object clone() { |
||||||
|
return new CommAreaRecord(this.bytes); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
/** |
||||||
|
* |
||||||
|
* Classes supporting the {@code com.fr.third.springframework.jca.cci.core} package. |
||||||
|
* Contains a DAO base class for CciTemplate usage. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.jca.cci.core.support; |
||||||
|
|
@ -0,0 +1,94 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.object; |
||||||
|
|
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.InteractionSpec; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.InitializingBean; |
||||||
|
import com.fr.third.springframework.jca.cci.core.CciTemplate; |
||||||
|
|
||||||
|
/** |
||||||
|
* Base class for EIS operation objects that work with the CCI API. |
||||||
|
* Encapsulates a CCI ConnectionFactory and a CCI InteractionSpec. |
||||||
|
* |
||||||
|
* <p>Works with a CciTemplate instance underneath. EIS operation objects |
||||||
|
* are an alternative to working with a CciTemplate directly. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see #setConnectionFactory |
||||||
|
* @see #setInteractionSpec |
||||||
|
*/ |
||||||
|
public abstract class EisOperation implements InitializingBean { |
||||||
|
|
||||||
|
private CciTemplate cciTemplate = new CciTemplate(); |
||||||
|
|
||||||
|
private InteractionSpec interactionSpec; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the CciTemplate to be used by this operation. |
||||||
|
* Alternatively, specify a CCI ConnectionFactory. |
||||||
|
* @see #setConnectionFactory |
||||||
|
*/ |
||||||
|
public void setCciTemplate(CciTemplate cciTemplate) { |
||||||
|
if (cciTemplate == null) { |
||||||
|
throw new IllegalArgumentException("cciTemplate must not be null"); |
||||||
|
} |
||||||
|
this.cciTemplate = cciTemplate; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the CciTemplate used by this operation. |
||||||
|
*/ |
||||||
|
public CciTemplate getCciTemplate() { |
||||||
|
return this.cciTemplate; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the CCI ConnectionFactory to be used by this operation. |
||||||
|
*/ |
||||||
|
public void setConnectionFactory(ConnectionFactory connectionFactory) { |
||||||
|
this.cciTemplate.setConnectionFactory(connectionFactory); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the CCI InteractionSpec for this operation. |
||||||
|
*/ |
||||||
|
public void setInteractionSpec(InteractionSpec interactionSpec) { |
||||||
|
this.interactionSpec = interactionSpec; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the CCI InteractionSpec for this operation. |
||||||
|
*/ |
||||||
|
public InteractionSpec getInteractionSpec() { |
||||||
|
return this.interactionSpec; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() { |
||||||
|
this.cciTemplate.afterPropertiesSet(); |
||||||
|
|
||||||
|
if (this.interactionSpec == null) { |
||||||
|
throw new IllegalArgumentException("interactionSpec is required"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,97 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.object; |
||||||
|
|
||||||
|
import java.io.IOException; |
||||||
|
|
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.InteractionSpec; |
||||||
|
import javax.resource.cci.Record; |
||||||
|
import javax.resource.cci.RecordFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
import com.fr.third.springframework.dao.DataRetrievalFailureException; |
||||||
|
import com.fr.third.springframework.jca.cci.core.support.CommAreaRecord; |
||||||
|
|
||||||
|
/** |
||||||
|
* EIS operation object for access to COMMAREA records. |
||||||
|
* Subclass of the generic MappingRecordOperation class. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @since 1.2 |
||||||
|
*/ |
||||||
|
public abstract class MappingCommAreaOperation extends MappingRecordOperation { |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MappingCommAreaQuery. |
||||||
|
* @see #setConnectionFactory |
||||||
|
* @see #setInteractionSpec |
||||||
|
*/ |
||||||
|
public MappingCommAreaOperation() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new MappingCommAreaQuery. |
||||||
|
* @param connectionFactory ConnectionFactory to use to obtain connections |
||||||
|
* @param interactionSpec specification to configure the interaction |
||||||
|
*/ |
||||||
|
public MappingCommAreaOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) { |
||||||
|
super(connectionFactory, interactionSpec); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected final Record createInputRecord(RecordFactory recordFactory, Object inObject) { |
||||||
|
try { |
||||||
|
return new CommAreaRecord(objectToBytes(inObject)); |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
throw new DataRetrievalFailureException("I/O exception during bytes conversion", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected final Object extractOutputData(Record record) throws DataAccessException { |
||||||
|
CommAreaRecord commAreaRecord = (CommAreaRecord) record; |
||||||
|
try { |
||||||
|
return bytesToObject(commAreaRecord.toByteArray()); |
||||||
|
} |
||||||
|
catch (IOException ex) { |
||||||
|
throw new DataRetrievalFailureException("I/O exception during bytes conversion", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Method used to convert an object into COMMAREA bytes. |
||||||
|
* @param inObject the input data |
||||||
|
* @return the COMMAREA's bytes |
||||||
|
* @throws IOException if thrown by I/O methods |
||||||
|
* @throws DataAccessException if conversion failed |
||||||
|
*/ |
||||||
|
protected abstract byte[] objectToBytes(Object inObject) throws IOException, DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Method used to convert the COMMAREA's bytes to an object. |
||||||
|
* @param bytes the COMMAREA's bytes |
||||||
|
* @return the output data |
||||||
|
* @throws IOException if thrown by I/O methods |
||||||
|
* @throws DataAccessException if conversion failed |
||||||
|
*/ |
||||||
|
protected abstract Object bytesToObject(byte[] bytes) throws IOException, DataAccessException; |
||||||
|
|
||||||
|
} |
@ -0,0 +1,151 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.object; |
||||||
|
|
||||||
|
import java.sql.SQLException; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.InteractionSpec; |
||||||
|
import javax.resource.cci.Record; |
||||||
|
import javax.resource.cci.RecordFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
import com.fr.third.springframework.jca.cci.core.RecordCreator; |
||||||
|
import com.fr.third.springframework.jca.cci.core.RecordExtractor; |
||||||
|
|
||||||
|
/** |
||||||
|
* EIS operation object that expects mapped input and output objects, |
||||||
|
* converting to and from CCI Records. |
||||||
|
* |
||||||
|
* <p>Concrete subclasses must implement the abstract |
||||||
|
* {@code createInputRecord(RecordFactory, Object)} and |
||||||
|
* {@code extractOutputData(Record)} methods, to create an input |
||||||
|
* Record from an object and to convert an output Record into an object, |
||||||
|
* respectively. |
||||||
|
* |
||||||
|
* @author Thierry Templier |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see #createInputRecord(javax.resource.cci.RecordFactory, Object) |
||||||
|
* @see #extractOutputData(javax.resource.cci.Record) |
||||||
|
*/ |
||||||
|
public abstract class MappingRecordOperation extends EisOperation { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor that allows use as a JavaBean. |
||||||
|
*/ |
||||||
|
public MappingRecordOperation() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Convenient constructor with ConnectionFactory and specifications |
||||||
|
* (connection and interaction). |
||||||
|
* @param connectionFactory ConnectionFactory to use to obtain connections |
||||||
|
*/ |
||||||
|
public MappingRecordOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) { |
||||||
|
getCciTemplate().setConnectionFactory(connectionFactory); |
||||||
|
setInteractionSpec(interactionSpec); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set a RecordCreator that should be used for creating default output Records. |
||||||
|
* <p>Default is none: CCI's {@code Interaction.execute} variant |
||||||
|
* that returns an output Record will be called. |
||||||
|
* <p>Specify a RecordCreator here if you always need to call CCI's |
||||||
|
* {@code Interaction.execute} variant with a passed-in output Record. |
||||||
|
* This RecordCreator will then be invoked to create a default output Record instance. |
||||||
|
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record) |
||||||
|
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record) |
||||||
|
* @see com.fr.third.springframework.jca.cci.core.CciTemplate#setOutputRecordCreator |
||||||
|
*/ |
||||||
|
public void setOutputRecordCreator(RecordCreator creator) { |
||||||
|
getCciTemplate().setOutputRecordCreator(creator); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the interaction encapsulated by this operation object. |
||||||
|
* @param inputObject the input data, to be converted to a Record |
||||||
|
* by the {@code createInputRecord} method |
||||||
|
* @return the output data extracted with the {@code extractOutputData} method |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
* @see #createInputRecord |
||||||
|
* @see #extractOutputData |
||||||
|
*/ |
||||||
|
public Object execute(Object inputObject) throws DataAccessException { |
||||||
|
return getCciTemplate().execute( |
||||||
|
getInteractionSpec(), new RecordCreatorImpl(inputObject), new RecordExtractorImpl()); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Subclasses must implement this method to generate an input Record |
||||||
|
* from an input object passed into the {@code execute} method. |
||||||
|
* @param inputObject the passed-in input object |
||||||
|
* @return the CCI input Record |
||||||
|
* @throws ResourceException if thrown by a CCI method, to be auto-converted |
||||||
|
* to a DataAccessException |
||||||
|
* @see #execute(Object) |
||||||
|
*/ |
||||||
|
protected abstract Record createInputRecord(RecordFactory recordFactory, Object inputObject) |
||||||
|
throws ResourceException, DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* Subclasses must implement this method to convert the Record returned |
||||||
|
* by CCI execution into a result object for the {@code execute} method. |
||||||
|
* @param outputRecord the Record returned by CCI execution |
||||||
|
* @return the result object |
||||||
|
* @throws ResourceException if thrown by a CCI method, to be auto-converted |
||||||
|
* to a DataAccessException |
||||||
|
* @see #execute(Object) |
||||||
|
*/ |
||||||
|
protected abstract Object extractOutputData(Record outputRecord) |
||||||
|
throws ResourceException, SQLException, DataAccessException; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Implementation of RecordCreator that calls the enclosing |
||||||
|
* class's {@code createInputRecord} method. |
||||||
|
*/ |
||||||
|
protected class RecordCreatorImpl implements RecordCreator { |
||||||
|
|
||||||
|
private final Object inputObject; |
||||||
|
|
||||||
|
public RecordCreatorImpl(Object inObject) { |
||||||
|
this.inputObject = inObject; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException { |
||||||
|
return createInputRecord(recordFactory, this.inputObject); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Implementation of RecordExtractor that calls the enclosing |
||||||
|
* class's {@code extractOutputData} method. |
||||||
|
*/ |
||||||
|
protected class RecordExtractorImpl implements RecordExtractor<Object> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object extractData(Record record) throws ResourceException, SQLException, DataAccessException { |
||||||
|
return extractOutputData(record); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,76 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.cci.object; |
||||||
|
|
||||||
|
import javax.resource.cci.ConnectionFactory; |
||||||
|
import javax.resource.cci.InteractionSpec; |
||||||
|
import javax.resource.cci.Record; |
||||||
|
|
||||||
|
import com.fr.third.springframework.dao.DataAccessException; |
||||||
|
|
||||||
|
/** |
||||||
|
* EIS operation object that accepts a passed-in CCI input Record |
||||||
|
* and returns a corresponding CCI output Record. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
*/ |
||||||
|
public class SimpleRecordOperation extends EisOperation { |
||||||
|
|
||||||
|
/** |
||||||
|
* Constructor that allows use as a JavaBean. |
||||||
|
*/ |
||||||
|
public SimpleRecordOperation() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Convenient constructor with ConnectionFactory and specifications |
||||||
|
* (connection and interaction). |
||||||
|
* @param connectionFactory ConnectionFactory to use to obtain connections |
||||||
|
*/ |
||||||
|
public SimpleRecordOperation(ConnectionFactory connectionFactory, InteractionSpec interactionSpec) { |
||||||
|
getCciTemplate().setConnectionFactory(connectionFactory); |
||||||
|
setInteractionSpec(interactionSpec); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the CCI interaction encapsulated by this operation object. |
||||||
|
* <p>This method will call CCI's {@code Interaction.execute} variant |
||||||
|
* that returns an output Record. |
||||||
|
* @param inputRecord the input record |
||||||
|
* @return the output record |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record) |
||||||
|
*/ |
||||||
|
public Record execute(Record inputRecord) throws DataAccessException { |
||||||
|
return getCciTemplate().execute(getInteractionSpec(), inputRecord); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the CCI interaction encapsulated by this operation object. |
||||||
|
* <p>This method will call CCI's {@code Interaction.execute} variant |
||||||
|
* with a passed-in output Record. |
||||||
|
* @param inputRecord the input record |
||||||
|
* @param outputRecord the output record |
||||||
|
* @throws DataAccessException if there is any problem |
||||||
|
* @see javax.resource.cci.Interaction#execute(javax.resource.cci.InteractionSpec, Record, Record) |
||||||
|
*/ |
||||||
|
public void execute(Record inputRecord, Record outputRecord) throws DataAccessException { |
||||||
|
getCciTemplate().execute(getInteractionSpec(), inputRecord, outputRecord); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,11 @@ |
|||||||
|
/** |
||||||
|
* |
||||||
|
* The classes in this package represent EIS operations as threadsafe, |
||||||
|
* reusable objects. This higher level of CCI abstraction depends on the |
||||||
|
* lower-level abstraction in the {@code com.fr.third.springframework.jca.cci.core} package. |
||||||
|
* Exceptions thrown are as in the {@code com.fr.third.springframework.dao} package, |
||||||
|
* meaning that code using this package does not need to worry about error handling. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.jca.cci.object; |
||||||
|
|
@ -0,0 +1,10 @@ |
|||||||
|
/** |
||||||
|
* |
||||||
|
* This package contains Spring's support for the Common Client Interface (CCI), |
||||||
|
* as defined by the J2EE Connector Architecture. It is conceptually similar |
||||||
|
* to the {@code com.fr.third.springframework.jdbc} package, providing the same |
||||||
|
* levels of data access abstraction. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.jca.cci; |
||||||
|
|
@ -0,0 +1,47 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.context; |
||||||
|
|
||||||
|
import javax.resource.spi.BootstrapContext; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.Aware; |
||||||
|
|
||||||
|
/** |
||||||
|
* Interface to be implemented by any object that wishes to be |
||||||
|
* notified of the BootstrapContext (typically determined by the |
||||||
|
* {@link ResourceAdapterApplicationContext}) that it runs in. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @author Chris Beams |
||||||
|
* @since 2.5 |
||||||
|
* @see javax.resource.spi.BootstrapContext |
||||||
|
*/ |
||||||
|
public interface BootstrapContextAware extends Aware { |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the BootstrapContext that this object runs in. |
||||||
|
* <p>Invoked after population of normal bean properties but before an init |
||||||
|
* callback like InitializingBean's {@code afterPropertiesSet} or a |
||||||
|
* custom init-method. Invoked after ApplicationContextAware's |
||||||
|
* {@code setApplicationContext}. |
||||||
|
* @param bootstrapContext BootstrapContext object to be used by this object |
||||||
|
* @see com.fr.third.springframework.beans.factory.InitializingBean#afterPropertiesSet |
||||||
|
* @see com.fr.third.springframework.context.ApplicationContextAware#setApplicationContext |
||||||
|
*/ |
||||||
|
void setBootstrapContext(BootstrapContext bootstrapContext); |
||||||
|
|
||||||
|
} |
@ -0,0 +1,62 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.context; |
||||||
|
|
||||||
|
import javax.resource.spi.BootstrapContext; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.BeansException; |
||||||
|
import com.fr.third.springframework.beans.factory.config.BeanPostProcessor; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link com.fr.third.springframework.beans.factory.config.BeanPostProcessor} |
||||||
|
* implementation that passes the BootstrapContext to beans that implement |
||||||
|
* the {@link BootstrapContextAware} interface. |
||||||
|
* |
||||||
|
* <p>{@link ResourceAdapterApplicationContext} automatically registers |
||||||
|
* this processor with its underlying bean factory. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.5 |
||||||
|
* @see BootstrapContextAware |
||||||
|
*/ |
||||||
|
class BootstrapContextAwareProcessor implements BeanPostProcessor { |
||||||
|
|
||||||
|
private final BootstrapContext bootstrapContext; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new BootstrapContextAwareProcessor for the given context. |
||||||
|
*/ |
||||||
|
public BootstrapContextAwareProcessor(BootstrapContext bootstrapContext) { |
||||||
|
this.bootstrapContext = bootstrapContext; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { |
||||||
|
if (this.bootstrapContext != null && bean instanceof BootstrapContextAware) { |
||||||
|
((BootstrapContextAware) bean).setBootstrapContext(this.bootstrapContext); |
||||||
|
} |
||||||
|
return bean; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { |
||||||
|
return bean; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,70 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.context; |
||||||
|
|
||||||
|
import javax.resource.spi.BootstrapContext; |
||||||
|
import javax.resource.spi.work.WorkManager; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.BeansException; |
||||||
|
import com.fr.third.springframework.beans.factory.ObjectFactory; |
||||||
|
import com.fr.third.springframework.beans.factory.config.ConfigurableListableBeanFactory; |
||||||
|
import com.fr.third.springframework.context.support.GenericApplicationContext; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link com.fr.third.springframework.context.ApplicationContext} implementation |
||||||
|
* for a JCA ResourceAdapter. Needs to be initialized with the JCA |
||||||
|
* {@link javax.resource.spi.BootstrapContext}, passing it on to |
||||||
|
* Spring-managed beans that implement {@link BootstrapContextAware}. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.5 |
||||||
|
* @see SpringContextResourceAdapter |
||||||
|
* @see BootstrapContextAware |
||||||
|
*/ |
||||||
|
public class ResourceAdapterApplicationContext extends GenericApplicationContext { |
||||||
|
|
||||||
|
private final BootstrapContext bootstrapContext; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new ResourceAdapterApplicationContext for the given BootstrapContext. |
||||||
|
* @param bootstrapContext the JCA BootstrapContext that the ResourceAdapter |
||||||
|
* has been started with |
||||||
|
*/ |
||||||
|
public ResourceAdapterApplicationContext(BootstrapContext bootstrapContext) { |
||||||
|
Assert.notNull(bootstrapContext, "BootstrapContext must not be null"); |
||||||
|
this.bootstrapContext = bootstrapContext; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { |
||||||
|
beanFactory.addBeanPostProcessor(new BootstrapContextAwareProcessor(this.bootstrapContext)); |
||||||
|
beanFactory.ignoreDependencyInterface(BootstrapContextAware.class); |
||||||
|
beanFactory.registerResolvableDependency(BootstrapContext.class, this.bootstrapContext); |
||||||
|
|
||||||
|
// JCA WorkManager resolved lazily - may not be available.
|
||||||
|
beanFactory.registerResolvableDependency(WorkManager.class, new ObjectFactory<WorkManager>() { |
||||||
|
@Override |
||||||
|
public WorkManager getObject() { |
||||||
|
return bootstrapContext.getWorkManager(); |
||||||
|
} |
||||||
|
}); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,250 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2013 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.context; |
||||||
|
|
||||||
|
import javax.resource.NotSupportedException; |
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.spi.ActivationSpec; |
||||||
|
import javax.resource.spi.BootstrapContext; |
||||||
|
import javax.resource.spi.ResourceAdapter; |
||||||
|
import javax.resource.spi.ResourceAdapterInternalException; |
||||||
|
import javax.resource.spi.endpoint.MessageEndpointFactory; |
||||||
|
import javax.transaction.xa.XAResource; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.support.BeanDefinitionRegistry; |
||||||
|
import com.fr.third.springframework.beans.factory.xml.XmlBeanDefinitionReader; |
||||||
|
import com.fr.third.springframework.context.ConfigurableApplicationContext; |
||||||
|
import com.fr.third.springframework.core.env.ConfigurableEnvironment; |
||||||
|
import com.fr.third.springframework.core.env.StandardEnvironment; |
||||||
|
import com.fr.third.springframework.util.ObjectUtils; |
||||||
|
import com.fr.third.springframework.util.StringUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* JCA 1.5 {@link javax.resource.spi.ResourceAdapter} implementation |
||||||
|
* that loads a Spring {@link com.fr.third.springframework.context.ApplicationContext}, |
||||||
|
* starting and stopping Spring-managed beans as part of the ResourceAdapter's |
||||||
|
* lifecycle. |
||||||
|
* |
||||||
|
* <p>Ideal for application contexts that do not need any HTTP entry points |
||||||
|
* but rather just consist of message endpoints and scheduled jobs etc. |
||||||
|
* Beans in such a context may use application server resources such as the |
||||||
|
* JTA transaction manager and JNDI-bound JDBC DataSources and JMS |
||||||
|
* ConnectionFactory instances, and may also register with the platform's |
||||||
|
* JMX server - all through Spring's standard transaction management and |
||||||
|
* JNDI and JMX support facilities. |
||||||
|
* |
||||||
|
* <p>If the need for scheduling asynchronous work arises, consider using |
||||||
|
* Spring's {@link com.fr.third.springframework.jca.work.WorkManagerTaskExecutor} |
||||||
|
* as a standard bean definition, to be injected into application beans |
||||||
|
* through dependency injection. This WorkManagerTaskExecutor will automatically |
||||||
|
* use the JCA WorkManager from the BootstrapContext that has been provided |
||||||
|
* to this ResourceAdapter. |
||||||
|
* |
||||||
|
* <p>The JCA {@link javax.resource.spi.BootstrapContext} may also be |
||||||
|
* accessed directly, through application components that implement the |
||||||
|
* {@link BootstrapContextAware} interface. When deployed using this |
||||||
|
* ResourceAdapter, the BootstrapContext is guaranteed to be passed on |
||||||
|
* to such components. |
||||||
|
* |
||||||
|
* <p>This ResourceAdapter is to be defined in a "META-INF/ra.xml" file |
||||||
|
* within a J2EE ".rar" deployment unit like as follows: |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* <?xml version="1.0" encoding="UTF-8"?> |
||||||
|
* <connector xmlns="http://java.sun.com/xml/ns/j2ee" |
||||||
|
* xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
* xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd" |
||||||
|
* version="1.5"> |
||||||
|
* <vendor-name>Spring Framework</vendor-name> |
||||||
|
* <eis-type>Spring Connector</eis-type> |
||||||
|
* <resourceadapter-version>1.0</resourceadapter-version> |
||||||
|
* <resourceadapter> |
||||||
|
* <resourceadapter-class>com.fr.third.springframework.jca.context.SpringContextResourceAdapter</resourceadapter-class> |
||||||
|
* <config-property> |
||||||
|
* <config-property-name>ContextConfigLocation</config-property-name> |
||||||
|
* <config-property-type>java.lang.String</config-property-type> |
||||||
|
* <config-property-value>META-INF/applicationContext.xml</config-property-value> |
||||||
|
* </config-property> |
||||||
|
* </resourceadapter> |
||||||
|
* </connector></pre> |
||||||
|
* |
||||||
|
* Note that "META-INF/applicationContext.xml" is the default context config |
||||||
|
* location, so it doesn't have to specified unless you intend to specify |
||||||
|
* different/additional config files. So in the default case, you may remove |
||||||
|
* the entire {@code config-property} section above. |
||||||
|
* |
||||||
|
* <p><b>For simple deployment needs, all you need to do is the following:</b> |
||||||
|
* Package all application classes into a RAR file (which is just a standard |
||||||
|
* JAR file with a different file extension), add all required library jars |
||||||
|
* into the root of the RAR archive, add a "META-INF/ra.xml" deployment |
||||||
|
* descriptor as shown above as well as the corresponding Spring XML bean |
||||||
|
* definition file(s) (typically "META-INF/applicationContext.xml"), |
||||||
|
* and drop the resulting RAR file into your application server's |
||||||
|
* deployment directory! |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.5 |
||||||
|
* @see #setContextConfigLocation |
||||||
|
* @see #loadBeanDefinitions |
||||||
|
* @see ResourceAdapterApplicationContext |
||||||
|
*/ |
||||||
|
public class SpringContextResourceAdapter implements ResourceAdapter { |
||||||
|
|
||||||
|
/** |
||||||
|
* Any number of these characters are considered delimiters between |
||||||
|
* multiple context config paths in a single String value. |
||||||
|
* @see #setContextConfigLocation |
||||||
|
*/ |
||||||
|
public static final String CONFIG_LOCATION_DELIMITERS = ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS; |
||||||
|
|
||||||
|
public static final String DEFAULT_CONTEXT_CONFIG_LOCATION = "META-INF/applicationContext.xml"; |
||||||
|
|
||||||
|
|
||||||
|
protected final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
private String contextConfigLocation = DEFAULT_CONTEXT_CONFIG_LOCATION; |
||||||
|
|
||||||
|
private ConfigurableApplicationContext applicationContext; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the location of the context configuration files, within the |
||||||
|
* resource adapter's deployment unit. This can be a delimited |
||||||
|
* String that consists of multiple resource location, separated |
||||||
|
* by commas, semicolons, whitespace, or line breaks. |
||||||
|
* <p>This can be specified as "ContextConfigLocation" config |
||||||
|
* property in the {@code ra.xml} deployment descriptor. |
||||||
|
* <p>The default is "classpath:META-INF/applicationContext.xml". |
||||||
|
*/ |
||||||
|
public void setContextConfigLocation(String contextConfigLocation) { |
||||||
|
this.contextConfigLocation = contextConfigLocation; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the specified context configuration files. |
||||||
|
*/ |
||||||
|
protected String getContextConfigLocation() { |
||||||
|
return this.contextConfigLocation; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return a new {@link StandardEnvironment}. |
||||||
|
* <p>Subclasses may override this method in order to supply |
||||||
|
* a custom {@link ConfigurableEnvironment} implementation. |
||||||
|
*/ |
||||||
|
protected ConfigurableEnvironment createEnvironment() { |
||||||
|
return new StandardEnvironment(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This implementation loads a Spring ApplicationContext through the |
||||||
|
* {@link #createApplicationContext} template method. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void start(BootstrapContext bootstrapContext) throws ResourceAdapterInternalException { |
||||||
|
if (logger.isInfoEnabled()) { |
||||||
|
logger.info("Starting SpringContextResourceAdapter with BootstrapContext: " + bootstrapContext); |
||||||
|
} |
||||||
|
this.applicationContext = createApplicationContext(bootstrapContext); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Build a Spring ApplicationContext for the given JCA BootstrapContext. |
||||||
|
* <p>The default implementation builds a {@link ResourceAdapterApplicationContext} |
||||||
|
* and delegates to {@link #loadBeanDefinitions} for actually parsing the |
||||||
|
* specified configuration files. |
||||||
|
* @param bootstrapContext this ResourceAdapter's BootstrapContext |
||||||
|
* @return the Spring ApplicationContext instance |
||||||
|
*/ |
||||||
|
protected ConfigurableApplicationContext createApplicationContext(BootstrapContext bootstrapContext) { |
||||||
|
ResourceAdapterApplicationContext applicationContext = |
||||||
|
new ResourceAdapterApplicationContext(bootstrapContext); |
||||||
|
// Set ResourceAdapter's ClassLoader as bean class loader.
|
||||||
|
applicationContext.setClassLoader(getClass().getClassLoader()); |
||||||
|
// Extract individual config locations.
|
||||||
|
String[] configLocations = |
||||||
|
StringUtils.tokenizeToStringArray(getContextConfigLocation(), CONFIG_LOCATION_DELIMITERS); |
||||||
|
if (configLocations != null) { |
||||||
|
loadBeanDefinitions(applicationContext, configLocations); |
||||||
|
} |
||||||
|
applicationContext.refresh(); |
||||||
|
return applicationContext; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Load the bean definitions into the given registry, |
||||||
|
* based on the specified configuration files. |
||||||
|
* @param registry the registry to load into |
||||||
|
* @param configLocations the parsed config locations |
||||||
|
* @see #setContextConfigLocation |
||||||
|
*/ |
||||||
|
protected void loadBeanDefinitions(BeanDefinitionRegistry registry, String[] configLocations) { |
||||||
|
new XmlBeanDefinitionReader(registry).loadBeanDefinitions(configLocations); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This implementation closes the Spring ApplicationContext. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void stop() { |
||||||
|
logger.info("Stopping SpringContextResourceAdapter"); |
||||||
|
this.applicationContext.close(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* This implementation always throws a NotSupportedException. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void endpointActivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec) |
||||||
|
throws ResourceException { |
||||||
|
|
||||||
|
throw new NotSupportedException("SpringContextResourceAdapter does not support message endpoints"); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This implementation does nothing. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void endpointDeactivation(MessageEndpointFactory messageEndpointFactory, ActivationSpec activationSpec) { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This implementation always returns {@code null}. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public XAResource[] getXAResources(ActivationSpec[] activationSpecs) throws ResourceException { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean equals(Object obj) { |
||||||
|
return (obj instanceof SpringContextResourceAdapter && |
||||||
|
ObjectUtils.nullSafeEquals(getContextConfigLocation(), |
||||||
|
((SpringContextResourceAdapter) obj).getContextConfigLocation())); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public int hashCode() { |
||||||
|
return ObjectUtils.nullSafeHashCode(getContextConfigLocation()); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Integration package that allows for deploying a Spring application context |
||||||
|
* as a JCA 1.5 compliant RAR file. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.jca.context; |
||||||
|
|
@ -0,0 +1,17 @@ |
|||||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||||
|
<connector xmlns="http://java.sun.com/xml/ns/j2ee" |
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||||
|
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd" |
||||||
|
version="1.5"> |
||||||
|
<vendor-name>Spring Framework</vendor-name> |
||||||
|
<eis-type>Spring Connector</eis-type> |
||||||
|
<resourceadapter-version>1.0</resourceadapter-version> |
||||||
|
<resourceadapter> |
||||||
|
<resourceadapter-class>com.fr.third.springframework.jca.context.SpringContextResourceAdapter</resourceadapter-class> |
||||||
|
<config-property> |
||||||
|
<config-property-name>ContextConfigLocation</config-property-name> |
||||||
|
<config-property-type>java.lang.String</config-property-type> |
||||||
|
<config-property-value>META-INF/applicationContext.xml</config-property-value> |
||||||
|
</config-property> |
||||||
|
</resourceadapter> |
||||||
|
</connector> |
@ -0,0 +1,341 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2013 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.endpoint; |
||||||
|
|
||||||
|
import java.lang.reflect.Method; |
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.spi.ApplicationServerInternalException; |
||||||
|
import javax.resource.spi.UnavailableException; |
||||||
|
import javax.resource.spi.endpoint.MessageEndpoint; |
||||||
|
import javax.resource.spi.endpoint.MessageEndpointFactory; |
||||||
|
import javax.transaction.Transaction; |
||||||
|
import javax.transaction.TransactionManager; |
||||||
|
import javax.transaction.xa.XAResource; |
||||||
|
|
||||||
|
import org.apache.commons.logging.Log; |
||||||
|
import org.apache.commons.logging.LogFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.BeanNameAware; |
||||||
|
import com.fr.third.springframework.transaction.jta.SimpleTransactionFactory; |
||||||
|
import com.fr.third.springframework.transaction.jta.TransactionFactory; |
||||||
|
|
||||||
|
/** |
||||||
|
* Abstract base implementation of the JCA 1.5/1.6/1.7 |
||||||
|
* {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface, |
||||||
|
* providing transaction management capabilities as well as ClassLoader |
||||||
|
* exposure for endpoint invocations. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.5 |
||||||
|
* @see #setTransactionManager |
||||||
|
*/ |
||||||
|
public abstract class AbstractMessageEndpointFactory implements MessageEndpointFactory, BeanNameAware { |
||||||
|
|
||||||
|
/** Logger available to subclasses */ |
||||||
|
protected final Log logger = LogFactory.getLog(getClass()); |
||||||
|
|
||||||
|
private TransactionFactory transactionFactory; |
||||||
|
|
||||||
|
private String transactionName; |
||||||
|
|
||||||
|
private int transactionTimeout = -1; |
||||||
|
|
||||||
|
private String beanName; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the the XA transaction manager to use for wrapping endpoint |
||||||
|
* invocations, enlisting the endpoint resource in each such transaction. |
||||||
|
* <p>The passed-in object may be a transaction manager which implements |
||||||
|
* Spring's {@link com.fr.third.springframework.transaction.jta.TransactionFactory} |
||||||
|
* interface, or a plain {@link javax.transaction.TransactionManager}. |
||||||
|
* <p>If no transaction manager is specified, the endpoint invocation |
||||||
|
* will simply not be wrapped in an XA transaction. Check out your |
||||||
|
* resource provider's ActivationSpec documentation for local |
||||||
|
* transaction options of your particular provider. |
||||||
|
* @see #setTransactionName |
||||||
|
* @see #setTransactionTimeout |
||||||
|
*/ |
||||||
|
public void setTransactionManager(Object transactionManager) { |
||||||
|
if (transactionManager instanceof TransactionFactory) { |
||||||
|
this.transactionFactory = (TransactionFactory) transactionManager; |
||||||
|
} |
||||||
|
else if (transactionManager instanceof TransactionManager) { |
||||||
|
this.transactionFactory = new SimpleTransactionFactory((TransactionManager) transactionManager); |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new IllegalArgumentException("Transaction manager [" + transactionManager + |
||||||
|
"] is neither a [com.fr.third.springframework.transaction.jta.TransactionFactory} nor a " + |
||||||
|
"[javax.transaction.TransactionManager]"); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the Spring TransactionFactory to use for wrapping endpoint |
||||||
|
* invocations, enlisting the endpoint resource in each such transaction. |
||||||
|
* <p>Alternatively, specify an appropriate transaction manager through |
||||||
|
* the {@link #setTransactionManager "transactionManager"} property. |
||||||
|
* <p>If no transaction factory is specified, the endpoint invocation |
||||||
|
* will simply not be wrapped in an XA transaction. Check out your |
||||||
|
* resource provider's ActivationSpec documentation for local |
||||||
|
* transaction options of your particular provider. |
||||||
|
* @see #setTransactionName |
||||||
|
* @see #setTransactionTimeout |
||||||
|
*/ |
||||||
|
public void setTransactionFactory(TransactionFactory transactionFactory) { |
||||||
|
this.transactionFactory = transactionFactory; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the name of the transaction, if any. |
||||||
|
* <p>Default is none. A specified name will be passed on to the transaction |
||||||
|
* manager, allowing to identify the transaction in a transaction monitor. |
||||||
|
*/ |
||||||
|
public void setTransactionName(String transactionName) { |
||||||
|
this.transactionName = transactionName; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the transaction timeout, if any. |
||||||
|
* <p>Default is -1: rely on the transaction manager's default timeout. |
||||||
|
* Specify a concrete timeout to restrict the maximum duration of each |
||||||
|
* endpoint invocation. |
||||||
|
*/ |
||||||
|
public void setTransactionTimeout(int transactionTimeout) { |
||||||
|
this.transactionTimeout = transactionTimeout; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the name of this message endpoint. Populated with the bean name |
||||||
|
* automatically when defined within Spring's bean factory. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void setBeanName(String beanName) { |
||||||
|
this.beanName = beanName; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Implementation of the JCA 1.7 {@code #getActivationName()} method, |
||||||
|
* returning the bean name as set on this MessageEndpointFactory. |
||||||
|
* @see #setBeanName |
||||||
|
*/ |
||||||
|
public String getActivationName() { |
||||||
|
return this.beanName; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This implementation returns {@code true} if a transaction manager |
||||||
|
* has been specified; {@code false} otherwise. |
||||||
|
* @see #setTransactionManager |
||||||
|
* @see #setTransactionFactory |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public boolean isDeliveryTransacted(Method method) throws NoSuchMethodException { |
||||||
|
return (this.transactionFactory != null); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The standard JCA 1.5 version of {@code createEndpoint}. |
||||||
|
* <p>This implementation delegates to {@link #createEndpointInternal()}, |
||||||
|
* initializing the endpoint's XAResource before the endpoint gets invoked. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException { |
||||||
|
AbstractMessageEndpoint endpoint = createEndpointInternal(); |
||||||
|
endpoint.initXAResource(xaResource); |
||||||
|
return endpoint; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* The alternative JCA 1.6 version of {@code createEndpoint}. |
||||||
|
* <p>This implementation delegates to {@link #createEndpointInternal()}, |
||||||
|
* ignoring the specified timeout. It is only here for JCA 1.6 compliance. |
||||||
|
*/ |
||||||
|
public MessageEndpoint createEndpoint(XAResource xaResource, long timeout) throws UnavailableException { |
||||||
|
AbstractMessageEndpoint endpoint = createEndpointInternal(); |
||||||
|
endpoint.initXAResource(xaResource); |
||||||
|
return endpoint; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create the actual endpoint instance, as a subclass of the |
||||||
|
* {@link AbstractMessageEndpoint} inner class of this factory. |
||||||
|
* @return the actual endpoint instance (never {@code null}) |
||||||
|
* @throws UnavailableException if no endpoint is available at present |
||||||
|
*/ |
||||||
|
protected abstract AbstractMessageEndpoint createEndpointInternal() throws UnavailableException; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Inner class for actual endpoint implementations, based on template |
||||||
|
* method to allow for any kind of concrete endpoint implementation. |
||||||
|
*/ |
||||||
|
protected abstract class AbstractMessageEndpoint implements MessageEndpoint { |
||||||
|
|
||||||
|
private TransactionDelegate transactionDelegate; |
||||||
|
|
||||||
|
private boolean beforeDeliveryCalled = false; |
||||||
|
|
||||||
|
private ClassLoader previousContextClassLoader; |
||||||
|
|
||||||
|
/** |
||||||
|
* Initialize this endpoint's TransactionDelegate. |
||||||
|
* @param xaResource the XAResource for this endpoint |
||||||
|
*/ |
||||||
|
void initXAResource(XAResource xaResource) { |
||||||
|
this.transactionDelegate = new TransactionDelegate(xaResource); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This {@code beforeDelivery} implementation starts a transaction, |
||||||
|
* if necessary, and exposes the endpoint ClassLoader as current |
||||||
|
* thread context ClassLoader. |
||||||
|
* <p>Note that the JCA 1.5 specification does not require a ResourceAdapter |
||||||
|
* to call this method before invoking the concrete endpoint. If this method |
||||||
|
* has not been called (check {@link #hasBeforeDeliveryBeenCalled()}), the |
||||||
|
* concrete endpoint method should call {@code beforeDelivery} and its |
||||||
|
* sibling {@link #afterDelivery()} explicitly, as part of its own processing. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void beforeDelivery(Method method) throws ResourceException { |
||||||
|
this.beforeDeliveryCalled = true; |
||||||
|
try { |
||||||
|
this.transactionDelegate.beginTransaction(); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
throw new ApplicationServerInternalException("Failed to begin transaction", ex); |
||||||
|
} |
||||||
|
Thread currentThread = Thread.currentThread(); |
||||||
|
this.previousContextClassLoader = currentThread.getContextClassLoader(); |
||||||
|
currentThread.setContextClassLoader(getEndpointClassLoader()); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Template method for exposing the endpoint's ClassLoader |
||||||
|
* (typically the ClassLoader that the message listener class
|
||||||
|
* has been loaded with). |
||||||
|
* @return the endpoint ClassLoader (never {@code null}) |
||||||
|
*/ |
||||||
|
protected abstract ClassLoader getEndpointClassLoader(); |
||||||
|
|
||||||
|
/** |
||||||
|
* Return whether the {@link #beforeDelivery} method of this endpoint |
||||||
|
* has already been called. |
||||||
|
*/ |
||||||
|
protected final boolean hasBeforeDeliveryBeenCalled() { |
||||||
|
return this.beforeDeliveryCalled; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Callback method for notifying the endpoint base class
|
||||||
|
* that the concrete endpoint invocation led to an exception. |
||||||
|
* <p>To be invoked by subclasses in case of the concrete |
||||||
|
* endpoint throwing an exception. |
||||||
|
* @param ex the exception thrown from the concrete endpoint |
||||||
|
*/ |
||||||
|
protected final void onEndpointException(Throwable ex) { |
||||||
|
this.transactionDelegate.setRollbackOnly(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This {@code afterDelivery} implementation resets the thread context |
||||||
|
* ClassLoader and completes the transaction, if any. |
||||||
|
* <p>Note that the JCA 1.5 specification does not require a ResourceAdapter |
||||||
|
* to call this method after invoking the concrete endpoint. See the |
||||||
|
* explanation in {@link #beforeDelivery}'s javadoc. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void afterDelivery() throws ResourceException { |
||||||
|
this.beforeDeliveryCalled = false; |
||||||
|
Thread.currentThread().setContextClassLoader(this.previousContextClassLoader); |
||||||
|
this.previousContextClassLoader = null; |
||||||
|
try { |
||||||
|
this.transactionDelegate.endTransaction(); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
throw new ApplicationServerInternalException("Failed to complete transaction", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void release() { |
||||||
|
try { |
||||||
|
this.transactionDelegate.setRollbackOnly(); |
||||||
|
this.transactionDelegate.endTransaction(); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
logger.error("Could not complete unfinished transaction on endpoint release", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Private inner class that performs the actual transaction handling, |
||||||
|
* including enlistment of the endpoint's XAResource. |
||||||
|
*/ |
||||||
|
private class TransactionDelegate { |
||||||
|
|
||||||
|
private final XAResource xaResource; |
||||||
|
|
||||||
|
private Transaction transaction; |
||||||
|
|
||||||
|
private boolean rollbackOnly; |
||||||
|
|
||||||
|
public TransactionDelegate(XAResource xaResource) { |
||||||
|
if (xaResource == null) { |
||||||
|
if (transactionFactory != null && !transactionFactory.supportsResourceAdapterManagedTransactions()) { |
||||||
|
throw new IllegalStateException("ResourceAdapter-provided XAResource is required for " + |
||||||
|
"transaction management. Check your ResourceAdapter's configuration."); |
||||||
|
} |
||||||
|
} |
||||||
|
this.xaResource = xaResource; |
||||||
|
} |
||||||
|
|
||||||
|
public void beginTransaction() throws Exception { |
||||||
|
if (transactionFactory != null && this.xaResource != null) { |
||||||
|
this.transaction = transactionFactory.createTransaction(transactionName, transactionTimeout); |
||||||
|
this.transaction.enlistResource(this.xaResource); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void setRollbackOnly() { |
||||||
|
if (this.transaction != null) { |
||||||
|
this.rollbackOnly = true; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
public void endTransaction() throws Exception { |
||||||
|
if (this.transaction != null) { |
||||||
|
try { |
||||||
|
if (this.rollbackOnly) { |
||||||
|
this.transaction.rollback(); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.transaction.commit(); |
||||||
|
} |
||||||
|
} |
||||||
|
finally { |
||||||
|
this.transaction = null; |
||||||
|
this.rollbackOnly = false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,160 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2013 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.endpoint; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.spi.UnavailableException; |
||||||
|
import javax.resource.spi.endpoint.MessageEndpoint; |
||||||
|
import javax.transaction.xa.XAResource; |
||||||
|
|
||||||
|
import org.aopalliance.intercept.MethodInterceptor; |
||||||
|
import org.aopalliance.intercept.MethodInvocation; |
||||||
|
|
||||||
|
import com.fr.third.springframework.aop.framework.ProxyFactory; |
||||||
|
import com.fr.third.springframework.aop.support.DelegatingIntroductionInterceptor; |
||||||
|
import com.fr.third.springframework.util.ReflectionUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Generic implementation of the JCA 1.5 |
||||||
|
* {@link javax.resource.spi.endpoint.MessageEndpointFactory} interface, |
||||||
|
* providing transaction management capabilities for any kind of message |
||||||
|
* listener object (e.g. {@link javax.jms.MessageListener} objects or |
||||||
|
* {@link javax.resource.cci.MessageListener} objects. |
||||||
|
* |
||||||
|
* <p>Uses AOP proxies for concrete endpoint instances, simply wrapping |
||||||
|
* the specified message listener object and exposing all of its implemented |
||||||
|
* interfaces on the endpoint instance. |
||||||
|
* |
||||||
|
* <p>Typically used with Spring's {@link GenericMessageEndpointManager}, |
||||||
|
* but not tied to it. As a consequence, this endpoint factory could |
||||||
|
* also be used with programmatic endpoint management on a native |
||||||
|
* {@link javax.resource.spi.ResourceAdapter} instance. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.5 |
||||||
|
* @see #setMessageListener |
||||||
|
* @see #setTransactionManager |
||||||
|
* @see GenericMessageEndpointManager |
||||||
|
*/ |
||||||
|
public class GenericMessageEndpointFactory extends AbstractMessageEndpointFactory { |
||||||
|
|
||||||
|
private Object messageListener; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the message listener object that the endpoint should expose |
||||||
|
* (e.g. a {@link javax.jms.MessageListener} objects or |
||||||
|
* {@link javax.resource.cci.MessageListener} implementation). |
||||||
|
*/ |
||||||
|
public void setMessageListener(Object messageListener) { |
||||||
|
this.messageListener = messageListener; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Wrap each concrete endpoint instance with an AOP proxy, |
||||||
|
* exposing the message listener's interfaces as well as the |
||||||
|
* endpoint SPI through an AOP introduction. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public MessageEndpoint createEndpoint(XAResource xaResource) throws UnavailableException { |
||||||
|
GenericMessageEndpoint endpoint = (GenericMessageEndpoint) super.createEndpoint(xaResource); |
||||||
|
ProxyFactory proxyFactory = new ProxyFactory(this.messageListener); |
||||||
|
DelegatingIntroductionInterceptor introduction = new DelegatingIntroductionInterceptor(endpoint); |
||||||
|
introduction.suppressInterface(MethodInterceptor.class); |
||||||
|
proxyFactory.addAdvice(introduction); |
||||||
|
return (MessageEndpoint) proxyFactory.getProxy(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Creates a concrete generic message endpoint, internal to this factory. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
protected AbstractMessageEndpoint createEndpointInternal() throws UnavailableException { |
||||||
|
return new GenericMessageEndpoint(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Private inner class that implements the concrete generic message endpoint, |
||||||
|
* as an AOP Alliance MethodInterceptor that will be invoked by a proxy. |
||||||
|
*/ |
||||||
|
private class GenericMessageEndpoint extends AbstractMessageEndpoint implements MethodInterceptor { |
||||||
|
|
||||||
|
@Override |
||||||
|
public Object invoke(MethodInvocation methodInvocation) throws Throwable { |
||||||
|
boolean applyDeliveryCalls = !hasBeforeDeliveryBeenCalled(); |
||||||
|
if (applyDeliveryCalls) { |
||||||
|
try { |
||||||
|
beforeDelivery(null); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
if (ReflectionUtils.declaresException(methodInvocation.getMethod(), ex.getClass())) { |
||||||
|
throw ex; |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new InternalResourceException(ex); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
try { |
||||||
|
return methodInvocation.proceed(); |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
onEndpointException(ex); |
||||||
|
throw ex; |
||||||
|
} |
||||||
|
finally { |
||||||
|
if (applyDeliveryCalls) { |
||||||
|
try { |
||||||
|
afterDelivery(); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
if (ReflectionUtils.declaresException(methodInvocation.getMethod(), ex.getClass())) { |
||||||
|
throw ex; |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new InternalResourceException(ex); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
protected ClassLoader getEndpointClassLoader() { |
||||||
|
return messageListener.getClass().getClassLoader(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Internal exception thrown when a ResourceException has been encountered |
||||||
|
* during the endpoint invocation. |
||||||
|
* <p>Will only be used if the ResourceAdapter does not invoke the |
||||||
|
* endpoint's {@code beforeDelivery} and {@code afterDelivery} |
||||||
|
* directly, leaving it up to the concrete endpoint to apply those - |
||||||
|
* and to handle any ResourceExceptions thrown from them. |
||||||
|
*/ |
||||||
|
@SuppressWarnings("serial") |
||||||
|
public static class InternalResourceException extends RuntimeException { |
||||||
|
|
||||||
|
protected InternalResourceException(ResourceException cause) { |
||||||
|
super(cause); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,334 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.endpoint; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.spi.ActivationSpec; |
||||||
|
import javax.resource.spi.ResourceAdapter; |
||||||
|
import javax.resource.spi.endpoint.MessageEndpointFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.DisposableBean; |
||||||
|
import com.fr.third.springframework.beans.factory.InitializingBean; |
||||||
|
import com.fr.third.springframework.context.SmartLifecycle; |
||||||
|
|
||||||
|
/** |
||||||
|
* Generic bean that manages JCA 1.5 message endpoints within a Spring |
||||||
|
* application context, activating and deactivating the endpoint as part |
||||||
|
* of the application context's lifecycle. |
||||||
|
* |
||||||
|
* <p>This class is completely generic in that it may work with any |
||||||
|
* ResourceAdapter, any MessageEndpointFactory, and any ActivationSpec. |
||||||
|
* It can be configured in standard bean style, for example through |
||||||
|
* Spring's XML bean definition format, as follows: |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* <bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointManager"> |
||||||
|
* <property name="resourceAdapter" ref="resourceAdapter"/> |
||||||
|
* <property name="messageEndpointFactory"> |
||||||
|
* <bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointFactory"> |
||||||
|
* <property name="messageListener" ref="messageListener"/> |
||||||
|
* </bean> |
||||||
|
* </property> |
||||||
|
* <property name="activationSpec"> |
||||||
|
* <bean class="org.apache.activemq.ra.ActiveMQActivationSpec"> |
||||||
|
* <property name="destination" value="myQueue"/> |
||||||
|
* <property name="destinationType" value="javax.jms.Queue"/> |
||||||
|
* </bean> |
||||||
|
* </property> |
||||||
|
* </bean></pre> |
||||||
|
* |
||||||
|
* In this example, Spring's own {@link GenericMessageEndpointFactory} is used |
||||||
|
* to point to a standard message listener object that happens to be supported |
||||||
|
* by the specified target ResourceAdapter: in this case, a JMS |
||||||
|
* {@link javax.jms.MessageListener} object as supported by the ActiveMQ |
||||||
|
* message broker, defined as a Spring bean: |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* <bean id="messageListener" class="com.myorg.messaging.myMessageListener"> |
||||||
|
* ... |
||||||
|
* </bean></pre> |
||||||
|
* |
||||||
|
* The target ResourceAdapter may be configured as a local Spring bean as well |
||||||
|
* (the typical case) or obtained from JNDI (e.g. on WebLogic). For the |
||||||
|
* example above, a local ResourceAdapter bean could be defined as follows |
||||||
|
* (matching the "resourceAdapter" bean reference above): |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* <bean id="resourceAdapter" class="com.fr.third.springframework.jca.support.ResourceAdapterFactoryBean"> |
||||||
|
* <property name="resourceAdapter"> |
||||||
|
* <bean class="org.apache.activemq.ra.ActiveMQResourceAdapter"> |
||||||
|
* <property name="serverUrl" value="tcp://localhost:61616"/> |
||||||
|
* </bean> |
||||||
|
* </property> |
||||||
|
* <property name="workManager"> |
||||||
|
* <bean class="com.fr.third.springframework.jca.work.SimpleTaskWorkManager"/> |
||||||
|
* </property> |
||||||
|
* </bean></pre> |
||||||
|
* |
||||||
|
* For a different target resource, the configuration would simply point to a |
||||||
|
* different ResourceAdapter and a different ActivationSpec object (which are |
||||||
|
* both specific to the resource provider), and possibly a different message |
||||||
|
* listener (e.g. a CCI {@link javax.resource.cci.MessageListener} for a |
||||||
|
* resource adapter which is based on the JCA Common Client Interface). |
||||||
|
* |
||||||
|
* <p>The asynchronous execution strategy can be customized through the |
||||||
|
* "workManager" property on the ResourceAdapterFactoryBean (as shown above). |
||||||
|
* Check out {@link com.fr.third.springframework.jca.work.SimpleTaskWorkManager}'s |
||||||
|
* javadoc for its configuration options; alternatively, any other |
||||||
|
* JCA-compliant WorkManager can be used (e.g. Geronimo's). |
||||||
|
* |
||||||
|
* <p>Transactional execution is a responsibility of the concrete message endpoint, |
||||||
|
* as built by the specified MessageEndpointFactory. {@link GenericMessageEndpointFactory} |
||||||
|
* supports XA transaction participation through its "transactionManager" property, |
||||||
|
* typically with a Spring {@link com.fr.third.springframework.transaction.jta.JtaTransactionManager} |
||||||
|
* or a plain {@link javax.transaction.TransactionManager} implementation specified there. |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* <bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointManager"> |
||||||
|
* <property name="resourceAdapter" ref="resourceAdapter"/> |
||||||
|
* <property name="messageEndpointFactory"> |
||||||
|
* <bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointFactory"> |
||||||
|
* <property name="messageListener" ref="messageListener"/> |
||||||
|
* <property name="transactionManager" ref="transactionManager"/> |
||||||
|
* </bean> |
||||||
|
* </property> |
||||||
|
* <property name="activationSpec"> |
||||||
|
* <bean class="org.apache.activemq.ra.ActiveMQActivationSpec"> |
||||||
|
* <property name="destination" value="myQueue"/> |
||||||
|
* <property name="destinationType" value="javax.jms.Queue"/> |
||||||
|
* </bean> |
||||||
|
* </property> |
||||||
|
* </bean> |
||||||
|
* |
||||||
|
* <bean id="transactionManager" class="com.fr.third.springframework.transaction.jta.JtaTransactionManager"/></pre> |
||||||
|
* |
||||||
|
* Alternatively, check out your resource provider's ActivationSpec object, |
||||||
|
* which should support local transactions through a provider-specific config flag, |
||||||
|
* e.g. ActiveMQActivationSpec's "useRAManagedTransaction" bean property. |
||||||
|
* |
||||||
|
* <pre class="code"> |
||||||
|
* <bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointManager"> |
||||||
|
* <property name="resourceAdapter" ref="resourceAdapter"/> |
||||||
|
* <property name="messageEndpointFactory"> |
||||||
|
* <bean class="com.fr.third.springframework.jca.endpoint.GenericMessageEndpointFactory"> |
||||||
|
* <property name="messageListener" ref="messageListener"/> |
||||||
|
* </bean> |
||||||
|
* </property> |
||||||
|
* <property name="activationSpec"> |
||||||
|
* <bean class="org.apache.activemq.ra.ActiveMQActivationSpec"> |
||||||
|
* <property name="destination" value="myQueue"/> |
||||||
|
* <property name="destinationType" value="javax.jms.Queue"/> |
||||||
|
* <property name="useRAManagedTransaction" value="true"/> |
||||||
|
* </bean> |
||||||
|
* </property> |
||||||
|
* </bean></pre> |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.5 |
||||||
|
* @see javax.resource.spi.ResourceAdapter#endpointActivation |
||||||
|
* @see javax.resource.spi.ResourceAdapter#endpointDeactivation |
||||||
|
* @see javax.resource.spi.endpoint.MessageEndpointFactory |
||||||
|
* @see javax.resource.spi.ActivationSpec |
||||||
|
*/ |
||||||
|
public class GenericMessageEndpointManager implements SmartLifecycle, InitializingBean, DisposableBean { |
||||||
|
|
||||||
|
private ResourceAdapter resourceAdapter; |
||||||
|
|
||||||
|
private MessageEndpointFactory messageEndpointFactory; |
||||||
|
|
||||||
|
private ActivationSpec activationSpec; |
||||||
|
|
||||||
|
private boolean autoStartup = true; |
||||||
|
|
||||||
|
private int phase = Integer.MAX_VALUE; |
||||||
|
|
||||||
|
private boolean running = false; |
||||||
|
|
||||||
|
private final Object lifecycleMonitor = new Object(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the JCA ResourceAdapter to manage endpoints for. |
||||||
|
*/ |
||||||
|
public void setResourceAdapter(ResourceAdapter resourceAdapter) { |
||||||
|
this.resourceAdapter = resourceAdapter; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the JCA ResourceAdapter to manage endpoints for. |
||||||
|
*/ |
||||||
|
public ResourceAdapter getResourceAdapter() { |
||||||
|
return this.resourceAdapter; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the JCA MessageEndpointFactory to activate, pointing to a |
||||||
|
* MessageListener object that the endpoints will delegate to. |
||||||
|
* <p>A MessageEndpointFactory instance may be shared across multiple |
||||||
|
* endpoints (i.e. multiple GenericMessageEndpointManager instances), |
||||||
|
* with different {@link #setActivationSpec ActivationSpec} objects applied. |
||||||
|
* @see GenericMessageEndpointFactory#setMessageListener |
||||||
|
*/ |
||||||
|
public void setMessageEndpointFactory(MessageEndpointFactory messageEndpointFactory) { |
||||||
|
this.messageEndpointFactory = messageEndpointFactory; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the JCA MessageEndpointFactory to activate. |
||||||
|
*/ |
||||||
|
public MessageEndpointFactory getMessageEndpointFactory() { |
||||||
|
return this.messageEndpointFactory; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the JCA ActivationSpec to use for activating the endpoint. |
||||||
|
* <p>Note that this ActivationSpec instance should not be shared |
||||||
|
* across multiple ResourceAdapter instances. |
||||||
|
*/ |
||||||
|
public void setActivationSpec(ActivationSpec activationSpec) { |
||||||
|
this.activationSpec = activationSpec; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the JCA ActivationSpec to use for activating the endpoint. |
||||||
|
*/ |
||||||
|
public ActivationSpec getActivationSpec() { |
||||||
|
return this.activationSpec; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set whether to auto-start the endpoint activation after this endpoint |
||||||
|
* manager has been initialized and the context has been refreshed. |
||||||
|
* <p>Default is "true". Turn this flag off to defer the endpoint |
||||||
|
* activation until an explicit {#start()} call. |
||||||
|
*/ |
||||||
|
public void setAutoStartup(boolean autoStartup) { |
||||||
|
this.autoStartup = autoStartup; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the value for the 'autoStartup' property. If "true", this |
||||||
|
* endpoint manager will start upon a ContextRefreshedEvent. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public boolean isAutoStartup() { |
||||||
|
return this.autoStartup; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the phase in which this endpoint manager should be started |
||||||
|
* and stopped. The startup order proceeds from lowest to highest, and |
||||||
|
* the shutdown order is the reverse of that. By default this value is |
||||||
|
* Integer.MAX_VALUE meaning that this endpoint manager starts as late |
||||||
|
* as possible and stops as soon as possible. |
||||||
|
*/ |
||||||
|
public void setPhase(int phase) { |
||||||
|
this.phase = phase; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the phase in which this endpoint manager will be started and stopped. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public int getPhase() { |
||||||
|
return this.phase; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Prepares the message endpoint, and automatically activates it |
||||||
|
* if the "autoStartup" flag is set to "true". |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() throws ResourceException { |
||||||
|
if (getResourceAdapter() == null) { |
||||||
|
throw new IllegalArgumentException("Property 'resourceAdapter' is required"); |
||||||
|
} |
||||||
|
if (getMessageEndpointFactory() == null) { |
||||||
|
throw new IllegalArgumentException("Property 'messageEndpointFactory' is required"); |
||||||
|
} |
||||||
|
ActivationSpec activationSpec = getActivationSpec(); |
||||||
|
if (activationSpec == null) { |
||||||
|
throw new IllegalArgumentException("Property 'activationSpec' is required"); |
||||||
|
} |
||||||
|
|
||||||
|
if (activationSpec.getResourceAdapter() == null) { |
||||||
|
activationSpec.setResourceAdapter(getResourceAdapter()); |
||||||
|
} |
||||||
|
else if (activationSpec.getResourceAdapter() != getResourceAdapter()) { |
||||||
|
throw new IllegalArgumentException("ActivationSpec [" + activationSpec + |
||||||
|
"] is associated with a different ResourceAdapter: " + activationSpec.getResourceAdapter()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Activates the configured message endpoint. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void start() { |
||||||
|
synchronized (this.lifecycleMonitor) { |
||||||
|
if (!this.running) { |
||||||
|
try { |
||||||
|
getResourceAdapter().endpointActivation(getMessageEndpointFactory(), getActivationSpec()); |
||||||
|
} |
||||||
|
catch (ResourceException ex) { |
||||||
|
throw new IllegalStateException("Could not activate message endpoint", ex); |
||||||
|
} |
||||||
|
this.running = true; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Deactivates the configured message endpoint. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void stop() { |
||||||
|
synchronized (this.lifecycleMonitor) { |
||||||
|
if (this.running) { |
||||||
|
getResourceAdapter().endpointDeactivation(getMessageEndpointFactory(), getActivationSpec()); |
||||||
|
this.running = false; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void stop(Runnable callback) { |
||||||
|
synchronized (this.lifecycleMonitor) { |
||||||
|
this.stop(); |
||||||
|
callback.run(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return whether the configured message endpoint is currently active. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public boolean isRunning() { |
||||||
|
synchronized (this.lifecycleMonitor) { |
||||||
|
return this.running; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Deactivates the message endpoint, preparing it for shutdown. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void destroy() { |
||||||
|
stop(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,8 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* This package provides a facility for generic JCA message endpoint management. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.jca.endpoint; |
||||||
|
|
@ -0,0 +1,141 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.support; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.spi.ConnectionManager; |
||||||
|
import javax.resource.spi.ManagedConnectionFactory; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.FactoryBean; |
||||||
|
import com.fr.third.springframework.beans.factory.InitializingBean; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link com.fr.third.springframework.beans.factory.FactoryBean} that creates |
||||||
|
* a local JCA connection factory in "non-managed" mode (as defined by the |
||||||
|
* Java Connector Architecture specification). This is a direct alternative |
||||||
|
* to a {@link com.fr.third.springframework.jndi.JndiObjectFactoryBean} definition that |
||||||
|
* obtains a connection factory handle from a J2EE server's naming environment. |
||||||
|
* |
||||||
|
* <p>The type of the connection factory is dependent on the actual connector: |
||||||
|
* the connector can either expose its native API (such as a JDBC |
||||||
|
* {@link javax.sql.DataSource} or a JMS {@link javax.jms.ConnectionFactory}) |
||||||
|
* or follow the standard Common Client Interface (CCI), as defined by the JCA spec. |
||||||
|
* The exposed interface in the CCI case is {@link javax.resource.cci.ConnectionFactory}. |
||||||
|
* |
||||||
|
* <p>In order to use this FactoryBean, you must specify the connector's |
||||||
|
* {@link #setManagedConnectionFactory "managedConnectionFactory"} (usually |
||||||
|
* configured as separate JavaBean), which will be used to create the actual |
||||||
|
* connection factory reference as exposed to the application. Optionally, |
||||||
|
* you can also specify a {@link #setConnectionManager "connectionManager"}, |
||||||
|
* in order to use a custom ConnectionManager instead of the connector's default. |
||||||
|
* |
||||||
|
* <p><b>NOTE:</b> In non-managed mode, a connector is not deployed on an |
||||||
|
* application server, or more specificially not interacting with an application |
||||||
|
* server. Consequently, it cannot use a J2EE server's system contracts: |
||||||
|
* connection management, transaction management, and security management. |
||||||
|
* A custom ConnectionManager implementation has to be used for applying those |
||||||
|
* services in conjunction with a standalone transaction coordinator etc. |
||||||
|
* |
||||||
|
* <p>The connector will use a local ConnectionManager (included in the connector) |
||||||
|
* by default, which cannot participate in global transactions due to the lack |
||||||
|
* of XA enlistment. You need to specify an XA-capable ConnectionManager in |
||||||
|
* order to make the connector interact with an XA transaction coordinator. |
||||||
|
* Alternatively, simply use the native local transaction facilities of the |
||||||
|
* exposed API (e.g. CCI local transactions), or use a corresponding |
||||||
|
* implementation of Spring's PlatformTransactionManager SPI |
||||||
|
* (e.g. {@link com.fr.third.springframework.jca.cci.connection.CciLocalTransactionManager}) |
||||||
|
* to drive local transactions. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 1.2 |
||||||
|
* @see #setManagedConnectionFactory |
||||||
|
* @see #setConnectionManager |
||||||
|
* @see javax.resource.cci.ConnectionFactory |
||||||
|
* @see javax.resource.cci.Connection#getLocalTransaction |
||||||
|
* @see com.fr.third.springframework.jca.cci.connection.CciLocalTransactionManager |
||||||
|
*/ |
||||||
|
public class LocalConnectionFactoryBean implements FactoryBean<Object>, InitializingBean { |
||||||
|
|
||||||
|
private ManagedConnectionFactory managedConnectionFactory; |
||||||
|
|
||||||
|
private ConnectionManager connectionManager; |
||||||
|
|
||||||
|
private Object connectionFactory; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Set the JCA ManagerConnectionFactory that should be used to create |
||||||
|
* the desired connection factory. |
||||||
|
* <p>The ManagerConnectionFactory will usually be set up as separate bean |
||||||
|
* (potentially as inner bean), populated with JavaBean properties: |
||||||
|
* a ManagerConnectionFactory is encouraged to follow the JavaBean pattern |
||||||
|
* by the JCA specification, analogous to a JDBC DataSource and a JDO |
||||||
|
* PersistenceManagerFactory. |
||||||
|
* <p>Note that the ManagerConnectionFactory implementation might expect |
||||||
|
* a reference to its JCA 1.5 ResourceAdapter, expressed through the |
||||||
|
* {@link javax.resource.spi.ResourceAdapterAssociation} interface. |
||||||
|
* Simply inject the corresponding ResourceAdapter instance into its |
||||||
|
* "resourceAdapter" bean property in this case, before passing the |
||||||
|
* ManagerConnectionFactory into this LocalConnectionFactoryBean. |
||||||
|
* @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory() |
||||||
|
*/ |
||||||
|
public void setManagedConnectionFactory(ManagedConnectionFactory managedConnectionFactory) { |
||||||
|
this.managedConnectionFactory = managedConnectionFactory; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the JCA ConnectionManager that should be used to create the |
||||||
|
* desired connection factory. |
||||||
|
* <p>A ConnectionManager implementation for local usage is often |
||||||
|
* included with a JCA connector. Such an included ConnectionManager |
||||||
|
* might be set as default, with no need to explicitly specify one. |
||||||
|
* @see javax.resource.spi.ManagedConnectionFactory#createConnectionFactory(javax.resource.spi.ConnectionManager) |
||||||
|
*/ |
||||||
|
public void setConnectionManager(ConnectionManager connectionManager) { |
||||||
|
this.connectionManager = connectionManager; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() throws ResourceException { |
||||||
|
if (this.managedConnectionFactory == null) { |
||||||
|
throw new IllegalArgumentException("Property 'managedConnectionFactory' is required"); |
||||||
|
} |
||||||
|
if (this.connectionManager != null) { |
||||||
|
this.connectionFactory = this.managedConnectionFactory.createConnectionFactory(this.connectionManager); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.connectionFactory = this.managedConnectionFactory.createConnectionFactory(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public Object getObject() { |
||||||
|
return this.connectionFactory; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<?> getObjectType() { |
||||||
|
return (this.connectionFactory != null ? this.connectionFactory.getClass() : null); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isSingleton() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,153 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.support; |
||||||
|
|
||||||
|
import javax.resource.ResourceException; |
||||||
|
import javax.resource.spi.BootstrapContext; |
||||||
|
import javax.resource.spi.ResourceAdapter; |
||||||
|
import javax.resource.spi.XATerminator; |
||||||
|
import javax.resource.spi.work.WorkManager; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.BeanUtils; |
||||||
|
import com.fr.third.springframework.beans.factory.DisposableBean; |
||||||
|
import com.fr.third.springframework.beans.factory.FactoryBean; |
||||||
|
import com.fr.third.springframework.beans.factory.InitializingBean; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link com.fr.third.springframework.beans.factory.FactoryBean} that bootstraps |
||||||
|
* the specified JCA 1.5 {@link javax.resource.spi.ResourceAdapter}, |
||||||
|
* starting it with a local {@link javax.resource.spi.BootstrapContext} |
||||||
|
* and exposing it for bean references. It will also stop the ResourceAdapter |
||||||
|
* on context shutdown. This corresponds to 'non-managed' bootstrap in a |
||||||
|
* local environment, according to the JCA 1.5 specification. |
||||||
|
* |
||||||
|
* <p>This is essentially an adapter for bean-style bootstrapping of a |
||||||
|
* JCA ResourceAdapter, allowing the BootstrapContext or its elements |
||||||
|
* (such as the JCA WorkManager) to be specified through bean properties. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0.3 |
||||||
|
* @see #setResourceAdapter |
||||||
|
* @see #setBootstrapContext |
||||||
|
* @see #setWorkManager |
||||||
|
* @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext) |
||||||
|
* @see javax.resource.spi.ResourceAdapter#stop() |
||||||
|
*/ |
||||||
|
public class ResourceAdapterFactoryBean implements FactoryBean<ResourceAdapter>, InitializingBean, DisposableBean { |
||||||
|
|
||||||
|
private ResourceAdapter resourceAdapter; |
||||||
|
|
||||||
|
private BootstrapContext bootstrapContext; |
||||||
|
|
||||||
|
private WorkManager workManager; |
||||||
|
|
||||||
|
private XATerminator xaTerminator; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the target JCA ResourceAdapter as class, to be instantiated |
||||||
|
* with its default configuration. |
||||||
|
* <p>Alternatively, specify a pre-configured ResourceAdapter instance |
||||||
|
* through the "resourceAdapter" property. |
||||||
|
* @see #setResourceAdapter |
||||||
|
*/ |
||||||
|
public void setResourceAdapterClass(Class<?> resourceAdapterClass) { |
||||||
|
Assert.isAssignable(ResourceAdapter.class, resourceAdapterClass); |
||||||
|
this.resourceAdapter = (ResourceAdapter) BeanUtils.instantiateClass(resourceAdapterClass); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the target JCA ResourceAdapter, passed in as configured instance |
||||||
|
* which hasn't been started yet. This will typically happen as an |
||||||
|
* inner bean definition, configuring the ResourceAdapter instance |
||||||
|
* through its vendor-specific bean properties. |
||||||
|
*/ |
||||||
|
public void setResourceAdapter(ResourceAdapter resourceAdapter) { |
||||||
|
this.resourceAdapter = resourceAdapter; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the JCA BootstrapContext to use for starting the ResourceAdapter. |
||||||
|
* <p>Alternatively, you can specify the individual parts (such as the |
||||||
|
* JCA WorkManager) as individual references. |
||||||
|
* @see #setWorkManager |
||||||
|
* @see #setXaTerminator |
||||||
|
*/ |
||||||
|
public void setBootstrapContext(BootstrapContext bootstrapContext) { |
||||||
|
this.bootstrapContext = bootstrapContext; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the JCA WorkManager to use for bootstrapping the ResourceAdapter. |
||||||
|
* @see #setBootstrapContext |
||||||
|
*/ |
||||||
|
public void setWorkManager(WorkManager workManager) { |
||||||
|
this.workManager = workManager; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the JCA XATerminator to use for bootstrapping the ResourceAdapter. |
||||||
|
* @see #setBootstrapContext |
||||||
|
*/ |
||||||
|
public void setXaTerminator(XATerminator xaTerminator) { |
||||||
|
this.xaTerminator = xaTerminator; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Builds the BootstrapContext and starts the ResourceAdapter with it. |
||||||
|
* @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext) |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() throws ResourceException { |
||||||
|
if (this.resourceAdapter == null) { |
||||||
|
throw new IllegalArgumentException("'resourceAdapter' or 'resourceAdapterClass' is required"); |
||||||
|
} |
||||||
|
if (this.bootstrapContext == null) { |
||||||
|
this.bootstrapContext = new SimpleBootstrapContext(this.workManager, this.xaTerminator); |
||||||
|
} |
||||||
|
this.resourceAdapter.start(this.bootstrapContext); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public ResourceAdapter getObject() { |
||||||
|
return this.resourceAdapter; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Class<? extends ResourceAdapter> getObjectType() { |
||||||
|
return (this.resourceAdapter != null ? this.resourceAdapter.getClass() : ResourceAdapter.class); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public boolean isSingleton() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Stops the ResourceAdapter. |
||||||
|
* @see javax.resource.spi.ResourceAdapter#stop() |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void destroy() { |
||||||
|
this.resourceAdapter.stop(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,83 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.support; |
||||||
|
|
||||||
|
import java.util.Timer; |
||||||
|
|
||||||
|
import javax.resource.spi.BootstrapContext; |
||||||
|
import javax.resource.spi.UnavailableException; |
||||||
|
import javax.resource.spi.XATerminator; |
||||||
|
import javax.resource.spi.work.WorkManager; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple implementation of the JCA 1.5 {@link javax.resource.spi.BootstrapContext} |
||||||
|
* interface, used for bootstrapping a JCA ResourceAdapter in a local environment. |
||||||
|
* |
||||||
|
* <p>Delegates to the given WorkManager and XATerminator, if any. Creates simple |
||||||
|
* local instances of {@code java.util.Timer}. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0.3 |
||||||
|
* @see javax.resource.spi.ResourceAdapter#start(javax.resource.spi.BootstrapContext) |
||||||
|
* @see ResourceAdapterFactoryBean |
||||||
|
*/ |
||||||
|
public class SimpleBootstrapContext implements BootstrapContext { |
||||||
|
|
||||||
|
private WorkManager workManager; |
||||||
|
|
||||||
|
private XATerminator xaTerminator; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new SimpleBootstrapContext for the given WorkManager, |
||||||
|
* with no XATerminator available. |
||||||
|
* @param workManager the JCA WorkManager to use (may be {@code null}) |
||||||
|
*/ |
||||||
|
public SimpleBootstrapContext(WorkManager workManager) { |
||||||
|
this.workManager = workManager; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new SimpleBootstrapContext for the given WorkManager and XATerminator. |
||||||
|
* @param workManager the JCA WorkManager to use (may be {@code null}) |
||||||
|
* @param xaTerminator the JCA XATerminator to use (may be {@code null}) |
||||||
|
*/ |
||||||
|
public SimpleBootstrapContext(WorkManager workManager, XATerminator xaTerminator) { |
||||||
|
this.workManager = workManager; |
||||||
|
this.xaTerminator = xaTerminator; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public WorkManager getWorkManager() { |
||||||
|
if (this.workManager == null) { |
||||||
|
throw new IllegalStateException("No WorkManager available"); |
||||||
|
} |
||||||
|
return this.workManager; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public XATerminator getXATerminator() { |
||||||
|
return this.xaTerminator; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Timer createTimer() throws UnavailableException { |
||||||
|
return new Timer(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Provides generic support classes for JCA usage within Spring, |
||||||
|
* mainly for local setup of a JCA ResourceAdapter and/or ConnectionFactory. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.jca.support; |
||||||
|
|
@ -0,0 +1,69 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.work; |
||||||
|
|
||||||
|
import javax.resource.spi.work.Work; |
||||||
|
|
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple Work adapter that delegates to a given Runnable. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0.3 |
||||||
|
* @see javax.resource.spi.work.Work |
||||||
|
* @see Runnable |
||||||
|
*/ |
||||||
|
public class DelegatingWork implements Work { |
||||||
|
|
||||||
|
private final Runnable delegate; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new DelegatingWork. |
||||||
|
* @param delegate the Runnable implementation to delegate to |
||||||
|
*/ |
||||||
|
public DelegatingWork(Runnable delegate) { |
||||||
|
Assert.notNull(delegate, "Delegate must not be null"); |
||||||
|
this.delegate = delegate; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the wrapped Runnable implementation. |
||||||
|
*/ |
||||||
|
public final Runnable getDelegate() { |
||||||
|
return this.delegate; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Delegates execution to the underlying Runnable. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
this.delegate.run(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This implementation is empty, since we expect the Runnable |
||||||
|
* to terminate based on some specific shutdown signal. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void release() { |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,260 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2012 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.work; |
||||||
|
|
||||||
|
import javax.resource.spi.work.ExecutionContext; |
||||||
|
import javax.resource.spi.work.Work; |
||||||
|
import javax.resource.spi.work.WorkAdapter; |
||||||
|
import javax.resource.spi.work.WorkCompletedException; |
||||||
|
import javax.resource.spi.work.WorkEvent; |
||||||
|
import javax.resource.spi.work.WorkException; |
||||||
|
import javax.resource.spi.work.WorkListener; |
||||||
|
import javax.resource.spi.work.WorkManager; |
||||||
|
import javax.resource.spi.work.WorkRejectedException; |
||||||
|
|
||||||
|
import com.fr.third.springframework.core.task.AsyncTaskExecutor; |
||||||
|
import com.fr.third.springframework.core.task.SimpleAsyncTaskExecutor; |
||||||
|
import com.fr.third.springframework.core.task.SyncTaskExecutor; |
||||||
|
import com.fr.third.springframework.core.task.TaskExecutor; |
||||||
|
import com.fr.third.springframework.core.task.TaskRejectedException; |
||||||
|
import com.fr.third.springframework.core.task.TaskTimeoutException; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
|
||||||
|
/** |
||||||
|
* Simple JCA 1.5 {@link javax.resource.spi.work.WorkManager} implementation that |
||||||
|
* delegates to a Spring {@link com.fr.third.springframework.core.task.TaskExecutor}. |
||||||
|
* Provides simple task execution including start timeouts, but without support |
||||||
|
* for a JCA ExecutionContext (i.e. without support for imported transactions). |
||||||
|
* |
||||||
|
* <p>Uses a {@link com.fr.third.springframework.core.task.SyncTaskExecutor} for {@link #doWork} |
||||||
|
* calls and a {@link com.fr.third.springframework.core.task.SimpleAsyncTaskExecutor} |
||||||
|
* for {@link #startWork} and {@link #scheduleWork} calls, by default. |
||||||
|
* These default task executors can be overridden through configuration. |
||||||
|
* |
||||||
|
* <p><b>NOTE: This WorkManager does not provide thread pooling by default!</b> |
||||||
|
* Specify a {@link com.fr.third.springframework.scheduling.concurrent.ThreadPoolTaskExecutor} |
||||||
|
* (or any other thread-pooling TaskExecutor) as "asyncTaskExecutor" in order to |
||||||
|
* achieve actual thread pooling. |
||||||
|
* |
||||||
|
* <p>This WorkManager automatically detects a specified |
||||||
|
* {@link com.fr.third.springframework.core.task.AsyncTaskExecutor} implementation |
||||||
|
* and uses its extended timeout functionality where appropriate. |
||||||
|
* JCA WorkListeners are fully supported in any case. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0.3 |
||||||
|
* @see #setSyncTaskExecutor |
||||||
|
* @see #setAsyncTaskExecutor |
||||||
|
*/ |
||||||
|
public class SimpleTaskWorkManager implements WorkManager { |
||||||
|
|
||||||
|
private TaskExecutor syncTaskExecutor = new SyncTaskExecutor(); |
||||||
|
|
||||||
|
private AsyncTaskExecutor asyncTaskExecutor = new SimpleAsyncTaskExecutor(); |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the TaskExecutor to use for <i>synchronous</i> work execution |
||||||
|
* (i.e. {@link #doWork} calls). |
||||||
|
* <p>Default is a {@link com.fr.third.springframework.core.task.SyncTaskExecutor}. |
||||||
|
*/ |
||||||
|
public void setSyncTaskExecutor(TaskExecutor syncTaskExecutor) { |
||||||
|
this.syncTaskExecutor = syncTaskExecutor; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the TaskExecutor to use for <i>asynchronous</i> work execution |
||||||
|
* (i.e. {@link #startWork} and {@link #scheduleWork} calls). |
||||||
|
* <p>This will typically (but not necessarily) be an |
||||||
|
* {@link com.fr.third.springframework.core.task.AsyncTaskExecutor} implementation. |
||||||
|
* Default is a {@link com.fr.third.springframework.core.task.SimpleAsyncTaskExecutor}. |
||||||
|
*/ |
||||||
|
public void setAsyncTaskExecutor(AsyncTaskExecutor asyncTaskExecutor) { |
||||||
|
this.asyncTaskExecutor = asyncTaskExecutor; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void doWork(Work work) throws WorkException { |
||||||
|
doWork(work, WorkManager.INDEFINITE, null, null); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doWork(Work work, long startTimeout, ExecutionContext executionContext, WorkListener workListener) |
||||||
|
throws WorkException { |
||||||
|
|
||||||
|
Assert.state(this.syncTaskExecutor != null, "No 'syncTaskExecutor' set"); |
||||||
|
executeWork(this.syncTaskExecutor, work, startTimeout, false, executionContext, workListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long startWork(Work work) throws WorkException { |
||||||
|
return startWork(work, WorkManager.INDEFINITE, null, null); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long startWork(Work work, long startTimeout, ExecutionContext executionContext, WorkListener workListener) |
||||||
|
throws WorkException { |
||||||
|
|
||||||
|
Assert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set"); |
||||||
|
return executeWork(this.asyncTaskExecutor, work, startTimeout, true, executionContext, workListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void scheduleWork(Work work) throws WorkException { |
||||||
|
scheduleWork(work, WorkManager.INDEFINITE, null, null); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void scheduleWork(Work work, long startTimeout, ExecutionContext executionContext, WorkListener workListener) |
||||||
|
throws WorkException { |
||||||
|
|
||||||
|
Assert.state(this.asyncTaskExecutor != null, "No 'asyncTaskExecutor' set"); |
||||||
|
executeWork(this.asyncTaskExecutor, work, startTimeout, false, executionContext, workListener); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Execute the given Work on the specified TaskExecutor. |
||||||
|
* @param taskExecutor the TaskExecutor to use |
||||||
|
* @param work the Work to execute |
||||||
|
* @param startTimeout the time duration within which the Work is supposed to start |
||||||
|
* @param blockUntilStarted whether to block until the Work has started |
||||||
|
* @param executionContext the JCA ExecutionContext for the given Work |
||||||
|
* @param workListener the WorkListener to clal for the given Work |
||||||
|
* @return the time elapsed from Work acceptance until start of execution |
||||||
|
* (or -1 if not applicable or not known) |
||||||
|
* @throws WorkException if the TaskExecutor did not accept the Work |
||||||
|
*/ |
||||||
|
protected long executeWork(TaskExecutor taskExecutor, Work work, long startTimeout, |
||||||
|
boolean blockUntilStarted, ExecutionContext executionContext, WorkListener workListener) |
||||||
|
throws WorkException { |
||||||
|
|
||||||
|
if (executionContext != null && executionContext.getXid() != null) { |
||||||
|
throw new WorkException("SimpleTaskWorkManager does not supported imported XIDs: " + executionContext.getXid()); |
||||||
|
} |
||||||
|
WorkListener workListenerToUse = workListener; |
||||||
|
if (workListenerToUse == null) { |
||||||
|
workListenerToUse = new WorkAdapter(); |
||||||
|
} |
||||||
|
|
||||||
|
boolean isAsync = (taskExecutor instanceof AsyncTaskExecutor); |
||||||
|
DelegatingWorkAdapter workHandle = new DelegatingWorkAdapter(work, workListenerToUse, !isAsync); |
||||||
|
try { |
||||||
|
if (isAsync) { |
||||||
|
((AsyncTaskExecutor) taskExecutor).execute(workHandle, startTimeout); |
||||||
|
} |
||||||
|
else { |
||||||
|
taskExecutor.execute(workHandle); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (TaskTimeoutException ex) { |
||||||
|
WorkException wex = new WorkRejectedException("TaskExecutor rejected Work because of timeout: " + work, ex); |
||||||
|
wex.setErrorCode(WorkException.START_TIMED_OUT); |
||||||
|
workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex)); |
||||||
|
throw wex; |
||||||
|
} |
||||||
|
catch (TaskRejectedException ex) { |
||||||
|
WorkException wex = new WorkRejectedException("TaskExecutor rejected Work: " + work, ex); |
||||||
|
wex.setErrorCode(WorkException.INTERNAL); |
||||||
|
workListenerToUse.workRejected(new WorkEvent(this, WorkEvent.WORK_REJECTED, work, wex)); |
||||||
|
throw wex; |
||||||
|
} |
||||||
|
catch (Throwable ex) { |
||||||
|
WorkException wex = new WorkException("TaskExecutor failed to execute Work: " + work, ex); |
||||||
|
wex.setErrorCode(WorkException.INTERNAL); |
||||||
|
throw wex; |
||||||
|
} |
||||||
|
if (isAsync) { |
||||||
|
workListenerToUse.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null)); |
||||||
|
} |
||||||
|
|
||||||
|
if (blockUntilStarted) { |
||||||
|
long acceptanceTime = System.currentTimeMillis(); |
||||||
|
synchronized (workHandle.monitor) { |
||||||
|
try { |
||||||
|
while (!workHandle.started) { |
||||||
|
workHandle.monitor.wait(); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (InterruptedException ex) { |
||||||
|
Thread.currentThread().interrupt(); |
||||||
|
} |
||||||
|
} |
||||||
|
return (System.currentTimeMillis() - acceptanceTime); |
||||||
|
} |
||||||
|
else { |
||||||
|
return WorkManager.UNKNOWN; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Work adapter that supports start timeouts and WorkListener callbacks |
||||||
|
* for a given Work that it delegates to. |
||||||
|
*/ |
||||||
|
private static class DelegatingWorkAdapter implements Work { |
||||||
|
|
||||||
|
private final Work work; |
||||||
|
|
||||||
|
private final WorkListener workListener; |
||||||
|
|
||||||
|
private final boolean acceptOnExecution; |
||||||
|
|
||||||
|
public final Object monitor = new Object(); |
||||||
|
|
||||||
|
public boolean started = false; |
||||||
|
|
||||||
|
public DelegatingWorkAdapter(Work work, WorkListener workListener, boolean acceptOnExecution) { |
||||||
|
this.work = work; |
||||||
|
this.workListener = workListener; |
||||||
|
this.acceptOnExecution = acceptOnExecution; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void run() { |
||||||
|
if (this.acceptOnExecution) { |
||||||
|
this.workListener.workAccepted(new WorkEvent(this, WorkEvent.WORK_ACCEPTED, work, null)); |
||||||
|
} |
||||||
|
synchronized (this.monitor) { |
||||||
|
this.started = true; |
||||||
|
this.monitor.notify(); |
||||||
|
} |
||||||
|
this.workListener.workStarted(new WorkEvent(this, WorkEvent.WORK_STARTED, this.work, null)); |
||||||
|
try { |
||||||
|
this.work.run(); |
||||||
|
} |
||||||
|
catch (RuntimeException ex) { |
||||||
|
this.workListener.workCompleted( |
||||||
|
new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, new WorkCompletedException(ex))); |
||||||
|
throw ex; |
||||||
|
} |
||||||
|
catch (Error err) { |
||||||
|
this.workListener.workCompleted( |
||||||
|
new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, new WorkCompletedException(err))); |
||||||
|
throw err; |
||||||
|
} |
||||||
|
this.workListener.workCompleted(new WorkEvent(this, WorkEvent.WORK_COMPLETED, this.work, null)); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void release() { |
||||||
|
this.work.release(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,319 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2013 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.work; |
||||||
|
|
||||||
|
import java.util.concurrent.Callable; |
||||||
|
import java.util.concurrent.Future; |
||||||
|
import java.util.concurrent.FutureTask; |
||||||
|
import javax.naming.NamingException; |
||||||
|
import javax.resource.spi.BootstrapContext; |
||||||
|
import javax.resource.spi.work.ExecutionContext; |
||||||
|
import javax.resource.spi.work.Work; |
||||||
|
import javax.resource.spi.work.WorkException; |
||||||
|
import javax.resource.spi.work.WorkListener; |
||||||
|
import javax.resource.spi.work.WorkManager; |
||||||
|
import javax.resource.spi.work.WorkRejectedException; |
||||||
|
|
||||||
|
import com.fr.third.springframework.beans.factory.InitializingBean; |
||||||
|
import com.fr.third.springframework.core.task.AsyncListenableTaskExecutor; |
||||||
|
import com.fr.third.springframework.core.task.TaskRejectedException; |
||||||
|
import com.fr.third.springframework.core.task.TaskTimeoutException; |
||||||
|
import com.fr.third.springframework.jca.context.BootstrapContextAware; |
||||||
|
import com.fr.third.springframework.jndi.JndiLocatorSupport; |
||||||
|
import com.fr.third.springframework.scheduling.SchedulingException; |
||||||
|
import com.fr.third.springframework.scheduling.SchedulingTaskExecutor; |
||||||
|
import com.fr.third.springframework.util.Assert; |
||||||
|
import com.fr.third.springframework.util.concurrent.ListenableFuture; |
||||||
|
import com.fr.third.springframework.util.concurrent.ListenableFutureTask; |
||||||
|
|
||||||
|
/** |
||||||
|
* {@link com.fr.third.springframework.core.task.TaskExecutor} implementation |
||||||
|
* that delegates to a JCA 1.5 WorkManager, implementing the |
||||||
|
* {@link javax.resource.spi.work.WorkManager} interface. |
||||||
|
* |
||||||
|
* <p>This is mainly intended for use within a JCA ResourceAdapter implementation, |
||||||
|
* but may also be used in a standalone environment, delegating to a locally |
||||||
|
* embedded WorkManager implementation (such as Geronimo's). |
||||||
|
* |
||||||
|
* <p>Also implements the JCA 1.5 WorkManager interface itself, delegating all |
||||||
|
* calls to the target WorkManager. Hence, a caller can choose whether it wants |
||||||
|
* to talk to this executor through the Spring TaskExecutor interface or the |
||||||
|
* JCA 1.5 WorkManager interface. |
||||||
|
* |
||||||
|
* <p>This adapter is also capable of obtaining a JCA WorkManager from JNDI. |
||||||
|
* This is for example appropriate on the Geronimo application server, where |
||||||
|
* WorkManager GBeans (e.g. Geronimo's default "DefaultWorkManager" GBean) |
||||||
|
* can be linked into the J2EE environment through "gbean-ref" entries |
||||||
|
* in the {@code geronimo-web.xml} deployment descriptor. |
||||||
|
* |
||||||
|
* <p><b>On JBoss and GlassFish, obtaining the default JCA WorkManager |
||||||
|
* requires special lookup steps.</b> See the |
||||||
|
* {@link com.fr.third.springframework.jca.work.jboss.JBossWorkManagerTaskExecutor} |
||||||
|
* {@link com.fr.third.springframework.jca.work.glassfish.GlassFishWorkManagerTaskExecutor} |
||||||
|
* classes which are the direct equivalent of this generic JCA adapter class. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.0.3 |
||||||
|
* @see #setWorkManager |
||||||
|
* @see javax.resource.spi.work.WorkManager#scheduleWork |
||||||
|
*/ |
||||||
|
public class WorkManagerTaskExecutor extends JndiLocatorSupport |
||||||
|
implements AsyncListenableTaskExecutor, SchedulingTaskExecutor, WorkManager, BootstrapContextAware, InitializingBean { |
||||||
|
|
||||||
|
private WorkManager workManager; |
||||||
|
|
||||||
|
private String workManagerName; |
||||||
|
|
||||||
|
private boolean blockUntilStarted = false; |
||||||
|
|
||||||
|
private boolean blockUntilCompleted = false; |
||||||
|
|
||||||
|
private WorkListener workListener; |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new WorkManagerTaskExecutor, expecting bean-style configuration. |
||||||
|
* @see #setWorkManager |
||||||
|
*/ |
||||||
|
public WorkManagerTaskExecutor() { |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Create a new WorkManagerTaskExecutor for the given WorkManager. |
||||||
|
* @param workManager the JCA WorkManager to delegate to |
||||||
|
*/ |
||||||
|
public WorkManagerTaskExecutor(WorkManager workManager) { |
||||||
|
setWorkManager(workManager); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the JCA WorkManager instance to delegate to. |
||||||
|
*/ |
||||||
|
public void setWorkManager(WorkManager workManager) { |
||||||
|
Assert.notNull(workManager, "WorkManager must not be null"); |
||||||
|
this.workManager = workManager; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set the JNDI name of the JCA WorkManager. |
||||||
|
* <p>This can either be a fully qualified JNDI name, |
||||||
|
* or the JNDI name relative to the current environment |
||||||
|
* naming context if "resourceRef" is set to "true". |
||||||
|
* @see #setWorkManager |
||||||
|
* @see #setResourceRef |
||||||
|
*/ |
||||||
|
public void setWorkManagerName(String workManagerName) { |
||||||
|
this.workManagerName = workManagerName; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify the JCA BootstrapContext that contains the |
||||||
|
* WorkManager to delegate to. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public void setBootstrapContext(BootstrapContext bootstrapContext) { |
||||||
|
Assert.notNull(bootstrapContext, "BootstrapContext must not be null"); |
||||||
|
this.workManager = bootstrapContext.getWorkManager(); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set whether to let {@link #execute} block until the work |
||||||
|
* has been actually started. |
||||||
|
* <p>Uses the JCA {@code startWork} operation underneath, |
||||||
|
* instead of the default {@code scheduleWork}. |
||||||
|
* @see javax.resource.spi.work.WorkManager#startWork |
||||||
|
* @see javax.resource.spi.work.WorkManager#scheduleWork |
||||||
|
*/ |
||||||
|
public void setBlockUntilStarted(boolean blockUntilStarted) { |
||||||
|
this.blockUntilStarted = blockUntilStarted; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Set whether to let {@link #execute} block until the work |
||||||
|
* has been completed. |
||||||
|
* <p>Uses the JCA {@code doWork} operation underneath, |
||||||
|
* instead of the default {@code scheduleWork}. |
||||||
|
* @see javax.resource.spi.work.WorkManager#doWork |
||||||
|
* @see javax.resource.spi.work.WorkManager#scheduleWork |
||||||
|
*/ |
||||||
|
public void setBlockUntilCompleted(boolean blockUntilCompleted) { |
||||||
|
this.blockUntilCompleted = blockUntilCompleted; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Specify a JCA 1.5 WorkListener to apply, if any. |
||||||
|
* <p>This shared WorkListener instance will be passed on to the |
||||||
|
* WorkManager by all {@link #execute} calls on this TaskExecutor. |
||||||
|
*/ |
||||||
|
public void setWorkListener(WorkListener workListener) { |
||||||
|
this.workListener = workListener; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void afterPropertiesSet() throws NamingException { |
||||||
|
if (this.workManager == null) { |
||||||
|
if (this.workManagerName != null) { |
||||||
|
this.workManager = lookup(this.workManagerName, WorkManager.class); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.workManager = getDefaultWorkManager(); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Obtain a default WorkManager to delegate to. |
||||||
|
* Called if no explicit WorkManager or WorkManager JNDI name has been specified. |
||||||
|
* <p>The default implementation returns a {@link SimpleTaskWorkManager}. |
||||||
|
* Can be overridden in subclasses. |
||||||
|
*/ |
||||||
|
protected WorkManager getDefaultWorkManager() { |
||||||
|
return new SimpleTaskWorkManager(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Implementation of the Spring SchedulingTaskExecutor interface
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void execute(Runnable task) { |
||||||
|
execute(task, TIMEOUT_INDEFINITE); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void execute(Runnable task, long startTimeout) { |
||||||
|
Assert.state(this.workManager != null, "No WorkManager specified"); |
||||||
|
Work work = new DelegatingWork(task); |
||||||
|
try { |
||||||
|
if (this.blockUntilCompleted) { |
||||||
|
if (startTimeout != TIMEOUT_INDEFINITE || this.workListener != null) { |
||||||
|
this.workManager.doWork(work, startTimeout, null, this.workListener); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.workManager.doWork(work); |
||||||
|
} |
||||||
|
} |
||||||
|
else if (this.blockUntilStarted) { |
||||||
|
if (startTimeout != TIMEOUT_INDEFINITE || this.workListener != null) { |
||||||
|
this.workManager.startWork(work, startTimeout, null, this.workListener); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.workManager.startWork(work); |
||||||
|
} |
||||||
|
} |
||||||
|
else { |
||||||
|
if (startTimeout != TIMEOUT_INDEFINITE || this.workListener != null) { |
||||||
|
this.workManager.scheduleWork(work, startTimeout, null, this.workListener); |
||||||
|
} |
||||||
|
else { |
||||||
|
this.workManager.scheduleWork(work); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
catch (WorkRejectedException ex) { |
||||||
|
if (WorkException.START_TIMED_OUT.equals(ex.getErrorCode())) { |
||||||
|
throw new TaskTimeoutException("JCA WorkManager rejected task because of timeout: " + task, ex); |
||||||
|
} |
||||||
|
else { |
||||||
|
throw new TaskRejectedException("JCA WorkManager rejected task: " + task, ex); |
||||||
|
} |
||||||
|
} |
||||||
|
catch (WorkException ex) { |
||||||
|
throw new SchedulingException("Could not schedule task on JCA WorkManager", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public Future<?> submit(Runnable task) { |
||||||
|
FutureTask<Object> future = new FutureTask<Object>(task, null); |
||||||
|
execute(future, TIMEOUT_INDEFINITE); |
||||||
|
return future; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> Future<T> submit(Callable<T> task) { |
||||||
|
FutureTask<T> future = new FutureTask<T>(task); |
||||||
|
execute(future, TIMEOUT_INDEFINITE); |
||||||
|
return future; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public ListenableFuture<?> submitListenable(Runnable task) { |
||||||
|
ListenableFutureTask<Object> future = new ListenableFutureTask<Object>(task, null); |
||||||
|
execute(future, TIMEOUT_INDEFINITE); |
||||||
|
return future; |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> ListenableFuture<T> submitListenable(Callable<T> task) { |
||||||
|
ListenableFutureTask<T> future = new ListenableFutureTask<T>(task); |
||||||
|
execute(future, TIMEOUT_INDEFINITE); |
||||||
|
return future; |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* This task executor prefers short-lived work units. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
public boolean prefersShortLivedTasks() { |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// Implementation of the JCA WorkManager interface
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override |
||||||
|
public void doWork(Work work) throws WorkException { |
||||||
|
this.workManager.doWork(work); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void doWork(Work work, long delay, ExecutionContext executionContext, WorkListener workListener) |
||||||
|
throws WorkException { |
||||||
|
|
||||||
|
this.workManager.doWork(work, delay, executionContext, workListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long startWork(Work work) throws WorkException { |
||||||
|
return this.workManager.startWork(work); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public long startWork(Work work, long delay, ExecutionContext executionContext, WorkListener workListener) |
||||||
|
throws WorkException { |
||||||
|
|
||||||
|
return this.workManager.startWork(work, delay, executionContext, workListener); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void scheduleWork(Work work) throws WorkException { |
||||||
|
this.workManager.scheduleWork(work); |
||||||
|
} |
||||||
|
|
||||||
|
@Override |
||||||
|
public void scheduleWork(Work work, long delay, ExecutionContext executionContext, WorkListener workListener) |
||||||
|
throws WorkException { |
||||||
|
|
||||||
|
this.workManager.scheduleWork(work, delay, executionContext, workListener); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,81 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2013 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.work.glassfish; |
||||||
|
|
||||||
|
import java.lang.reflect.Method; |
||||||
|
import javax.resource.spi.work.WorkManager; |
||||||
|
|
||||||
|
import com.fr.third.springframework.jca.work.WorkManagerTaskExecutor; |
||||||
|
import com.fr.third.springframework.util.ReflectionUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Spring TaskExecutor adapter for the GlassFish JCA WorkManager. |
||||||
|
* Can be defined in web applications to make a TaskExecutor reference |
||||||
|
* available, talking to the GlassFish WorkManager (thread pool) underneath. |
||||||
|
* |
||||||
|
* <p>This is the GlassFish equivalent of the CommonJ |
||||||
|
* {@link com.fr.third.springframework.scheduling.commonj.WorkManagerTaskExecutor} |
||||||
|
* adapter for WebLogic and WebSphere. |
||||||
|
* |
||||||
|
* <p>Note: On GlassFish 4 and higher, a |
||||||
|
* {@link com.fr.third.springframework.scheduling.concurrent.DefaultManagedTaskExecutor} |
||||||
|
* should be preferred, following JSR-236 support in Java EE 7. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.5.2 |
||||||
|
*/ |
||||||
|
public class GlassFishWorkManagerTaskExecutor extends WorkManagerTaskExecutor { |
||||||
|
|
||||||
|
private static final String WORK_MANAGER_FACTORY_CLASS = "com.sun.enterprise.connectors.work.WorkManagerFactory"; |
||||||
|
|
||||||
|
private final Method getWorkManagerMethod; |
||||||
|
|
||||||
|
|
||||||
|
public GlassFishWorkManagerTaskExecutor() { |
||||||
|
try { |
||||||
|
Class<?> wmf = getClass().getClassLoader().loadClass(WORK_MANAGER_FACTORY_CLASS); |
||||||
|
this.getWorkManagerMethod = wmf.getMethod("getWorkManager", String.class); |
||||||
|
} |
||||||
|
catch (Exception ex) { |
||||||
|
throw new IllegalStateException( |
||||||
|
"Could not initialize GlassFishWorkManagerTaskExecutor because GlassFish API is not available", ex); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Identify a specific GlassFish thread pool to talk to. |
||||||
|
* <p>The thread pool name matches the resource adapter name |
||||||
|
* in default RAR deployment scenarios. |
||||||
|
*/ |
||||||
|
public void setThreadPoolName(String threadPoolName) { |
||||||
|
WorkManager wm = (WorkManager) ReflectionUtils.invokeMethod(this.getWorkManagerMethod, null, threadPoolName); |
||||||
|
if (wm == null) { |
||||||
|
throw new IllegalArgumentException("Specified thread pool name '" + threadPoolName + |
||||||
|
"' does not correspond to an actual pool definition in GlassFish. Check your configuration!"); |
||||||
|
} |
||||||
|
setWorkManager(wm); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Obtains GlassFish's default thread pool. |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
protected WorkManager getDefaultWorkManager() { |
||||||
|
return (WorkManager) ReflectionUtils.invokeMethod(this.getWorkManagerMethod, null, new Object[] {null}); |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,9 @@ |
|||||||
|
|
||||||
|
/** |
||||||
|
* |
||||||
|
* Convenience package for obtaining a GlassFish JCA WorkManager for use in |
||||||
|
* web applications. Provides a Spring TaskExecutor adapter for GlassFish. |
||||||
|
* |
||||||
|
*/ |
||||||
|
package com.fr.third.springframework.jca.work.glassfish; |
||||||
|
|
@ -0,0 +1,67 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2002-2013 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. |
||||||
|
*/ |
||||||
|
|
||||||
|
package com.fr.third.springframework.jca.work.jboss; |
||||||
|
|
||||||
|
import javax.resource.spi.work.WorkManager; |
||||||
|
|
||||||
|
import com.fr.third.springframework.jca.work.WorkManagerTaskExecutor; |
||||||
|
|
||||||
|
/** |
||||||
|
* Spring TaskExecutor adapter for the JBoss JCA WorkManager. |
||||||
|
* Can be defined in web applications to make a TaskExecutor reference |
||||||
|
* available, talking to the JBoss WorkManager (thread pool) underneath. |
||||||
|
* |
||||||
|
* <p>This is the JBoss equivalent of the CommonJ |
||||||
|
* {@link com.fr.third.springframework.scheduling.commonj.WorkManagerTaskExecutor} |
||||||
|
* adapter for WebLogic and WebSphere. |
||||||
|
* |
||||||
|
* <p>This class does not work on JBoss 7 or higher. There is no known |
||||||
|
* immediate replacement, since JBoss does not want its JCA WorkManager |
||||||
|
* to be exposed anymore. As of JBoss/WildFly 8, a |
||||||
|
* {@link com.fr.third.springframework.scheduling.concurrent.DefaultManagedTaskExecutor} |
||||||
|
* may be used, following JSR-236 support in Java EE 7. |
||||||
|
* |
||||||
|
* @author Juergen Hoeller |
||||||
|
* @since 2.5.2 |
||||||
|
* @see org.jboss.resource.work.JBossWorkManagerMBean |
||||||
|
* @deprecated as of Spring 4.0, since there are no fully supported versions |
||||||
|
* of JBoss that this class works with anymore |
||||||
|
*/ |
||||||
|
@Deprecated |
||||||
|
public class JBossWorkManagerTaskExecutor extends WorkManagerTaskExecutor { |
||||||
|
|
||||||
|
/** |
||||||
|
* Identify a specific JBossWorkManagerMBean to talk to, |
||||||
|
* through its JMX object name. |
||||||
|
* <p>The default MBean name is "jboss.jca:service=WorkManager". |
||||||
|
* @see JBossWorkManagerUtils#getWorkManager(String) |
||||||
|
*/ |
||||||
|
public void setWorkManagerMBeanName(String mbeanName) { |
||||||
|
setWorkManager(JBossWorkManagerUtils.getWorkManager(mbeanName)); |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Obtains the default JBoss JCA WorkManager through a JMX lookup |
||||||
|
* for the JBossWorkManagerMBean. |
||||||
|
* @see JBossWorkManagerUtils#getWorkManager() |
||||||
|
*/ |
||||||
|
@Override |
||||||
|
protected WorkManager getDefaultWorkManager() { |
||||||
|
return JBossWorkManagerUtils.getWorkManager(); |
||||||
|
} |
||||||
|
|
||||||
|
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue