001: /*
002: * Copyright 2002-2007 the original author or authors.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.jms.support;
018:
019: import javax.jms.Connection;
020: import javax.jms.ConnectionFactory;
021: import javax.jms.JMSException;
022: import javax.jms.Session;
023:
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026:
027: import org.springframework.beans.factory.InitializingBean;
028: import org.springframework.core.Constants;
029: import org.springframework.jms.JmsException;
030:
031: /**
032: * Base class for {@link org.springframework.jms.core.JmsTemplate} and other
033: * JMS-accessing gateway helpers, defining common properties such as the
034: * JMS {@link ConnectionFactory} to operate on. The subclass
035: * {@link org.springframework.jms.support.destination.JmsDestinationAccessor}
036: * adds further, destination-related properties.
037: *
038: * <p>Not intended to be used directly.
039: * See {@link org.springframework.jms.core.JmsTemplate}.
040: *
041: * @author Juergen Hoeller
042: * @since 1.2
043: * @see org.springframework.jms.support.destination.JmsDestinationAccessor
044: * @see org.springframework.jms.core.JmsTemplate
045: */
046: public abstract class JmsAccessor implements InitializingBean {
047:
048: /** Constants instance for javax.jms.Session */
049: private static final Constants sessionConstants = new Constants(
050: Session.class);
051:
052: /** Logger available to subclasses */
053: protected final Log logger = LogFactory.getLog(getClass());
054:
055: private ConnectionFactory connectionFactory;
056:
057: private boolean sessionTransacted = false;
058:
059: private int sessionAcknowledgeMode = Session.AUTO_ACKNOWLEDGE;
060:
061: /**
062: * Set the ConnectionFactory to use for obtaining JMS
063: * {@link Connection Connections}.
064: */
065: public void setConnectionFactory(ConnectionFactory connectionFactory) {
066: this .connectionFactory = connectionFactory;
067: }
068:
069: /**
070: * Return the ConnectionFactory that this accessor uses for
071: * obtaining JMS {@link Connection Connections}.
072: */
073: public ConnectionFactory getConnectionFactory() {
074: return this .connectionFactory;
075: }
076:
077: /**
078: * Set the transaction mode that is used when creating a JMS {@link Session}.
079: * Default is "false".
080: * <p>Note that within a JTA transaction, the parameters passed to
081: * <code>create(Queue/Topic)Session(boolean transacted, int acknowledgeMode)</code>
082: * method are not taken into account. Depending on the J2EE transaction context,
083: * the container makes its own decisions on these values. Analogously, these
084: * parameters are not taken into account within a locally managed transaction
085: * either, since the accessor operates on an existing JMS Session in this case.
086: * <p>Setting this flag to "true" will use a short local JMS transaction
087: * when running outside of a managed transaction, and a synchronized local
088: * JMS transaction in case of a managed transaction (other than an XA
089: * transaction) being present. The latter has the effect of a local JMS
090: * transaction being managed alongside the main transaction (which might
091: * be a native JDBC transaction), with the JMS transaction committing
092: * right after the main transaction.
093: * @param sessionTransacted the transaction mode
094: * @see javax.jms.Connection#createSession(boolean, int)
095: */
096: public void setSessionTransacted(boolean sessionTransacted) {
097: this .sessionTransacted = sessionTransacted;
098: }
099:
100: /**
101: * Return whether the JMS {@link Session sessions} used by this
102: * accessor are supposed to be transacted.
103: * @return <code>true</code> if the JMS Sessions used are transacted
104: * @see #setSessionTransacted(boolean)
105: */
106: public boolean isSessionTransacted() {
107: return this .sessionTransacted;
108: }
109:
110: /**
111: * Set the JMS acknowledgement mode by the name of the corresponding constant
112: * in the JMS {@link Session} interface, e.g. "CLIENT_ACKNOWLEDGE".
113: * <p>If you want to use vendor-specific extensions to the acknowledgment mode,
114: * use {@link #setSessionAcknowledgeModeName(String)} instead.
115: * @param constantName the name of the {@link Session} acknowledge mode constant
116: * @see javax.jms.Session#AUTO_ACKNOWLEDGE
117: * @see javax.jms.Session#CLIENT_ACKNOWLEDGE
118: * @see javax.jms.Session#DUPS_OK_ACKNOWLEDGE
119: * @see javax.jms.Connection#createSession(boolean, int)
120: */
121: public void setSessionAcknowledgeModeName(String constantName) {
122: setSessionAcknowledgeMode(sessionConstants.asNumber(
123: constantName).intValue());
124: }
125:
126: /**
127: * Set the JMS acknowledgement mode that is used when creating a JMS
128: * {@link Session} to send a message.
129: * <p>Default is {@link Session#AUTO_ACKNOWLEDGE}.
130: * <p>Vendor-specific extensions to the acknowledgment mode can be set here as well.
131: * <p>Note that that inside an EJB the parameters to
132: * create(Queue/Topic)Session(boolean transacted, int acknowledgeMode) method
133: * are not taken into account. Depending on the transaction context in the EJB,
134: * the container makes its own decisions on these values. See section 17.3.5
135: * of the EJB spec.
136: * @param sessionAcknowledgeMode the acknowledgement mode
137: * @see javax.jms.Session#AUTO_ACKNOWLEDGE
138: * @see javax.jms.Session#CLIENT_ACKNOWLEDGE
139: * @see javax.jms.Session#DUPS_OK_ACKNOWLEDGE
140: * @see javax.jms.Connection#createSession(boolean, int)
141: */
142: public void setSessionAcknowledgeMode(int sessionAcknowledgeMode) {
143: this .sessionAcknowledgeMode = sessionAcknowledgeMode;
144: }
145:
146: /**
147: * Return the acknowledgement mode for JMS {@link Session sessions}.
148: * @return the acknowledgement mode applied by this accessor
149: */
150: public int getSessionAcknowledgeMode() {
151: return this .sessionAcknowledgeMode;
152: }
153:
154: public void afterPropertiesSet() {
155: if (getConnectionFactory() == null) {
156: throw new IllegalArgumentException(
157: "Property 'connectionFactory' is required");
158: }
159: }
160:
161: /**
162: * Convert the specified checked {@link javax.jms.JMSException JMSException} to
163: * a Spring runtime {@link org.springframework.jms.JmsException JmsException}
164: * equivalent.
165: * <p>The default implementation delegates to the
166: * {@link org.springframework.jms.support.JmsUtils#convertJmsAccessException} method.
167: * @param ex the original checked {@link JMSException} to convert
168: * @return the Spring runtime {@link JmsException} wrapping <code>ex</code>
169: * @see org.springframework.jms.support.JmsUtils#convertJmsAccessException
170: */
171: protected JmsException convertJmsAccessException(JMSException ex) {
172: return JmsUtils.convertJmsAccessException(ex);
173: }
174:
175: //-------------------------------------------------------------------------
176: // JMS 1.1 factory methods, potentially overridden for JMS 1.0.2
177: //-------------------------------------------------------------------------
178:
179: /**
180: * Create a JMS Connection via this template's ConnectionFactory.
181: * <p>This implementation uses JMS 1.1 API.
182: * @return the new JMS Connection
183: * @throws JMSException if thrown by JMS API methods
184: * @see javax.jms.ConnectionFactory#createConnection()
185: */
186: protected Connection createConnection() throws JMSException {
187: return getConnectionFactory().createConnection();
188: }
189:
190: /**
191: * Create a JMS Session for the given Connection.
192: * <p>This implementation uses JMS 1.1 API.
193: * @param con the JMS Connection to create a Session for
194: * @return the new JMS Session
195: * @throws JMSException if thrown by JMS API methods
196: * @see javax.jms.Connection#createSession(boolean, int)
197: */
198: protected Session createSession(Connection con) throws JMSException {
199: return con.createSession(isSessionTransacted(),
200: getSessionAcknowledgeMode());
201: }
202:
203: /**
204: * Determine whether the given Session is in client acknowledge mode.
205: * <p>This implementation uses JMS 1.1 API.
206: * @param session the JMS Session to check
207: * @return whether the given Session is in client acknowledge mode
208: * @throws javax.jms.JMSException if thrown by JMS API methods
209: * @see javax.jms.Session#getAcknowledgeMode()
210: * @see javax.jms.Session#CLIENT_ACKNOWLEDGE
211: */
212: protected boolean isClientAcknowledge(Session session)
213: throws JMSException {
214: return (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE);
215: }
216:
217: }
|