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 }