View Javadoc

1   /*
2    * Copyright 2005-2010 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ws.transport.jms;
18  
19  import javax.ejb.EJBException;
20  import javax.ejb.MessageDrivenBean;
21  import javax.jms.Connection;
22  import javax.jms.ConnectionFactory;
23  import javax.jms.JMSException;
24  import javax.jms.Message;
25  import javax.jms.Session;
26  import javax.naming.NamingException;
27  
28  import org.springframework.ejb.support.AbstractJmsMessageDrivenBean;
29  import org.springframework.jms.connection.ConnectionFactoryUtils;
30  import org.springframework.jms.core.MessagePostProcessor;
31  import org.springframework.jms.support.JmsUtils;
32  import org.springframework.jndi.JndiLookupFailureException;
33  import org.springframework.ws.WebServiceMessageFactory;
34  import org.springframework.ws.transport.WebServiceMessageReceiver;
35  
36  /**
37   * EJB {@link MessageDrivenBean} that can be used to handleMessage incoming JMS messages.
38   * <p/>
39   * This class needs a JMS {@link ConnectionFactory}, a {@link WebServiceMessageFactory} and {@link
40   * WebServiceMessageReceiver} to operate. By default, these are obtained by doing a bean lookup on the bean factory
41   * provided by {@link #getBeanFactory()} the super class.
42   *
43   * @author Arjen Poutsma
44   * @see #createConnectionFactory()
45   * @see #createMessageFactory()
46   * @see #createMessageReceiver()
47   */
48  public class WebServiceMessageDrivenBean extends AbstractJmsMessageDrivenBean {
49  
50      /** Well-known name for the {@link ConnectionFactory} object in the bean factory for this bean. */
51      public static final String CONNECTION_FACTORY_BEAN_NAME = "connectionFactory";
52  
53      /** Well-known name for the {@link WebServiceMessageFactory} bean in the bean factory for this bean. */
54      public static final String MESSAGE_FACTORY_BEAN_NAME = "messageFactory";
55  
56      /** Well-known name for the {@link WebServiceMessageReceiver} object in the bean factory for this bean. */
57      public static final String MESSAGE_RECEIVER_BEAN_NAME = "messageReceiver";
58  
59      private JmsMessageReceiver delegate;
60  
61      private ConnectionFactory connectionFactory;
62  
63      /** Delegates to {@link JmsMessageReceiver#handleMessage(Message,Session)}. */
64      public void onMessage(Message message) {
65          Connection connection = null;
66          Session session = null;
67          try {
68              connection = createConnection(connectionFactory);
69              session = createSession(connection);
70              delegate.handleMessage(message, session);
71          }
72          catch (JmsTransportException ex) {
73              throw JmsUtils.convertJmsAccessException(ex.getJmsException());
74          }
75          catch (JMSException ex) {
76              throw JmsUtils.convertJmsAccessException(ex);
77          }
78          catch (Exception ex) {
79              throw new EJBException(ex);
80          }
81          finally {
82              JmsUtils.closeSession(session);
83              ConnectionFactoryUtils.releaseConnection(connection, connectionFactory, true);
84          }
85      }
86  
87      /**
88       * Creates a new {@link Connection}, {@link WebServiceMessageFactory}, and {@link WebServiceMessageReceiver}.
89       *
90       * @see #createConnectionFactory()
91       * @see #createMessageFactory()
92       * @see #createMessageReceiver()
93       */
94      @Override
95      protected void onEjbCreate() {
96          try {
97              connectionFactory = createConnectionFactory();
98              delegate = new JmsMessageReceiver();
99              delegate.setMessageFactory(createMessageFactory());
100             delegate.setMessageReceiver(createMessageReceiver());
101 	        delegate.setPostProcessor(createPostProcessor());
102         }
103         catch (NamingException ex) {
104             throw new JndiLookupFailureException("Could not create connection", ex);
105         }
106         catch (JMSException ex) {
107             throw JmsUtils.convertJmsAccessException(ex);
108         }
109         catch (Exception ex) {
110             throw new EJBException(ex);
111         }
112     }
113 
114     /** Creates a connection factory. Default implementation does a bean lookup for {@link #CONNECTION_FACTORY_BEAN_NAME}. */
115     protected ConnectionFactory createConnectionFactory() throws Exception {
116         return (ConnectionFactory) getBeanFactory().getBean(CONNECTION_FACTORY_BEAN_NAME, ConnectionFactory.class);
117     }
118 
119     /** Creates a message factory. Default implementation does a bean lookup for {@link #MESSAGE_FACTORY_BEAN_NAME}. */
120     protected WebServiceMessageFactory createMessageFactory() {
121         return (WebServiceMessageFactory) getBeanFactory()
122                 .getBean(MESSAGE_FACTORY_BEAN_NAME, WebServiceMessageFactory.class);
123     }
124 
125     /** Creates a connection factory. Default implementation does a bean lookup for {@link #MESSAGE_RECEIVER_BEAN_NAME}. */
126     protected WebServiceMessageReceiver createMessageReceiver() {
127         return (WebServiceMessageReceiver) getBeanFactory()
128                 .getBean(MESSAGE_RECEIVER_BEAN_NAME, WebServiceMessageReceiver.class);
129     }
130 
131     /**
132      * Create a JMS {@link Connection} using the given {@link ConnectionFactory}.
133      * <p/>
134      * This implementation uses JMS 1.1 API.
135      *
136      * @param connectionFactory the JMS ConnectionFactory to create a Connection with
137      * @return the new JMS Connection
138      * @throws JMSException if thrown by JMS API methods
139      * @see ConnectionFactory#createConnection()
140      */
141     protected Connection createConnection(ConnectionFactory connectionFactory) throws JMSException {
142         return connectionFactory.createConnection();
143     }
144 
145     /**
146      * Creates a JMS {@link Session}. Default implementation creates a non-transactional, {@link Session#AUTO_ACKNOWLEDGE
147      * auto acknowledged} session.
148      * <p/>
149      * This implementation uses JMS 1.1 API.
150      *
151      * @param connection the JMS Connection to create a Session for
152      * @return the new JMS Session
153      * @throws JMSException if thrown by JMS API methods
154      * @see Connection#createSession(boolean,int)
155      */
156     protected Session createSession(Connection connection) throws JMSException {
157         return connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
158     }
159 
160 	/**
161 	 * Creates a JMS {@link MessagePostProcessor} to process JMS messages. Default
162 	 * implementation returns {@code null}, meaning that no post processor is used.
163 	 *
164 	 * @return a message post processor
165 	 */
166 	protected MessagePostProcessor createPostProcessor() {
167 		return null;
168 	}
169 
170 }