/* * Copyright 2002-2016 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.config.xml; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.handler.ServiceActivatingHandler; import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Mark Fisher * @author Gary Russell * @since 2.0 */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class ServiceActivatorParserTests { @Autowired private MessageChannel literalExpressionInput; @Autowired private MessageChannel beanAsTargetInput; @Autowired private MessageChannel beanAsArgumentInput; @Autowired private MessageChannel beanInvocationResultInput; @Autowired private MessageChannel multipleLiteralArgsInput; @Autowired private MessageChannel multipleArgsFromPayloadInput; @Autowired private MessageChannel advisedInput; @SuppressWarnings("unused") // testing auto wiring only @Autowired @Qualifier("org.springframework.integration.config.ServiceActivatorFactoryBean#0") private ServiceActivatingHandler testAliasByGeneratedName; @SuppressWarnings("unused") // testing auto wiring only @Autowired @Qualifier("testAlias.handler") private ServiceActivatingHandler testAlias; @Test public void literalExpression() { Object result = this.sendAndReceive(literalExpressionInput, "hello"); assertEquals("foo", result); } @Test public void beanAsTarget() { Object result = this.sendAndReceive(beanAsTargetInput, "hello"); assertEquals("HELLO", result); } @Test public void beanAsArgument() { Object result = this.sendAndReceive(beanAsArgumentInput, new TestPayload()); assertEquals("TestBean", result); } @Test public void beanInvocationResult() { Object result = this.sendAndReceive(beanInvocationResultInput, "hello"); assertEquals("helloFOO", result); } @Test public void multipleLiteralArgs() { Object result = this.sendAndReceive(multipleLiteralArgsInput, "hello"); assertEquals("foobar", result); } @Test public void multipleArgsFromPayload() { Object result = this.sendAndReceive(multipleArgsFromPayloadInput, new TestPerson("John", "Doe")); assertEquals("JohnDoe", result); } @Test public void advised() { Object result = this.sendAndReceive(advisedInput, "hello"); assertEquals("bar", result); } @Test public void failRefAndExpression() { try { new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail-ref-and-expression-context.xml", this.getClass()).close(); fail("Expected exception"); } catch (BeanDefinitionParsingException e) { assertTrue(e.getMessage().startsWith("Configuration problem: Only one of 'ref' or 'expression' is permitted, not both, " + "on element 'service-activator' with id='test'.")); } } @Test public void failRefAndBean() { try { new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail-ref-and-bean-context.xml", this.getClass()).close(); fail("Expected exception"); } catch (BeanDefinitionParsingException e) { assertTrue(e.getMessage().startsWith("Configuration problem: Ambiguous definition. " + "Inner bean org.springframework.integration.config.xml.ServiceActivatorParserTests$TestBean " + "declaration and \"ref\" testBean are not allowed together on element " + "'service-activator' with id='test'.")); } } @Test public void failExpressionAndBean() { try { new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail-expression-and-bean-context.xml", this.getClass()).close(); fail("Expected exception"); } catch (BeanDefinitionParsingException e) { assertTrue(e.getMessage().startsWith("Configuration problem: Neither 'ref' nor 'expression' " + "are permitted when an inner bean (<bean/>) is configured on element " + "'service-activator' with id='test'.")); } } @Test public void failNoService() { try { new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail-no-service-context.xml", this.getClass()).close(); fail("Expected exception"); } catch (BeanDefinitionParsingException e) { assertTrue(e.getMessage().startsWith("Configuration problem: Exactly one of the 'ref' " + "attribute, 'expression' attribute, or inner bean (<bean/>) definition " + "is required for element 'service-activator' with id='test'.")); } } @Test public void failExpressionAndExpression() { try { new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail-expression-and-expression-element-context.xml", this.getClass()).close(); fail("Expected exception"); } catch (BeanDefinitionParsingException e) { assertTrue(e.getMessage().startsWith("Configuration problem: Neither 'ref' nor 'expression' are permitted when " + "an inner 'expression' element is configured on element " + "'service-activator' with id='test'.")); } } @Test public void failMethodAndExpressionElement() { try { new ClassPathXmlApplicationContext(this.getClass().getSimpleName() + "-fail-method-and-expression-element-context.xml", this.getClass()).close(); fail("Expected exception"); } catch (BeanDefinitionParsingException e) { assertTrue(e.getMessage().startsWith("Configuration problem: A 'method' attribute is not permitted when configuring " + "an 'expression' on element 'service-activator' with id='test'.")); } } private Object sendAndReceive(MessageChannel channel, Object payload) { MessagingTemplate template = new MessagingTemplate(); template.setDefaultDestination(channel); return template.convertSendAndReceive(payload, null); } @SuppressWarnings("unused") private static class TestBean { TestBean() { super(); } public String caps(String s) { return s.toUpperCase(); } public String concat(String s1, String s2) { return s1 + s2; } } @SuppressWarnings("unused") private static class TestPayload { TestPayload() { super(); } public String getSimpleClassName(Object o) { return o.getClass().getSimpleName(); } } @SuppressWarnings("unused") private static class TestPerson { private final String firstName; private final String lastName; TestPerson(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } } public static class BarAdvice extends AbstractRequestHandlerAdvice { @Override protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception { callback.execute(); return "bar"; } } }