Alibaba Cloud offers a language translation service powered by machine learning. You can use this to easily present your e-commerce site in multiple languages, enable multi-lingual search and even translate support chats in real-time.

The service is currently made available as an SDK called “Machine Translation,” also known as Ali MT. Users are required to integrate the SDK into their application components that need to perform language translation. One approach would be implementing a client-server model with the SDK implemented in just the designated ‘server’ process(es) with the clients making translation requests to it. This offers some abstraction in your architecture by avoiding the need to have every process that wants to use the translation service be familiar with the full Machine Translation SDK.

For example, in a modern event-driven microservices architecture you can envision a set of elastically scaled microservices that offer the translation capability to all other microservices.

In many enterprises, JMS brokers are a very common way of connecting applications and services. As an easy to use messaging API, JMS is embedded in many integration products. If you have an enterprise service bus (ESB) in use today, a JMS provider is probably part of the stack.

Looking across your enterprise IT infrastructure, you may need to expose new cloud-based services like this to existing applications that are connected to an ESB, in addition to connecting them to new applications in a microservices architecture or functions-as-a-service (FaaS) deployment. You may also have some Internet of Things (IoT) devices that need to access them.

Wouldn’t it be great if you could deploy just one set of services and handle all these different client and protocol needs? With the help of an event broker like PubSub+, you can.

Starting with JMS for existing legacy applications

With JMS being an API specification only, and not tied to any particular product, it is possible to code an application against the API so that it works with any JMS-compliant JMS broker. The client libraries that contain vendor-specific detail can be resolved at runtime from the classpath. To eliminate the need for even this vendor specific library dependency in your application, the Advanced Message Queuing Protocol (AMQP) defines a standards-based connectivity protocol so an open source library can connect to brokers from multiple vendors without so much as a library change.

To support JMS connectivity to Alibaba MT, I have created a wrapper around the SDK and made it available here on Github. There are two demo JMS applications (as runnable JARs) in the repository that are implementing the request-reply pattern:

  1. A “Requester” program that makes requests to translate English text to Chinese, sent over a JMS destination.
  2. A “Replier” program that listens to requests on a JMS destination, translates the text to Chinese and responds to the original requestor over another JMS destination.

The Replier program is in the server role in the client-server pattern and is the only program needing to implement the Machine Translation SDK; the Requestor program is completely unaware of the SDK.

The repository by default builds with support for the AMQP JMS libraries from Apache Qpid, so it’s immediately ready to connect to a JMS broker such as Solace PubSub+ that supports AMQP.

To run the programs you need to update the contents of two files that are also in the checked out repository:

  1. jndi.properties – This tells the programs how to connect to the JMS broker and what destination to use
  2. alibaba-mt.properties – This tells the Replier program how to connect to the Alibaba Machine Translation service.

Get your Solace PubSub+ Connection Details

The easiest way to get started is to sign up for a free developer plan of PubSub+ Cloud. Once you have your service, jump down into the AMQP connectivity details from the “Connect” tab like so:

Console shot of the AMQP connectivity details from within Solace PubSub+ Cloud

You can then modify the jndi.properties file to add the connection URI, username and password into the jndi.properties file like so in the “connectionfactory.ConnectionFactory” line:

connectionfactory.ConnectionFactory = amqp://your-service-here.messaging.solace.cloud:5672?jms.username=solace-cloud-client&jms.password=YourPasswordHere&jms.clientIDPrefix=NLPTranslationSample-&

For the purposes of this demo, also update the JMS destinations names like so:

topic.nlp-translation-requests-send = jms/nlp/translation/requests
topic.nlp-translation-requests-receive = */nlp/translation/requests

Get your Alibaba Machine Translation Service Details

Next, we need to provide the details of your Machine Translation service to the programs. You can get these details by following the instructions here.

In alibaba-mt.properties enter your service details like so:

service-region=cn-hangzhou
access-key-id=IDGoesHere
access-key-secret=SecretGoesHere

If you don’t have access to the service yet, you can also run the programs in offline/simulation mode. Just add the following line to the file instead:

simulation-mode=true

Start Translating

Now you are ready to run the programs and access Machine Translation over JMS. Start the replier program first:

java -jar AlibabaNLPReplier.jar -j ./jndi.properties -a ./alibaba-mt.properties

Then start the requesting program:

java -jar AlibabaNLPRequestor.jar -j ./jndi.properties

The requesting program will collect keyboard input as you type and submit each new line as a request for translation.

Adding HTTP support for new microservices

