From 4b89c406a9c72dc50b2f5eb836524b6fe9275099 Mon Sep 17 00:00:00 2001 From: Arjen Poutsma Date: Mon, 17 Oct 2011 10:16:54 +0000 Subject: [PATCH] SWS-718 - Reloading the spring context does not refresh the MessageDispatcherServlet --- .../http/MessageDispatcherServlet.java | 84 ++++++++-------- ...ssageDispatcherServletIntegrationTest.java | 96 +++++++++++++++++++ .../support/EchoPayloadEndpoint.java | 38 ++++++++ .../ws/transport/http/WEB-INF/sws-servlet.xml | 13 +++ 4 files changed, 192 insertions(+), 39 deletions(-) create mode 100644 core/src/test/java/org/springframework/ws/transport/http/MessageDispatcherServletIntegrationTest.java create mode 100644 core/src/test/java/org/springframework/ws/transport/support/EchoPayloadEndpoint.java create mode 100644 core/src/test/resources/org/springframework/ws/transport/http/WEB-INF/sws-servlet.xml diff --git a/core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java b/core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java index fc475da7..ba1e368f 100644 --- a/core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java +++ b/core/src/main/java/org/springframework/ws/transport/http/MessageDispatcherServlet.java @@ -1,11 +1,11 @@ /* - * Copyright 2005-2010 the original author or authors. + * Copyright 2005-2011 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -17,16 +17,15 @@ package org.springframework.ws.transport.http; import java.util.Map; -import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.NoSuchBeanDefinitionException; +import org.springframework.context.ApplicationContext; import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.FrameworkServlet; import org.springframework.web.util.WebUtils; @@ -222,14 +221,12 @@ public class MessageDispatcherServlet extends FrameworkServlet { messageReceiverHandlerAdapter.handle(httpServletRequest, httpServletResponse, messageReceiver); } + /** + * This implementation calls {@link #initStrategies}. + */ @Override - protected void initFrameworkServlet() throws ServletException, BeansException { - initMessageReceiverHandlerAdapter(); - initWsdlDefinitionHandlerAdapter(); - initXsdSchemaHandlerAdapter(); - initMessageReceiver(); - initWsdlDefinitions(); - initXsdSchemas(); + protected void onRefresh(ApplicationContext context) { + initStrategies(context); } @Override @@ -264,7 +261,7 @@ public class MessageDispatcherServlet extends FrameworkServlet { if (HttpTransportConstants.METHOD_GET.equals(request.getMethod()) && request.getRequestURI().endsWith(WSDL_SUFFIX_NAME)) { String fileName = WebUtils.extractFilenameFromUrlPath(request.getRequestURI()); - return (WsdlDefinition) wsdlDefinitions.get(fileName); + return wsdlDefinitions.get(fileName); } else { return null; @@ -285,24 +282,37 @@ public class MessageDispatcherServlet extends FrameworkServlet { if (HttpTransportConstants.METHOD_GET.equals(request.getMethod()) && request.getRequestURI().endsWith(XSD_SUFFIX_NAME)) { String fileName = WebUtils.extractFilenameFromUrlPath(request.getRequestURI()); - return (XsdSchema) xsdSchemas.get(fileName); + return xsdSchemas.get(fileName); } else { return null; } } - private void initMessageReceiverHandlerAdapter() { + /** + * Initialize the strategy objects that this servlet uses. + *

May be overridden in subclasses in order to initialize further strategy objects. + */ + protected void initStrategies(ApplicationContext context) { + initMessageReceiverHandlerAdapter(context); + initWsdlDefinitionHandlerAdapter(context); + initXsdSchemaHandlerAdapter(context); + initMessageReceiver(context); + initWsdlDefinitions(context); + initXsdSchemas(context); + } + + + private void initMessageReceiverHandlerAdapter(ApplicationContext context) { try { try { - messageReceiverHandlerAdapter = (WebServiceMessageReceiverHandlerAdapter) getWebApplicationContext() - .getBean(getMessageReceiverHandlerAdapterBeanName(), - WebServiceMessageReceiverHandlerAdapter.class); + messageReceiverHandlerAdapter = context.getBean(getMessageReceiverHandlerAdapterBeanName(), + WebServiceMessageReceiverHandlerAdapter.class); } catch (NoSuchBeanDefinitionException ignored) { messageReceiverHandlerAdapter = new WebServiceMessageReceiverHandlerAdapter(); } - initWebServiceMessageFactory(); + initWebServiceMessageFactory(context); messageReceiverHandlerAdapter.afterPropertiesSet(); } catch (Exception ex) { @@ -310,15 +320,14 @@ public class MessageDispatcherServlet extends FrameworkServlet { } } - private void initWebServiceMessageFactory() { + private void initWebServiceMessageFactory(ApplicationContext context) { WebServiceMessageFactory messageFactory; try { - messageFactory = (WebServiceMessageFactory) getWebApplicationContext() - .getBean(getMessageFactoryBeanName(), WebServiceMessageFactory.class); + messageFactory = context.getBean(getMessageFactoryBeanName(), WebServiceMessageFactory.class); } catch (NoSuchBeanDefinitionException ignored) { - messageFactory = (WebServiceMessageFactory) defaultStrategiesHelper - .getDefaultStrategy(WebServiceMessageFactory.class, getWebApplicationContext()); + messageFactory = defaultStrategiesHelper + .getDefaultStrategy(WebServiceMessageFactory.class, context); if (logger.isDebugEnabled()) { logger.debug("No WebServiceMessageFactory found in servlet '" + getServletName() + "': using default"); } @@ -326,11 +335,11 @@ public class MessageDispatcherServlet extends FrameworkServlet { messageReceiverHandlerAdapter.setMessageFactory(messageFactory); } - private void initWsdlDefinitionHandlerAdapter() { + private void initWsdlDefinitionHandlerAdapter(ApplicationContext context) { try { try { - wsdlDefinitionHandlerAdapter = (WsdlDefinitionHandlerAdapter) getWebApplicationContext() - .getBean(getWsdlDefinitionHandlerAdapterBeanName(), WsdlDefinitionHandlerAdapter.class); + wsdlDefinitionHandlerAdapter = + context.getBean(getWsdlDefinitionHandlerAdapterBeanName(), WsdlDefinitionHandlerAdapter.class); } catch (NoSuchBeanDefinitionException ignored) { @@ -344,10 +353,10 @@ public class MessageDispatcherServlet extends FrameworkServlet { } } - private void initXsdSchemaHandlerAdapter() { + private void initXsdSchemaHandlerAdapter(ApplicationContext context) { try { try { - xsdSchemaHandlerAdapter = (XsdSchemaHandlerAdapter) getWebApplicationContext() + xsdSchemaHandlerAdapter = context .getBean(getXsdSchemaHandlerAdapterBeanName(), XsdSchemaHandlerAdapter.class); } @@ -363,14 +372,13 @@ public class MessageDispatcherServlet extends FrameworkServlet { } } - private void initMessageReceiver() { + private void initMessageReceiver(ApplicationContext context) { try { - messageReceiver = (WebServiceMessageReceiver) getWebApplicationContext() - .getBean(getMessageReceiverBeanName(), WebServiceMessageReceiver.class); + messageReceiver = context.getBean(getMessageReceiverBeanName(), WebServiceMessageReceiver.class); } catch (NoSuchBeanDefinitionException ex) { - messageReceiver = (WebServiceMessageReceiver) defaultStrategiesHelper - .getDefaultStrategy(WebServiceMessageReceiver.class, getWebApplicationContext()); + messageReceiver = defaultStrategiesHelper + .getDefaultStrategy(WebServiceMessageReceiver.class, context); if (messageReceiver instanceof BeanNameAware) { ((BeanNameAware) messageReceiver).setBeanName(getServletName()); } @@ -380,10 +388,9 @@ public class MessageDispatcherServlet extends FrameworkServlet { } } - /** Find all {@link WsdlDefinition WsdlDefinitions} in the ApplicationContext, incuding ancestor contexts. */ - private void initWsdlDefinitions() { + private void initWsdlDefinitions(ApplicationContext context) { wsdlDefinitions = BeanFactoryUtils - .beansOfTypeIncludingAncestors(getWebApplicationContext(), WsdlDefinition.class, true, false); + .beansOfTypeIncludingAncestors(context, WsdlDefinition.class, true, false); if (logger.isDebugEnabled()) { for (Map.Entry entry : wsdlDefinitions.entrySet()) { String beanName = entry.getKey(); @@ -393,10 +400,9 @@ public class MessageDispatcherServlet extends FrameworkServlet { } } - /** Find all {@link XsdSchema} in the ApplicationContext, incuding ancestor contexts. */ - private void initXsdSchemas() { + private void initXsdSchemas(ApplicationContext context) { xsdSchemas = BeanFactoryUtils - .beansOfTypeIncludingAncestors(getWebApplicationContext(), XsdSchema.class, true, false); + .beansOfTypeIncludingAncestors(context, XsdSchema.class, true, false); if (logger.isDebugEnabled()) { for (Map.Entry entry : xsdSchemas.entrySet()) { String beanName = entry.getKey(); diff --git a/core/src/test/java/org/springframework/ws/transport/http/MessageDispatcherServletIntegrationTest.java b/core/src/test/java/org/springframework/ws/transport/http/MessageDispatcherServletIntegrationTest.java new file mode 100644 index 00000000..783d0785 --- /dev/null +++ b/core/src/test/java/org/springframework/ws/transport/http/MessageDispatcherServletIntegrationTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2005-2011 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 + * + * http://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.ws.transport.http; + +import java.io.File; +import javax.xml.namespace.QName; +import javax.xml.soap.MessageFactory; +import javax.xml.soap.SOAPConnection; +import javax.xml.soap.SOAPConnectionFactory; +import javax.xml.soap.SOAPElement; +import javax.xml.soap.SOAPException; +import javax.xml.soap.SOAPMessage; + +import org.springframework.ws.transport.support.EchoPayloadEndpoint; +import org.springframework.ws.transport.support.FreePortScanner; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.mortbay.jetty.Server; +import org.mortbay.jetty.servlet.Context; +import org.mortbay.jetty.servlet.ServletHolder; + +import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; + +/** + * @author Arjen Poutsma + */ +public class MessageDispatcherServletIntegrationTest { + + private static Server jettyServer; + + private static String url; + + private MessageFactory messageFactory; + + private SOAPConnectionFactory connectionFactory; + + @BeforeClass + public static void startJetty() throws Exception { + int port = FreePortScanner.getFreePort(); + url = "http://localhost:" + port; + jettyServer = new Server(port); + Context jettyContext = new Context(jettyServer, "/"); + String resourceBase = + new File(MessageDispatcherServletIntegrationTest.class.getResource("WEB-INF").toURI()).getParent(); + jettyContext.setResourceBase(resourceBase); + ServletHolder servletHolder = new ServletHolder(new MessageDispatcherServlet()); + servletHolder.setName("sws"); + jettyContext.addServlet(servletHolder, "/"); + jettyServer.start(); + } + + @Before + public void setUpSaaj() throws SOAPException { + messageFactory = MessageFactory.newInstance(); + connectionFactory = SOAPConnectionFactory.newInstance(); + } + + @AfterClass + public static void stopJetty() throws Exception { + if (jettyServer.isRunning()) { + jettyServer.stop(); + } + } + + @Test + public void echo() throws SOAPException { + SOAPMessage request = messageFactory.createMessage(); + SOAPElement element = request.getSOAPBody().addChildElement(new QName(EchoPayloadEndpoint.NAMESPACE, EchoPayloadEndpoint.LOCAL_PART)); + element.setTextContent("Hello World"); + + SOAPConnection connection = connectionFactory.createConnection(); + + SOAPMessage response = connection.call(request, url); + + assertXMLEqual(request.getSOAPPart(), response.getSOAPPart()); + } + + +} diff --git a/core/src/test/java/org/springframework/ws/transport/support/EchoPayloadEndpoint.java b/core/src/test/java/org/springframework/ws/transport/support/EchoPayloadEndpoint.java new file mode 100644 index 00000000..41972f73 --- /dev/null +++ b/core/src/test/java/org/springframework/ws/transport/support/EchoPayloadEndpoint.java @@ -0,0 +1,38 @@ +/* + * Copyright 2005-2011 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 + * + * http://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.ws.transport.support; + +import javax.xml.transform.Source; + +import org.springframework.ws.server.endpoint.annotation.Endpoint; +import org.springframework.ws.server.endpoint.annotation.PayloadRoot; +import org.springframework.ws.server.endpoint.annotation.RequestPayload; +import org.springframework.ws.server.endpoint.annotation.ResponsePayload; + +@Endpoint +public class EchoPayloadEndpoint { + + public static final String NAMESPACE = "http://springframework.org"; + + public static final String LOCAL_PART = "root"; + + @PayloadRoot(localPart = LOCAL_PART, namespace = NAMESPACE) + @ResponsePayload + public Source invoke(@RequestPayload Source request) throws Exception { + return request; + } +} diff --git a/core/src/test/resources/org/springframework/ws/transport/http/WEB-INF/sws-servlet.xml b/core/src/test/resources/org/springframework/ws/transport/http/WEB-INF/sws-servlet.xml new file mode 100644 index 00000000..c86c1376 --- /dev/null +++ b/core/src/test/resources/org/springframework/ws/transport/http/WEB-INF/sws-servlet.xml @@ -0,0 +1,13 @@ + + + + + + + + + \ No newline at end of file