Skip to content

Latest commit

 

History

History
 
 

emjapi-samples-jms-pubsub

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 

SAP Enterprise Messaging JMS: Publish and Subscribe

Sample application of how to use the JMS client to send and receive messages using a topic via SAP Cloud Platform Enterprise Messaging.

Prerequisites

  • Installed Java 8Java download

  • Installed GitGit download

  • Installed Maven 3.xMaven download

  • Optional: Installed Postman

  • A SAP CP Account with Enterprise Messaging Service is required.
    For more detailed information and help on how to start with SAP Cloud Platform Enterprise Messaging please check the SAP help page.

    • Optional: Installed CloudFoundry CLIInstalling the cf CLI

      • This must be also fully configured with the corresponding Cloud Foundry landscape to be able to do a cf push.

    • Created Enterprise Messaging Instance

      • e.g. via cli: cf cs enterprise-messaging default emjapi-samples-sapcp -c <contents of default descriptor>

      • The Service Descriptors can be found here

      • Remember to adjust the manifest file of the application

    • Create queues (e.g. NameOfQueue) and subscribe a queue to a topic of choice (e.g. NameOfTopic) via e.g. MM API, UI

      • For queue creation with the MM API you need to provide a fully qualified queue name including the namespace

Project

The publish and subscribe (pubsub) sample is a small spring boot (version 2.0.6) applications which provides three different REST endpoints to send and receive messages from a topic.

Steps to Start

  1. Check all Prerequisites fulfilled (see section Prerequisites above)

  2. Clone the repository via git clone

  3. Build the project with maven (mvn clean install)

  4. Push to Cloud Foundry via cf push (if the service was renamed please adopt the manifest accordingly)

Steps to Use

  • The queue name has to be URL encoded. The samples provide a function to URL encode

    • curl -X POST -H "Content-Type: text/plain" -H "Cache-Control: no-cache" -d "https://<application-path>/encode"(the body must contain the queue name)

  • Send a message with a HTTP POST via https://<application-path>/topic/<topic-name>/message (The body must contain the message)

    • Note that a client or a queue must be subscribed to the topic before

    • The queue name has to be url encoded. The

    • curl -X POST -H "Content-Type: text/plain" -H "Cache-Control: no-cache" -d '<message>' "https://<application-path>/topic/<topic-name>/message"

  • Receive a message via a queue with a HTTP GET via https://<application-path>/queue/<queue-name>/message

    • Note that a queue subscription is needed before. A queue subscription can be created via e.G. the UI.

    • curl -X GET -H "Content-Type: text/plain" -H "Cache-Control: no-cache" "https://<application-path>/queue/<queue-name>/message"

Code Snippets

In order to use the messaging service the spring cloud service connector can be used to receive a MessagingServiceFactory.

ServiceConnectorConfig config = null; // currently there are no configurations for the MessagingServiceFactory supported
Cloud cloud = new CloudFactory().getCloud();
// get a messaging service factory via the service connector
MessagingService messagingService = cloud.getSingletonServiceConnector(MessagingService.class, config);

Create a the MessagingServiceFactory object with the help of the MessagingServiceFactoryCreator and get a MessagingServiceJmsConnectionFactory. The Connection Factory can be configured with the MessagingServiceJmsSettings. In case the reconnection feature is not needed and an individual connection mechanism (e.G. through a connection cache) is used the settings can be skipped. The connection factory can be built with messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class,settings).

MessagingServiceJmsSettings settings = new MessagingServiceJmsSettings(); // settings are preset with default values (see JavaDoc)
settings.setMaxReconnectAttempts(5); // use -1 for unlimited attempts
settings.setInitialReconnectDelay(3000);
settings.setReconnectDelay(3000);
MessagingServiceFactory messagingServiceFactory = MessagingServiceFactoryCreator.createFactory(messagingService);
MessagingServiceJmsConnectionFactory connectionFactory = messagingServiceFactory.createConnectionFactory(MessagingServiceJmsConnectionFactory.class, settings)

Sending

For sending messages a Connection and a Session is needed first. Note that those resources must be closed if they are not needed anymore. As those objects are implementing the autoclosable interface they will be closed automatically after the try-catch-block. Now a BytesMessage can be created. In the next steps a topic is bound (not created) to a producer. Note, that the prefix "topic:" is mandatory. Finally, the message can be sent to the topic.

try (Connection connection = connectionFactory.createConnection();Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
	connection.start();
	Topic topic = session.createTopic("topic:" + "<topic-name>");
	BytesMessage byteMessage = session.createBytesMessage();
	byteMessage.writeBytes(message.getBytes());
	MessageProducer producer = session.createProducer(topic);
	producer.send(byteMessage);
} catch (JMSException e) {
	LOG.error("Could not send message={}.", message, e);
}

Receiving

Currently direct topic subscription is not supported for the plan default. In this example a consumer is subscribed to a specific topic. Again a Connection and a Session is needed. Note that those resources must be closed if they are not needed anymore. First a topic (not created) with the mandatory prefix "topic:" is bound to consumer. As the messages are sent as a ByteMassage the message needs to be converted to e.g. a String

 try (Connection connection = connectionFactory.createConnection();Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
	connection.start();
	Topic topic = session.createTopic(TOPIC_PREFIX + topicName);
	MessageConsumer consumer = session.createConsumer(topic);
	// Blocking call. Define a timeout or use a Message Listener
	BytesMessage message = (BytesMessage) consumer.receive();
	byte[] byteData = new byte[(int) message.getBodyLength()];
	message.readBytes(byteData);
} catch (JMSException e) {
	LOG.error("Could not receive message.", e);
}

Messaging Management API

The messaging management api (MM API) provides functionality for creating, deleting and updating queues and queue subscriptions. Further more it provides APIs to get information on queues and queue subscriptions. The MM API documentation can be found here. The MM APIs have to be enabled in the service descriptor. A description for enabling the MM API can be found here.

Creation of queues with the UI

Queues can be created through the SAP Cloud Platform Cockpit UI. More information regarding the creation of queues through the UI can be found here

Service Descriptor

Examples for the different service descriptors can be found here on the help site and in the config folder of this project.

Support

This project is 'as-is' with no support, no changes being made.
You are welcome to make changes to improve it but we are not available for questions or support of any kind.

License

Copyright (c) 2017 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the SAP SAMPLE CODE LICENSE AGREEMENT, v1.0-071618 except as noted otherwise in the LICENSE file.