For lightweight microservices running in a Functions-as-a-Service manner without a lot of library dependencies, communicating over HTTP is a popular mechanism. So let’s add HTTP support for the translation service next.

With the Java replier program running, we can actually have the same process respond to requests delivered over HTTP without deploying any further services or components. By selecting Solace PubSub+ as the JMS provider, its REST Microgateway provides access to the same JMS destinations over HTTP.

The Solace PubSub+ REST connectivity feature can operate in two modes: messaging and gateway. The default setting for a newly created event broker or cloud service is messaging but we need it operating in ‘gateway’ mode for this exercise.

Follow the instructions here to change the mode for your broker.

Get your REST connectivity details

Going back to the Connection tab of your PubSub+ Cloud instance, now collect the details on how to connect the same instance via HTTP REST:
Console screenshot inside PubSub+ Cloud about how to details on how to connect the same instance via HTTP REST

Set up cURL command example

Assuming a Linux shell environment, we can use the curl client to make a translation request over the HTTP POST method. To facilitate this, we’ll put the relevant connectivity details into shell variables for convenience like so:

$ USER=solace-cloud-client
$ PASS=your-password-here
$ REST_ENDPOINT="http://your-instance-here.messaging.solace.cloud:9000/nlp/translation/requests"

You’ll note the REST endpoint adds the nlp/translation/requests path as a way of matching up to the JMS program and the destination it is already listening to.

When the JMS programs receive requests and respond to them, they expect a CorrelationID to be present to properly respond to the requests. For the HTTP POST we can pass this in the header, so let’s setup a variable for this too:

$ CORRELATION="Solace-Correlation-ID: aRandomString"

Lastly, another header is required to specify that this is plain text being sent and not, say, binary. This final shell variable can set this up too:

$ TYPE="Content-Type: text/plain"

That’s all that is required. We are ready to run the curl command with the relevant arguments:

$ curl -u $USER:$PASS -d "This request is via HTTP POST" -H "$TYPE" -H "$CORRELATION" -X POST $REST_ENDPOINT

Here is an example response with it all put together:

On the Replier logs you can see messages being handled from both the JMS and HTTP sources:

Adding MQTT support for IoT devices

MQTT is a low power and low bandwidth protocol which makes it a very popular choice for IoT systems. With these devices typically being supported by applications and services running elsewhere (such as on-premises or in a cloud) there is a need to get bidirectional data flows from these devices using MQTT to applications and services using different protocols. Fortunately, PubSub+ event brokers will easily do this protocol translation for you.

Keeping the same Java program running, let’s get a request for translation sent using the MQTT protocol so that the Java program can consume it over JMS.

Get your MQTT connectivity details

Just as before, go back to the Connection tab of your PubSub+ Cloud instance and this time collect the details on how to connect to the instance via MQTT:
PubSub+ Cloud screenshot with details on how to connect to the instance via MQTT

Connect your MQTT Client

As MQTT is a standard connectivity protocol, any MQTT client API can publish to the PubSub+ event broker (i.e. There is no API required to be fetched from Solace.) Therefore, we can use the online hosted JavaScript-over-WebSocket MQTT utility by Eclipse Paho for this demonstration.

Copy in the connectivity details into the online client:
Screenshot from online hosted JavaScript-over-WebSocket MQTT utility by Eclipse Paho
Publish a message from the web client:
Eclipse Paho: Publish a message from the web client
Note: This request can be sent to the MQTT specific topic of 'mqtt/nlp/translation/requests'

Review the request arrival in the JMS Replier logs:
MQTT: request arrival in the JMS Replier logs

You will recall that our JMS programs are utilizing a ‘request-reply’ pattern of message exchange, with a ‘reply-to’ topic being essential to see the translation response. As this hosted MQTT client is not carrying out all these necessary steps, the request will not be properly dealt with. However, evidence of the message arrival and processing of the content can be seen in the logs.

While the lightweight MQTT protocol does not explicitly define a request-reply mechanism, it can very easily be simulated using custom defined topics and headers. For further information on how you may build your own MQTT sender to properly implement the request-reply pattern to successfully get a translation response back to the MQTT sender, read the Request/Reply guide.

That’s all, folks!

That’s the end of the tutorial. If you have any questions or comments, you can find me at solace.community.

Jamil Ahmed

A senior middleware specialist with an in-depth knowledge of enterprise messaging products and architectures. This experience is across a variety of deployed use cases and institutions, in different capacities such as in-house service owner and vendor consultant, as well as different contexts such as operational support and strategic engineering.