package org.talend.esb.mep.requestcallback.sample; import java.io.IOException; import java.net.Socket; import java.util.Arrays; import java.util.Collection; import java.util.Map; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ConcurrentHashMap; import javax.xml.namespace.QName; import javax.xml.transform.stream.StreamSource; import javax.xml.ws.Dispatch; import javax.xml.ws.Endpoint; import javax.xml.ws.Service; import org.apache.cxf.Bus; import org.apache.cxf.BusFactory; import org.apache.cxf.bus.CXFBusFactory; import org.apache.cxf.endpoint.Server; import org.apache.cxf.jaxws.JaxWsServerFactoryBean; import org.apache.cxf.service.model.EndpointInfo; import org.apache.cxf.service.model.ServiceInfo; import org.apache.cxf.transport.ConduitInitiatorManager; import org.apache.cxf.transport.DestinationFactoryManager; import org.apache.cxf.transport.jms.JMSTransportFactory; import org.apache.cxf.wsdl11.WSDLServiceFactory; import org.junit.After; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; import org.talend.esb.mep.requestcallback.beans.JmsUriConfigurator; import org.talend.esb.mep.requestcallback.feature.CallContext; import org.talend.esb.mep.requestcallback.sample.internal.ClientProviderHandler; import org.talend.esb.mep.requestcallback.sample.internal.ClientProviderHandler.IncomingMessageHandler; import org.talend.esb.mep.requestcallback.sample.internal.SeekBookInBasementFaultCallback; import org.talend.esb.mep.requestcallback.sample.internal.SeekBookInBasementHandler; import org.talend.esb.mep.requestcallback.sample.internal.SeekBookInBasementResponseCallback; import org.talend.esb.mep.requestcallback.sample.internal.ServiceProviderHandler; import static org.junit.Assert.*; @Ignore @RunWith(Parameterized.class) public class RequestCallbackJmsTest { private static final int NO_RUN = 0; // private static final int REQUEST_RESPONSE = 1; // private static final int ONE_WAY = 2; private static final int REQUEST_CALLBACK = 3; private static final int REQUEST_CALLBACK_ENFORCED = 4; private static final String SERVICE_NAMESPACE = "http://services.talend.org/demos/Library/1.0"; private static final String SERVICE_NAMESPACE_A = "http://services.talend.org/demos/Library/1.1"; private static final QName SERVICE_NAME = new QName(SERVICE_NAMESPACE, "LibraryProvider"); private static final QName SERVICE_NAME_A = new QName(SERVICE_NAMESPACE_A, "LibraryProvider"); private static final QName PORT_NAME = new QName(SERVICE_NAMESPACE, "Library_jmsPort"); private static final QName PORT_NAME_A = new QName(SERVICE_NAMESPACE_A, "Library_jmsPort"); private static boolean hasActiveMQ = probeActiveMQ(); private final QName serviceName; private final QName portName; private final String wsdlLocation; private final String requestLocation; private final String responseLocation; private final String operation; private final int mep; private final BlockingQueue<String> messageTransfer = new ArrayBlockingQueue<String>(8); private final BlockingQueue<Throwable> errorTransfer = new ArrayBlockingQueue<Throwable>(8); private final Map<String, IncomingMessageHandler> callbackMap = new ConcurrentHashMap<String, IncomingMessageHandler>(); private EndpointInfo endpointInfo = null; private Server server = null; private Endpoint callbackEndpoint = null; public RequestCallbackJmsTest( String wsdlLocation, String requestLocation, String responseLocation, String operation, int mep, boolean alternateName) { super(); this.wsdlLocation = wsdlLocation; this.requestLocation = requestLocation; this.responseLocation = responseLocation; this.operation = operation; this.mep = hasActiveMQ ? mep : NO_RUN; if (alternateName) { serviceName = SERVICE_NAME_A; portName = PORT_NAME_A; } else { serviceName = SERVICE_NAME; portName = PORT_NAME; } } @Parameterized.Parameters public static Collection<Object[]> getParameters() { return Arrays.asList(new Object[][] { { "/LibraryJmsA.wsdl", "/request-library-rc.xml", "/response-library-rc.xml", "seekBookInBasement", REQUEST_CALLBACK_ENFORCED, false }, { "/LibraryJmsB.wsdl", "/request-library-rc.xml", "/response-library-rc.xml", "seekBookInBasement", REQUEST_CALLBACK, true }, { "/LibraryJmsC.wsdl", "/request-library-rc-C.xml", "/response-library-rc-C.xml", "seekBookInBasement", REQUEST_CALLBACK, false }, { "", "", "", "", NO_RUN, false } }); } @Before public void initialize() throws Exception { if (mep == NO_RUN) { return; } final Bus bus = BusFactory.getDefaultBus(); final JMSTransportFactory jmsTransport = new JMSTransportFactory(); final DestinationFactoryManager dfm = bus.getExtension(DestinationFactoryManager.class); dfm.registerDestinationFactory( "http://schemas.xmlsoap.org/soap/http", jmsTransport); dfm.registerDestinationFactory( "http://schemas.xmlsoap.org/soap/jms", jmsTransport); dfm.registerDestinationFactory( "http://schemas.xmlsoap.org/wsdl/soap/http", jmsTransport); dfm.registerDestinationFactory( "http://cxf.apache.org/bindings/xformat", jmsTransport); final ConduitInitiatorManager extension = bus.getExtension(ConduitInitiatorManager.class); extension.registerConduitInitiator( "http://schemas.xmlsoap.org/wsdl/soap/http", jmsTransport); extension.registerConduitInitiator( "http://schemas.xmlsoap.org/soap/http", jmsTransport); extension.registerConduitInitiator( "http://schemas.xmlsoap.org/soap/jms", jmsTransport); extension.registerConduitInitiator( "http://cxf.apache.org/bindings/xformat", jmsTransport); final WSDLServiceFactory wsdlSvcFactory = new WSDLServiceFactory (CXFBusFactory.getThreadDefaultBus(), wsdlLocation); final org.apache.cxf.service.Service cxfService = wsdlSvcFactory.create(); final ServiceInfo si = findServiceByName(cxfService, serviceName); if (si == null) { throw new RuntimeException("WSDL does not contain service " + serviceName); } final EndpointInfo ei = findEndpoint(si, portName); if (ei == null) { throw new RuntimeException("WSDL does not contain port " + portName); } endpointInfo = ei; callbackMap.put("seekBookInBasementResponse", new SeekBookInBasementResponseCallback(messageTransfer)); callbackMap.put("seekBookInBasementFault", new SeekBookInBasementFaultCallback(messageTransfer)); } @Test(timeout = 300000L) public void testRequestCallback() throws Exception { if (mep == NO_RUN) { if (!hasActiveMQ) { System.err.println("ActiveMQ is not available"); } return; } subTestServerStartup(); subTestServiceCall(); } @After public void done() throws Exception { if (mep == NO_RUN) { return; } if (callbackEndpoint != null) { callbackEndpoint.stop(); } if (server != null) { server.stop(); server.destroy(); } checkError(true); } private void subTestServerStartup() throws Exception { final SeekBookInBasementHandler businessHandler = new SeekBookInBasementHandler(responseLocation, "classpath:" + wsdlLocation); final ServiceProviderHandler implementor = new ServiceProviderHandler( errorTransfer, messageTransfer, businessHandler, operation); final JaxWsServerFactoryBean factory = new JaxWsServerFactoryBean(); factory.setServiceName(serviceName); factory.setEndpointName(portName); factory.setWsdlLocation(wsdlLocation); factory.setServiceBean(implementor); CallContext.setupServerFactory(factory); JmsUriConfigurator configurator = JmsUriConfigurator.create(factory); factory.setAddress(configurator.getJmsAddress()); server = factory.create(); sleep(1); checkError(false); } private void subTestServiceCall() throws Exception { // server.start(); final Service service = Service.create( getClass().getResource(wsdlLocation), serviceName); service.addPort(portName, endpointInfo.getBinding().getBindingId(), endpointInfo.getAddress()); // 1. Register a local callback endpoint on the client side final ClientProviderHandler callbackHandler = new ClientProviderHandler( errorTransfer, messageTransfer, callbackMap); final Endpoint ep = CallContext.createCallbackEndpoint( callbackHandler, wsdlLocation); callbackEndpoint = ep; JmsUriConfigurator cConfigurator = JmsUriConfigurator.create(ep); ep.publish(cConfigurator.getJmsAddress()); // 2. Create a client final Dispatch<StreamSource> dispatcher = service.createDispatch( portName, StreamSource.class, Service.Mode.PAYLOAD); CallContext.setupDispatch(dispatcher, ep); JmsUriConfigurator configurator = JmsUriConfigurator.create(dispatcher); configurator.configureDispatch(dispatcher); if (mep == REQUEST_CALLBACK_ENFORCED) { final QName opName = new QName(serviceName.getNamespaceURI(), operation); CallContext.enforceOperation(opName, dispatcher); } // 3. Invoke the service operation final StreamSource request = new StreamSource( getClass().getResourceAsStream(requestLocation)); dispatcher.invokeOneWay(request); assertTrue(messageTransfer.take() != null); sleep(1); checkError(false); } private void checkError(boolean clear) throws Exception { try { final Throwable t = errorTransfer.poll(); if (t != null) { throw t; } } catch (Exception e) { throw e; } catch (Error e) { throw e; } catch (Throwable e) { throw new RuntimeException("Unknown Throwable. ", e); } finally { if (clear) { errorTransfer.clear(); } } } private static void sleep(int seconds) { try { Thread.sleep(1000L * (long) seconds); } catch (InterruptedException e) { // ignore } } private static ServiceInfo findServiceByName( org.apache.cxf.service.Service cxfService, QName serviceName) { for (ServiceInfo si : cxfService.getServiceInfos()) { if (si.getName().equals(serviceName)) { return si; } } return null; } private static EndpointInfo findEndpoint(ServiceInfo si, QName name) { for (EndpointInfo ei : si.getEndpoints()) { if (name.equals(ei.getName())) { return ei; } } return null; } private static boolean probeActiveMQ() { try { Socket s = new Socket("localhost", 61616); s.close(); return true; } catch (IOException e) { return false; } } }