Rabbit Template back off policy with automatic recovery disabled - spring-rabbit

I've configured the CachingConnectionFactory with automatic recovery enabled set to false and assigned it to rabbit template preliminary set back off policy to it. However when I break a rabbit connection before publishing a message to rabbit seems like back off policy doesn't work and the exception is immediately thrown out. Why its not working as expected and thrown without 5s delay.
one more thing is it possible to apply back off policy to connection factory itself in order to enable auto recovery policy without fear of getting errors each 5s in the logs?
Caused by: java.net.SocketException: Broken pipe (Write failed)
#Bean
public CachingConnectionFactory connectionFactory() {
ConnectionFactory factory = new ConnectionFactory();
factory.setPassword(password);
factory.setRequestedHeartbeat(requestedHeartbeat);
factory.setAutomaticRecoveryEnabled(false);
CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory(factory);
cachingConnectionFactory.setAddress(address1 + ", " + address2);
return cachingConnectionFactory;
}
#Bean
public RabbitTemplate rabbitTemplate() {
ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
backOffPolicy.setInitialInterval(500);
backOffPolicy.setMultiplier(10);
backOffPolicy.setMaxInterval(10000);
RetryTemplate retryTemplate = new RetryTemplate();
retryTemplate.setBackOffPolicy(backOffPolicy);
RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory());
rabbitTemplate.setRetryTemplate(retryTemplate);
return rabbitTemplate;
}

Related

JAX WS multiple requests management

