/** * 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.cxf.systest.jaxrs.jms; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.HashMap; import java.util.Map; import java.util.Properties; import javax.jms.BytesMessage; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Session; import javax.naming.Context; import javax.naming.InitialContext; import javax.ws.rs.core.Response; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import org.apache.cxf.ext.logging.LoggingInInterceptor; import org.apache.cxf.jaxrs.client.JAXRSClientFactory; import org.apache.cxf.jaxrs.client.WebClient; import org.apache.cxf.jaxrs.model.AbstractResourceInfo; import org.apache.cxf.systest.jaxrs.Book; import org.apache.cxf.systest.jaxrs.JMSBookStore; import org.apache.cxf.testutil.common.AbstractBusClientServerTestBase; import org.apache.cxf.testutil.common.EmbeddedJMSBrokerLauncher; import org.junit.BeforeClass; import org.junit.Test; public class JAXRSJmsTest extends AbstractBusClientServerTestBase { protected static boolean serversStarted; static final String JMS_PORT = EmbeddedJMSBrokerLauncher.PORT; @BeforeClass public static void startServers() throws Exception { if (serversStarted) { return; } AbstractResourceInfo.clearAllMaps(); Map<String, String> props = new HashMap<>(); if (System.getProperty("org.apache.activemq.default.directory.prefix") != null) { props.put("org.apache.activemq.default.directory.prefix", System.getProperty("org.apache.activemq.default.directory.prefix")); } props.put("java.util.logging.config.file", System.getProperty("java.util.logging.config.file")); assertTrue("server did not launch correctly", launchServer(EmbeddedJMSBrokerLauncher.class, props, null)); assertTrue("server did not launch correctly", launchServer(JMSServer.class, true)); serversStarted = true; } @Test public void testGetBookFromWebClient() throws Exception { // setup the the client String endpointAddressUrlEncoded = "jms:jndi:dynamicQueues/test.jmstransport.text" + "?replyToName=dynamicQueues/test.jmstransport.response" + "&jndiInitialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&jndiURL=tcp://localhost:" + JMS_PORT; WebClient client = WebClient.create(endpointAddressUrlEncoded); WebClient.getConfig(client).getInInterceptors().add(new LoggingInInterceptor()); WebClient.getConfig(client).getRequestContext() .put(org.apache.cxf.message.Message.REQUEST_URI, "/bookstore/books/123"); Book book = client.get(Book.class); assertEquals("Get a wrong response code.", 200, client.getResponse().getStatus()); assertEquals("Get a wrong book id.", 123, book.getId()); } @Test public void testPutBookOneWayWithWebClient() throws Exception { // setup the the client String endpointAddressUrlEncoded = "jms:jndi:dynamicQueues/test.jmstransport.text" + "?replyToName=dynamicQueues/test.jmstransport.response" + "&jndiInitialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&jndiURL=tcp://localhost:" + JMS_PORT; WebClient client = WebClient.create(endpointAddressUrlEncoded); WebClient.getConfig(client).getRequestContext() .put(org.apache.cxf.message.Message.REQUEST_URI, "/bookstore/oneway"); client.header("OnewayRequest", "true"); Response r = client.put(new Book("OneWay From WebClient", 129L)); assertEquals(202, r.getStatus()); assertFalse(r.hasEntity()); Context ctx = getContext(); ConnectionFactory factory = (ConnectionFactory)ctx.lookup("ConnectionFactory"); Destination replyToDestination = (Destination)ctx.lookup("dynamicQueues/test.jmstransport.response"); Connection connection = null; try { connection = factory.createConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); checkBookInResponse(session, replyToDestination, 129L, "OneWay From WebClient"); session.close(); } finally { close(connection); } } @Test public void testGetBookFromWebClientWithPath() throws Exception { // setup the the client String endpointAddressUrlEncoded = "jms:jndi:dynamicQueues/test.jmstransport.text" + "?jndiInitialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&replyToName=dynamicQueues/test.jmstransport.response" + "&jndiURL=tcp://localhost:" + JMS_PORT + "&jndiConnectionFactoryName=ConnectionFactory"; WebClient client = WebClient.create(endpointAddressUrlEncoded); client.path("bookstore").path("books").path("123"); Book book = client.get(Book.class); assertEquals("Get a wrong response code.", 200, client.getResponse().getStatus()); assertEquals("Get a wrong book id.", 123, book.getId()); } @Test public void testGetBookFromProxyClient() throws Exception { // setup the the client String endpointAddressUrlEncoded = "jms:jndi:dynamicQueues/test.jmstransport.text" + "?jndiInitialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&replyToName=dynamicQueues/test.jmstransport.response" + "&jndiURL=tcp://localhost:" + JMS_PORT + "&jndiConnectionFactoryName=ConnectionFactory"; JMSBookStore client = JAXRSClientFactory.create(endpointAddressUrlEncoded, JMSBookStore.class); Book book = client.getBook("123"); assertEquals("Get a wrong response code.", 200, WebClient.client(client).getResponse().getStatus()); assertEquals("Get a wrong book id.", 123, book.getId()); } @Test public void testGetBookFromSubresourceProxyClient() throws Exception { // setup the the client String endpointAddressUrlEncoded = "jms:jndi:dynamicQueues/test.jmstransport.text" + "?jndiInitialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&replyToName=dynamicQueues/test.jmstransport.response" + "&jndiURL=tcp://localhost:" + JMS_PORT + "&jndiConnectionFactoryName=ConnectionFactory"; JMSBookStore client = JAXRSClientFactory.create(endpointAddressUrlEncoded, JMSBookStore.class); Book bookProxy = client.getBookSubResource("123"); Book book = bookProxy.retrieveState(); assertEquals("Get a wrong response code.", 200, WebClient.client(bookProxy).getResponse().getStatus()); assertEquals("Get a wrong book id.", 123, book.getId()); } @Test public void testGetBookFromProxyClientWithQuery() throws Exception { // setup the the client String endpointAddressUrlEncoded = "jms:jndi:dynamicQueues/test.jmstransport.text" + "?jndiInitialContextFactory=org.apache.activemq.jndi.ActiveMQInitialContextFactory" + "&replyToName=dynamicQueues/test.jmstransport.response" + "&jndiURL=tcp://localhost:" + JMS_PORT + "&jndiConnectionFactoryName=ConnectionFactory"; JMSBookStore client = JAXRSClientFactory.create(endpointAddressUrlEncoded, JMSBookStore.class); Book book = client.getBookByURLQuery(new String[] {"1", "2", "3"}); assertEquals("Get a wrong response code.", 200, WebClient.client(client).getResponse().getStatus()); assertEquals("Get a wrong book id.", 123, book.getId()); } @Test public void testGetBook() throws Exception { Context ctx = getContext(); ConnectionFactory factory = (ConnectionFactory)ctx.lookup("ConnectionFactory"); Destination destination = (Destination)ctx.lookup("dynamicQueues/test.jmstransport.text"); Destination replyToDestination = (Destination)ctx.lookup("dynamicQueues/test.jmstransport.response"); Connection connection = null; try { connection = factory.createConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); postGetMessage(session, destination, replyToDestination); checkBookInResponse(session, replyToDestination, 123L, "CXF JMS Rocks"); session.close(); } finally { close(connection); } } @Test public void testAddGetBook() throws Exception { Context ctx = getContext(); ConnectionFactory factory = (ConnectionFactory)ctx.lookup("ConnectionFactory"); Destination destination = (Destination)ctx.lookup("dynamicQueues/test.jmstransport.text"); Destination replyToDestination = (Destination)ctx.lookup("dynamicQueues/test.jmstransport.response"); Connection connection = null; try { connection = factory.createConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); postBook(session, destination, replyToDestination); checkBookInResponse(session, replyToDestination, 124L, "JMS"); session.close(); } finally { close(connection); } } @Test public void testOneWayBook() throws Exception { Context ctx = getContext(); ConnectionFactory factory = (ConnectionFactory)ctx.lookup("ConnectionFactory"); Destination destination = (Destination)ctx.lookup("dynamicQueues/test.jmstransport.text"); Destination replyToDestination = (Destination)ctx.lookup("dynamicQueues/test.jmstransport.response"); Connection connection = null; try { connection = factory.createConnection(); connection.start(); Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE); postOneWayBook(session, destination); checkBookInResponse(session, replyToDestination, 125L, "JMS OneWay"); session.close(); } finally { close(connection); } } private void checkBookInResponse(Session session, Destination replyToDestination, long bookId, String bookName) throws Exception { MessageConsumer consumer = session.createConsumer(replyToDestination); BytesMessage jmsMessage = (BytesMessage)consumer.receive(5000); if (jmsMessage == null) { throw new RuntimeException("No response recieved on " + replyToDestination); } byte[] bytes = new byte[(int)jmsMessage.getBodyLength()]; jmsMessage.readBytes(bytes); InputStream is = new ByteArrayInputStream(bytes); Book b = readBook(is); assertEquals(bookId, b.getId()); assertEquals(bookName, b.getName()); } private Context getContext() throws Exception { Properties props = new Properties(); props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.activemq.jndi.ActiveMQInitialContextFactory"); props.setProperty(Context.PROVIDER_URL, "tcp://localhost:" + JMS_PORT); return new InitialContext(props); } private void postGetMessage(Session session, Destination destination, Destination replyTo) throws Exception { MessageProducer producer = session.createProducer(destination); Message message = session.createBytesMessage(); message.setJMSReplyTo(replyTo); message.setStringProperty("Accept", "application/xml"); message.setStringProperty(org.apache.cxf.message.Message.REQUEST_URI, "/bookstore/books/123"); message.setStringProperty(org.apache.cxf.message.Message.HTTP_REQUEST_METHOD, "GET"); producer.send(message); producer.close(); } private void postOneWayBook(Session session, Destination destination) throws Exception { MessageProducer producer = session.createProducer(destination); byte[] payload = writeBook(new Book("JMS OneWay", 125L)); BytesMessage message = session.createBytesMessage(); message.writeBytes(payload); message.setStringProperty("Content-Type", "application/xml"); message.setStringProperty(org.apache.cxf.message.Message.REQUEST_URI, "/bookstore/oneway"); message.setStringProperty(org.apache.cxf.message.Message.HTTP_REQUEST_METHOD, "PUT"); producer.send(message); producer.close(); } private void postBook(Session session, Destination destination, Destination replyTo) throws Exception { MessageProducer producer = session.createProducer(destination); byte[] payload = writeBook(new Book("JMS", 3L)); BytesMessage message = session.createBytesMessage(); message.writeBytes(payload); message.setJMSReplyTo(replyTo); // or, if oneway, // message.setStringProperty("OnewayRequest", "true"); // we could've set this header in JMSDestination if no replyTo were set // but in CXF one could also provide the replyTo in the configuration // so it is just simpler to set this header if needed to avoid some // complex logic on the server side // all these properties are optional // CXF JAXRS and JMS Transport will default to // Content-Type : text/xml // Accept : */* // POST // Message.REQUEST_URI : "/" message.setStringProperty("Content-Type", "application/xml"); message.setStringProperty("Accept", "text/xml"); message.setStringProperty(org.apache.cxf.message.Message.REQUEST_URI, "/bookstore/books"); message.setStringProperty(org.apache.cxf.message.Message.HTTP_REQUEST_METHOD, "POST"); message.setStringProperty("custom.protocol.header", "custom.value"); producer.send(message); producer.close(); } private Book readBook(InputStream is) throws Exception { JAXBContext c = JAXBContext.newInstance(new Class[]{Book.class}); Unmarshaller u = c.createUnmarshaller(); return (Book)u.unmarshal(is); } private byte[] writeBook(Book b) throws Exception { JAXBContext c = JAXBContext.newInstance(new Class[]{Book.class}); Marshaller m = c.createMarshaller(); ByteArrayOutputStream bos = new ByteArrayOutputStream(); m.marshal(b, bos); return bos.toByteArray(); } private void close(Connection connection) { try { if (connection != null) { connection.stop(); connection.close(); } } catch (JMSException ex) { // ignore } } }