Browse Source
* commit '145bd139ed1f06c6b41838765df383e9d0f9a273': KERNEL-753 增加对LDAP的支持,将Spring的LDAP模块编译到third中research/11.0
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