/* * Copyright 2002-2017 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.integration.ws.config; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.doAnswer; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.concurrent.atomic.AtomicReference; import javax.jms.BytesMessage; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.DeliveryMode; import javax.jms.JMSException; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.Session; import org.hamcrest.Matchers; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.packet.Stanza; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.integration.support.MessageBuilder; import org.springframework.integration.test.util.TestUtils; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessageHandlingException; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.ws.client.WebServiceClientException; import org.springframework.ws.client.WebServiceIOException; import org.springframework.ws.client.core.WebServiceMessageCallback; import org.springframework.ws.client.core.WebServiceMessageExtractor; import org.springframework.ws.client.core.WebServiceTemplate; import org.springframework.ws.client.support.interceptor.ClientInterceptor; import org.springframework.ws.context.MessageContext; import org.springframework.ws.transport.WebServiceConnection; import org.springframework.ws.transport.WebServiceMessageSender; import org.springframework.ws.transport.context.TransportContext; import org.springframework.ws.transport.context.TransportContextHolder; import org.springframework.ws.transport.mail.MailSenderConnection; /** * @author Mark Fisher * @author Artem Bilan * @author Andy Wilkinson * @since 2.1 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class UriVariableTests { @Autowired @Qualifier("httpOutboundGateway.handler") private MessageHandler httpOutboundGateway; @Autowired private TestClientInterceptor interceptor; @Autowired private MessageChannel inputHttp; @Autowired private MessageChannel inputJms; @Autowired private WebServiceMessageSender jmsMessageSender; @Autowired private ConnectionFactory jmsConnectionFactory; @Autowired private MessageChannel inputXmpp; @Autowired private XMPPConnection xmppConnection; @Autowired private MessageChannel inputEmail; @Autowired private Int2720EmailTestClientInterceptor emailInterceptor; @Test @SuppressWarnings("unchecked") public void testHttpUriVariables() { WebServiceTemplate webServiceTemplate = TestUtils.getPropertyValue(this.httpOutboundGateway, "webServiceTemplate", WebServiceTemplate.class); webServiceTemplate = Mockito.spy(webServiceTemplate); final AtomicReference<String> uri = new AtomicReference<>(); doAnswer(invocation -> { uri.set(invocation.getArgument(0)); throw new WebServiceIOException("intentional"); }).when(webServiceTemplate) .sendAndReceive(Mockito.anyString(), Mockito.any(WebServiceMessageCallback.class), (WebServiceMessageExtractor<Object>) Mockito.any(WebServiceMessageExtractor.class)); new DirectFieldAccessor(this.httpOutboundGateway).setPropertyValue("webServiceTemplate", webServiceTemplate); Message<?> message = MessageBuilder.withPayload("<spring/>") .setHeader("x", "integration") .setHeader("param", "test1 & test2") .build(); try { this.inputHttp.send(message); } catch (MessageHandlingException e) { // expected assertThat(e.getCause(), Matchers.is(Matchers.instanceOf(WebServiceIOException.class))); // offline } assertEquals("http://localhost/spring-integration?param=test1%20&%20test2", uri.get()); } @Test public void testInt2720JmsUriVariables() throws JMSException, IOException { final String destinationName = "SPRING.INTEGRATION.QUEUE"; Queue queue = Mockito.mock(Queue.class); // Need for 'QueueSession#createQueue()' Mockito.when(queue.getQueueName()).thenReturn(destinationName); Session session = Mockito.mock(Session.class); Mockito.when(session.createQueue(Mockito.anyString())).thenReturn(queue); Mockito.when(session.createBytesMessage()).thenReturn(Mockito.mock(BytesMessage.class)); MessageProducer producer = Mockito.mock(MessageProducer.class); Mockito.when(session.createProducer(queue)).thenReturn(producer); // For this test it's enough to not go ahead. Invoked in the 'JmsSenderConnection#onSendAfterWrite' on the // 'WebServiceTemplate#sendRequest' after invocation of our 'TestClientInterceptor' Mockito.when(session.createTemporaryQueue()).thenThrow(new WebServiceIOException("intentional")); Connection connection = Mockito.mock(Connection.class); Mockito.when(connection.createSession(Mockito.anyBoolean(), Mockito.anyInt())).thenReturn(session); Mockito.when(this.jmsConnectionFactory.createConnection()).thenReturn(connection); Message<?> message = MessageBuilder.withPayload("<spring/>") .setHeader("jmsQueue", destinationName) .setHeader("deliveryMode", "NON_PERSISTENT") .setHeader("jms_priority", "5") .build(); try { this.inputJms.send(message); } catch (MessageHandlingException e) { // expected Class<?> causeType = e.getCause().getClass(); assertTrue(WebServiceIOException.class.equals(causeType)); // offline } URI uri = URI.create("jms:SPRING.INTEGRATION.QUEUE?deliveryMode=NON_PERSISTENT&priority=5"); Mockito.verify(this.jmsMessageSender).createConnection(uri); Mockito.verify(session).createQueue(destinationName); assertEquals("jms:" + destinationName, this.interceptor.getLastUri().toString()); Mockito.verify(producer).setDeliveryMode(DeliveryMode.NON_PERSISTENT); Mockito.verify(producer).setPriority(5); } @Test public void testInt2720EmailUriVariables() { final String testEmailTo = "user@example.com"; final String testEmailSubject = "Test subject"; Message<?> message = MessageBuilder.withPayload("<spring/>") .setHeader("to", testEmailTo) .setHeader("subject", testEmailSubject) .build(); try { this.inputEmail.send(message); } catch (MessageHandlingException e) { // expected Class<?> causeType = e.getCause().getClass(); assertTrue(WebServiceIOException.class.equals(causeType)); // offline } WebServiceConnection webServiceConnection = this.emailInterceptor.getLastWebServiceConnection(); assertEquals(testEmailTo, TestUtils.getPropertyValue(webServiceConnection, "to").toString()); assertEquals(testEmailSubject, TestUtils.getPropertyValue(webServiceConnection, "subject")); assertEquals("mailto:user@example.com?subject=Test%20subject", this.emailInterceptor.getLastUri().toString()); } @Test public void testInt2720XmppUriVariables() throws SmackException.NotConnectedException { Mockito.doThrow(new WebServiceIOException("intentional")).when(this.xmppConnection).sendStanza(Mockito.any(Stanza.class)); Message<?> message = MessageBuilder.withPayload("<spring/>").setHeader("to", "user").build(); try { this.inputXmpp.send(message); } catch (MessageHandlingException e) { // expected Class<?> causeType = e.getCause().getClass(); assertTrue(WebServiceIOException.class.equals(causeType)); // offline } ArgumentCaptor<Stanza> argument = ArgumentCaptor.forClass(Stanza.class); Mockito.verify(this.xmppConnection).sendStanza(argument.capture()); assertEquals("user@jabber.org", argument.getValue().getTo()); assertEquals("xmpp:user@jabber.org", this.interceptor.getLastUri().toString()); } private static class TestClientInterceptor implements ClientInterceptor { private volatile URI lastUri; TestClientInterceptor() { super(); } public URI getLastUri() { return this.lastUri; } @Override public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException { TransportContext tc = TransportContextHolder.getTransportContext(); if (tc != null) { try { this.lastUri = tc.getConnection().getUri(); } catch (URISyntaxException e) { throw new IllegalStateException(e); } } else { throw new IllegalStateException("expected WebServiceConnection in the TransportContext"); } return true; } @Override public boolean handleResponse(MessageContext messageContext) throws WebServiceClientException { return false; } @Override public boolean handleFault(MessageContext messageContext) throws WebServiceClientException { return false; } @Override public void afterCompletion(MessageContext messageContext, Exception ex) throws WebServiceClientException { } } private static class Int2720EmailTestClientInterceptor extends TestClientInterceptor { private volatile WebServiceConnection webServiceConnection; public WebServiceConnection getLastWebServiceConnection() { return webServiceConnection; } @Override public boolean handleRequest(MessageContext messageContext) throws WebServiceClientException { TransportContext tc = TransportContextHolder.getTransportContext(); WebServiceConnection webServiceConnection = tc.getConnection(); if (webServiceConnection instanceof MailSenderConnection) { this.webServiceConnection = webServiceConnection; } else { throw new IllegalStateException("expected MailSenderConnection in the TransportContext"); } super.handleRequest(messageContext); throw new WebServiceIOException("intentional"); } } }