When using KafkaListener, how can I check that a topic message has been read to the end? - spring-boot

When using #KafkaListener, how can I check that a topic message has been read to the end?

See this answer about getting an event notification when there are no more records to read.
You can use the Consumer in the event to get the current position(), and endOffsets(); the following shows how to get the end offsets:
#EventListener
void listen(ListenerContainerIdleEvent event) {
System.out.println(event);
try {
System.out.println(event.getConsumer().assignment());
System.out.println(event.getConsumer().endOffsets(event.getConsumer().assignment(), Duration.ofSeconds(5)));
}
catch (Exception e) {
e.printStackTrace();
}
}

Related

How to handle InterruptException on Future#get()?

public void produceMessage(String dataPushNotif) {
PushNotif msg = PushNotif.newBuilder()
.setDatapushnotif(dataPushNotif)
.build();
ListenableFuture<SendResult<String, PushNotif>> future =
kafkaTemplate.send(destTopic, msg);
try {
var result = future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
log.debug(buildSuccesLogMessage(result));
}
catch (InterruptedException | ExecutionException | TimeoutException e) {
log.debug("FAILED: {}", e);
}
}
With the code above I'm getting a sonarlint warning of Either re-interrupt this method or rethrow the "InterruptedException" that can be caught here. (java:S2142)
I could handle success and failure to send gracefully with addCallback(), but I don't see any other way to set a timeout on the thread execution.
Is there any way to handle the sonarlint warning? Or handle the future gracefully with a timeout option?
Don't use multi-catch and call Thread.currentThread().interrupt() in the InterruptedException catch block so that the next interruptible operation will get the exception.
It is bad practice to "swallow" interrupts.

Unable to save screenshots in the designated path or attach the screen shot to extentreports in MAC

I have tried many ways to take screenshot on test case failure but nothing works. unable to take a screenshot and attach it to extentreport in MAC os while using selenium.
public void onTestFailure(ITestResult tr)
{
logger=extent.createTest(tr.getName()); // create new entry in the report
logger.log(Status.FAIL,MarkupHelper.createLabel(tr.getName(),ExtentColor.RED)); // send the passed information to the report with GREEN color highlighted
String screenshotPath="./Stest-output/"+tr.getName()+".png";
TakesScreenshot ts = (TakesScreenshot)driver;
File img =ts.getScreenshotAs(OutputType.FILE);
File destination =new File(screenshotPath);
try {
FileUtils.copyFile(img,destination);
logger.addScreenCaptureFromPath(screenshotPath);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
if(img != null)
{
System.out.println("Screenshot is below:"+tr.getName());
try {
logger.info("Screenshot is below:" + logger.addScreenCaptureFromPath(screenshotPath));
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
throws null pointer exception when trying to copy the image from source to destination.
Have all the methods available in stack overflow.
You are unable to attach screenshot into extent report html because you forget to call flush() method that appends the report HTML file with all the tests result/screenshots. There must be at least one ended test for anything to be appended to the report.
Note: If flush() is called before any of the ended tests, no information will be appended to report.
#AfterTest
public void tearDown() {
extent.flush();

Spring Integration and returning schema validation errors

We are using Spring Integration to process a JSON payload passed into a RESTful endpoint. As part of this flow we are using a filter to validate the JSON:
.filter(schemaValidationFilter, s -> s
.discardFlow(f -> f
.handle(message -> {
throw new SchemaValidationException(message);
}))
)
This works great. However, if the validation fails we want to capture the parsing error and return that to the user so they can act on the error. Here is the overridden accept method in the SchemaValidationFilter class:
#Override
public boolean accept(Message<?> message) {
Assert.notNull(message);
Assert.isTrue(message.getHeaders().containsKey(TYPE_NAME));
String historyType = (String)message.getHeaders().get(TYPE_NAME);
JSONObject payload = (JSONObject) message.getPayload();
String jsonString = payload.toJSONString();
try {
ProcessingReport report = schemaValidator.validate(historyType, payload);
return report.isSuccess();
} catch (IOException | ProcessingException e) {
throw new MessagingException(message, e);
}
}
What we have done is in the catch block we throw a MessageException which seems to solve the problem. However this seems to break what a filter should do (simply return a true or false).
Is there a best practice for passing the error details from the filter to the client? Is the filter the right solution for this use case?
Thanks for your help!
John
I'd say you go correct way. Please, refer to the XmlValidatingMessageSelector, so your JsonValidatingMessageSelector should be similar and must follow the same design.
Since we have a throwExceptionOnRejection option we always can be sure that throwing Exception instead of just true/false is correct behavior.
What Gary says is good, too, but according to the existing logic in that MessageSelector impl we can go ahead with the same and continue to use .filter(), but, of course, already without .discardFlow(), because we won't send invalid message to the discardChannel.
When your JsonValidatingMessageSelector is ready, feel free to contribute it back to the Framework!
It's probably more correct to do the validation in a <service-activator/>...
public Message<?> validate(Message<?> message) {
...
try {
ProcessingReport report = schemaValidator.validate(historyType, payload);
return message;
}
catch (IOException | ProcessingException e) {
throw new MessagingException(message, e);
}
}
...since you're never really filtering.

Not able to receive notification on android device using Parse.com push notification service

I am not able to receive notification on android device. I am seeing following error message on app startup.
Could not find method android.database.Cursor.getNotificationUri, referenced from method com.parse.ParseSQLiteCursor.getNotificationUri
Any pointers?
If your code was similar to old code in parse sample code like above.
// Specify an Activity to handle all pushes by default.
PushService.setDefaultPushCallback(this, SavedVideoListActivity.class);
ParseInstallation.getCurrentInstallation().saveInBackground();
Try to choose this code in new sample code. (https://parse.com/tutorials/android-push-notifications)
ParsePush.subscribeInBackground("", new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.d("com.parse.push", "successfully subscribed to the broadcast channel.");
} else {
Log.e("com.parse.push", "failed to subscribe for push", e);
}
}
});

How to synchronize onMessage() of MessageListener

I have a spring3 web application.I use org.springframework.jms.listener.DefaultMessageListenerContainer to configure my message listener.I have a MDPOJO registered. What I wanted is, when onMessage() is getting executed for a particular request,others should wait until the first one finishes.In other words, onMessage() method invokes further work flow and it would take time to finish it off.Other messages in the queue should not be picked by onMessage until it confirms that previous request is complete.
Does it possible to synchronize the processing onMessage().I need to do the following :
Users will be posting n number of message into the Queue
I should be having an interface where user can remove a message from the queue.
When one message is under process, any of the other messages should not be picked up.
User should be able to change the priority of message processing
I could programatically list the messages in the queue using below code :
public void listAllJMS_Messages()
{
try {
ObjectName objectName=new ObjectName("jboss.messaging.destination:name=DLQ,service=Queue");
List ls = (List) server.invoke(objectName, "listAllMessages" , null, null);
List<javax.jms.Message> messages=(List<javax.jms.Message>)server.invoke(objectName, "listAllMessages" , null, null);
int count=0;
for(javax.jms.Message msg : messages) {
System.out.println((++count)+"t"+msg.getJMSMessageID());
if(msg.getJMSType() != null && msg.getJMSType().equalsIgnoreCase("Text")) {
TextMessage text = (TextMessage)msg;
System.out.println(text.getText());
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// System.out.println((++count)+"t"+msg.getText());
}
But the above code list messages from those Queue which do not have any consumers so far.My case I have an MDPOJO as message consumer which processes message synchronously. Still I want list messages from the Queue, so that user can delete it if he wishes.Above code return null list in case I have a consumer of the queue.

Resources