-
Notifications
You must be signed in to change notification settings - Fork 439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Messaging polyglot support #1472
Conversation
I get that I can set up an application that has a messaging endpoint to use with contracts. I don't know Python, so I can't comment on that code. I did have a couple questions as I went along: What setup steps do I need to do in Docker? |
Set the env vars really. Also mind you that in the documentation we already have a whole chapter on how to configure the docker stuff. So this is just a flow with messaging basing on previously presented docker example.
With Java you don't really need to use Docker cause you can generate tests directly in your codebase |
I would definitely add those bits to the docs. I'll read it again after a meeting, to see if I have any further ideas. |
Passing part of the documentation as the description of what we're trying to achieve for adding polyglot messaging support.
How can you help
Please read the extract from the documentation below and answer the following questions
If you know python:
If you know any other language
In addition to this please provide any feedback that you have with regards to this feature.
Additional links
Example: Repository with contracts (picked the groovy contract for messaging):
https://github.com/marcingrzejszczak/cdct_python_contracts/blob/master/META-INF/group/application/0.0.1-SNAPSHOT/contracts/consumer1/messaging/pingPong.groovy
Example: Python producer (highlighted the problematic HTTP endpoint to trigger a message)
https://github.com/marcingrzejszczak/cdct_python_producer/blob/patch-1/main.py#L52-L59
Example: Python script to run spring cloud contract messaging test with running middleware
https://github.com/marcingrzejszczak/cdct_python_producer/blob/patch-1/run_contract_tests.sh
Documentation of the feature
Example of Usage via Messaging
If you want to use Spring Cloud Contract with messaging via the Docker images (e.g.
in case of polyglot applications) then you'll have to have the following prerequisites met:
triggerMessage(...)
with aString
parameter that is equal to the contract'slabel
.Example of a Messaging Contract
The contract needs to call a
triggerMessage(...)
method. That method is already provided in the base class for all tests in the docker image and will send out a request to the HTTP endpoint on the producer side. Below you can find examples of such contracts.HTTP Endpoint to Trigger a Message
Why is there need to develop such an endpoint? Spring Cloud Contract
would have to generate code in various languages (as it does in Java) to make it possible to trigger production
code that sends a message to a broker. If such code is not generated then we need to be able to trigger the message anyways, and the way to do it is to provide an HTTP endpoint that the user will prepare in the language of their choosing.
The endpoint must have the following configuration:
/springcloudcontract/{label}
wherelabel
can be any textPOST
label
will generate a message that will be sent to a given destination according to the contract definitionBelow you have an example of such an endpoint. If you're interested in
providing an example in your language don't hesitate to file an issue in
the Spring Cloud Contract repository at Github - https://github.com/spring-cloud/spring-cloud-contract/issues/new?assignees=&labels=&template=feature_request.md&title=New+Polyglot+Sample+of+a+HTTP+controller
Running Message Tests on the Producer Side
Now, let's generate tests from contracts to test the producer side.
We will run bash code to start the Docker image
with attached contracts, however we will also add variables for the messaging
code to work. In this case let's assume that the contracts are being stored in
a Git repository.
What will happen is:
declareQueueWithName
that will lead to creation of a queue in RabbitMQ with the given name before the request to trigger the message is senttriggerMessage("ping_pong")
method call a POST request to the Python application to the/springcloudcontract/ping_pong
endpoint will be made'{"message":"pong"}'
JSON via RabbitMQ to an exchange calledoutput
output
exchangeAfter the tests have passed we know that the message was properly sent from the Python app to RabbitMQ.
Example of Usage of Stub Runner with Messaging
In order to make messaging work it's enough to pass the
MESSAGING_TYPE
environment variable withkafka
orrabbit
values. This will lead to setting upthe Stub Runner Boot Docker image with dependencies required to connect to the broker.
In order to set the connection properties you can check out Spring Cloud Stream properties page to set proper environment variables.
** You can search for
spring.rabbitmq.xxx
orspring.kafka.xxx
propertiesThe most common property you would set is the location of the running middleware.
If a property to set it is called
spring.rabbitmq.addresses
orspring.kafka.bootstrap-servers
then you should name the environment variableSPRING_RABBITMQ_ADDRESSES
and SPRING_KAFKA_BOOTSTRAP_SERVERS` respectively.Documentation of the feature with standalone mode (aka with running middleware)
Running Contract Tests against Existing Middleware
There is legitimate reason to run your contract tests against existing middleware. Some
testing frameworks might give you false positive results - the test within your build
passes whereas on production the communication fails.
In Spring Cloud Contract docker images we give an option to connect to existing middleware.
As presented in previous subsections we do support Kafka and RabbitMQ out of the box. However,
via https://camel.apache.org/components/latest/index.html[Apache Camel Components] we can support
other middleware too. Let's take a look at the following examples of usage.
Spring Cloud Contract Docker and running Middleware
In order to connect to arbitrary middleware, we'll leverage the
standalone
metadata entryin the contract section.
protocol:destination
as requested by Apache Cameloutput
exchange and due to to having thequeue=output
androutingKey=#
a queue with nameoutput
will be set and bound to theoutput
exchange with routing key#
protocol:destination
from point (3) - together will be combined in the following formatrabbitmq:output?routingKey=#&queue=output
.For the contract tests to pass we will need as usual in case of messaging in polyglot environment
a running application and running middleware. This time we will have different environment variables set for the Spring Cloud Contract Docker image.
STANDALONE_PROTOCOL
environment variable we will fetch a https://camel.apache.org/components/latest/index.html[Apache Camel Component]. The artifact that we will fetch isorg.apache.camel.springboot:camel-${STANDALONE_PROTOCOL}-starter
. In other wordsSTANDALONE_PROTOCOL
is matching Camel's component.Stub Runner Docker and running Middleware
In order to trigger a stub message against running middleware, we can run Stub Runner Docker image in the following manner.
Example of usage
ADDITIONAL_OPTS=--thin.properties.dependencies.XXX=GROUP:ARTIFACT:VERSION
property we're telling Stub Runner which additional dependency to fetch at runtime. In this case we want to fetchcamel-rabbitmq-starter
soXXX
is a random string and we want to fetchorg.apache.camel.springboot:camel-rabbitmq-starter
artifact in version3.4.0
..m2
as a volume. If you don't have it populated you can consider setting the write permissions via:rw
instead read only:ro
.8750
at which Stub Runner is running.After a while you'll notice the following text in your console, which means that Stub Runner is ready to accept requests.
To get the list of triggers you can send an HTTP GET request to
localhost:8750/triggers
endpoint. To trigger a stub message, you can send a HTTP POST request tolocalhost:8750/triggers/standalone_ping_pong
. In the console you'll see:If you check the RabbitMQ management console, you'll see that there's 1 message available in the
output
queue.cc @Buzzardo there are some documentation changes here