-
Notifications
You must be signed in to change notification settings - Fork 37.8k
/
JmsAccessor.java
223 lines (197 loc) · 8.41 KB
/
JmsAccessor.java
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/*
* Copyright 2002-2018 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
*
* https://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 org.springframework.jms.support;
import jakarta.jms.Connection;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.JMSException;
import jakarta.jms.Session;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.core.Constants;
import org.springframework.jms.JmsException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
/**
* Base class for {@link org.springframework.jms.core.JmsTemplate} and other
* JMS-accessing gateway helpers, defining common properties such as the
* JMS {@link ConnectionFactory} to operate on. The subclass
* {@link org.springframework.jms.support.destination.JmsDestinationAccessor}
* adds further, destination-related properties.
*
* <p>Not intended to be used directly.
* See {@link org.springframework.jms.core.JmsTemplate}.
*
* @author Juergen Hoeller
* @since 1.2
* @see org.springframework.jms.support.destination.JmsDestinationAccessor
* @see org.springframework.jms.core.JmsTemplate
*/
public abstract class JmsAccessor implements InitializingBean {
/** Constants instance for {@code jakarta.jms.Session}. */
private static final Constants sessionConstants = new Constants(Session.class);
/** Logger available to subclasses. */
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private ConnectionFactory connectionFactory;
private boolean sessionTransacted = false;
private int sessionAcknowledgeMode = Session.AUTO_ACKNOWLEDGE;
/**
* Set the ConnectionFactory to use for obtaining JMS {@link Connection Connections}.
*/
public void setConnectionFactory(@Nullable ConnectionFactory connectionFactory) {
this.connectionFactory = connectionFactory;
}
/**
* Return the ConnectionFactory that this accessor uses for obtaining
* JMS {@link Connection Connections}.
*/
@Nullable
public ConnectionFactory getConnectionFactory() {
return this.connectionFactory;
}
/**
* Obtain the ConnectionFactory for actual use.
* @return the ConnectionFactory (never {@code null})
* @throws IllegalStateException in case of no ConnectionFactory set
* @since 5.0
*/
protected final ConnectionFactory obtainConnectionFactory() {
ConnectionFactory connectionFactory = getConnectionFactory();
Assert.state(connectionFactory != null, "No ConnectionFactory set");
return connectionFactory;
}
/**
* Set the transaction mode that is used when creating a JMS {@link Session}.
* Default is "false".
* <p>Note that within a JTA transaction, the parameters passed to
* {@code create(Queue/Topic)Session(boolean transacted, int acknowledgeMode)}
* method are not taken into account. Depending on the Jakarta EE transaction context,
* the container makes its own decisions on these values. Analogously, these
* parameters are not taken into account within a locally managed transaction
* either, since the accessor operates on an existing JMS Session in this case.
* <p>Setting this flag to "true" will use a short local JMS transaction
* when running outside a managed transaction, and a synchronized local
* JMS transaction in case of a managed transaction (other than an XA
* transaction) being present. This has the effect of a local JMS
* transaction being managed alongside the main transaction (which might
* be a native JDBC transaction), with the JMS transaction committing
* right after the main transaction.
* @see jakarta.jms.Connection#createSession(boolean, int)
*/
public void setSessionTransacted(boolean sessionTransacted) {
this.sessionTransacted = sessionTransacted;
}
/**
* Return whether the JMS {@link Session sessions} used by this
* accessor are supposed to be transacted.
* @see #setSessionTransacted(boolean)
*/
public boolean isSessionTransacted() {
return this.sessionTransacted;
}
/**
* Set the JMS acknowledgement mode by the name of the corresponding constant
* in the JMS {@link Session} interface, e.g. "CLIENT_ACKNOWLEDGE".
* <p>If you want to use vendor-specific extensions to the acknowledgement mode,
* use {@link #setSessionAcknowledgeMode(int)} instead.
* @param constantName the name of the {@link Session} acknowledge mode constant
* @see jakarta.jms.Session#AUTO_ACKNOWLEDGE
* @see jakarta.jms.Session#CLIENT_ACKNOWLEDGE
* @see jakarta.jms.Session#DUPS_OK_ACKNOWLEDGE
* @see jakarta.jms.Connection#createSession(boolean, int)
*/
public void setSessionAcknowledgeModeName(String constantName) {
setSessionAcknowledgeMode(sessionConstants.asNumber(constantName).intValue());
}
/**
* Set the JMS acknowledgement mode that is used when creating a JMS
* {@link Session} to send a message.
* <p>Default is {@link Session#AUTO_ACKNOWLEDGE}.
* <p>Vendor-specific extensions to the acknowledgement mode can be set here as well.
* <p>Note that inside an EJB, the parameters to the
* {@code create(Queue/Topic)Session(boolean transacted, int acknowledgeMode)} method
* are not taken into account. Depending on the transaction context in the EJB,
* the container makes its own decisions on these values. See section 17.3.5
* of the EJB spec.
* @param sessionAcknowledgeMode the acknowledgement mode constant
* @see jakarta.jms.Session#AUTO_ACKNOWLEDGE
* @see jakarta.jms.Session#CLIENT_ACKNOWLEDGE
* @see jakarta.jms.Session#DUPS_OK_ACKNOWLEDGE
* @see jakarta.jms.Connection#createSession(boolean, int)
*/
public void setSessionAcknowledgeMode(int sessionAcknowledgeMode) {
this.sessionAcknowledgeMode = sessionAcknowledgeMode;
}
/**
* Return the acknowledgement mode for JMS {@link Session sessions}.
*/
public int getSessionAcknowledgeMode() {
return this.sessionAcknowledgeMode;
}
@Override
public void afterPropertiesSet() {
if (getConnectionFactory() == null) {
throw new IllegalArgumentException("Property 'connectionFactory' is required");
}
}
/**
* Convert the specified checked {@link jakarta.jms.JMSException JMSException} to
* a Spring runtime {@link org.springframework.jms.JmsException JmsException}
* equivalent.
* <p>The default implementation delegates to the
* {@link JmsUtils#convertJmsAccessException} method.
* @param ex the original checked {@link JMSException} to convert
* @return the Spring runtime {@link JmsException} wrapping {@code ex}
* @see JmsUtils#convertJmsAccessException
*/
protected JmsException convertJmsAccessException(JMSException ex) {
return JmsUtils.convertJmsAccessException(ex);
}
/**
* Create a JMS Connection via this template's ConnectionFactory.
* <p>This implementation uses JMS 1.1 API.
* @return the new JMS Connection
* @throws JMSException if thrown by JMS API methods
* @see jakarta.jms.ConnectionFactory#createConnection()
*/
protected Connection createConnection() throws JMSException {
return obtainConnectionFactory().createConnection();
}
/**
* Create a JMS Session for the given Connection.
* <p>This implementation uses JMS 1.1 API.
* @param con the JMS Connection to create a Session for
* @return the new JMS Session
* @throws JMSException if thrown by JMS API methods
* @see jakarta.jms.Connection#createSession(boolean, int)
*/
protected Session createSession(Connection con) throws JMSException {
return con.createSession(isSessionTransacted(), getSessionAcknowledgeMode());
}
/**
* Determine whether the given Session is in client acknowledge mode.
* <p>This implementation uses JMS 1.1 API.
* @param session the JMS Session to check
* @return whether the given Session is in client acknowledge mode
* @throws jakarta.jms.JMSException if thrown by JMS API methods
* @see jakarta.jms.Session#getAcknowledgeMode()
* @see jakarta.jms.Session#CLIENT_ACKNOWLEDGE
*/
protected boolean isClientAcknowledge(Session session) throws JMSException {
return (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE);
}
}