Camel log doesn't work - spring

Camel route:
from("seda:rest_upload")
.log(LoggingLevel.WARN, "Got new file from sftp with name ${header.filename}")
.to("file://rest_files?fileName=${header.filename}");
I see new files into rest_files but I don't see log about it.
What do I wrong?
P.S.
Bu the way I tried to write:
from("seda:rest_upload")
.process(new Processor() {
#Override
public void process(Exchange exchange) throws Exception {
logger.info("Got new file from sftp with name {}", exchange.getIn().getHeader("filename"));
}
})
.to("file://rest_files?fileName=${header.filename}");
The behaviour really strange - file saves successfully but process method is not invoked.

Related

How can I test a direct route with MQ?

I have a camel 3 with springboot application that contains this route:
public class SendForRatingRoute extends RouteBuilder
{
public void configure() throws Exception
{
onException(Exception.class)
.handled(true)
.process(exProcessor);
// Queue
String qn = "ratingmq:queue:MY_OUT_QUEUE");
from("direct:sendRate")
.routeId("sendRate")
.bean(MessagingBean.class, "createMessage" )//creates input object
.marshal().xstream()
.log(LoggingLevel.INFO,logger, "~~~ sending to MQ: ${body} " )
.to(qn)
.log(LoggingLevel.INFO,logger, "~~~ Message was sent to MQ successfully ");
} `
}
this route takes an Order object as input, converts it to a java class that matches the Queue message schema (in the MessagingBean) and then mashall that class to XML and send it to an IBM MQ endpoint.
(for simplicity the configuration of the queue is skipped)
I need to write a test case that passes a sample order to this route and see if it actually sends it to the queue correctly. (I want the message to get sent and not mock the sending)
I created a test class like this:
class SendForRatingTest extends CamelTestSupport
{
public void setUp() throws Exception
{
super.setUp();
}
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return new SendForRatingRoute();
}
#Test
void testSendingForRating() throws Exception
{
template.sendBody("direct:sendRate", getSampleOrder());
assertTrue(true); //??
}
}
The method GetSampleOrder() creates the order object with sample data to pass to the route.
I am not sure if I am doing this right (I have never written test case for camel before)
When I try to run the test case using maven:
mvn test -Dtest=SendForRatingTest -X
I am getting this error:
<<< ERROR!
org.junit.platform.commons.PreconditionViolationException: You must register at least one TestTemplateInvocationContextProvider that supports #TestTemplate method [void SendForRatingTest.testSendingForRating() throws java.lang.Exception]
What am I doing wrong?
Also I am not sure how to test that the route was executed successfully. Ultimately I am going to check the queue for a message but also I want the route test to validate it worked without errors. Since I don't return anything in the route, I am not sure what to put in the assertTrue()
Thank you in advance.

Camel no error handler invoked on exception with multipleConsumer=true and POJO #Consume Annotation

I've been trying to figure out how route errors to my own error handler with the following, seemingly simple configuration, but Camel is swallowing the exception without routing it to any error handler I configure. I've run out of ideas. Any help would be much appreciated.
I've got a seda route that supports multiple consumers:
#Component
public class MessageGenerator {
public static final String ERROR_GENERATOR_CHANNEL = "seda:my-error-generator?multipleConsumers=true&concurrentConsumers=3";
private final FluentProducerTemplate producerTemplate;
public MessageGenerator(FluentProducerTemplate producerTemplate) {
this.producerTemplate = producerTemplate;
}
public void generateMessage() {
producerTemplate
.to(ERROR_GENERATOR_CHANNEL)
.withBody("Hello World")
.asyncSend();
}
}
I've got two separate POJO consumers:
#Configuration
public class MessageConsumer1 {
#Consume(ERROR_GENERATOR_CHANNEL)
void receiveMessage(String message) {
System.out.println("Received message 1: " + message);
throw new NullPointerException("Error generated");
}
}
#Configuration
public class MessageConsumer2 {
#Consume(ERROR_GENERATOR_CHANNEL)
void receiveMessage(String message) {
System.out.println("Received message 2: " + message);
}
}
When I run the following example, the NullPointerException gets swallowed by the underlying Camel MulticastProcessor as we can see in the logs:
Received message 2: Hello World
Received message 1: Hello World
2022-01-15 13:40:23.711 DEBUG 32945 --- [error-generator] o.a.camel.processor.MulticastProcessor : Message exchange has failed: Multicast processing failed for number 0 for exchange: Exchange[] Exception: java.lang.NullPointerException: Error generated
2022-01-15 13:40:23.711 DEBUG 32945 --- [error-generator] o.a.camel.processor.MulticastProcessor : Message exchange has failed: Multicast processing failed for number 0 for exchange: Exchange[] Exception: java.lang.NullPointerException: Error generated
The exception only gets logged as debug and never gets propagated to any error handler I set up.
Any thoughts on how I could receive the error in my own error handler rather than Camel swallowing the exception as a debug statement?
Note1: I've attempted many variations on both default error handling and default dead letter handling to no avail. I could just be doing it wrong...
Note2: that I'm using Spring[Boot] here too, hence the #Configuration annotation.
Note1: I've attempted many variations on both default error handling and default dead letter handling to no avail. I could just be doing it wrong...
Haven't used #Consume annotations but generally if you want Camel route not to handle any errors you can use .errorHandler(noErrorHandler()). This can be used to pass the error back to parent route or all the way to the code calling ProducerTemplate.sendBody.
Example:
public class ExampleTest extends CamelTestSupport {
#Test
public void noErrorHandlerTest() {
try {
template.sendBody("direct:noErrorHandler", null);
fail();
} catch (Exception e) {
System.out.println("Caught Exception: " + e.getMessage());
}
}
#Override
protected RoutesBuilder createRouteBuilder() throws Exception {
return new RouteBuilder(){
#Override
public void configure() throws Exception {
from("direct:noErrorHandler")
.errorHandler(noErrorHandler())
.log("Throwing error")
.throwException(Exception.class, "Test Exception");
}
};
}
}

How to enable Spring Boot to display a list of files under a directory

I have a folder structure /data/reports on a file system, which contains all reports.
How can I configure a SpringBoot application to serve the contents of this file sytem.
Currently I have tried few options, but none working
#Configuration
#EnableWebMvc
public class AppConfig implements WebMvcConfigurer {
#Value(value = "${spring.resources.static-locations:#{null}}")
private String fileSystem;
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/data/reports/**")
.addResourceLocations(fileSystem)
.setCachePeriod(3600)
.resourceChain(true)
.addResolver(new PathResourceResolver());
}
}
and in application.properties I have defined
spring.resources.static-locations=file:///data/reports
server.servlet.jsp.init-parameters.listings=true
But in both cases, when I try
http://host:port/application/data/reports
I'm getting 404
What am I missing ?
Based on the suggestions given, I realized that one mistake I'm doing is to access the reports via
http://host:port/application/data/reports
instead of
http://host:port/data/reports
if I use application in the request, those calls will go through RequestDispatcher and will try to find for a matching RequestMapping, which does not exist. I think I'm convinced so far.
But the problem I'm seeing now is, I'm getting SocketTimeoutException while trying to read from the resource listed in the URL. I had put some breakpoints in Spring source "ResourceHttpMessageConverter.java"
protected void writeContent(Resource resource, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
try {
InputStream in = resource.getInputStream(); //It is timing out here
try {
StreamUtils.copy(in, outputMessage.getBody());
}
catch (NullPointerException ex) {
// ignore, see SPR-13620
}
The resource is a small text file with 1 line "Hello World". Yet it is timing out.
The resource in the above class is a FileUrlResource opened on file:///c:/data/reports/sample.txt
On the other hand, I tried to read that resource as
File file = new File("c:/data/reports/sample.txt");
System.out.println(file.exists());
URL url = file.toURI().toURL();
URLConnection con = url.openConnection();
InputStream is = con.getInputStream(); //This works
Thanks

Spring Websocket connection getting closed automatically with reason Invalid reserved bit

My spring websocket code runs in Liberty server. The code works fine in local. When I move to my server, when I try from 'Simple Websocket Client', I get an error like
WebSocket connection to 'wss://url' failed: One or more reserved bits
are on: reserved1 = 0, reserved2 = 1, reserved3 = 1
On the server side logs, I can see that afterConnectionEstablished method gets triggered, and immediately afterConnectionClosed gets triggered and when I print close status, it gives me
Code 1002 Reason:: Invalid reserved bit.
Am not clear on what this means and what are reasons this could come from.
public class NotificationHandler extends TextWebSocketHandler {
Logger logger = LogManager.getLogger(NotificationHandler.class);
#Override
public void afterConnectionEstablished(WebSocketSession session)
throws IOException {
logger.info("In NotificationHandler, afterConnectionEstablished.. ");
session.sendMessage(new TextMessage("Hello !"));
}
#Override
public void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
logger.info("In NotificationHandler, handleTextMessage.. ");
session.sendMessage(new TextMessage("Hello Text Message!"));
}
#Override
public void afterConnectionClosed(WebSocketSession session, CloseStatus status) {
logger.info("In NotificationHandler, afterConnectionClosed, Code:: "+ status.getCode() + ".. Reason:: " + status.getReason());
}
}
Please let me know if you need more details.
Given the exact wording, that is not a reason code coming from the Liberty Websocket code, so I am guessing it is coming from the Spring code. If you are running on Liberty I would think you would want the system configured to use the Liberty Websocket code and not another provider.

Write log messages to the log file in openscript

I need to write log messages to the log file instead of console in script.
By default few methods are provided by openscript.info(), warn().
where did they configured to write messages to the console.
when I have written info(message); it's writing message to the console.
where is the log4j.properties configured? Do I need to override to write to log file?
All log messages are stored in your OATS location, default in: C:\OracleATS\logs. Files are named "process_console_[timestamp].[hash].log"
However, if you want to create your own log file, I suggest to create a dedicated method, which uses built-in methods. In my code I did something like this:
private String filePath = "c:/warnings.log";
public void saveLog(String message) throws Exception {
DateFormat df = new SimpleDateFormat("[yyyy/MM/dd HH:mm:ss]");
Date sysdate = new Date();
String modifiedText = df.format(sysdate) + " " + message + "\n";
Files.write(Paths.get(filePath), modifiedText.getBytes(),
StandardOpenOption.APPEND);
}
public void warning(String message) throws Exception {
saveLog(message);
warn(message);
}
public void run() throws Exception {
warning("Test");
}

Resources