How I can set timer on a single line code in java - java

My requirements is.. I want to set a timer on a single line code in java. If time exceeded then it will throw a timeout exception and it will start to execute that single line code into a different thread.
Here is my code
public Object ShootSMTPMail(String subject,String body,Session session,SMTPServerInfo smtpserverInfo,InternetAddress[] mailAddress_TO) throws Exception
{
try
{
Message message = new MimeMessage(session);
message.setFrom(new InternetAddress(smtpserverInfo.SMTPUsername));
message.setRecipients(Message.RecipientType.TO, mailAddress_TO);
message.setSubject(subject);
message.setContent(body, "text/html");
Transport.send(message);// I want to set a timer on this line;
return true;
}
catch(Exception e)
{
throw e;
}
finally
{
}
}
Basically here I am sending emails through Transport.send(), and this statement taking some time to execute, So I want to throw a timeout exception to the font end and want to show the user that it will take some times to execute. and meanwhile I want to execute Transport.send(message); this line in different thread and when I will receive response from Transport.send(message); this execution I will send it to font end. Actually I want make this whole process asynchronous. Please help me..

In java things like that are usually implemented as a service with internal pool of threads.
Something like that:
public class EmailSenderService {
private ExecutorService threadPool = Executors.new***Pool();
public Future<?> send(Message message) {
return threadPool.submit(() -> Transport.send(message));
}
public void shutDownService() {
threadPool.shutdownNow();
...
}
}
Here Transport.send(message) is executing asynchronously in another thread, while the Future instance returned by send() allows the caller to check if the task has finished, to cancel the task, etc.

Related

How to handle lots of messages being sent from android service?

