The Channel class (Java Client) provide three methods to publish a message, all of them with the routingkey parameter. The headers exchange does not need the routingkey.
If i pass a null value for the routingkey, the following exception is returned: "java.lang.IllegalStateException: Invalid configuration: 'routingKey' must be non-null."
However, if i pass an empty string it works. So the question is: Is it correct to use an empty string?
Yes, it is correct to use empty string. The routing key is not used by headers exchanges as defined in AMQP protocol specification.
Most likely exception is thrown because driver doesn't know anything about setup and it's much safer to handle all errors, including potential errors, on client side.
Related
I need to send json using rabbit mq web
I have the following structure of email json, you can see on photo. I listen queue using org.springframework.amqp.rabbit.annotation.RabbitListener;
and have the follwing exception - No method found for class java.util.LinkedHashMap
is there any way to deal with it?
I managed to manually send a message by defining a __TypeId__ header, with value corresponding to the class that represents your message payload:
__TypeId__ = your.message.class
Note that the value has to be your class' canonical name, including its package path.
When you don't specify this header, Spring tries to desserialize your payload string to a LinkedHashMap by default.
I know sending a body with a GET request isn't the best idea but I'm trying to consume an existing API which requires it.
Sending a body with POST is straight-forward:
webClient.post()
.uri("/employees")
.body(Mono.just(empl), Employee.class)
.retrieve()
.bodyToMono(Employee.class);
It won't work with webClient.get() though, because while the post() method returns a WebClient.RequestBodyUriSpec, the get() method returns WebClient.RequestHeadersUriSpec<?>, which doesn't seem to allow any body definitions.
I've found a workaround for Spring RestTemplate here: RestTemplate get with body,
but had no luck finding any for the new WebClient.
While the other responses are correct that you shouldn't use a body with a GET request, that is not helpful when you do not own, or cannot change the already existing method you are calling.
The problems is WebClient#get returns a WebClient.RequestHeadersUriSpec which does not provide a way for us to set the body.
WebClient#post returns a WebClient.RequestBodyUriSpec which does provide us a way to set the body but will cause us to use the wrong HTTP method, POST instead of GET.
Thankfully for us stuck in this situation there is WebClient#method which returns a WebClient.RequestBodyUriSpec and allows us to set the HTTP method.
webClient.method(HttpMethod.GET)
.uri("/employees")
.body(Mono.just(empl), Employee.class)
.retrieve()
.bodyToMono(Employee.class);
You may still run into issues in your testing libraries though...
A GET reques has no body. It is forbidden (well, not forbidden, but not used at all) by the HTTP specification. You have two approaches here:
Do a POST. It is there just for that.
Use a query string and pass the data in that part of the URL.
Of course, you can attach the needed fields and pass a payload to the GET request, but it will probably be ignored, or worse, identified as an error and rejected by the server, before your served code has access to it. But if you are passing data to the server to do some processing with it, then POST is what you need to use.
Extracted from RFC-7231. HTTP 1.1. Semantics and code:
A payload within a GET request message has no defined semantics;
sending a payload body on a GET request might cause some existing
implementations to reject the request.
(markup is mine)
Reasons for this are, mainly, that a GET method must be idempotent, producing the same output for the same URL, if repeated. POST doesn't have these requirements, so POST is your friend.
The context: I have a message channel that does a post request to a service A and 2 interceptors - one that does some processing and another one that sends to another service B.
The problem: Where to add a feature toggle such that I can stop sending to A but still send to B? (also 1st interceptor does some processing that is needed before sending to B)
My approach was to add the feature toggle in the 2nd interceptor and return a null message object so that the messageChannel.send won't be executed. This works but also throws an error which is not desirable.
According to spring's message channel documentation:
The preSend of an interceptor is invoked before the Message is
actually sent to the channel. This allows for modification of the
Message if necessary. If this method returns {#code null} then the
actual send invocation will not occur.
Is there a way to silently kill the sending process or would there be a better approach?
Instead of using a ChannelInterceptor, try a Filter
Message filters are used to decide whether a Message should be passed along or dropped based on some criteria, such as a message header value or message content itself.
With a Filter you can specify your own implementation of a MessageSelector, which when returning false, will cause the Filter to discard the message.
package exampleCode;
import org.springframework.integration.core.MessageSelector;
import org.springframework.messaging.Message;
public class MySelector implements MessageSelector {
#Override
public boolean accept(Message<?> message) {
// If the message should continue through the filter, return true
// If the message should be blocked from continuing, return false
}
}
Then you can configure your selector to be used by a filter
<bean id="MySelector" class="exampleCode.MySelector" />
<int:filter input-channel="someChannel" ref="MySelector"
output-channel="someOtherChannel" />
Prior to version 3.0, invoking the send method on a PublishSubscribeChannel that had no subscribers returned false. When used in conjunction with a MessagingTemplate, a MessageDeliveryException was thrown. Starting with version 3.0, the behavior has changed such that a send is always considered successful if at least the minimum subscribers are present (and successfully handle the message). This behavior can be modified by setting the minSubscribers property, which defaults to 0.
Reference: https://docs.spring.io/spring-integration/docs/5.0.5.RELEASE/reference/html/messaging-channels-section.html
Also, I think you can implement Conditional Variables with Spring using #Conditional for the interceptors to execute for a given condition.
Reference: https://javapapers.com/spring/spring-conditional-annotation/#:~:text=Spring%20Boot%20module%20makes%20heavy,variables%2C%20irrespective%20of%20its%20value.
I have one webservice which can take multiple content-types in request
text/plain
application/json
Now, client can send any of them either json or text.
I have two options available on server
I can create separate apis for different content types
I can parse request data and check if its json or text?
What is better approach here?Is there a design pattern suited for this need?
Note: Management prefer to have one api which can support multiple content-types.
The client must include a Content-Type header indicating the format of the entity they are sending to the server. If the server does not support the format which a client has sent, the expected response is 415 Unsupported Media Type.
I would go with option 1 and have the common logic placed in a seperate method. That way you let the API check and parse the input data for you.
In http you use the "accept"- header to define what type you expect the response to be. The server delivers the content as defined in accept header, the default if it's not set or 406 - "Not acceptable" if the type is not supported
https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
One way would be to use #Path annotations more thoroughly-
The #javax.ws.rs.Path annotation must exist on either the class and/or a resource method. If it exists on both the class and method, the relative path to the resource method is a concatenation of the class and method.
See this link https://docs.jboss.org/resteasy/docs/1.1.GA/userguide/html/Using__Path_and__GET___POST__etc..html
Could you please explain what exactly the method getHeaders from SOAPHandler interface is supposed to do?
http://docs.oracle.com/javaee/5/api/javax/xml/ws/handler/soap/SOAPHandler.html#getHeaders%28%29
I'm not sure if it creates additional headers or if it should just tell the runtime which headers the message should have.
I've been sweeping the internet looking for detailed information but I couldn't find any. I think is is so basic and obvious that no documentation is needed LOL :-)
Thanks
The description you're looking for can be found in the JAX-WS 2.2 spec in the section titled, "10.2.1 SOAP mustUnderstand Processing". Inbound messages require an additional processing step that occurs before the start of normal handler processing. Basically, the set of QName instances returned from getHeaders allows the handler to contribute to the full set of SOAP headers that a node understands (the other contributors to the full set are documented in the spec). If an inbound SOAP header contains the mustUnderstand attribute with a value of 1 or true, then an exception will be generated if that header can't be marked as understood.
EDIT: Apparently I was wrong and after reading further I must agree, therefore please ignore this.
A SOAP message is a HTTP request. HTTP requests can have number of different headers as a part of the message (e.g. in SOAP 1.1 there was a header called SOAPAction, which could contain the name of the service and operation). The getHeaders function returns the list of all the headers QNames that came with the request, so in case of previous example, you would get a list that would contain element of value "SOAPAction".