Can anyone show me how to handle exceptions when using the .NET SDK for AWS SES?
The implementation of IAsyncResult that is returned has the Exception on it, but its internal.
Is there an alternative method for accessing this, or do I need to reflect it :(
amazonSimpleEmailServiceClient.BeginSendEmail(sendEmailRequest, ar => {
var result = ar as AsyncResult;
// result has .Exception, but its internal :(
}, null);
Thanks
The standard approach with Begin*/End* methods in the .NET AWS SDK (and .NET overall, as discussed in a bit of detail here) is to call the corresponding End* method.
amazonSimpleEmailServiceClient.BeginSendEmail(sendEmailRequest, ar =>
{
try
{
amazonSimpleEmailServiceClient.EndSendEmail(ar);
}
catch (Exception e)
{
Console.WriteLine(e);
}
}, null);
Related
There is a concept I don't really understand when looking at the sample code for Cloud Monitoring API (v3).
In all the code examples for creating an alert policy there is code that "restores" the policies first before making a new one. Also the function names for the examples isn't "creating" a policy, it's "restoring". I don't quite understand why this is needed. Is there a reason for why policies need to be "restored"? What does "restored" mean?
https://cloud.google.com/monitoring/alerts/using-alerting-api#api-create-policy
Here is one of the examples (Java)
private static void restoreRevisedPolicies(
String projectId, boolean isSameProject, List<AlertPolicy> policies) throws IOException {
try (AlertPolicyServiceClient client = AlertPolicyServiceClient.create()) {
for (AlertPolicy policy : policies) {
if (!isSameProject) {
policy = client.createAlertPolicy(ProjectName.of(projectId), policy);
} else {
try {
client.updateAlertPolicy(null, policy);
} catch (Exception e) {
policy =
client.createAlertPolicy(
ProjectName.of(projectId), policy.toBuilder().clearName().build());
}
}
System.out.println(String.format("Restored %s", policy.getName()));
}
}
}
Those are valid examples of using the "create" API call, and the "restore" function is there because the same example code is used also in the "Backup and restore" section, but this makes it no less of a valid example.
what is the best way to check whether a stack exists using the AWS Java SDK, given a stack name?
I've tried the below code based on - https://github.com/aws/aws-sdk-java/blob/master/src/samples/AwsCloudFormation/CloudFormationSample.java
DescribeStacksRequest wait = new DescribeStacksRequest();
wait.setStackName(stackName);
List<Stack> stacks = awsCFTClient.describeStacks(wait).getStacks();
if (stacks.isEmpty()) {
logger.log("NO_SUCH_STACK");
return true;
}
However, I am getting:
AmazonServiceException:com.amazonaws.services.cloudformation.model.AmazonCloudFormationException: Stack with id "stackName" does not exist.
Thanks in advance!
In case someone else is looking for a quick and dirty solution, this works,
//returns true if stack exists
public boolean stackExists(AmazonCloudFormation awsCFTClient, String stackName) throws Exception{
DescribeStacksRequest describe = new DescribeStacksRequest();
describe.setStackName(stackName);
//If stack does not exist we will get an exception with describe stack
try {
awsCFTClient.describeStacks(describe).getStacks();
} catch (Exception e) {
logger.log("Error Message: " + e.getMessage());
if (e.getMessage().matches("(.*)" + stackName + "(.*)does not exist(.*)")) {
return false;
} else {
throw e;
}
}
return true;
}
If there is a better way for doing this, please let me know.
Found a slightly better way to do it but with a few remarks:
aws java sdk 2.0 is used here https://github.com/aws/aws-sdk-java-v2
in the example below, you see kotlin syntax
client.listStacks().stackSummaries().any{ it.stackName() == stackName }
In Java you can simply replace any method anyMatch.
According to the shallow check of the former aws java sdk 1.0 there is also listStacks() method in AmazonCLoudFormationClient class which does the same.
But in my case, I needed to filter those stacks (because if the stack has status DELETED... it will still appear in the list above) based on the status. So probably overloaded method will be more useful:
#Override
public ListStacksResult listStacks(ListStacksRequest request) {
request = beforeClientExecution(request);
return executeListStacks(request);
}
I have a MVC app where I am trying to capture all the incoming requests in a ActionFilter. Here is the logging code. I am trying to log in a fire and forget model.
My issue is if I execute this code synchronously by taking out the Task.Run Elmah does send out an email. But for the code shown below I can see the error getting logged to the InMemory logger in elmah.axd but no emails.
public void Log(HttpContextBase context)
{
Task.Run(() =>
{
try
{
throw new NotImplementedException(); //simulating an error condition
using (var s = _documentStore.OpenSession())
{
s.Store(GetDataToLog(context));
s.SaveChanges();
}
}
catch (Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
}
});
}
Got this answer from Atif Aziz (ELMAH Lead contributor) on the ELMAH google group:
When you use Task.Run, the HttpContext is not transferred to the thread pool thread on which your action will execute. When ErrorSignal.FromCurrentContext is called from within your action, my guess is that it's probably failing with another exception because there is no current context. That exception is lying with the Task. If you're on .NET 4, you're lucky because you'll see the ASP.NET app crash eventually (but possibly much after the fact) when the GC will kick in and collect the Task and its exception will go “unobserved”. If you're on .NET 4.5, the policy has been changed and the exception will simply get lost. Either way, your observation will be that mailing is not working. In fact, logging won't work either unless you use Elmah.ErrorLog.GetDefault(null).Log(new Error(ex)), where a null context is allowed. But that call only logs the error but does not do any mailing. ELMAH's modules are connected to the ASP.NET context. If you detach from that context by forking to another thread, then you cannot rely on ELMAH's modules. You can only use Elmah.ErrorLog.GetDefault(null).Log(new Error(ex)) reliably to log an error.
We have a web application using Jetty 8.1, dojo, and cometd that interacts between the browser and web container using (1) a JSON/HTTP REST API for synchronous operations and (2) a cometd API to receive numerous events from the server.
What we are not entirely clear on is how to elegantly manage the authentication sessions of these two different API's especially since cometd for us will use websocket instead of regular HTTP whenever possible. The application is using form-based authentication using a standard Jetty LDAP module. So from an HTTP perspective the container provides the browser with a standard jsessionid which looks like this:
Cookie: jsessionid=758E2FAD7C199D722DA8B5E243E0E27D
Based on Simone Bordet's post here it seems the recommended solution is to pass this token during the cometd handshake which is what we are doing.
The problem we have is there are two fundamentally different sessions - the HTTP session and the Bayeux cometd session. For reasons such as potential memory leaks and security issues, we want them to terminate in unison or to be "paired." If a user's HTTP session is terminated, we want the corresponding Bayeux session to terminate as well and vis-versa. Is there a recommended way of doing this?
The HTTP session and the CometD sessions have different lifecycles: for example, if there is a temporary connection failure, the CometD session will fail, and the server will ask to the client to re-handshake, thus creating a different CometD session (representing the same user, but with a different CometD clientId). In the same case, the HttpSession will remain the same.
Having this in mind, you need to maintain - at the application level - a mapping between a username, the correspondent HttpSession, and the correspondent ServerSession.
Let's call this mapping HttpCometDMapper.
Every time a new user logs in, you register its name (or another unique identifier of the user), the HttpSession, and the current ServerSession.
Probably you will need a two step process, where you first link the username and the HttpSession, and then the same username with the ServerSession.
If a CometD re-handshake is performed, you update the mapper with the new ServerSession.
You can link the two sessions by registering an HttpSessionListener to the HttpSession so that when it's destroyed, you retrieve the current CometD ServerSession from the mapper and call ServerSession.disconnect() on it.
The viceversa is a bit trickier because CometD does not have a concept of inactivity timeout like HttpSession has. It must be implemented in the application with your own logic.
One part of doing it is to register a RemoveListener on the ServerSession, like that:
serverSession.addListener(new ServerSession.RemoveListener()
{
public void removed(ServerSession session, boolean timeout);
{
if (!timeout)
{
// Explicitly disconnected, invalidate the HttpSession
httpCometDMapper.invalidate(session);
}
}
});
This listener watches for explicit disconnects from the client (and the server - beware of reentrancy).
Slightly more difficult is to implement the same mechanism for non-explicit disconnects. In this case, the timeout parameter will be true, but could have happened because of a temporary network failure (as opposed to the client disappearing for good), and the same user may have already re-handshaken with a new ServerSession.
I think in this case an application timeout could solve the issue: when you see a ServerSession removed because of a timeout, you note that user and start an application timeout. If the same user re-handshakes, cancel the application timeout; otherwise the user is really gone, the application timeout expires, and you invalidate the HttpSession too.
What above are just ideas and suggestions; the actual implementation depends heavily on application details (and that's why is not provided by CometD out of the box).
The key points are the mapper, the HttpSessionListener and the RemoveListener, and knowing the lifecycles of those components.
Once you manage that, you can write the right code that does the right thing for your application.
Finally, note that CometD has a transport-agnostic way of interacting with the HttpSession via the BayeuxContext instance, that you can obtain from BayeuxServer.getContext().
I suggest that you look at that also, to see if it can simplify things, especially for retrieving tokens stored in the HttpSession.
Is there any problem encountered if we are going to create a BayeuxClient after the temporary connection failure?
You can try with this below code.
try {
log.info("Running streaming client example....");
makeConnect();
} catch (Exception e) {
handleException("Error while setup the salesforce connection.", e);
}
}
private void makeConnect() {
try{
client = makeClient();
client.getChannel(Channel.META_HANDSHAKE).addListener
(new ClientSessionChannel.MessageListener() {
public void onMessage(ClientSessionChannel channel, Message message) {
log.info("[CHANNEL:META_HANDSHAKE]: " + message);
boolean success = message.isSuccessful();
if (!success) {
String error = (String) message.get("error");
if (error != null) {
log.error("Error during HANDSHAKE: " + error);
}
Exception exception = (Exception) message.get("exception");
if (exception != null) {
handleException("Exception during HANDSHAKE: ", exception);
}
}
}
});
client.getChannel(Channel.META_CONNECT).addListener(
new ClientSessionChannel.MessageListener() {
public void onMessage(ClientSessionChannel channel, Message message) {
log.info("[CHANNEL:META_CONNECT]: " + message);
boolean success = message.isSuccessful();
if (!success) {
client.disconnect();
makeConnect();
String error = (String) message.get("error");
if (error != null) {
//log.error("Error during CONNECT: " + error);
}
}
}
});
client.getChannel(Channel.META_SUBSCRIBE).addListener(
new ClientSessionChannel.MessageListener() {
public void onMessage(ClientSessionChannel channel, Message message) {
log.info("[CHANNEL:META_SUBSCRIBE]: " + message);
boolean success = message.isSuccessful();
if (!success) {
String error = (String) message.get("error");
if (error != null) {
makeConnect();
log.error("Error during SUBSCRIBE: " + error);
}
}
}
});
client.handshake();
log.info("Waiting for handshake");
boolean handshaken = client.waitFor(waitTime, BayeuxClient.State.CONNECTED);
if (!handshaken) {
log.error("Failed to handshake: " + client);
}
log.info("Subscribing for channel: " + channel);
client.getChannel(channel).subscribe(new MessageListener() {
public void onMessage(ClientSessionChannel channel, Message message) {
injectSalesforceMessage(message);
}
});
log.info("Waiting for streamed data from your organization ...");
}catch (Exception e) {
handleException("Error while setup the salesforce connection.", e);
}
}
Can I just do this below? Or is there a more proper way to do it ?
ServiceReferenceSLHS.HighScoreWSClient client = new ServiceReferenceSLHS.HighScoreWSClient();
client.GetHighScoresCompleted += new EventHandler<ServiceReferenceSLHS.GetHighScoresCompletedEventArgs>(client_GetHighScoresCompleted);
try
{
client.GetHighScoresAsync();
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
Your code will only capture errors generated when calling the method GetHighScoresAsync. It's normally very unlikely that you'll have sure exceptions.
It's much more likley that you want to capture exceptions in the callback function (client_GetHighScoresCompleted).
Check the EventArgs there for errors.