I am developing an app that communicates using the MAVLINK protocol. I am using dronefleet for this purpose. My app has a service which runs a ReadThread that checks the incoming MAVLINK messages for their type. ReadThread then sends messages to the UI for updating some TextViews with the drone's information like battery status, etc. Here is my code.
ReadThread in DService.java
import io.dronefleet.mavlink.MavlinkMessage;
import io.dronefleet.mavlink.common.Attitude;
import io.dronefleet.mavlink.common.SysStatus;
public static final int ATTITUDE = 1;
public static final int SYS_STATUS = 2;
private class ReadThread extends Thread {
private AtomicBoolean keep = new AtomicBoolean(true);
#Override
public void run() {
while(keep.get()){
if(inputStream == null)
return;
MavlinkMessage message;
try {
---------------------get MAVLINK message from stream here---------------
message = mavlinkConnection.next();
-------------------check MAVLINK message type and then send message to UI for updating related fields--------------------
if(message.getPayload() instanceof Attitude) {
MavlinkMessage<Attitude> attitudeMessage = (MavlinkMessage<Attitude>)message;
myHandler.obtainMessage(ATTITUDE, attitudeMessage).sendToTarget();
}
----------------removing comments causes app to crash---------------------
/*if(message.getPayload() instanceof SysStatus) {
MavlinkMessage<SysStatus> sysStatusMessage = (MavlinkMessage<SysStatus>)message;
int battery = sysStatusMessage.getPayload().batteryRemaining();
myHandler.obtainMessage(SYS_STATUS, Integer.toString(battery)).sendToTarget();*/
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void setKeep(boolean keep) {
this.keep.set(keep);
}
}
handleMessage() in MainActivity.java
switch (msg.what) {
case DService.SYS_STATUS:
String battery = (String) msg.obj + "%";
myActivity.get().batteryView.setText(battery);
case DService.ATTITUDE:
MavlinkMessage<Attitude> message = (MavlinkMessage<Attitude>) msg.obj;
String pitch = Float.toString(message.getPayload().pitch());
String roll = Float.toString(message.getPayload().roll());
String yaw = Float.toString(message.getPayload().yaw());
myActivity.get().pitchView.setText(pitch);
myActivity.get().rollView.setText(roll);
myActivity.get().yawView.setText(yaw);
break;
}
}
My problem is my app is crashing if I am checking for more than one type of MAVLINK message in my ReadThread. If I check for (say) either SYS_STATUS or ATTITUDE, then the corresponding TextViewss in the UI are getting updated seamlessly every second (which is the rate of messages sent by MAVLINK). But not for 2 message classes. If I remove comments from one if block, my app crashes.
Whats could be the reason? Is my handleMessage() wrong? Do I need to use MessageQueue or some other android mechanism? Should I run separate threads like ReadThread for each MAVLINK message type?
I am developing on Ubuntu 18, and using Android Studio.
Does logcat have any exceptions being thrown by your program before it crashes?
I would not use multiple threads for each MAVLink message type's handlemessage because I'm guessing the dronefleet parser for the MAVLink connection is stateful (MAVLink uses a magic prefix and payload length to delimit packets) and it would probably either break or be nearly synchronous if called from multiple threads.
If you're worried that you might be sending updates too frequently you could have the read thread store the values from the different MAVLink messages and a separate thread send updates at a fixed interval based on either the latest value for each message or on the set of messages received since the last update.

How do I send a message directly to a parking lot queue, prevent requeue and exit the program flow?

I currently have 4 queues:
test-queue
test-queue-short-term-dead-letter
test-queue-long-term-dead-letter
test-queue-parking-lot
When a message comes into test-queue, I do a check to see if the message is in the correct format. If it isn't I want to send the message directly to the parking lot queue.
I can't use AmqpRejectAndDontRequeue() because it will automatically send the message to the configured DLQ (test-queue-short-term-dead-letter).
Using RabbitTemplate.convertAndSend() with another exception such as BadRequestException doesn't work. The message goes to the parking lot queue as expected, however the same message will stay in the test-queue
Using RabbitTemplate.convertAndSend() on it's own won't work as the program continues execution.
All queues are bound to a single direct exchange, each with unique routing keys. The test-queue is configured with the following arguments:
x-dead-letter-exchange: ""
x-dead-letter-routing-key: <shortTermDeadLetterKey>
Receiver:
#RabbitListener(queues = "test-queue")
public void receiveMessage(byte[] person) {
String personString = new String(person);
if (!personString.matches(desiredRegex)) {
rabbitTemplate.convertAndSend("test-exchange", "test-queue-parking-lot",
"invalid person");
log.info("Invalid person");
}
...some other code which I dont want to run as the message has arrived in the incorrect format
}
The problem was solved by manually acknowledging the message and returning from the method.
#RabbitListener(queues = "test-queue")
public void receiveMessage(byte[] person, Channel channel,
#Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception) {
String personString = new String(person);
if (!personString.matches(desiredRegex)) {
rabbitTemplate.convertAndSend("test-exchange", "test-queue-parking-lot",
"invalid person");
log.info("Invalid person");
channel.basicAck(tag, false);
return;
}
...some other code which I dont want to run as the message has arrived in the incorrect format
}

How to receive message from wildfly jms queue using consumer

I encountered a knotty problem when receiving message from WildFly JMS queue. My code is below:
Session produceSession = connectionFactory.createConnection().createSession(false, Session
.CLIENT_ACKNOWLEDGE);
Session consumerSession = connectionFactory.createConnection().createSession(false, Session
.CLIENT_ACKNOWLEDGE);
ApsSchedule apsSchedule = new ApsSchedule();
boolean success;
MessageProducer messageProducer = produceSession.createProducer(outQueueMaxusOrder);
success = apsSchedule.sendD90Order(produceSession,messageProducer, d90OrderAps);
if (!success) {
logger.error("Can't send APS schedule msg ");
} else {
MessageConsumer consumer = consumerSession.createConsumer(inQueueDeliveryDate);
data = apsSchedule.receiveD90Result(consumerSession,consumer);
}
then getting into the receiveD90Result():
public DeliveryData receiveD90Result(Session session, MessageConsumer consumer) {
DeliveryData data = null;
try {
Message message = consumer.receive(10000);
if (message == null) {
return null;
}
TextMessage msg = (TextMessage) message;
String text = msg.getText();
logger.debug("Receive APS d90 result: {}", text);
ObjectMapper mapper = new ObjectMapper();
data = mapper.readValue(text, DeliveryData.class);
} catch (JMSException je) {
logger.error("Can't receive APS d90 order result: {}", je.getMessage());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
consumer.close();
} catch (JMSException e) {
e.printStackTrace();
}
}
return data;
}
But when implementing the consumer.receive(10000), the project can't get a message from queue. If I use asynchronous way of MDB to listen the queue, I can get the message from queue. How to resolve it?
There are multiple modes you can choose to get a message from the queue. Message Queues are by default asynchronous in usage. There are however cases when you want to read it synchronously , for example sending a message with account number and using another queue to read the response and match it with a message id or a message correlation id. When you do a receive , the program is waiting for a message to arrive within that polling interval specified in receive.
The code snippet you have , as i see it uses the psuedo synchronous approach. If you have to use it as an MDB , you will have to implement message driven bean (EJB Resource) or message listener.
The way that MDB/Message Listener works is more event based , instead of a poll with a timeout (like the receive) , you implement a callback called onMessage() that is invoked every time there is a message. Instead of a synchronous call , this becomes asynchronous. Your application may require some changes both in terms of design.
I don't see where you're calling javax.jms.Connection.start(). In fact, it doesn't look like you even have a reference to the javax.jms.Connection instance used for your javax.jms.MessageConsumer. If you don't have a reference to the javax.jms.Connection then you can't invoke start() and you can't invoke close() when you're done so you'll be leaking connections.
Furthermore, connections are "heavy" objects and are meant to be re-used. You should create a single connection for both the producer and consumer. Also, if your application is not going to use the javax.jms.Session from multiple threads then you don't need multiple sessions either.

Apache HttpAsyncClient response not received

In my servlet, I am executing the following code:
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(3000).setConnectTimeout(3000).build();
CloseableHttpAsyncClient client = HttpAsyncClients.custom().setDefaultRequestConfig(requestConfig).build();
try
{
client.start();
for (String request : preparedURLs)
{
client.execute(new HttpGet(request), new FutureCallback<HttpResponse>()
{
public void failed(Exception ex)
{
System.out.println("\n\nRequest Failed Due to : " + ex.getMessage());
}
public void completed(HttpResponse response)
{
System.out.println("\n\nRequest COMPLETED");
}
public void cancelled()
{
System.out.println("\n\nRequest CANCELLED");
}
});
System.out.println("\n\n" + request);
}
}
finally
{
System.out.println("\n*** Finally called ***\n\n");
client.close();
}
But I don't get any response at all. Following is printed in my catalina.out:
http://localhost:8080/servlet/?ps=true
http://localhost:8080/servlet/?ps=true
http://localhost:8080/servlet/?ps=false
*** Finally called ***
I have wrote this code, taking this as example from apache's official site.
I have only omitted the latch part. Is this some thing to do with latch?
If possible please explain the reason of failure too.
This latch that you have removed is actually the synchronization part of the example.
The idea of async client is to make some requests and wait for the responses on other thread. By removing the synchronization the execution directly passes to the finally block instead of waiting the responses and closes the HttpAsyncClient.
In order to get it back working add the latch code from the example.
This is the correct behaviour. You are creating a socket with a conditional Future, and then you proceed to close it without waiting for it.
The example code you linked use a "latch" variable to do so.
You may move the close code inside future callback, but probably this will confuse your waring.
Or you can use the same system of the example, with a shared synchronised counter (maybe just a final AtomicBoolean triggered by an aswer) and wait for it before continuing with your program flow, but that destroy the idea of using async call

ActiveMQ register listener to StompConnection

I'm using a variation of the example at http://svn.apache.org/repos/asf/activemq/trunk/assembly/src/release/example/src/StompExample.java to receive message from a queue. What I'm trying to do is to keep listening to a queue and perform some action upon reception of a new message. The problem is that I couldn't find a way to register a listener to any of the related objects. I've tried something like:
public static void main(String args[]) throws Exception {
StompConnection connection = null;
try {
connection = new StompConnection();
connection.open("localhost", 61613);
connection.connect("admin", "activemq");
connection.subscribe("/queue/worker", Subscribe.AckModeValues.AUTO);
while (true) {
StompFrame message = connection.receive();
System.out.println(message.getBody());
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
but this doesn't work as a time out occurs after a few seconds (java.net.SocketTimeoutException: Read timed out). Is there anything I can do to indefinitely listen to this queue?
ActiveMQ's StompConnection class is a relatively primitive STOMP client. Its not capable of async callbacks on Message or for indefinite waits. You can pass a timeout to receive but depending on whether you are using STOMP v1.1 it could still timeout early if a heart-beat isn't received in time. You can of course always catch the timeout exception and try again.
For STOMP via Java you're better off using StompJMS or the like which behaves like a real JMS client and allows for async Message receipt.
#Tim Bish: I tried StompJMS, but couldn't find any example that I could use (maybe you can provide a link). I 'fixed' the problem by setting the timeout to 0 which seems to be blocking.
even i was facing the same issue.. you can fix this by adding time out to your receive() method.
Declare a long type variable.
long waitTimeOut = 5000; //this is 5 seconds
now modify your receive function like below.
StompFrame message = connection.receive(waitTimeOut);
This will definitely work.

Categories