I'm starting studying java web services with JAX WS. The first chapter of the book I'm reading shows how to build and deploy a simple jax ws web service using only java SE. In particular, the web service is published through the Endpoint class. After publishing the web service, the author specifies that "Out of the box, the Endpoint publisher handles one client request at a
time ... if the processing of a given request should hang, then
all other client requests are effectively blocked. An example at the end
of this chapter shows how Endpoint can handle requests concurrently
so that one hung request does not block the others."
To see this, I tried to send two requests to a web service with 2 threads. Here is the code:
#WebService(endpointInterface = "ProveVelociJava.WS.MyWsWithJavaSE.SayHello")
public class SayHelloImpl implements SayHello {
public String greetings(String param) {
System.out.println("\nStarting " + param + "...\n");
if(param.equals("miao")) {
try {
Thread.sleep(9000);
}
catch(Exception e) {}
}
System.out.println("Ended " + param + "\n\n");
return "Hi, " + param;
}
}
public class SayHelloPublisher {
public static void main(String[ ] args) {
// 1st argument is the publication URL
// 2nd argument is an SIB instance
Endpoint.publish("http://127.0.0.1:9899/say", new SayHelloImpl());
}
}
class MyClient extends Thread {
private static URL url;
private static QName qname;
private static Service service;
private static SayHello eif;
static {
try {
url = new URL("http://127.0.0.1:9899/say?wsdl");
qname = new QName("http://MyWsWithJavaSE.WS.ProveVelociJava/", "SayHelloImplService");
service = Service.create(MyClient.url, MyClient.qname);
// Extract the endpoint interface, the service "port".
eif = service.getPort(SayHello.class);
}
catch(Exception e) {}
}
private String name;
public MyClient(String n) {
name = n;
}
public void run() {
System.out.println(MyClient.eif.greetings(this.name));
}
public static void main(String args[ ]) throws Exception {
MyClient t1 = new MyClient("miao");
MyClient t2 = new MyClient("bau");
t1.start();
t2.start();
}
}
If I start MyClient class, the thread called "miao" sends its request and then goes to sleep. However, the thread called "bau" does not wait for the previous thread and its request is immediately satisfied.
Am I missing something? Can java threads be used to simulate multiple requests?
Thanks a lot for your help,
Nico.
I downloaded JAX-WS 2.0 specification and it disproves what the book I'm reading says:
"An endpoint consists of an object that acts as the Web service
implementation (called here implementor) plus some configuration
information ... An Endpoint will be typically invoked to serve
concurrent requests, so its implementor should be written so as to
support multiple threads. The synchronized keyword may be used as
usual to control access to critical sections of code. For finer
control over the threads used to dispatch incoming requests, an
application can directly set the executor to be used"
(http://jcp.org/aboutJava/communityprocess/final/jsr224/index.html, section 5.2.2 "Publishing", page 67)
The book speaks about JAX-WS 2.1 but I didn't manage to download that version of the specification. Anyway, JAX-WS 2.2 specification (current version) confirms the concurrent nature of the Endpoint class (it contains the same sentences as above).
I don't know what the author of the book means exactly.
By default Endpoint handles multiple requests at the same time, and create separate thread for every new concurrent request. You can insert following line into your WebMethod implementation, to see thread id:
System.out.println(Thread.currentThread().toString());
If you request one-by-one this will print the same thread info, because terminated thread will be reused in next http request. But if you make multiple requests at the same time then you will see that different threads will be calling your webmethod.
One request will not block any other concurrent one as long your webmethod does not have synchronized blocks, whole webmethod is not synchronized or you are using some kind semaphores.
Its late but might help.
Endpoint.publish(Url, ServiceImplObj) publishes a webservice at a given url.
The no. of threads assigned for request handling truly is under control of the jvm because this is a light weight deployment which is handled by jvm itself.
For better clarification you can print the current thread name at service side and you can see that the service threads are being assigned from a thread pool which is managed by jvm.
[pool-1-thread-1]: Response[57]:
[pool-1-thread-5]: Response[58]:
[pool-1-thread-4]: Response[59]:
[pool-1-thread-3]: Response[60]:
[pool-1-thread-6]: Response[61]:
[pool-1-thread-6]: Response[62]:

IPC windows service windows forms

I have an IPC problem. I have created into a windows service a NamedPipeServer:
serverPipe = new NamedPipeServerStream(Constants.PIPE_NAME, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous);
Thread thread = new Thread(new ThreadStart(pipeWork));
thread.Start();
where pipeWork is
private static void pipeWork()
{
try
{
byte[] buffer = new byte[1024];
while (true)
{
if (!serverPipe.IsConnected)
serverPipe.WaitForConnection();
int nr = serverPipe.Read(buffer, 0, buffer.Length);
String str=Encoding.Default.GetString(buffer);
…
}
}
catch (Exception ex)
{
}
}
and into a Windows forms I have the client
clientPipe = new NamedPipeClientStream(".", PhotoServiceClassLibrary.Constants.PIPE_NAME, PipeDirection.InOut,PipeOptions.Asynchronous);
clientPipe.Connect();
clientPipe.ReadMode = PipeTransmissionMode.Message;
pipeThread=new Thread(new ThreadStart(pipeWork));
pipeThread.Start();
where pipeWork is
private void pipeWork()
{
try
{
while (true)
{
using (StreamReader sr = new StreamReader(clientPipe))
{
string message;
while ((message = sr.ReadLine()) != null)
{
…
}
}
}
}
catch (Exception ex)
{
}
}
I want when the service begin an action to disable a ContextMenuStrip from the windows forms, for that the service writes a message into a StreamWriter sw:
StreamWriter write = null;
write = new StreamWriter(serverPipe);
if (serverPipe.IsConnected)
{
write.Write(message);
write.Flush();
}
The code is correct because I created for testing another windows forms which implements the same things like the windows service and the communication between
windows forms pipe server -> windows forms pipe client is working well.
The problem is that the windows form - client pipe doesn't receive the message from windows service - server pipe.
I know that WCF can be a better idea but i want to understand why is not working at low-level IPC. Why? I've seen an very strange behavior. My service interact 2 times with the windows forms:
1.My service is designed for downloading some photos. When he begin download he sends a message to the windows forms to announcing him that.
2.When i stop the service he sends a message to windows forms and he stops also.
i've just discovered that both messages arrive at windows agent only after the service is stoped. Can someone explain why?
I hope this isn't your real code. It's good that you've got try/catch blocks around the code of your ThreadStart handlers (otherwise an exception would just quietly delete the thread). However, if you're not logging the exception in the catch block, then it's really just as bad.
You've got a mystery (server doesn't receive message), and you're hiding information (an exception has occurred). If you weren't hiding information, you might have the answer for your mystery (server doesn't receive message because an exception has occurred).
I'm trying to implement the same thing.
I noticed you're passing the PipeTransmissionMode.Message enumeration in the NamedPipeServerStream (serverPipe) constructor. That means the stream will contain strings.
But in pipeWork, you're reading them in as an array of bytes.
Look in the example in this article on MSDN:
http://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeclientstream.aspx

Messages marked as Deferred when consuming Azure Service Bus messages with Spring JMS and qpid

I can receive messages from my service bus subscription just fine, but when an exception occurs in my listener, it appears that ultimately a Disposition frame with state=Modified and undeliverableHere=true is sent to service bus. The docs for service bus say that it doesn't support the amqp Modified disposition.
The message ends up with a Deferred state in service bus, and I can't figure out how to nudge the message back into activity.
JMS Config:
#Bean
public ConnectionFactory jmsConnectionFactory(MessageStoreProperties properties) throws UnsupportedEncodingException {
JmsConnectionFactory connectionFactory = new JmsConnectionFactory(properties.getUrlString());
connectionFactory.setClientID(clientId);
connectionFactory.setUsername(properties.getUsername());
connectionFactory.setPassword(properties.getPassword());
connectionFactory.setRedeliveryPolicy(redeliveryPolicy());
return new CachingConnectionFactory(connectionFactory);
}
#Bean
public JmsDefaultRedeliveryPolicy redeliveryPolicy() {
JmsDefaultRedeliveryPolicy policy = new JmsDefaultRedeliveryPolicy();
policy.setMaxRedeliveries(50);
return policy;
}
#Bean
public JmsListenerContainerFactory topicContainerFactory(ConnectionFactory connectionFactory) {
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
factory.setSubscriptionDurable(true);
factory.setPubSubDomain(true);
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
return factory;
}
Listener:
#JmsListener(destination = "crm-customer-event/subscriptions/test-sub", containerFactory = "topicContainerFactory")
public void receiveCustomerEvent(#Payload ExecutionContextDTO dto) {
logger.debug("Got payload: " + dto);
throw new RuntimeException("Oops");
}
Here's what I'm seeing in the logs:
Message transfer starts
[299309872:1] <- Transfer{handle=0, deliveryId=0, deliveryTag=\x97\x1c\x87\x04\xb7\xea\x86#\xb3n\xbd\x9fg\x81\x00\x11, messageFormat=0, settled=null, more=false, rcvSettleMode=null, state=null, resume=false, aborted=false, batchable=true} (16695) "\x00Sp\xc0\x0a\x05##p.........
Exception is thrown, then JMS redelivers the message locally 50 times (why does it do this?)
The next amqp protocol frame I see after that is
[299309872:1] -> Disposition{role=RECEIVER, first=0, last=0, settled=true, state=Modified{deliveryFailed=true, undeliverableHere=true, messageAnnotations=null}, batchable=false}
It appears to me that this last Disposition frame causes the message to enter the Deferred state. There's also still a lock token on the message. Even when the TTL passes, the message is still stuck in the subscription and no amount of poking at it through the REST api helps. I've tried unlocking it (with PUT) and deleting it (with DELETE). I've also tried just receiving it with the REST api (both PeekLock and receive and delete varieties) and it just looks like they aren't there. I have the option set on the subscription to auto-move the messages to the dead letter queue after expiration, and they are never moved.
The code from qpid-jms that makes the ack happen is here, and it appears that this part of the library is not meant to be extended, otherwise I'd make my own implementation that returns a different ack.
How do I get qpid/JMS to
Use the FAILED ack instead of the MODIFIED_FAILED_UNDELIVERABLE ack
Clear out those Deferred messages.
First, the JMS specification rightly states that it is really an application programming error for an exception to be thrown from the MessageListener callback, your application should be handling these error itself.
Second, The client is using a correct disposition to indicate that the message failed to be delivered to this client, the remote should support all the dispositions outlined in the AMQP 1.0 specification, I'd contact Microsoft and request they implement the specification more closely.
To work around both the above you can receive messages in Client Acknowledge mode and when you intercept the exception that is being thrown you can configure the Message acknowledgement using the mechanisms described in this JIRA Issue.
The code would look something like the following:
message.setIntProperty("JMS_AMQP_ACK_TYPE", 2);
message.acknowledge();
Where the modes are defined as:
ACCEPTED = 1;
REJECTED = 2;
RELEASED = 3;
MODIFIED_FAILED = 4;
MODIFIED_FAILED_UNDELIVERABLE = 5;

Verticles and uncaught exceptions

Considering the scenario that one of the verticles throws an uncaught exception.
What happens next?
If the verticle state is removed from the system is there some mechanism similar to erlang supervisors to restart the verticle?
Documentation is not very clear about this aspect.
Update based on comments:
What interest me the most is the situation when an exception is thrown from the processing handlers of a received message (through the bus)
Regards
Vert.x is all about the same style, asynchronous programming, which is mainly highlighted by callback handlers.
To handle the deployment failure case, you have first to go the programmatic way, i.e. you have to deploy your verticle programmatically through let's say a deployment verticle providing a completion handler that will be populated with deployment result, here down a sample using Java (since your haven't opt for a specific language, I will go with my best) where:
MainVerticle: is your deployment verticle (used mainly to deploy other verticles)
some.package.MyVerticle: is your real verticle, note that I used the id here and not an instance.
public class MainVerticle extends AbstractVerticle {
public void start() {
vertx.deployVerticle("some.package.MyVerticle", res -> {
if (res.succeeded()) {
// Do whatever if deployment succeeded
} else {
// Handle deployment failure here...
}
});
}
}
Now when it comes to 'messaging failures', it would be harder to highlight a specific case since it can occur at many places and on behalf of both messaging ends.
If you want to register a failure case handler when sending a message, you can instantiate a MessageProducer<T> representing the stream it can be written to, then register an exception handler on it:
EventBus eb = vertx.eventBus();
MessageProducer<String> sender = eb.sender("someAddress");
sender.exceptionHandler(e -> {
System.out.println("An error occured" + e.getCause());
});
sender.write("Hello...");
On the other side, you can handle failure case when reading the received messages pretty much the same way, but using a MessageConsumer<T> this time:
EventBus eb = vertx.eventBus();
MessageConsumer<String> receiver = eb.consumer("someAddress");
receiver.exceptionHandler(e -> {
System.out.println("An error occured while readeing data" + e.getCause());
}).handler(msg -> {
System.out.println("A message has been received: " + msg.body());
});
I have answered part of my own question (with the help of a test program)
When exception is thrown in a event handler then the exception is caught by vert.x and swallowed (ignored). The event handler will process the next message.
Update: The app can register an exception handler and have all the uncaught Throwable delivered to this handler. There you can perform additional general processing
To add a bit to the previous answer, if you want to react to all uncaught exceptions, register handler on vertx object, as follows:
vertx.exceptionHandler(new Handler<Throwable>() {
#Override
public void handle(Throwable event) {
// do what you meant to do on uncaught exception, e.g.:
System.err.println("Error");
someLogger.error(event + " throws exception: " + event.getStackTrace());
}
});
I ran into something similar to this. When an exception happens as part of processing a message in a Verticle, I just wanted to reply with the Exception.
The idea is to just bubble up the exceptions all the way back to the entry point in the app where a decision can be made about what to do with the failure, while capturing the entire stack along the way.
To accomplish it I wrote this function:
protected ReplyException buildReplyException(Throwable cause, String message)
{
ReplyException ex = new ReplyException(ReplyFailure.RECIPIENT_FAILURE, -1, message);
ex.initCause(cause);
return ex;
}
Which I then use to build handlers, or reply handlers, like this:
reply -> {
if (reply.succeeded()) {
message.reply(true);
} else {
message.reply(buildReplyException(reply.cause(), ""));
}
});
This way the guy that sent the original message will get a failed response which contains a cause that's an exception which has a full stack trace populated on it.
This approach worked very well for me to handle errors while processing messages.

