Events stuck durin processing in Java app +Srping Amqp - spring-amqp

After addded concurrrency to the #RabbitListened faced with problem that sometimes events are stuck in app.
When restarting app it's continue works normally. But then could aslo stuck suddenly after sometime.
#RabbitListener(
queues = "${app.queue}",
ackMode = "MANUAL",
concurrency = 2-5,
messageConverter = "jsonMessageConverter")
public void consumeEvent(AppEvent event, Channel channel, #Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag) {
try {
.....
doAck(channel, deliveryTag);
} catch (Throwable e) {
.....
doNack(channel, deliveryTag);
}
}
#Bean
public PooledChannelConnectionFactory connectionFactory(){
ConnectionFactory rabbitConnectionFactory = new ConnectionFactory();
rabbitConnectionFactory.setHost(host);
rabbitConnectionFactory.setPort(port);
rabbitConnectionFactory.setUsername(userName);
rabbitConnectionFactory.setPassword(password);
return new PooledChannelConnectionFactory(rabbitConnectionFactory);
}
#Bean
public RabbitTemplate rabbitTemplate(){
final var rabbitTemplate = new RabbitTemplate(connectionFactory());
rabbitTemplate.setMessageConverter(getJsonMessageConverter());
return rabbitTemplate;
}
#Bean("jsonMessageConverter")
public Jackson2JsonMessageConverter getJsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
In thread dump there are 3 threads like on picture

Related

mosquito MQTT message handler getting messages with some delay not real time

Following is the MQTT configuration to listening event.
For high message load around 100 message per second I noticed messages not received realtime on handler.
public class VehicleEventMqttConfig {
#Value("${mqtt.auto-startup.vehicleEvent:false}")
private boolean autoStartup;
#Value("${mqtt.completion-timeout.vehicleEvent:30000}")
private int completionTimeout;
#Bean
public MessageChannel vehicleMqttInputChannel() {
return new DirectChannel();
}
#Bean
public MessageProducer inboundVehicleEvent(
final MqttPahoClientFactory mqttPahoClientFactory,
final MqttAdapters adapters,
#Value("${mqtt.topic.vehicleEvent}") final String topic) {
log.info("Register vehicleEvent mqtt");
if (StringUtils.isEmpty(topic)) {
log.warn("vehicleEvent disabled!");
return null;
}
final MqttPahoMessageDrivenChannelAdapter adapter =
new MqttPahoMessageDrivenChannelAdapter(
getClientIdWithHost("inboundVehicleEvent"), mqttPahoClientFactory, topic);
adapter.setCompletionTimeout(completionTimeout);
adapter.setConverter(new DefaultPahoMessageConverter());
adapter.setOutputChannel(vehicleMqttInputChannel());
adapter.setAutoStartup(autoStartup);
adapter.setQos(1);
adapters.add(adapter);
return adapter;
}
#Bean
#ServiceActivator(inputChannel = "vehicleMqttInputChannel")
public MessageHandler vehicleEventHandler() {
return new VehicleEventMessageHandler();
}
}

How to get consumerTag in spring-rabbitmq 1.x

the spring-rabbitmq config is like
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit</artifactId>
<version>1.1.3.RELEASE</version>
I want to canceling a consumer , use channel.basicCannel(consumerTag)
when i use ChannelAwareMessageListener in spring-rabbitmq 2.x version, consumerTag are
in MessageProperties,
but my online service is use 1.x version, there has no consumerTag in MessageProperties,
so i cant use the basicCancel api
my full listener code below
public class RPCListener implements ChannelAwareMessageListener {
private static final Logger log = LoggerFactory.getLogger(RPCListener.class);
#Autowired
private MessagePropertiesConverter messagePropertiesConverter;
private MessageConverter messageConverter = new SimpleMessageConverter();
#Autowired
private AmqpTemplate amqpTemplate;
private Boolean flag = false;
#Override
public void onMessage(Message message, Channel channel) throws Exception {
try {
log.error("DeliveryTag(): {}", message.getMessageProperties().getDeliveryTag());
if (flag) {
log.error("canceling....");
//If true, messages will be requeued and possibly
channel.basicRecover(true);
// there is no consumerTag property in MessageProperties
//channel.basicCancel(message.getMessageProperties().getConsumerTag());
return;
}
amqpTemplate.send(message.getMessageProperties().getReplyTo(), message);
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} catch (Exception e) {
e.printStackTrace();
}
}
public Boolean getFlag() {
return flag;
}
public void setFlag(Boolean flag) {
this.flag = flag;
}
}
Is there any way to get consumerTag?
Thanks all!
1.1.3 is 7 years old; the consumerTag was added to MessageProperties in 1.4.2.
The only supported 1.x version is 1.7.14 - see the project page.
1.7.x will no longer be supported after this year.
However; you should NOT manually cancel the consumer; stop the container instead.

