Set ActiveMQ message header while using Camel's #Produce annotation - header

We are using Camel to send messages via ActiveMQ. In our code, we have the following configuration, it works:
#Produce(uri = IEventService.QUEUE_NAME)
private IProducer sender;
#Override
public void emit(final Event e) {
sender.emit(e);
}
Now, we want to use ActiveMQ Message Groups:
http://activemq.apache.org/message-groups.html
According to the documentation, I need to set JMSXGroupID in the message header. How do I get at the message header so that I can set this property in my emit() api?
Thanks.
-AP_

Instead of annotating #Produce to a IProducer (which you defined yourself, right?), you could do
#EndpointInject(uri = IEventService.QUEUE_NAME)
private ProducerTemplate sender;
#Override
public void emit(final Event e){
sender.sendBodyAndHeader(e,"JMSXGroupID",someId);
}
Not sure if this is ok though, or if you are using IProducer for something else.

Another solution is to send to a direct:myname endpoint. Then you have a small route from("direct:myname").to(IEventService.QUEUE_NAME)
So in this route you can easily add headers.

Related

Is it possible to add a custom `ChannelInboundHandler` in Micronaut?

I would like to add a custom ChannelInboundHandler in my Micronaut service so that I can listen for the SslHandshakeCompletionEvent produced after a TLS handshake has been attempted.
I seem to be able to add a ChannelOutboundHandler simply enough by annotating it with #Singleton, however when I try to do the same with a ChannelInboundHandler, it does not seem to be added to the pipeline.
What's the correct way to do this?
Edit
This looks promising: https://docs.micronaut.io/snapshot/guide/index.html#nettyPipeline
You can create an implementation of BeanCreatedEventListener<ChannelPipelineCustomizer>, and provide an implementation of the onCreated method, e.g.
#Override
public ChannelPipelineCustomizer onCreated(BeanCreatedEvent<ChannelPipelineCustomizer> event) {
ChannelPipelineCustomizer customizer = event.getBean();
if (!customizer.isServerChannel()) {
customizer.doOnConnect(pipeline -> {
pipeline.addAfter(
ChannelPipelineCustomizer.HANDLER_HTTP_CLIENT_CODEC,
"my-handler",
new MyChannelInboundHandler()
);
return pipeline;
});
}
return customizer;
}
Then, in your MyChannelInboundHandler class, implement the userEventTriggered method and listen to the SslHandshakeCompletionEvent.SUCCESS event. You can then make some assertions on e.g. the public key of some of the certificates in the chain if you're doing HPKP.

spring amqp RPC copy headers from request to response

I'm looking for a way to copy some headers from the request message to the response message when I use RabbitMq in RPC mode.
so far I have tried with setBeforeSendReplyPostProcessors but I can only access the response and add headers to it. but I don't have access to the request to get the values I need.
I have also tried with the advice chain, but the returnObject is null after proceeding so I can't modify it (I admit I don't understand why it is null... I thought I could get the object to modify it):
#Bean
public SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory(SimpleRabbitListenerContainerFactoryConfigurer simpleRabbitListenerContainerFactoryConfigurer, ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory simpleRabbitListenerContainerFactory = new SimpleRabbitListenerContainerFactory();
simpleRabbitListenerContainerFactory.setAdviceChain(new MethodInterceptor() {
#Override
public Object invoke(MethodInvocation invocation) throws Throwable {
Object returnObject = invocation.proceed();
//returnObject is null here
return returnObject;
}
});
simpleRabbitListenerContainerFactoryConfigurer.configure(simpleRabbitListenerContainerFactory, connectionFactory);
return simpleRabbitListenerContainerFactory;
}
a working way is to change my method annotated with #RabbitListener so it returns a Message and there I can access both the requesting message (via arguments of the annotated method) and the response.
But I would like to do it automatically, since I need this feature at different places.
Basicaly I want to copy one header from the request message to the response.
this code do the job, but I want to do it through an aspect, or an interceptor.
#RabbitListener(queues = "myQueue"
, containerFactory = "simpleRabbitListenerContainerFactory")
public Message<MyResponseObject> execute(MyRequestObject myRequestObject, #Header("HEADER_TO_COPY") String headerToCopy) {
MyResponseObject myResponseObject = compute(myRequestObject);
return MessageBuilder.withPayload(myResponseObject)
.setHeader("HEADER_RESPONSE", headerToCopy)
.build();
}
The Message<?> return type support was added for this reason, but we could add an extension point to allow this, please open a GitHub issue.
Contributions are welcome.