I don't know where to catch this error: Access to the port is denied

I'm using a serial port with a Serial Object and sometimes I get this error.
UnauthorizedAccessException: Access to the port is denied.
with a stack trace of:
at System.IO.Ports.InternalResources.WinIOError(Int32 errorCode, String str)
at System.IO.Ports.InternalResources.WinIOError()
at System.IO.Ports.SerialStream.Dispose(Boolean disposing)
at System.IO.Ports.SerialStream.Finalize()
It doesn't occur at any line of code (within my code at least) so I'm not sure how to trap it. I figure what is happening is the serial (via USB) port is being physically unplugged/disconnected for a split second and is throwing everything into whack.
I can click Continue on the error which I'm debugging and everything is fine. Communication with the serial device is flawless otherwise. But when the program is actually published, deployed and running it gives me several error messages and is all ugly for the user.
How can I trap this error/what can I do to prevent it in the first place?
Thanks
I encounter the same exception and stack trace in my WinForms application when used with a USB-to-serial converter. I can consistently recreate it by
creating an instance of SerialPort
calling SerialPort.Open,
removing the USB-to-serial converter,
closing the app (which calls SerialPort.Dispose)
My suspicion is that the exception is being thrown in SerialPort's finalizer.
Others have experienced the same symptoms - see here.
To work around I followed the recommendation of Kuno and KyferEz (from link above) to implement my own ExtSerialPort. This inherits SerialPort, overrides the Dispose method and (using reflection) disposes the SerialPort's internalSerialStream.
Imports System.IO.Ports
Public Class ExtSerialPort
Inherits SerialPort
Public Sub New()
MyBase.new()
End Sub
Public Sub New(ByVal portName As String)
MyBase.New(portName)
End Sub
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Dim mytype As Type = GetType(SerialPort)
Dim field As Reflection.FieldInfo = mytype.GetField("internalSerialStream", Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
Dim stream As Object = field.GetValue(Me)
If stream IsNot Nothing Then
Try
stream.Dispose()
Catch ex As Exception
End Try
End If
MyBase.Dispose(disposing)
End Sub
End Class

Resources