Call to Dropbox API Client.Files.DownloadAsync does not return metadata when call from an instance of TimerCallback

I’ve got a mobile crossplatform Xamarin.Forms project in which I try to download a file from a Dropbox repository at startup. It’s a tiny json file of less than 50kB. The code operating the Dropbox API call is shared between my Android and my iOS projects, and my Android implementation works as intended. It’s a Task method which I’ll call the downloader here for convenience.
UPDATED: With the iOS version, I can download the file successfully only when calling my downloader’s launcher (which is a also Task) directly from the BackgroundSynchronizer.Launch() method of my only AppDelegate, but not when delegating this call using a timer to call my downloader through a TimerCallback which calls an EventHandler at recurring times.
I can’t figure out why.
The downloader:
public class DropboxStorage : IDistantStoreService
{
private string oAuthToken;
private DropboxClientConfig clientConfig;
private Logger logger = new Logger
(DependencyService.Get<ILoggingBackend>());
public DropboxStorage()
{
var httpClient = new HttpClient(new NativeMessageHandler());
clientConfig = new DropboxClientConfig
{
HttpClient = httpClient
};
}
public async Task SetConnection()
{
await GetAccessToken();
}
public async Task<Stream> DownloadFile(string distantUri)
{
logger.Info("Dropbox downloader called.");
try
{
await SetConnection();
using var client = new DropboxClient(oAuthToken, clientConfig);
var downloadArg = new DownloadArg(distantUri);
var metadata = await client.Files.DownloadAsync(downloadArg);
var stream = metadata?.GetContentAsStreamAsync();
return await stream;
}
catch (Exception ex)
{
logger.Error(ex);
}
return null;
}
UPDATED: The AppDelegate:
using Foundation;
using UIKit;
namespace Izibio.iOS
{
// The UIApplicationDelegate for the application. This class is responsible for launching the
// User Interface of the application, as well as listening (and optionally responding) to
// application events from iOS.
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
private BackgroundSynchronizer synchronizer = new BackgroundSynchronizer();
//
// This method is invoked when the application has loaded and is ready to run. In this
// method you should instantiate the window, load the UI into it and then make the window
// visible.
//
// You have 17 seconds to return from this method, or iOS will terminate your application.
//
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
public override void OnActivated(UIApplication uiApplication)
{
synchronizer.Launch();
base.OnActivated(uiApplication);
}
}
}
EDIT: The intermediary class (which embeds the DownloadProducts function):
public static class DropboxNetworkRequests
{
public static async Task DownloadProducts(IDistantStoreService distantStorage,
IStoreService localStorage)
{
try
{
var productsFileName = Path.GetFileName(Globals.ProductsFile);
var storeDirectory = $"/{Globals.StoreId}_products";
var productsFileUri = Path.Combine(storeDirectory, productsFileName);
var stream = await distantStorage.DownloadFile(productsFileUri);
if (stream != null)
{
await localStorage.Save(stream, productsFileUri);
}
else
{
var logger = GetLogger();
logger.Info($"No file with the uri ’{productsFileUri}’ could " +
$"have been downloaded.");
}
}
catch (Exception ex)
{
var logger = GetLogger();
logger.Error(ex);
}
}
private static Logger GetLogger()
{
var loggingBackend = DependencyService.Get<ILoggingBackend>();
return new Logger(loggingBackend);
}
}
UPDATED: And the failing launcher class (the commented TriggerNetworkOperations(this, EventArgs.Empty);
in the Launch method succeeds in downloading the file) :
public class BackgroundSynchronizer
{
private bool isDownloadRunning;
private IDistantStoreService distantStorage;
private IStoreService localStorage;
private Timer timer;
public event EventHandler SynchronizationRequested;
public BackgroundSynchronizer()
{
Forms.Init();
isDownloadRunning = false;
distantStorage = DependencyService.Get<IDistantStoreService>();
localStorage = DependencyService.Get<IStoreService>();
Connectivity.ConnectivityChanged += TriggerNetworkOperations;
SynchronizationRequested += TriggerNetworkOperations;
}
public void Launch()
{
try
{
var millisecondsInterval = Globals.AutoDownloadMillisecondsInterval;
var callback = new TimerCallback(SynchronizationCallback);
timer = new Timer(callback, this, 0, 0);
timer.Change(0, millisecondsInterval);
//TriggerNetworkOperations(this, EventArgs.Empty);
}
catch (Exception ex)
{
throw ex;
}
}
protected virtual void OnSynchronizationRequested(object sender, EventArgs e)
{
SynchronizationRequested?.Invoke(sender, e);
}
private async void TriggerNetworkOperations(object sender, ConnectivityChangedEventArgs e)
{
if ((e.NetworkAccess == NetworkAccess.Internet) && !isDownloadRunning)
{
await DownloadProducts(sender);
}
}
private async void TriggerNetworkOperations(object sender, EventArgs e)
{
if (!isDownloadRunning)
{
await DownloadProducts(sender);
}
}
private void SynchronizationCallback(object state)
{
SynchronizationRequested(state, EventArgs.Empty);
}
private async Task DownloadProducts(object sender)
{
var instance = (BackgroundSynchronizer)sender;
//Anti-reentrance assignments commented for debugging purposes
//isDownloadRunning = true;
await DropboxNetworkRequests.DownloadProducts(instance.distantStorage, instance.localStorage);
//isDownloadRunning = false;
}
}
I set a logging file to record my application behaviour when trying to download.
EDIT: Here are the messages I get when calling directly TriggerNetworkOperations from the Launch method:
2019-11-12 19:31:57.1758|INFO|xamarinLogger|iZiBio Mobile Launched
2019-11-12 19:31:57.4875|INFO|persistenceLogger|Dropbox downloader called.
2019-11-12 19:31:58.4810|INFO|persistenceLogger|Writing /MAZEDI_products/assortiment.json at /Users/dev3/Library/Developer/CoreSimulator/Devices/5BABB56B-9B42-4653-9D3E-3C60CFFD50A8/data/Containers/Data/Application/D6C517E9-3446-4916-AD8D-565F4C206AF2/Library/assortiment.json
EDIT: And are those I get when launching through the timer and its callback (with a 10 seconds interval for debugging purposes):
2019-11-12 19:34:05.5166|INFO|xamarinLogger|iZiBio Mobile Launched
2019-11-12 19:34:05.8149|INFO|persistenceLogger|Dropbox downloader called.
2019-11-12 19:34:15.8083|INFO|persistenceLogger|Dropbox downloader called.
2019-11-12 19:34:25.8087|INFO|persistenceLogger|Dropbox downloader called.
2019-11-12 19:34:35.8089|INFO|persistenceLogger|Dropbox downloader called.
EDIT: In this second scenario, the launched task event eventually gets cancelled by the OS:
2019-11-13 09:36:29.7359|ERROR|persistenceLogger|System.Threading.Tasks.TaskCanceledException: A task was canceled.
at ModernHttpClient.NativeMessageHandler.SendAsync (System.Net.Http.HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) [0x002a5] in /Users/paul/code/paulcbetts/modernhttpclient/src/ModernHttpClient/iOS/NSUrlSessionHandler.cs:139
at System.Net.Http.HttpClient.SendAsyncWorker (System.Net.Http.HttpRequestMessage request, System.Net.Http.HttpCompletionOption completionOption, System.Threading.CancellationToken cancellationToken) [0x0009e] in /Users/builder/jenkins/workspace/xamarin-macios/xamarin-macios/external/mono/mcs/class/System.Net.Http/System.Net.Http/HttpClient.cs:281
at Dropbox.Api.DropboxRequestHandler.RequestJsonString (System.String host, System.String routeName, System.String auth, Dropbox.Api.DropboxRequestHandler+RouteStyle routeStyle, System.String requestArg, System.IO.Stream body) [0x0030f] in <8d8475f2111a4ae5850a1c1349c08d28>:0
at Dropbox.Api.DropboxRequestHandler.RequestJsonStringWithRetry (System.String host, System.String routeName, System.String auth, Dropbox.Api.DropboxRequestHandler+RouteStyle routeStyle, System.String requestArg, System.IO.Stream body) [0x000f6] in <8d8475f2111a4ae5850a1c1349c08d28>:0
at Dropbox.Api.DropboxRequestHandler.Dropbox.Api.Stone.ITransport.SendDownloadRequestAsync[TRequest,TResponse,TError] (TRequest request, System.String host, System.String route, System.String auth, Dropbox.Api.Stone.IEncoder`1[T] requestEncoder, Dropbox.Api.Stone.IDecoder`1[T] resposneDecoder, Dropbox.Api.Stone.IDecoder`1[T] errorDecoder) [0x000a5] in <8d8475f2111a4ae5850a1c1349c08d28>:0
at Izibio.Persistence.DropboxStorage.DownloadFile (System.String distantUri) [0x00105] in /Users/dev3/Virtual Machines.localized/shared/TRACAVRAC/izibio-mobile/Izibio/Izibio.Persistence/Services/DropboxStorage.cs:44
2019-11-13 09:36:29.7399|INFO|persistenceLogger|No file with the uri ’/******_products/assortiment.json’ could have been downloaded.
I’ll simply add a last observation: when debugging the DownloadFile Task from the BackgroundSynchronizer, I can reach the call to client.Files.DowloadAsync: var metadata = await client.Files.DownloadAsync(downloadArg);, but I won’t retrieve any return from this await statement.
OK, I finally found a way out of this by replacing the .NET timer by the iOS implementation (NSTimer).
My new code for the BackgroundSynchronizer class:
public class BackgroundSynchronizer
{
private bool isDownloadRunning;
private IDistantStoreService distantStorage;
private IStoreService localStorage;
private NSTimer timer;
public event EventHandler SynchronizationRequested;
public BackgroundSynchronizer()
{
Forms.Init();
isDownloadRunning = false;
distantStorage = DependencyService.Get<IDistantStoreService>();
localStorage = DependencyService.Get<IStoreService>();
Connectivity.ConnectivityChanged += TriggerNetworkOperations;
SynchronizationRequested += TriggerNetworkOperations;
}
public void Launch()
{
try
{
var seconds = Globals.AutoDownloadMillisecondsInterval / 1000;
var interval = new TimeSpan(0, 0, seconds);
var callback = new Action<NSTimer>(SynchronizationCallback);
StartTimer(interval, callback);
}
catch (Exception ex)
{
throw ex;
}
}
protected virtual void OnSynchronizationRequested(object sender, EventArgs e)
{
SynchronizationRequested?.Invoke(sender, e);
}
private async void TriggerNetworkOperations(object sender, ConnectivityChangedEventArgs e)
{
if ((e.NetworkAccess == NetworkAccess.Internet) && !isDownloadRunning)
{
await DownloadProducts();
}
}
private async void TriggerNetworkOperations(object sender, EventArgs e)
{
if (!isDownloadRunning)
{
await DownloadProducts();
}
}
private void SynchronizationCallback(object state)
{
SynchronizationRequested(state, EventArgs.Empty);
}
private async Task DownloadProducts()
{
isDownloadRunning = true;
await DropboxNetworkRequests.DownloadProducts(distantStorage, localStorage);
isDownloadRunning = false;
}
private void StartTimer(TimeSpan interval, Action<NSTimer> callback)
{
timer = NSTimer.CreateRepeatingTimer(interval, callback);
NSRunLoop.Main.AddTimer(timer, NSRunLoopMode.Common);
}
}
Which produces the following logging lines:
2019-11-13 14:00:58.2086|INFO|xamarinLogger|iZiBio Mobile Launched
2019-11-13 14:01:08.5378|INFO|persistenceLogger|Dropbox downloader called.
2019-11-13 14:01:09.5656|INFO|persistenceLogger|Writing /****_products/assortiment.json at /Users/dev3/Library/Developer/CoreSimulator/Devices/****/data/Containers/Data/Application/****/Library/assortiment.json
2019-11-13 14:01:18.5303|INFO|persistenceLogger|Dropbox downloader called.
2019-11-13 14:01:19.2375|INFO|persistenceLogger|Writing /****_products/assortiment.json at /Users/dev3/Library/Developer/CoreSimulator/Devices/****/data/Containers/Data/Application/****/Library/assortiment.json
But I’m still open to an enlighted explanation of the reason why both timers result in such different behaviours.

How can I convert an Object to Json in a Rabbit reply?

I have two applications communicating with each other using rabbit.
I need to send (from app1) an object to a listener (in app2) and after some process (on listener) it answer me with another object, now I am receiving this error:
ClassNotFound
I am using this config for rabbit in both applications:
#Configuration
public class RabbitConfiguration {
public final static String EXCHANGE_NAME = "paymentExchange";
public final static String EVENT_ROUTING_KEY = "eventRoute";
public final static String PAYEMNT_ROUTING_KEY = "paymentRoute";
public final static String QUEUE_EVENT = EXCHANGE_NAME + "." + "event";
public final static String QUEUE_PAYMENT = EXCHANGE_NAME + "." + "payment";
public final static String QUEUE_CAPTURE = EXCHANGE_NAME + "." + "capture";
#Bean
public List<Declarable> ds() {
return queues(QUEUE_EVENT, QUEUE_PAYMENT);
}
#Autowired
private ConnectionFactory rabbitConnectionFactory;
#Bean
public AmqpAdmin amqpAdmin() {
return new RabbitAdmin(rabbitConnectionFactory);
}
#Bean
public DirectExchange exchange() {
return new DirectExchange(EXCHANGE_NAME);
}
#Bean
public RabbitTemplate rabbitTemplate() {
RabbitTemplate r = new RabbitTemplate(rabbitConnectionFactory);
r.setExchange(EXCHANGE_NAME);
r.setChannelTransacted(false);
r.setConnectionFactory(rabbitConnectionFactory);
r.setMessageConverter(jsonMessageConverter());
return r;
}
#Bean
public MessageConverter jsonMessageConverter() {
return new Jackson2JsonMessageConverter();
}
private List<Declarable> queues(String... nomes) {
List<Declarable> result = new ArrayList<>();
for (int i = 0; i < nomes.length; i++) {
result.add(newQueue(nomes[i]));
if (nomes[i].equals(QUEUE_EVENT))
result.add(makeBindingToQueue(nomes[i], EVENT_ROUTING_KEY));
else
result.add(makeBindingToQueue(nomes[i], PAYEMNT_ROUTING_KEY));
}
return result;
}
private static Binding makeBindingToQueue(String queueName, String route) {
return new Binding(queueName, DestinationType.QUEUE, EXCHANGE_NAME, route, null);
}
private static Queue newQueue(String nome) {
return new Queue(nome);
}
}
I send the message using this:
String response = (String) rabbitTemplate.convertSendAndReceive(RabbitConfiguration.EXCHANGE_NAME,
RabbitConfiguration.PAYEMNT_ROUTING_KEY, domainEvent);
And await for a response using a cast to the object.
This communication is between two different applications using the same rabbit server.
How can I solve this?
I expected rabbit convert the message to a json in the send operation and the same in the reply, so I've created the object to correspond to a json of reply.
Show, please, the configuration for the listener. You should be sure that ListenerContainer there is supplied with the Jackson2JsonMessageConverter as well to carry __TypeId__ header back with the reply.
Also see Spring AMQP JSON sample for some help.

LWUIT Uncaught exception: java.lang.OutOfMemoryError(stack trace incomplete)

I developed an Rss Application using LWUIT Tabs,i want to display Rss Feed Titles and images on my Lwuit Tab screen,but when i run my application i am able to display three List (title with image)items Sucessfully,after that i am facing java.lang.OutOfMemoryError(stack trace incomplete) Eventhough there are list items present?can any one help......thanks...
Here my Code:
public class Process {
protected XMLMidlet midlet;
Form form1;
Image image;
Tabs tabs;
private List myNewsList;
private Vector topnews;
private Vector topstory;
private Command cmdExit;
private Command m_backCommand;
private List newsList;
private Form form2;
Process(XMLMidlet midlet) throws IOException {
this.midlet=midlet;
topnews = new Vector();
topstory = new Vector();
tabs = new Tabs();
form1 = new Form();
form2=new Form();
try {
newsList = new List(topnews);
newsList.setScrollVisible(false);
newsList.setRenderer(new NewsListCellRenderer());
m_backCommand = new Command("Back");
cmdExit = new Command("EXIT");
tabs.addTab("Topstory", newsList);
form1.addComponent(BorderLayout.CENTER, tabs);
}
catch(Exception e){
e.printStackTrace();
} }
public void process() {
try{
String url = "http://www.teluguone.com/news/tonefeeds/news/news-1.rss";
form1.show();
ParseThread myThread = new ParseThread(this);
myThread.getXMLFeed(url);
} catch (Exception e) {
}
}
public void addNews(News newsItem) {
try{
topnews.addElement(newsItem);
newsList.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
List source = (List) ae.getSource();
News selectedNewsItem = (News) source.getSelectedItem();
if (selectedNewsItem != null) {
displayCompleteNewsScreen(selectedNewsItem);
}
}
});
}
catch(OutOfMemoryError r){
}
form1.show();
}
private void displayCompleteNewsScreen(News detailNews) {
try{
form2.removeAll();
form2.repaint();
form2.addCommand(m_backCommand);
form2.addCommandListener(new ActionListener() {
public void actionPerformed(ActionEvent ae) {
form1.show();
}
});
HTMLComponent com=new HTMLComponent();
com.setPreferredSize(new Dimension(300,300));
com.setShowImages(false);
com.setBodyText(detailNews.getDescription());
form2.addComponent(com);
//form2.addComponent(big);
}
catch(OutOfMemoryError e){
}
form2.show();
}
}
How big are the images? What handset are we talking about here?
I am betting that the images you're getting are not being scaled down before being displayed. I believe there are methods in LWUIT to scale down the size of an image. Remember to dispose of the temp image you create after adding the image to your form.

Resources