RabbitMQ browser-based UI unable to innest HashMap in Headers field - rabbitmq

The header of my message in RabbitMQ Queue has this specification:
headers={
httpHeaders={transactionID=123, sessionID=451554},
contentType=text/plain,
timestamp=1539607167303
}
so I have an embedded Hashmap in the key named httpHeaders.
I want replicate this behaviour using the RabbitMQ UI, but I do not understand how to set it
The select List options are only: String, Boolean, Number and List
This is my test that replicate programmatically the Message Header:
#Test
public void getTransactionId() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
String payload = "payload";
Map messageHeader = new HashMap();
Map httpHeader = new HashMap();
httpHeader.put(HttpHeaderKeys.TRANSACTION_ID_KEY, "123");
messageHeader.put(HTTP_HEADER_KEY, httpHeader);
MessageHeaders messageHeaders = new MessageHeaders(messageHeader);
GenericMessage message = new GenericMessage(payload, messageHeaders);
Method method = MDCUtils.class.getDeclaredMethod("getTransactionId", Message.class);
method.setAccessible(true);
Object result = method.invoke(null, message);
assertEquals("123", result);
}

You can add the headers in this way:

Related

Apache CXF Password Type Always Sets Digest

I am working on a web service client project and using Apache CXF to send request to web service.
I need to set passwordType as PasswordText. But even if I set it in OutInterceptor property, It always sets passwordType as Digest. How can I solve this issue?
My Code is this:
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
factory.setServiceClass(Test.class);
factory.setAddress(url);
factory.getInInterceptors().add(new SoapActionInInterceptor(action));
factory.getOutInterceptors().add(new SoapActionOutInterceptor());
Map<String, Object> outProps = new HashMap<String, Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, username);
outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PASSWORD_TEXT);
ClientPasswordHandler handler = new ClientPasswordHandler();
handler.setPassword(password);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);
WSS4JStaxOutInterceptor wssOut = new WSS4JStaxOutInterceptor(outProps);
factory.getOutInterceptors().add(wssOut);
T serviceClient = (T) factory.create();
Client client = ClientProxy.getClient(serviceClient);
setClientPolicy(client);
And clientPolicy is this
protected synchronized void setClientPolicy(Client client) {
if (client != null) {
HTTPConduit httpConduit = (HTTPConduit) client.getConduit();
httpConduit.setAuthSupplier(null);
httpConduit.setAuthorization(null);
HTTPClientPolicy clientPolicy = new HTTPClientPolicy();
clientPolicy.setConnectionTimeout(60000L);
clientPolicy.setReceiveTimeout(60000L);
httpConduit.setClient(clientPolicy);
}
}
org.apache.cxf -> version 3.1.6
org.apache.wss4j -> version 2.1.7
I have found the solution. WSS4JStaxOutInterceptor extends AbstractWSS4JStaxInterceptor and it has a function to set incoming properties which we have send. When it try to set password property it checks incoming property with "PasswordText" string and when we use WSConstants its value is different. That's why when we set property value with "PasswordText" string it works fine. Final code for interceptor is:
private WSS4JStaxOutInterceptor createSecurityInterceptor() {
Map<String, Object> outProps = new HashMap<>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN);
outProps.put(WSHandlerConstants.USER, username);
// AbstractWSS4JStaxInterceptor class parseNonBooleanProperties require "PasswordText" check this function before changing this line
outProps.put(WSHandlerConstants.PASSWORD_TYPE, "PasswordText");
// AbstractWSS4JStaxInterceptor class parseNonBooleanProperties require "PasswordText" check this function before changing this line
ClientPasswordHandler handler = new ClientPasswordHandler();
handler.setPassword(password);
outProps.put(WSHandlerConstants.PW_CALLBACK_REF, handler);
return new WSS4JStaxOutInterceptor(outProps);
}
This solves the issue.

How to use IBM MobileFirst java adapter to update existing entity?

