001/* 002 * Copyright 2002-2015 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 * https://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 017package org.springframework.jms.support; 018 019import javax.jms.Connection; 020import javax.jms.ConnectionFactory; 021import javax.jms.JMSException; 022import javax.jms.Session; 023 024import org.apache.commons.logging.Log; 025import org.apache.commons.logging.LogFactory; 026 027import org.springframework.beans.factory.InitializingBean; 028import org.springframework.core.Constants; 029import 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 */ 046public abstract class JmsAccessor implements InitializingBean { 047 048 /** Constants instance for javax.jms.Session */ 049 private static final Constants sessionConstants = new Constants(Session.class); 050 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 /** 063 * Set the ConnectionFactory to use for obtaining JMS {@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 obtaining 071 * 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)} 082 * method are not taken into account. Depending on the Java EE 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. This 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 * @see javax.jms.Connection#createSession(boolean, int) 094 */ 095 public void setSessionTransacted(boolean sessionTransacted) { 096 this.sessionTransacted = sessionTransacted; 097 } 098 099 /** 100 * Return whether the JMS {@link Session sessions} used by this 101 * accessor are supposed to be transacted. 102 * @see #setSessionTransacted(boolean) 103 */ 104 public boolean isSessionTransacted() { 105 return this.sessionTransacted; 106 } 107 108 /** 109 * Set the JMS acknowledgement mode by the name of the corresponding constant 110 * in the JMS {@link Session} interface, e.g. "CLIENT_ACKNOWLEDGE". 111 * <p>If you want to use vendor-specific extensions to the acknowledgment mode, 112 * use {@link #setSessionAcknowledgeMode(int)} instead. 113 * @param constantName the name of the {@link Session} acknowledge mode constant 114 * @see javax.jms.Session#AUTO_ACKNOWLEDGE 115 * @see javax.jms.Session#CLIENT_ACKNOWLEDGE 116 * @see javax.jms.Session#DUPS_OK_ACKNOWLEDGE 117 * @see javax.jms.Connection#createSession(boolean, int) 118 */ 119 public void setSessionAcknowledgeModeName(String constantName) { 120 setSessionAcknowledgeMode(sessionConstants.asNumber(constantName).intValue()); 121 } 122 123 /** 124 * Set the JMS acknowledgement mode that is used when creating a JMS 125 * {@link Session} to send a message. 126 * <p>Default is {@link Session#AUTO_ACKNOWLEDGE}. 127 * <p>Vendor-specific extensions to the acknowledgment mode can be set here as well. 128 * <p>Note that inside an EJB, the parameters to the 129 * {@code create(Queue/Topic)Session(boolean transacted, int acknowledgeMode)} method 130 * are not taken into account. Depending on the transaction context in the EJB, 131 * the container makes its own decisions on these values. See section 17.3.5 132 * of the EJB spec. 133 * @param sessionAcknowledgeMode the acknowledgement mode constant 134 * @see javax.jms.Session#AUTO_ACKNOWLEDGE 135 * @see javax.jms.Session#CLIENT_ACKNOWLEDGE 136 * @see javax.jms.Session#DUPS_OK_ACKNOWLEDGE 137 * @see javax.jms.Connection#createSession(boolean, int) 138 */ 139 public void setSessionAcknowledgeMode(int sessionAcknowledgeMode) { 140 this.sessionAcknowledgeMode = sessionAcknowledgeMode; 141 } 142 143 /** 144 * Return the acknowledgement mode for JMS {@link Session sessions}. 145 */ 146 public int getSessionAcknowledgeMode() { 147 return this.sessionAcknowledgeMode; 148 } 149 150 @Override 151 public void afterPropertiesSet() { 152 if (getConnectionFactory() == null) { 153 throw new IllegalArgumentException("Property 'connectionFactory' is required"); 154 } 155 } 156 157 158 /** 159 * Convert the specified checked {@link javax.jms.JMSException JMSException} to 160 * a Spring runtime {@link org.springframework.jms.JmsException JmsException} 161 * equivalent. 162 * <p>The default implementation delegates to the 163 * {@link JmsUtils#convertJmsAccessException} method. 164 * @param ex the original checked {@link JMSException} to convert 165 * @return the Spring runtime {@link JmsException} wrapping {@code ex} 166 * @see JmsUtils#convertJmsAccessException 167 */ 168 protected JmsException convertJmsAccessException(JMSException ex) { 169 return JmsUtils.convertJmsAccessException(ex); 170 } 171 172 /** 173 * Create a JMS Connection via this template's ConnectionFactory. 174 * <p>This implementation uses JMS 1.1 API. 175 * @return the new JMS Connection 176 * @throws JMSException if thrown by JMS API methods 177 * @see javax.jms.ConnectionFactory#createConnection() 178 */ 179 protected Connection createConnection() throws JMSException { 180 return getConnectionFactory().createConnection(); 181 } 182 183 /** 184 * Create a JMS Session for the given Connection. 185 * <p>This implementation uses JMS 1.1 API. 186 * @param con the JMS Connection to create a Session for 187 * @return the new JMS Session 188 * @throws JMSException if thrown by JMS API methods 189 * @see javax.jms.Connection#createSession(boolean, int) 190 */ 191 protected Session createSession(Connection con) throws JMSException { 192 return con.createSession(isSessionTransacted(), getSessionAcknowledgeMode()); 193 } 194 195 /** 196 * Determine whether the given Session is in client acknowledge mode. 197 * <p>This implementation uses JMS 1.1 API. 198 * @param session the JMS Session to check 199 * @return whether the given Session is in client acknowledge mode 200 * @throws javax.jms.JMSException if thrown by JMS API methods 201 * @see javax.jms.Session#getAcknowledgeMode() 202 * @see javax.jms.Session#CLIENT_ACKNOWLEDGE 203 */ 204 protected boolean isClientAcknowledge(Session session) throws JMSException { 205 return (session.getAcknowledgeMode() == Session.CLIENT_ACKNOWLEDGE); 206 } 207 208}