Store Soap Response Message in Citrus Framework - java

Good Morning:
I'm new in Citrus Framework. Actually i work in a Test Case that consumes one soap webservice. I can send request message from a xml file and i need to store response message from server into another xml file for trazability and audit.
I try some options but still not working. Can you help me with posibles solutions to this requirement?
My test look like this:
public class DummyIT extends TestNGCitrusTestDesigner {
#Autowired
private WebServiceClient DummyClient;
#Test
#CitrusTest
public void dummyTest() {
soap()
.client(DummyClient)
.send()
.messageType(MessageType.XML)
.charset("UTF-8")
.contentType("text/xml")
.payload(new ClassPathResource("templates/DummyRequest.xml"));
soap()
.client(DummyClient)
.receive()
.schemaValidation(false);
}
I'm using Citrus Framework version 2.7.2.
Thanks for your help.

You can add a message tracing test listener to the Spring application context. This listener is called with all inbound and/or outbound messages. With a custom implementation you can write the message content as file to an external folder.
There is a default message listener implementation available that is a good starting point. See if this default tracing listener fits your requirements. Otherwise you would have to implement the listener logic on your own.
You can add the default listener to the application context as bean:
#Bean
public MessageTracingTestListener tracingTestListener() {
return new MessageTracingTestListener();
}
After that you should see .msgs files in target/citrus-logs/trace/messages folder containing all exchanged inbound and outbound messages.
Here is the default implementation: https://github.com/citrusframework/citrus/blob/master/modules/citrus-core/src/main/java/com/consol/citrus/report/MessageTracingTestListener.java

Related

How to handle exception using onException() in Spring Boot Camel

Spring boot Apache Camel-Java DSL app reads messages from Kafka topic.
#Component
public class KafkaTopicService extends RouteBilder {
public void configure(){
from("kafka:myTopic?brokers=localhost:9092")
.log("Message received from Kafka: ${body}")}
}
If I stop Kafka I get org.apache.kafka.common.errors.DisconnectException
I looked into onException(...class).handled(true) but Im not sure how to implement handling of the exception in my code. Can someone give me few implementation examples? What options are available? For example logging the message or reattempting to read message?
Documentation also mentions Quarkus. Do I need Quarkus to use onException()?
You can do something like (have not tried running it so please take care of any typos)
#Component
public class KafkaTopicService extends RouteBilder {
public void configure(){
onException(org.apache.kafka.common.errors.DisconnectException.class)
.log("Error connecting kafka");
from("kafka:myTopic?brokers=localhost:9092&bridgeErrorHandler=true")
.log("Message received from Kafka: ${body}")}
}
Please note that I have added bridgeErrorHandler=true. Normally exception handling happens after from. In most of the case using bridgeErrorHandler we can use onException function for those.
Also note that I have defined onException outside your route, so the exception handling logic which you add would be global and applicable to all routes wherever you encounter DisconnectException

Unit Test Apache-Camel JmsReplyTo route flow

I have the following sample route flow, where I receive a jms message, built a webservice request and then respond to the JMSReplyTo with the webservice response:
from("{{jms.input.queue}}).routeId("Receive JMS Message")
.to("direct:start");
from("direct:start").routeId("Build & Send Http Request")
.bean(processRequest)
.to("{{http.endpoint}}")
.to("direct:processResponse");
from("direct:processResponse").routeId("Build XML Response")
.convertBodyTo(String.class)
.bean(processResponse);
I have successfuly unit tested my processes, but now I want to unit test my route flow. Instead of having a EMS server running during tests, I have started from the second route:
camelContext.getRouteDefinition("Build & Send Http Request").adviceWith(camelContext,
new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
interceptSendToEndpoint("http://*")
.skipSendToOriginalEndpoint()
.setBody("Hello");
}
});
#Test
#DirtiesContext
public void RouteFlowTest() throws Exception{
Map<String,Object> jmsHeaders = new HashMap<>();
jmsHeaders.put("Auth","helloWorld");
jmsHeaders.put("JMSReplyTo","sample");
String jmsBody = "Help Me"
incomingJmsRequestMessage.sendBodyAndHeaders("direct:start", jmsBody, jmsHeaders);
}
but now how to I assert the exchange after the processResponse bean has been executed?
Or is there a way to test from the first route and satisfy the JMSReplyTo without actually having a EMS server running?
As you are already weaving the route, you'd could add a propagation to a mock endpoint within your route advice such as:
this.weaveAddLast().to("mock:done");
which just adds a .to("mock:done") defintion to the end of your "Build & Send Http Request" route. From the given problem statement it is a bit unclear what .bean(processResponse); actually does. You could also add this mock endpoint propagation to the "Build XML Response" route in which case you'd need a further route advice definition.
Next, you can either let Camel inject a mock endpoint via
#EndpointInject(uri = "mock:done")
private MockEndpoint done;
or define it manually inside your test via:
MockEndpoint done = camelContext.getEndpoint("mock:done", MockEndpoint.class);
This mock endpoint can be used to define certain expectations such that you'd expect one message to be received by that endpoint
done.expectedMessageCount(1);
...
// invoke your route here
template.sendBody(...);
...
done.assertIsSatisfied();
You can also access the exchanges received by this endpoint directly via the following direction and perform further assertions on it:
Exchange exchange = done.getExchanges().get(0);
...
If you'r using Camel on top of Spring (Boot) you might also read through how to test Camel with Spring enabled

