/** * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.camel.impl.transformer; import java.io.BufferedReader; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.util.Map; import org.apache.camel.AsyncCallback; import org.apache.camel.Consumer; import org.apache.camel.ContextTestSupport; import org.apache.camel.Converter; import org.apache.camel.Endpoint; import org.apache.camel.Exchange; import org.apache.camel.ExchangePattern; import org.apache.camel.Message; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.TypeConverters; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.impl.DefaultAsyncProducer; import org.apache.camel.impl.DefaultComponent; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.impl.DefaultExchange; import org.apache.camel.model.DataFormatDefinition; import org.apache.camel.spi.DataFormat; import org.apache.camel.spi.DataType; import org.apache.camel.spi.DataTypeAware; import org.apache.camel.spi.RouteContext; import org.apache.camel.spi.Transformer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * A TransformerTest demonstrates contract based declarative transformation via Java DSL. */ public class TransformerRouteTest extends ContextTestSupport { protected static final Logger LOG = LoggerFactory.getLogger(TransformerRouteTest.class); public void testJavaTransformer() throws Exception { MockEndpoint abcresult = getMockEndpoint("mock:abcresult"); abcresult.expectedMessageCount(1); abcresult.whenAnyExchangeReceived(new Processor() { @Override public void process(Exchange exchange) throws Exception { LOG.info("Asserting String -> XOrderResponse convertion"); assertEquals(XOrderResponse.class, exchange.getIn().getBody().getClass()); } }); MockEndpoint xyzresult = getMockEndpoint("mock:xyzresult"); xyzresult.expectedMessageCount(1); xyzresult.whenAnyExchangeReceived(new Processor() { @Override public void process(Exchange exchange) throws Exception { LOG.info("Asserting String -> XOrderResponse convertion is not yet performed"); assertEquals("response", exchange.getIn().getBody()); } }); Exchange exchange = new DefaultExchange(context, ExchangePattern.InOut); exchange.getIn().setBody(new AOrder()); Exchange answerEx = template.send("direct:abc", exchange); if (answerEx.getException() != null) { throw answerEx.getException(); } assertEquals(AOrderResponse.class, answerEx.getOut().getBody().getClass()); assertMockEndpointsSatisfied(); } public void testDataFormatTransformer() throws Exception { MockEndpoint xyzresult = getMockEndpoint("mock:xyzresult"); xyzresult.expectedMessageCount(1); xyzresult.whenAnyExchangeReceived(new Processor() { @Override public void process(Exchange exchange) throws Exception { LOG.info("Asserting String -> XOrderResponse convertion is not yet performed"); assertEquals("response", exchange.getIn().getBody()); } }); Exchange exchange = new DefaultExchange(context, ExchangePattern.InOut); ((DataTypeAware)exchange.getIn()).setBody("{name:XOrder}", new DataType("json:JsonXOrder")); Exchange answerEx = template.send("direct:dataFormat", exchange); if (answerEx.getException() != null) { throw answerEx.getException(); } assertEquals("{name:XOrderResponse}", answerEx.getOut().getBody(String.class)); assertMockEndpointsSatisfied(); } public void testEndpointTransformer() throws Exception { MockEndpoint xyzresult = getMockEndpoint("mock:xyzresult"); xyzresult.expectedMessageCount(1); xyzresult.whenAnyExchangeReceived(new Processor() { @Override public void process(Exchange exchange) throws Exception { LOG.info("Asserting String -> XOrderResponse convertion is not yet performed"); assertEquals("response", exchange.getIn().getBody()); } }); Exchange exchange = new DefaultExchange(context, ExchangePattern.InOut); exchange.getIn().setBody("<XOrder/>"); Exchange answerEx = template.send("direct:endpoint", exchange); if (answerEx.getException() != null) { throw answerEx.getException(); } assertEquals("<XOrderResponse/>", answerEx.getOut().getBody(String.class)); assertMockEndpointsSatisfied(); } public void testCustomTransformer() throws Exception { MockEndpoint xyzresult = getMockEndpoint("mock:xyzresult"); xyzresult.expectedMessageCount(1); xyzresult.whenAnyExchangeReceived(new Processor() { @Override public void process(Exchange exchange) throws Exception { LOG.info("Asserting String -> XOrderResponse convertion is not yet performed"); assertEquals("response", exchange.getIn().getBody()); } }); Exchange exchange = new DefaultExchange(context, ExchangePattern.InOut); exchange.getIn().setBody("name=XOrder"); Exchange answerEx = template.send("direct:custom", exchange); if (answerEx.getException() != null) { throw answerEx.getException(); } assertEquals("name=XOrderResponse", answerEx.getOut().getBody(String.class)); assertMockEndpointsSatisfied(); } @Override protected RouteBuilder createRouteBuilder() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { context.getTypeConverterRegistry().addTypeConverters(new MyTypeConverters()); from("direct:abc") .inputType(AOrder.class) .outputType(AOrderResponse.class) .process(new Processor() { public void process(Exchange exchange) throws Exception { LOG.info("Asserting input -> AOrder convertion"); assertEquals(AOrder.class, exchange.getIn().getBody().getClass()); } }) .inOut("direct:xyz") .to("mock:abcresult"); from("direct:xyz") .inputType(XOrder.class) .outputType(XOrderResponse.class) .process(new Processor() { public void process(Exchange exchange) throws Exception { LOG.info("Asserting input -> XOrder convertion"); assertEquals(XOrder.class, exchange.getIn().getBody().getClass()); exchange.getIn().setBody("response"); } }).to("mock:xyzresult"); transformer() .scheme("json") .withDataFormat(new MyJsonDataFormatDefinition()); from("direct:dataFormat") .inputType("json:JsonXOrder") .outputType("json:JsonXOrderResponse") .inOut("direct:xyz"); context.addComponent("myxml", new MyXmlComponent()); transformer() .fromType("xml:XmlXOrder") .toType(XOrder.class) .withUri("myxml:endpoint"); transformer() .fromType(XOrderResponse.class) .toType("xml:XmlXOrderResponse") .withUri("myxml:endpoint"); from("direct:endpoint") .inputType("xml:XmlXOrder") .outputType("xml:XmlXOrderResponse") .inOut("direct:xyz"); transformer() .fromType("other:OtherXOrder") .toType(XOrder.class) .withJava(OtherToXOrderTransformer.class); transformer() .fromType(XOrderResponse.class) .toType("other:OtherXOrderResponse") .withJava(XOrderResponseToOtherTransformer.class); from("direct:custom") .inputType("other:OtherXOrder") .outputType("other:OtherXOrderResponse") .inOut("direct:xyz"); } }; } public static class MyTypeConverters implements TypeConverters { @Converter public AOrder toAOrder(String order) { LOG.info("TypeConverter: String -> AOrder"); return new AOrder(); } @Converter public XOrder toXOrder(AOrder aorder) { LOG.info("TypeConverter: AOrder -> XOrder"); return new XOrder(); } @Converter public XOrderResponse toXOrderResponse(String res) { LOG.info("TypeConverter: String -> XOrderResponse"); return new XOrderResponse(); } @Converter public AOrderResponse toAOrderResponse(XOrderResponse xres) { LOG.info("TypeConverter: XOrderResponse -> AOrderResponse"); return new AOrderResponse(); } } public static class MyJsonDataFormatDefinition extends DataFormatDefinition { public static DataFormat getDataFormat(RouteContext routeContext, DataFormatDefinition type, String ref) { return new MyJsonDataFormatDefinition().createDataFormat(); } public DataFormat getDataFormat(RouteContext routeContext) { return createDataFormat(); } private DataFormat createDataFormat() { return new DataFormat() { @Override public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception { assertEquals(graph.toString(), XOrderResponse.class, graph.getClass()); LOG.info("DataFormat: XOrderResponse -> JSON"); stream.write("{name:XOrderResponse}".getBytes()); } @Override public Object unmarshal(Exchange exchange, InputStream stream) throws Exception { BufferedReader reader = new BufferedReader(new InputStreamReader(stream)); String line = ""; String input = ""; while ((line = reader.readLine()) != null) { input += line; } reader.close(); assertEquals("{name:XOrder}", input); LOG.info("DataFormat: JSON -> XOrder"); return new XOrder(); } }; } } public static class MyXmlComponent extends DefaultComponent { @Override protected Endpoint createEndpoint(String uri, String remaining, Map<String, Object> parameters) throws Exception { return new MyXmlEndpoint(); } } public static class MyXmlEndpoint extends DefaultEndpoint { @Override public Producer createProducer() throws Exception { return new DefaultAsyncProducer(this) { @Override public boolean process(Exchange exchange, AsyncCallback callback) { Object input = exchange.getIn().getBody(); if (input instanceof XOrderResponse) { LOG.info("Endpoint: XOrderResponse -> XML"); exchange.getIn().setBody("<XOrderResponse/>"); } else { assertEquals("<XOrder/>", input); LOG.info("Endpoint: XML -> XOrder"); exchange.getIn().setBody(new XOrder()); } callback.done(true); return true; } }; } @Override public Consumer createConsumer(Processor processor) throws Exception { return null; } @Override public boolean isSingleton() { return false; } @Override protected String createEndpointUri() { return "myxml:endpoint"; } } public static class OtherToXOrderTransformer extends Transformer { @Override public void transform(Message message, DataType from, DataType to) throws Exception { assertEquals("name=XOrder", message.getBody()); LOG.info("Bean: Other -> XOrder"); message.setBody(new XOrder()); } } public static class XOrderResponseToOtherTransformer extends Transformer { @Override public void transform(Message message, DataType from, DataType to) throws Exception { LOG.info("Bean: XOrderResponse -> Other"); message.setBody("name=XOrderResponse"); } } public static class AOrder { } public static class AOrderResponse { } public static class XOrder { } public static class XOrderResponse { } }