Retrieve WS request in CXF Web service

I got a CXF OSGi Web service (based on the example demo in servicemix: https://github.com/apache/servicemix/tree/master/examples/cxf/cxf-jaxws-blueprint)
The Web service works fine and i call all the available implemented methods of the service.
My question is how can i retrieve the request inside a WS method and parse in a string XML format.
I have found that this is possible inside interceptors for logging, but i want also to the WS-Request inside my methods.
For storing the request in the database I suggest to extend the new CXF message logging.
You can implement a custom LogEventSender that writes into the database.
I had similar requirement where I need to save data into DB once method is invoked. I had used ThreadLocal with LoggingInInterceptor and LoggingOutInterceptor. For example in LoggingInInterceptor I used to set the message into ThreadContext and in webservice method get the message using LoggingContext.getMessage() and in LoggingOutInterceptor I used to removed the message(NOTE: Need to be careful here you need to explictly remove the message from thread context else you will end up with memory leak, and also incase of client side code interceptors get reversed.
public class LoggingContext {
private static ThreadLocal<String> message;
public static Optional<String> getMessage() {
return Optional.ofNullable(message.get());
}
public static void setMessage(final String message) {
LoggingContext.message = new ThreadLocal<>();
LoggingContext.message.set(message);
}
}
Not an answer to this question but i achieved to do my task by using JAXB in the end and do some manipulations there.

Extract org.restlet.http.headers value from Camel headers inside a .choice()

I'm trying to extract a value from org.restlet.http.headers header collection in a Camel route.
My incoming POST has a http header property called IncomingRequestType: ABCD.
Camel moves this inside the exchange headers collection, but it is buried inside org.restlet.http.headers which is in-itself a collection of headers.
I can extract the value in a process using the code below:
.process(new Processor() {
public void process(Exchange exchange) throws Exception {
org.restlet.util.Series<Header> httpHeaders = null;
httpHeaders = (Series<Header>) exchange.getIn().getHeader("org.restlet.http.headers");
String reqType = httpHeaders.getValues("IncomingRequestType").toString();
}})
Outside of a process I need to access the IncomingRequestType inside a .choice().when()
e.g. i want to be able to do:
.choice()
.when(header("org.restlet.http.headers")["IncomingRequestType"]).isEqualTo("ABCD"))
Any suggestions on how this can be done. I've tried creating predicates but cannot get a suitable solution.
This can be done in the simple language:
.choice()
.when(simple("${in.header.org.restlet.http.headers[IncomingRequestType]} == 'ABCD'"))

Call OutgoingHeaders using NServiceBus.Host

Using NServiceBus 4.0.11
I would like to call
Bus.OutgoingHeaders["user"] = "john";
The Header Manipulation sample shows how to call it with a custom host.
I would like to call it while using the NServiceBus.Host.
So actually I would like to have a reference to the instance of the Bus, to call OutgoingHeaders on.
Tried IWantCustomInitialization but that gives me an exception when calling CreateBus in it. INeedInitialization isn't the way to go neither.
How should I call Bus.OutgoingHeaders["user"] = "john"; while using the NServiceBus.Host?
Reading your question makes me think that you want to add this header to a certain message that you want to send during initialization/startup or when handling a message. Usually, headers have a more generic behavior as they need to be applied to more than one message.
Instead of setting the header before sending the message you can also add the header via a message mutator or behavior.
Behavior
public class OutgoingBehavior : IBehavior<SendPhysicalMessageContext>
{
public void Invoke(SendPhysicalMessageContext context, Action next)
{
Dictionary<string, string> headers = context.MessageToSend.Headers;
headers["MyCustomHeader"] = "My custom value";
next();
}
}
Mutator
public class MutateOutgoingTransportMessages : IMutateOutgoingTransportMessages
{
public void MutateOutgoing(object[] messages, TransportMessage transportMessage)
{
Dictionary<string, string> headers = transportMessage.Headers;
headers["MyCustomHeader"] = "My custom value";
}
}
Documentation
See: http://docs.particular.net/nservicebus/messaging/message-headers#replying-to-a-saga-writing-outgoing-headers for samples.