Soap over JMS comes with several benefits like, asynchronous processing, one time delivery, assured delivery. This paradigm is mainly used internally in an organization (service providers and clients).
In this tutorial we are going to use Spring boot and Apache CXF to develop a Soap service and then use Active MQ to make it work as "Soap Over JMS".
https://www.thetechnojournals.com/2020/01/soap-services-with-spring-boot-and.html
We will follow below steps to add JMS features in existing Soap service which we had created in above section.
http://activemq.apache.org/download.html
Once downloaded, please extract it to desired location and execute below command in "bin" folder to start it. I have downloaded and running it in MAC OS X.
To send the Soap request using JMS below code is required. We are using EventListener to run this code at startup (To know more on Spring events refer https://www.thetechnojournals.com/2019/10/spring-boot-application-events.html). This code sends the message to request queue and provides response queue details using JMSReplyTo header.
Once application is started, it will execute the Soap client code and you will see below output in console.
https://github.com/thetechnojournals/spring-tutorials/tree/master/CxfSoapService
https://www.thetechnojournals.com/2020/02/xml-validation-using-xsd-schema.html
In this tutorial we are going to use Spring boot and Apache CXF to develop a Soap service and then use Active MQ to make it work as "Soap Over JMS".
Creating Soap service using Spring boot and Apache CXF
It is very easy to develop a Soap service with Spring boot. We will follow contract first approach to develop the service. We will create a XML schema & use jaxb2 plugin to generate necessary schema classes and then implement the service using them. Please refer below post where it explains in detail, how to develop a Soap service using Spring boot and CXF.https://www.thetechnojournals.com/2020/01/soap-services-with-spring-boot-and.html
Implementing Soap over JMS
To implement the Soap over JMS we need to integrate JMS with soap service where our service listens to a request queue and replies to a response queue which is coming as JMSReplyTo header in JMS message. In JMS message we put the Soap message which is received by Soap service and processed.We will follow below steps to add JMS features in existing Soap service which we had created in above section.
Install Active MQ
You can download the Active MQ binaries from below URL.http://activemq.apache.org/download.html
Once downloaded, please extract it to desired location and execute below command in "bin" folder to start it. I have downloaded and running it in MAC OS X.
./activemq startNow open the link http://localhost:8161/admin/ in a browser to check if Active MQ is started. In same link you can browse all the objects and other JMS related stuffs provided by Active MQ.
Maven dependencies
Add below dependencies for Active MQ API and CXF API to JMS integration with Soap.<dependency> <groupId>org.apache.cxf</groupId> <artifactId>cxf-rt-transports-jms</artifactId> <version>3.3.5</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-activemq</artifactId> </dependency>
Properties Configuration
Add below properties in application.properties.spring.activemq.broker-url=tcp://localhost:61616 spring.activemq.user=admin spring.activemq.password=admin
Active MQ Configurations
Create given configuration class where we are creating below Spring beans.- mqConnectionFactory This bean creates a connection factory to connect with local Active MQ.
- jmsListenerContainerFactory This bean is a message listener which will be used to listen the response queue with our Soap client.
- JmsTemplate This bean is used to use the connection factory to send the Soap request message with our Soap client.
@Configuration public class ActiveMqConfig { @Value("${spring.activemq.broker-url}") private String activeMqUrl; @Value("${spring.activemq.broker-url}") private String userName; @Value("${spring.activemq.broker-url}") private String password; @Bean public JmsTemplate jmsTemplate(){ JmsTemplate template = new JmsTemplate(); template.setConnectionFactory(mqConnectionFactory()); return template; } @Bean public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() { DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory(); factory.setConnectionFactory(mqConnectionFactory()); return factory; } @Bean public SingleConnectionFactory mqConnectionFactory(){ SingleConnectionFactory factory = new SingleConnectionFactory(); ActiveMQConnectionFactory mqConnectionFactory = new ActiveMQConnectionFactory(); mqConnectionFactory.setBrokerURL(activeMqUrl); mqConnectionFactory.setUserName(userName); mqConnectionFactory.setPassword(password); factory.setTargetConnectionFactory(mqConnectionFactory); return factory; } }
JMS Integration with Soap Endpoints
Below configuration class is created which defines the JMS configuration to use the defined connection factory and request queue. Also we define the endpoint to publish the service using JMS endpoint.@Configuration public class JmsSoapEndpointsConfig { @Bean public Endpoint jmsEndpoint(SpringBus bus, JMSConfigFeature jmsConfigFeature) { EndpointImpl endpoint = new EndpointImpl(bus, new HelloServiceEndpoint()); endpoint.getFeatures().add(jmsConfigFeature); endpoint.publish("jms://"); return endpoint; } @Bean public JMSConfigFeature jmsConfigFeature(ConnectionFactory mqConnectionFactory){ JMSConfigFeature feature = new JMSConfigFeature(); JMSConfiguration jmsConfiguration = new JMSConfiguration(); jmsConfiguration.setConnectionFactory(mqConnectionFactory); jmsConfiguration.setTargetDestination("test.req.queue"); jmsConfiguration.setMessageType("text"); feature.setJmsConfig(jmsConfiguration); return feature; }
Soap over JMS client
We are implementing this soap client to just test our service using JMS queues when application is up and running.To send the Soap request using JMS below code is required. We are using EventListener to run this code at startup (To know more on Spring events refer https://www.thetechnojournals.com/2019/10/spring-boot-application-events.html). This code sends the message to request queue and provides response queue details using JMSReplyTo header.
@Autowired private JmsTemplate template; @EventListener(ApplicationReadyEvent.class) public void applicationReadyEvent()throws JMSException { String msg = "<soapenv:Envelope \n" + "xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" + "xmlns:ser=\"http://services.ttj.com/\"\n" + "xmlns:hs=\"http://services.ttj.com/hello-service\">\n" + " <soapenv:Header/>\n" + " <soapenv:Body>\n" + " <ser:sayHelloRequest>\n" + " <arg0>\n" + " <hs:userName>Black swan</hs:userName>\n" + " </arg0>\n" + " </ser:sayHelloRequest>\n" + " </soapenv:Body>\n" + "</soapenv:Envelope>"; Session session = template.getConnectionFactory().createConnection() .createSession(false, Session.AUTO_ACKNOWLEDGE); TextMessage message = session.createTextMessage(msg); message.setJMSReplyTo(new ActiveMQQueue("test.response.queue")); template.convertAndSend("test.req.queue", message); System.out.println("Jms Message sent"); }To receive the Soap service response we need to use JMS listener which is listening on response queue and will print the message once it receives the response. Below code defines the method to process the message using JMSListener on response queue.
@JmsListener(destination = "test.response.queue") public void receiveMessage(final Message message) throws JMSException { String messageData = null; System.out.println("Received message-> " + message); String response = null; if(message instanceof TextMessage) { TextMessage textMessage = (TextMessage)message; messageData = textMessage.getText(); System.out.println("Message data-> "+messageData); } }
Running & Testing Application
To run this application we need to execute below maven command in root directory. Before running the application please make sure that Active MQ server is up and running.Once application is started, it will execute the Soap client code and you will see below output in console.
Request execution message:
Jms Message sent
Response received and printed to console:
Received message-> ActiveMQTextMessage {commandId = 18, responseRequired = true, messageId = ID:Ashoks-MacBook-Pro.local-53071-1579434139156-1:1:6:1:1, originalDestination = null, originalTransactionId = null, producerId = ID:Ashoks-MacBook-Pro.local-53071-1579434139156-1:1:6:1, destination = queue://test.response.queue, transactionId = null, expiration = 0, timestamp = 1579434139891, arrival = 0, brokerInTime = 1579434139892, brokerOutTime = 1579434139893, correlationId = ID:Ashoks-MacBook-Pro.local-53071-1579434139156-1:1:5:1:1, replyTo = null, persistent = true, type = null, priority = 4, groupID = null, groupSequence = 0, targetConsumerId = null, compressed = false, userID = null, content = org.apache.activemq.util.ByteSequence@1cd9167a, marshalledProperties = org.apache.activemq.util.ByteSequence@17248241, dataStructure = null, redeliveryCounter = 0, size = 0, properties = {SOAPJMS_bindingVersion=1.0, SOAPJMS_contentType=text/xml; charset=UTF-8, SOAPJMS_isFault=false}, readOnlyProperties = true, readOnlyBody = true, droppable = false, jmsXGroupFirstForConsumer = false, text = <soap:Envelope xmlns:soap="http://schemas.xml...ap:Envelope>} Message data-> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"><soap:Body><ns3:sayHelloRequestResponse xmlns:ns3="http://services.ttj.com/" xmlns:ns2="http://services.ttj.com/hello-service"><message>Hello Black swan!!!</message></ns3:sayHelloRequestResponse></soap:Body></soap:Envelope>
Source Code
Complete source code is available at below Git location.https://github.com/thetechnojournals/spring-tutorials/tree/master/CxfSoapService
Links to other related Posts
Soap Request SSL signature validation in Spring boothttps://www.thetechnojournals.com/2020/02/xml-validation-using-xsd-schema.html
Comments
Post a Comment