private Transformer<?, ?> getJavaFallbackTransformer(QName from, QName to) { Class<?> javaType = JavaService.toJavaMessageType(from); if (javaType == null) { return null; } Set<Map.Entry<NameKey, Transformer<?, ?>>> entrySet = _transformers.entrySet(); List<JavaSourceFallbackTransformer> fallbackTransforms = new ArrayList<JavaSourceFallbackTransformer>(); for (Map.Entry<NameKey, Transformer<?, ?>> entry : entrySet) { NameKey nameKey = entry.getKey(); // "to" must be an exact match... if (nameKey.getTo().equals(to)) { if (JavaService.isJavaMessageType(nameKey.getFrom())) { Class<?> candidateType = JavaService.toJavaMessageType(nameKey.getFrom()); if (candidateType != null && candidateType.isAssignableFrom(javaType)) { fallbackTransforms.add( new JavaSourceFallbackTransformer(candidateType, entry.getValue())); } } } } if (fallbackTransforms.size() == 0) { // No fallback... return null; } if (fallbackTransforms.size() == 1) { Transformer<?, ?> fallbackTransformer = fallbackTransforms.get(0)._transformer; addFallbackTransformer(fallbackTransformer, from, to); return fallbackTransformer; } try { JavaSourceFallbackTransformerComparator comparator = new JavaSourceFallbackTransformerComparator(); Collections.sort(fallbackTransforms, comparator); // Closest super-type will be first in the list.. Transformer<?, ?> fallbackTransformer = fallbackTransforms.get(0)._transformer; addFallbackTransformer(fallbackTransformer, from, to); return fallbackTransformer; } catch (MultipleFallbacks e) { _log.debug( "Cannot resolve fallback Transformer from '" + from + "' to '" + to + "'. " + e.getMessage()); return null; } }
@Test public void test_transform_anno_no_types_defined() { org.switchyard.transform.Transformer transformer = TransformerUtil.newTransformer( TestTransformer.class, JavaService.toMessageType(B.class), JavaService.toMessageType(A.class)); Assert.assertTrue(!(transformer instanceof TestTransformer)); Assert.assertTrue(transformer.transform(new B()) instanceof A); }
@Test public void test_transform_interface_impl() { org.switchyard.transform.Transformer transformer = TransformerUtil.newTransformer( TestTransformer.class, JavaService.toMessageType(A.class), JavaService.toMessageType(B.class)); Assert.assertTrue(transformer instanceof TestTransformer); Assert.assertTrue(transformer.transform(new A()) instanceof B); }
@Override public int compare(T t1, T t2) { if (t1._javaType == t2._javaType) { return 0; } else if (t1._javaType.isAssignableFrom(t2._javaType)) { return 1; } else if (t2._javaType.isAssignableFrom(t1._javaType)) { return -1; } else { // Unrelated types. This means there are branches in the inheritance options, // which means there are multiple possibilities, therefore it's not uniquely resolvable. throw new MultipleFallbacks( "Multiple possible fallback types '" + JavaService.toMessageType(t1._javaType) + "' and '" + JavaService.toMessageType(t2._javaType) + "'."); } }
@Override public Transformer<?, ?> getTransformer(QName from, QName to) { NameKey nameKey = new NameKey(from, to); Transformer<?, ?> transformer = _transformers.get(nameKey); if (transformer == null) { transformer = _fallbackTransformers.get(nameKey); if (transformer == null && JavaService.isJavaMessageType(from)) { transformer = getJavaFallbackTransformer(from, to); } } return transformer; }
@Test public void wrongOperationSelectorTest() { MockHandler mock = new MockHandler().forwardInToOut(); JavaService metadata = JavaService.fromClass(TestService.class); _serviceDomain.registerService(_serviceName, metadata, mock); _serviceDomain.registerServiceReference(_serviceName, metadata); InboundHandler<?> handler = createInboundHandler( _serviceName, "direct:input", new V1StaticOperationSelectorModel().setOperationName("missing")); handler.start(); sendBody("direct:input", PAYLOAD); assertTrue(mock.getMessages().isEmpty()); handler.stop(); }
@Test public void test_listTransformations() { List<TransformerTypes> transformTypes = TransformerUtil.listTransformations(TestTransformer.class); Assert.assertEquals(5, transformTypes.size()); Assert.assertEquals(QName.valueOf("X"), transformTypes.get(0).getFrom()); Assert.assertEquals(QName.valueOf("Y"), transformTypes.get(0).getTo()); Assert.assertEquals(QName.valueOf("Z"), transformTypes.get(1).getFrom()); Assert.assertEquals(JavaService.toMessageType(A.class), transformTypes.get(1).getTo()); Assert.assertEquals(JavaService.toMessageType(A.class), transformTypes.get(2).getFrom()); Assert.assertEquals(JavaService.toMessageType(B.class), transformTypes.get(2).getTo()); Assert.assertEquals(JavaService.toMessageType(B.class), transformTypes.get(3).getFrom()); Assert.assertEquals(QName.valueOf("Z"), transformTypes.get(3).getTo()); Assert.assertEquals(JavaService.toMessageType(B.class), transformTypes.get(4).getFrom()); Assert.assertEquals(JavaService.toMessageType(A.class), transformTypes.get(4).getTo()); }
private ServiceReference createMockServiceRef() { final ServiceReference serviceReference = mock(ServiceReference.class); when(serviceReference.getInterface()).thenReturn(JavaService.fromClass(MockService.class)); return serviceReference; }
public TestTransformer() { super(JavaService.toMessageType(A.class), JavaService.toMessageType(B.class)); }
@Override public <T> T getContent(final Class<T> type) { if (type == null) { throw new IllegalArgumentException("null 'type' argument."); } if (_content == null) { return null; } if (type.isInstance(_content)) { return type.cast(_content); } if (_transformerRegistry == null) { throw new SwitchYardException( "Cannot convert from '" + _content.getClass().getName() + "' to '" + type.getName() + "'. No TransformRegistry available."); } QName fromType = JavaService.toMessageType(_content.getClass()); QName toType = JavaService.toMessageType(type); Transformer transformer = _transformerRegistry.getTransformer(fromType, toType); if (transformer == null) { throw new SwitchYardException( "Cannot convert from '" + _content.getClass().getName() + "' to '" + type.getName() + "'. No registered Transformer available for transforming from '" + fromType + "' to '" + toType + "'. A Transformer must be registered."); } Object transformedContent = transformer.transform(_content); if (transformedContent == null) { throw new SwitchYardException( "Error converting from '" + _content.getClass().getName() + "' to '" + type.getName() + "'. Transformer '" + transformer.getClass().getName() + "' returned null."); } if (!type.isInstance(transformedContent)) { throw new SwitchYardException( "Error converting from '" + _content.getClass().getName() + "' to '" + type.getName() + "'. Transformer '" + transformer.getClass().getName() + "' returned incompatible type '" + transformedContent.getClass().getName() + "'."); } return type.cast(transformedContent); }
/** * Send a message hash to the specified operation. * * @param operationName The operation name. * @param rubyHash The message hash. * @return The response object if an IN_OUT operation was invoked, otherwise null. * @throws Throwable An exception occurred while invoking the target operation. */ public Object send(String operationName, RubyHash rubyHash) throws Throwable { if (operationName == null) { throw new IllegalArgumentException("null 'operationName' argument."); } if (rubyHash == null) { throw new IllegalArgumentException("null 'rubyHash' argument."); } ServiceOperation operation = _serviceReference.getInterface().getOperation(operationName); if (operation == null) { throw new IllegalArgumentException( "Unknown operation name '" + operationName + "' on Service '" + _serviceReference.getName() + "'."); } // Clone the RubyHash to convert it to a normal Map based graph. This makes it possible // to more safely transport the payload data out of the ruby app via a SwitchYard Exchange... Map<String, Object> payload = deepClone(rubyHash); // Create the exchange contract... BaseExchangeContract exchangeContract = new BaseExchangeContract(operation); // Set the input type... exchangeContract .getInvokerInvocationMetaData() .setInputType(JavaService.toMessageType(payload.getClass())); if (operation.getExchangePattern() == ExchangePattern.IN_OUT) { final BlockingQueue<Exchange> responseQueue = new ArrayBlockingQueue<Exchange>(1); AtomicReference<ExchangeHandler> responseExchangeHandler = new AtomicReference<ExchangeHandler>( new ExchangeHandler() { public void handleMessage(Exchange exchange) throws HandlerException { responseQueue.offer(exchange); } public void handleFault(Exchange exchange) { responseQueue.offer(exchange); } }); Exchange exchange = _serviceReference.createExchange(exchangeContract, responseExchangeHandler.get()); Message message = exchange.createMessage().setContent(payload); exchange.send(message); Exchange exchangeOut = null; try { exchangeOut = responseQueue.take(); } catch (InterruptedException e) { throw new SwitchYardException( "Operation '" + operationName + "' on Service '" + _serviceReference.getName() + "' interrupted.", e); } if (exchangeOut.getState() == ExchangeState.OK) { return exchangeOut.getMessage().getContent(); } else { Object failureObj = exchangeOut.getMessage().getContent(); if (failureObj instanceof Throwable) { if (failureObj instanceof InvocationTargetException) { throw ((Throwable) failureObj).getCause(); } else { throw (Throwable) failureObj; } } else { throw new SwitchYardException( "Service invocation failure. Service '" + _serviceReference.getName() + "', operation '" + operationName + "'. Non Throwable failure message payload: " + failureObj); } } } else { Exchange exchange = _serviceReference.createExchange(exchangeContract); Message message = exchange.createMessage().setContent(payload); exchange.send(message); } return null; }