Spring Cloud Stream error handling... error - spring-boot

That's not really an issue, beacause I found a workaround, but it conflicts with the documentation, so I wanted to share and document about it.
FYI Spring Boot 2.1.10 + SCSt 2.1.4 + RabbitMQ binder
I first implemented an application local error handler as given into official docs :
#StreamListener(Sink.INPUT)
public void handle(Person value) {
throw new RuntimeException("BOOM!");
}
#ServiceActivator(inputChannel = Sink.INPUT + ".my-group.errors") // won't work
public void error(ErrorMessage message) {
log.error("Handling ERROR: " + message.getPayload().getMessage());
}
spring.cloud.stream.bindings.input.destination=persons.inputs
spring.cloud.stream.bindings.input.group=my-group
But that didn't go well, to say the least. This is what I eventually had to keep:
#ServiceActivator(inputChannel = "persons.inputs.my-group.errors")
As you can see, what's happening is that I had to stick to the actual destination definition instead of the channel's; which I think is very uncomfortable! And I want to underline, again, that this is contradictory to the official docs here: https://docs.spring.io/spring-cloud-stream/docs/current/reference/htmlsingle/#_application_error_handling (plus there are noticeable typos, IMHO: they even write that the destinationName is actually required)
Can anyone share thoughts about the situation with me? Have I done it right and am I right to think that this is wrong?

It's a bug in the documentation; it is, indeed, unfortunate the binding name was not used in the error channel name instead of the destination and group, but it's too late to change it now. We could possibly do something in a future release.
Please open 2 GitHub issues to
fix the documentation
consider adding an option to name the error channel using the binding name instead.

Related

Aws integration spring: Extend Visibility Timeout

Is it possible to extend the visibility time out of a message that is in flight.
See:
http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/AboutVT.html.
Section: Changing a Message's Visibility Timeout.
http://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/services/sqs/AmazonSQSClient.html#changeMessageVisibility-com.amazonaws.services.sqs.model.ChangeMessageVisibilityRequest-
In summary I want to be able to extend the first set visibility timeout for a given message that is in flight.
Example if 15secs have passed I then want to extend the timeout by another 20secs. Better example in java docs above.
From my understanding in the links above you can do this on the amazon side.
Below are my current settings;
SqsMessageDrivenChannelAdapter adapter =
new SqsMessageDrivenChannelAdapter(queue);
adapter.setMessageDeletionPolicy(SqsMessageDeletionPolicy.ON_SUCCESS);
adapter.setMaxNumberOfMessages(1);
adapter.setSendTimeout(2000);
adapter.setVisibilityTimeout(200);
adapter.setWaitTimeOut(20);
Is it possible to extend this timeout?
Spring Cloud AWS supports this starting with Version 2.0. Injecting a Visiblity parameter in your SQS listener method does the trick:
#SqsListener(value = "my-sqs-queue")
void onMessageReceived(#Payload String payload, Visibility visibility) {
...
var extension = visibility.extend(20);
...
}
Note, that extend will work asynchronously and will return a Future. So if you want to be sure further down the processing, that the visibility of the message is really extended at the AWS side of things, either block on the Future using extension.get() or query the Future with extension.isDone()
OK. Looks like I see your point.
We can change visibility for particular message using API:
AmazonSQS.changeMessageVisibility(String queueUrl, String receiptHandle, Integer visibilityTimeout)
For this purpose in downstream flow you have to get access to (inject) AmazonSQS bean and extract special headers from the Message:
#Autowired
AmazonSQS amazonSqs;
#Autowired
ResourceIdResolver resourceIdResolver;
...
MessageHeaders headers = message.getHeaders();
DestinationResolver destinationResolver = new DynamicQueueUrlDestinationResolver(this.amazonSqs, this.resourceIdResolver);
String queueUrl = destinationResolver.resolveDestination(headers.get(AwsHeaders.QUEUE));
String receiptHandle = headers.get(AwsHeaders.RECEIPT_HANDLE);
amazonSqs.changeMessageVisibility(queueUrl, receiptHandle, YOUR_DESIRED_VISIBILITY_TIMEOUT);
But eh, I agree that we should provide something on the matter as out-of-the-box feature. That may be even something similar to QueueMessageAcknowledgment as a new header. Or even just one more changeMessageVisibility method to this one.
Please, raise a GH issue for Spring Cloud AWS project on the matter with link to this SO topic.

Joomla 3.0 generic database error handling

Going from Joomla 2.5 to 3.0 with my extension, I'm struggling with how to do the DB error handling (since GetErrorNum is deprecated, see also Joomla! JDatabase::getErrorNum() is deprecated, use exception handling instead).
The way that seems to be the one to go according to the question linked above, is to add the following code for each db->query() code:
if (!$db->query()) {
throw new Exception($db->getErrorMsg());
}
In my opinion, that makes DB error handling more awkward than it was before. So far, I simply called a checkDBError() function after a DB call, which queried the ErrorNum and handled any possible error accordingly.
That was independent from how the DB query was actually triggered - there are different ways to do that, and different results on an error: $db->loadResult() returns null on error, $db->query() returns false. So there will now be different checks for different DB access types.
Isn't there any generic way to handle this, e.g. a way to tell Joomla to throw some exception on DB problems? Or do I have to write my own wrapper around the DatabaseDriver to achieve that? Or am I maybe missing something obvious?
Or should I just ignore the deprecation warning for now and continue with using getErrorNum()? I'd like to make my extension future-proof, but I also don't want to clutter it too much with awkward error handling logic.
Just found this discussion: https://groups.google.com/forum/#!msg/joomla-dev-general/O-Hp0L6UGcM/XuWLqu2vhzcJ
As I interpret it, there is that deprecation warning, but there is no proper replacement yet anyway...
Unless somebody points out any other proper documentation of how to do it in 3.0, I will keep to the getErrorNum method of doing stuff...
Get getErrorNum() function will solve your problem....
$result = $db->loadResult();
// Check for a database error.
if ($db->getErrorNum())
{
JFactory::getApplication()->enqueueMessage($db->getErrorMsg());
return false;
}