The jax-rs resource method can get JSON which is part of document.
My issue is that I have to update existing object (entity). So I decided on creating jax-rs ContainerRequestFilter. This filter has to get existing object, replace its properties with new one and put it back to stream. Therefore I hope that I get entity completely in my resource method.
At first I has to get data for authenticated user. But 'securityContext.getAuthenticatedUser()' returns partially provided JSON data?
Is there any possibility to get authenticated user data in jax-rs filter (on ibm MobileFirst platform)?
There is the code of my filter:
#Provider
//#ManagedBean
public class UpdateFilter implements ContainerRequestFilter {
//ReaderInterceptor {
//#Inject
//ExistingObjectDao existingObjectDao;
#Context
AdapterSecurityContext securityContext;
#Override
#OAuthSecurity(scope = "protected") //doesn't work
public void filter(ContainerRequestContext context) throws IOException {
//context.getSecurityContext().getUserPrincipal() // is null
AuthenticatedUser user = securityContext.getAuthenticatedUser(); //is null
Map<String, String> authParams = (Map<String, String>) user.getAttributes().get("lotusCredentials");
InputStream inputStream = context.getEntityStream();
byte[] bytes = new byte[inputStream.available()];
inputStream.read(bytes);
String responseContent = new String(bytes);
String id = context.getUriInfo().getPathParameters().getFirst("id");
Object existingObject = null;
try {
existingObject = existingObjectDao.get(id, authParams);
} catch (Exception e) {
e.printStackTrace();
}
if (existingObject != null) {
ObjectMapper objectMapper = new ObjectMapper();
ObjectReader reader = objectMapper.readerForUpdating(existingObject );
JsonNode r = reader.readTree(responseContent);
responseContent = objectMapper.writer().writeValueAsString(r);
}
context.setEntityStream(new ByteArrayInputStream(responseContent.getBytes()));
}
}

Set message header in rabbitmq while sending

I want to set message header while sending a message to rabbit.
I am using below code, but confused how to set message header in it.
public static <T> void sendMessage(String routingKey,final Object message,Class<T> type){
DefaultClassMapper typeMapper = new DefaultClassMapper();
typeMapper.setDefaultType(type);
Jackson2JsonMessageConverter converter = new Jackson2JsonMessageConverter();
converter.setClassMapper(typeMapper);
RabbitTemplate template = new RabbitTemplate(getConnectionFactory));
template.setMessageConverter(converter);
template.convertAndSend(routingKey, message);
}
In above method i am simply arguementing java POJO object and its type to send. I want to know where should i set message header here.
How to listen the message properties at listener end?
Java 8:
template.convertAndSend(routingKey, message, m -> {
m.getMessageProperties().getHeaders().put("foo", "bar");
m.getMessageProperties().setPriority(priority);
return m;
});
Java 6,7:
template.convertAndSend(routingKey, message, new MessagePostProcessor() {
#Override
public Message postProcessMessage(Message m) throws AmqpException {
m.getMessageProperties().getHeaders().put("foo", "bar");
m.getMessageProperties().setPriority(priority);
return m;
}
});

How can I know where does a message in rabbitMQ send from?

When we using rabbitMQ topic exchange, We can send a message at everywhere. And our project is very large, when I receive a message, and we found there is a problem in the message and we want to modify the message at where it was sent. But it is hardly be found where the message was sent.
Is there a method or a command tool in rabbitMQ to find out where that message sent from.
there are a few information that you can take using the envelop, as exchange, delivery_tag, routing_key :
Consumer consumer_a = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
String message = new String(body, "UTF-8");
long delivery_tag = envelope.getDeliveryTag();
String exchange_from = envelope.getExchange();
String routing_key = envelope.getRoutingKey();
}
};
if you need more info you can use the headers to add custom information as:
var properties = new BasicProperties();
properties.Headers = new Dictionary<string, object>();
properties.Headers.Add("mysender_user", "my_server");
properties.Headers.Add("my_custom_info", "my_info");
channel.BasicPublish(ExchangeName, "", properties, message);

How to consume an object from azure service bus topic subscription

I got this error upon receving an object from a subscription in azure service bus.
An exception of type 'System.Runtime.Serialization.SerializationException' occurred in System.Runtime.Serialization.dll but was not handled in user code
I've tried some deserialization code but nothing works.
This is how I send a message. Please tell me how to receive it.
public void SendMessage()
{
BrokeredMessage message = new BrokeredMessage(new TestMessage() {
MsgNumber = 1, MsgContent = "testing message" }, new DataContractSerializer(typeof(TestMessage)));
// Send message to the topic
TopicClient topicClient = TopicClient.CreateFromConnectionString(cn, topicNamespace);
topicClient.Send(message);
}
public string ReceiveMessage(){
//??????
}
To receive a single message, you need to get the SubscriptionClient :
public void ReceiveMessage(string connectionString, string topicPath, string subscriptionName)
{
var subscriptionClient = SubscriptionClient.CreateFromConnectionString(connectionString, topicPath, subscriptionName);
var brokeredMessage = subscriptionClient.Receive();
var message = brokeredMessage.GetBody<TestMessage>();
}