apache cxf LoggingFeature mask senstive information

I'm using Logging feature to log in/out message to my cxf rest server on Spring boot. Similarly using the same to log outward Rest API connections initiated by cxf WebClient.
I came across few parameters which I do not want to be logged in to the log file. either completely removing them or masking them is sufficient for my case.
I found on the internet that previous (now depreciated) LoginIntercepter had transform operation to modify the log entry. I was not able to find a solution to mask/truncate the log entries wirg LoggingFeature.
any help would be appreciated
Current configuration of the server's logging feature is like below.
factory.setProviders(providers);
LoggingFeature loggingFeature = new LoggingFeature();
loggingFeature.setPrettyLogging(true);
loggingFeature.setLogBinary(false);
loggingFeature.setLogMultipart(false);
factory.getFeatures().add(loggingFeature);
Server server = factory.create();
web client configuration is as below
LoggingFeature loggingFeature = new LoggingFeature();
loggingFeature.setPrettyLogging(true);
WebClient client = WebClient.create(url, Collections.singletonList(new JacksonJsonProvider()),
Arrays.asList(loggingFeature), null);
To change the log message, you can ...
Write a custom LogSender and set it on the LoggingFeature to do custom
logging. All meta data can be access[ed] from the class LogEvent.
(Source: http://cxf.apache.org/docs/message-logging.html)
With a sender like:
// ...
import org.apache.cxf.ext.logging.event.LogEvent;
class MyLogEventSender implements org.apache.cxf.ext.logging.event.LogEventSender {
#Override
public void send(LogEvent event) {
event.setPayload(maskSensibleParameters(event.getPayload()));
}
private String maskSensibleParameters(String pIn) {
// here goes the tricky part
// ... but no details on this in your question
// ... here you can stick to "old" LogInterceptor examples
// ... and also to PrettyLoggingFilter.
}
}
A code example is given by (the default) PrettyLoggingFilter.
To mask (hide) it (completely) is easier and guaranteed more performant, it depends on the used "logging framework" (java.util, log4j or slf4j) and accomplished with an according "logger configuration". (see here)

Spring Remoting with AMQP - Client is not seeing the beans exposed from Server

I'm trying to run example from http://www.baeldung.com/spring-remoting-amqp, even when I set up the connection to the dedicated vhost to my RabbitMQ broker, I can only send the request from client (I see it in RabbitMQ UI), but I never get the answer from the server.
The server seems to bean the service (the returning Impl class) with getBeanDefinitionNames(), but I definitly do not see those beans on the client side. I use annotations to set up beans, not the .xml file.
So the question is - why my client is not seeing the Server beans, I discover it more a less in following way:
#Autowired
private ApplicationContext appContext;
public GetResponse get(String id) {
Service service = appContext.getBean(Service.class);
System.out.println(service.ping());
return new GetResponse();
}
The answer which I get on the level of webservice is:
{
"timestamp": "2018-02-01T10:09:00.809Z",
"status": 500,
"error": "Internal Server Error",
"exception": "org.springframework.remoting.RemoteProxyFailureException",
"message": "No reply received from 'toString' with arguments '[]' - perhaps a timeout in the template?",
"path": "/v3/app/r"
}
Service:
public interface Service extends Serializable{
String ping();
}
Service Impl:
public class ServiceImpl implements Service {
#Override
public String ping() {
System.out.println("ponged");
return "pong";
}
#Override
public String toString() {
return "to string";
}
EDITED + BOUNTY
In the link you can find extracted modules which I want to connect together. I suppose that it is still about 'not seeing' the beans from one module in the second one.
The action can be trigerd with GET http://localhost:8081/v3/app/u The RabbitMQ settings has to be adjusted to your set-up.
https://bitbucket.org/herbatnic/springremotingexample/overview
I think you shouldn't set the routing key in your client, in amqpFactoryBean (and the one you set seems invalid):
https://bitbucket.org/herbatnic/springremotingexample/src/b1f08a5398889525a0b1a439b9bb4943f345ffd1/Mod1/src/main/java/simpleremoting/mod1/messaging/Caller.java?at=master&fileviewer=file-view-default
Did you try to run their example?
https://github.com/eugenp/tutorials/tree/master/spring-remoting/remoting-amqp
Just stumbled upon this question 3 years later.. trying to run the Baeldung example!
I tried debugging the issue and as far as I can tell, something internal in the AMQP implementation of spring remoting is not using the correct Routing Key when sending the client message, meaning the payload arrives at the broker and is never put into the queue for processing, we then timeout after 5s (default) on the client.
I tried the other answer by Syl to remove the routingKey however it doesn't seem to allow us to create a binding without one, and even when creating a binding directly on the broker management page (without a routing key) it doesn't route the messages.
I have not managed to make the example work, however I found a blog post on fatalerrors.org that shows a custom implementation of the AmqpProxyFactoryBean and it has custom handling for the routing key, this one works.
I've create this gist with the example that is working for me in case the blog post above goes under.
One other thing to note is that on the Baeldung example they are using a DirectExchange, while here we are using a TopicExchange.

Message Queue Listener and RESTful integration

My project publishes RESTful/SOAP services. One of these sends messages to a JMS queue on a Websphere application server. The application runs on the same application server. What I need is to define a listener to this queue. How can I activate this listener without a direct call from the service?
The project structure looks like this:
Project:
-ejb
-rest
-soap
The user calls methods on the service, which calls the EJB component, so I dont have any main method where I can init the listener.
I need a solution which activates a permanent listener to the queue.
I already have the source code I just don't know how to initialize the listener.
Not sure where you have the issues:
Do something like:
define the JMS resources in WebSphere
inject the javax.jms.Queue as a Resource (or maybe using CDI? Not sure if CDI supports this) in a EJB
use this Queue to send messages
define a MDB (#MessageDriven) to listen for messages
WebSphere MDB with a lot of configuration it works!!!! But look at this:
#MessageDriven(activationConfig={
#ActivationConfigProperty(propertyName="destination", propertyValue="myDestination"),
#ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue")
})
public class MsgBean implements javax.jms.MessageListener {
public void onMessage(javax.jms.Message msg) {
String receivedMsg = ((TextMessage) msg).getText();
System.out.println("Received message: " + receivedMsg);
}
}

Categories

Resources