Avoiding javax.el.PropertyNotFoundException for resource bundle lookups in jsf 2.1 + spring 3

We have defined properties in several resource bundles, which are configured in the faces-config.xml
<resource-bundle>
<base-name>webMessages</base-name>
<var>feBundle</var>
</resource-bundle>
We then try to access a property which is not defined.
<tag infoText="#{feBundle['insurance.comparison.household.details.aicraftCrash.tooltip']}"
/>
If the property is not available a javax.el.PropertyNotFoundException is thrown and causes the faces servlet to render a blank page. From the documentation of the ResourceBundleELResolver this should not happen, as it does not throw this exception. I can see it is part of the resolvers of the DemuxCompositeELResolver.But it seems it is never called. Instead the MapELResolver (which is placed after the RBELResolver in the list of resolvers) is called and throws an exception. I can't really make something of that behaviour and debugging is tedious. There must be some way to get around this. A missing property can not break my whole page rendering process. Any ideas?
Note: This is an issue only with the javax.el library as provided with tomcat > 6 distributions
I investigated the issue a bit further and found that it is caused by the implementation of javax.el package in the tomcat distribution. So the described behaviuor only occurs when using tomcat > 6. I filed a bug report in their bug tracking tool already although one can argue that it is not a real bug but a sort of wanted (but, IMHO, ugly) behaviour. I also found a solution for jsf.
Subclass the
ResourceBundleELResolver and override its getValue(...) method. Change it such
that it sets the PropertyResolved attribute to true before any exception might
occur.
if (base instanceof ResourceBundle) {
if (property != null) {
try {
context.setPropertyResolved(true);
Object result = ((ResourceBundle) base).getObject(property
.toString());
return result;
} catch (MissingResourceException mre) {
System.out.println("Missing property: " + property);
return "?" + property.toString() + "?";
}
}
}
Register this custom resolver in the faces-config.xml with
<el-resolver>your.package.TheResolverImplementation</el-resolver>
And the link to the bug report https://issues.apache.org/bugzilla/show_bug.cgi?id=53001

How does someone use Guava's CacheLoader asynchronously

The question says it all I'd like to use CacheBuilder, but my values are pulled in asynchronously. This worked previously with MapMaker as the CacheLoader wasn't a requirement. Now I'd like to know if I can hack this up or if there are any non deprecated alternatives. Thank you.
I think the question you're trying to ask is "How can I use CacheBuilder without having to specify a CacheLoader?" If that's the case, then there will be support for this in Guava release 11.0. In the meantime a build() method on CacheLoader is already checked into trunk (as of this morning):
http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/cache/CacheBuilder.html
One method would be to make with generic parameters K and V as your desired outputs:
LoadingCache<K, ListenableFuture<V>> values = CacheBuilder.newBuilder()
.build(
new CacheLoader<K, ListenableFuture<V>>() {
public ListenableFuture<V> load(K key) {
/* Get your future */
}
});

Do you know how to implement transactions in Castle ActiveRecord?

I decided to make a system for a client using Castle ActiveRecord, everything went well until I found that the transactions do not work, for instance;
TransactionScope t = new TransactionScope();
try
{
member.Save();
//This is just to see transaction working
throw new Exception("Exception");
foreach (qfh.Beneficiary b1 in l)
{
b1.Create();
}
}
catch (Exception ex)
{
t.VoteRollBack();
MessageBox.Show(ex.Message);
}
finally
{
t.Dispose();
}
But it doesn't work, I throw an Exception just to try the transaction rolls back, but for my surprise I see that the first [Save] records into the database. What is happening?
I'm new on Castle and NHibernate, firstly I saw it very attractive and I decided to go on with it and MySQL (I've never worked with this DB), I tried ActiveWriter and it seemed very promising but after a long and effortly week I see this issue and now I feel like I'm stuck and like I've wasted my time. It is supposed to be easy but right now I'm feeling a frustated cause I cannot find enough information to make this workout, can you help me?
You need to wrap the code in a session scope, like this:
using(new SessionScope())
{
a.Save();
b.Save();
c.Save();
}
Read more here.
Ben's got it. That doc is a little confusing. Refer to the last block on the page, "Nested transactions".
I finally fixed, it happened that I was doing wrong, I overrode the Save method of the Member class and made sessionScope inside and inside of it a transaction scope, so when a involved all of that in a transaction scope it saved in the database, so when I threw the exception everything was already saved, I think that's it.
All in all, thanks for the help.

Resources