-
Notifications
You must be signed in to change notification settings - Fork 5
/
EnforceT.groovy
176 lines (158 loc) · 8.5 KB
/
EnforceT.groovy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*
* Some of the setup is derived from the fllowing grails plugings(Appache Licence)
* https://github.com/groovy/groovy-core/blob/4993b10737881b2491c2daa01526fb15dd889ac5/src/main/org/codehaus/groovy/transform/NewifyASTTransformation.java
* https://github.com/grails-plugins/grails-redis/tree/master/src/main/groovy/grails/plugins/redis
*/
package com.virtualdogbert.ast
import org.codehaus.groovy.transform.GroovyASTTransformationClass
import org.grails.datastore.mapping.core.connections.ConnectionSourcesProvider
import org.springframework.transaction.annotation.Isolation
import org.springframework.transaction.annotation.Propagation
import java.lang.annotation.ElementType
import java.lang.annotation.Retention
import java.lang.annotation.RetentionPolicy
import java.lang.annotation.Target
/**
* The annotation enforce takes up to 3 closures can injects a call to the enforce method of the enforcerService at the
* beginning of the method.
*
* This can be applied to a method or a class, but the method will take precedence.
*
* This also adds transactionality to the method using the transform from @Transactional.
*
* The first closure is value, just so that the transform can be called without naming the parameter.
* If your specifying two or more closures you will have to specify there names in the annotation call.
* Examples:
* @Enforce ( { true } )
* @Enforce ( value = { true } , failure = { println " nice " } )
* @Enforce ( value = { true } , failure = { println " nice " } , success = { println " not nice " } )
* @Enforce ( value = { false } , failure = { println " not nice " } , success = { println " nice " } )
*
* parameters
* value is the predicate for the enforce service, named value so that you don't have to name it
* failure is the code to run if the predicate returns false, if not specified, the default for the enforcerService is used.
* success the code to run if the predicate returns true, if not specified, the default for the enforcerService is used.
* All the parameters that @ Transactional can take, listed below.
*/
@Retention(RetentionPolicy.SOURCE)
@Target([ElementType.TYPE, ElementType.METHOD])
@GroovyASTTransformationClass("com.virtualdogbert.ast.EnforceTASTTransformation")
@interface EnforceT {
Class value()
Class failure() default { false }
Class success() default { true }
/**
* A qualifier value for the specified transaction.
* <p>May be used to determine the target transaction manager,
* matching the qualifier value (or the bean name) of a specific
* {@link org.springframework.transaction.PlatformTransactionManager}
* bean definition.
*/
String transactionalValue() default "";
/**
* The transaction propagation type.
* Defaults to {@link org.springframework.transaction.annotation.Propagation#REQUIRED}.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getPropagationBehavior()
*/
Propagation propagation() default Propagation.REQUIRED;
/**
* The transaction isolation level.
* Defaults to {@link org.springframework.transaction.annotation.Isolation#DEFAULT}.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getIsolationLevel()
*/
Isolation isolation() default Isolation.DEFAULT;
/**
* The timeout for this transaction.
* Defaults to the default timeout of the underlying transaction system.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout()
*/
int timeout() default -1;
/**
* {@code true} if the transaction is read-only.
* Defaults to {@code false}.
* <p>This just serves as a hint for the actual transaction subsystem;
* it will <i>not necessarily</i> cause failure of write access attempts.
* A transaction manager which cannot interpret the read-only hint will
* <i>not</i> throw an exception when asked for a read-only transaction.
* @see org.springframework.transaction.interceptor.TransactionAttribute#isReadOnly()
*/
boolean readOnly() default false;
/**
* Defines zero (0) or more exception {@link Class classes}, which must be a
* subclass of {@link Throwable}, indicating which exception types must cause
* a transaction rollback.
* <p>This is the preferred way to construct a rollback rule, matching the
* exception class and subclasses.
* <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(Class clazz)}
*/
Class<? extends Throwable>[] rollbackFor() default [];
/**
* Defines zero (0) or more exception names (for exceptions which must be a
* subclass of {@link Throwable}), indicating which exception types must cause
* a transaction rollback.
* <p>This can be a substring, with no wildcard support at present.
* A value of "ServletException" would match
* javax.servlet.ServletException and subclasses, for example.
* <p><b>NB: </b>Consider carefully how specific the pattern is, and whether
* to include package information (which isn't mandatory). For example,
* "Exception" will match nearly anything, and will probably hide other rules.
* "java.lang.Exception" would be correct if "Exception" was meant to define
* a rule for all checked exceptions. With more unusual {@link Exception}
* names such as "BaseBusinessException" there is no need to use a FQN.
* <p>Similar to {@link org.springframework.transaction.interceptor.RollbackRuleAttribute#RollbackRuleAttribute(String exceptionName)}
*/
String[] rollbackForClassName() default [];
/**
* Defines zero (0) or more exception {@link Class Classes}, which must be a
* subclass of {@link Throwable}, indicating which exception types must <b>not</b>
* cause a transaction rollback.
* <p>This is the preferred way to construct a rollback rule, matching the
* exception class and subclasses.
* <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(Class clazz)}
*/
Class<? extends Throwable>[] noRollbackFor() default [];
/**
* Defines zero (0) or more exception names (for exceptions which must be a
* subclass of {@link Throwable}) indicating which exception types must <b>not</b>
* cause a transaction rollback.
* <p>See the description of {@link #rollbackForClassName()} for more info on how
* the specified names are treated.
* <p>Similar to {@link org.springframework.transaction.interceptor.NoRollbackRuleAttribute#NoRollbackRuleAttribute(String exceptionName)}
*/
String[] noRollbackForClassName() default [];
/**
* In Spring, when there are nested transaction calls, the execution of the outermost callback will throw UnexpectedRollbackException if TransactionStatus.setRollbackOnly() was called in a nested transaction callback.
*
* This feature will make the setRollbackOnly state get inherited to parent level transaction template calls and therefore prevent UnexpectedRollbackException.
* The default value is true.
*
*/
boolean inheritRollbackOnly() default true;
/**
* If you are using multiple GORM implementations and wish to create a transaction for a specific implementation then use this. For example {@code @Transactional(forDatastore=HibernateDatastore) }
*
* @return The type of the datastore
*/
Class<? extends ConnectionSourcesProvider>[] datastore() default [];
/**
* The connection to use by default
*/
String connection() default "DEFAULT";
}