EXECABORT Transaction discarded because of previous error - redis

I am trying to use redis cache with spring MVC but the issue I am getting when I try to use #Cacheable over the controller method. It gives me the above error. I looked at various articles it suggests some command issue. But via Java code we are just annotating it with #Cacheable. can anyone help on this please?
spring data redis 1.4.1.RELEASE
JEDIS 2.6.1
Controller->
#Cacheable("testRedis")
#RequestMapping(value = "/testCache", method = RequestMethod.GET, produces = { "application/json",
"application/xml" })
public String test(#RequestParam(value = "message", required = false) String message) throws Exception {
return "from method---"+message;
}

Related

got 'CancellationException: Request execution cancelled' always when throwing an exception in httpasyncclient callback

I use HttpAysnClient to do http requests, and I found when I throw an exception in the failed callback, the next request always be failed, how to fix it?
I use maven dependency: 'org.apache.httpcomponents:httpasyncclient:4.1.5'.
my java test code:
CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault();
try {
httpclient.start();
AtomicBoolean fireException = new AtomicBoolean(false);
while (true) {
try {
String url;
if (fireException.compareAndSet(false, true)) {
url = "http://localhost:8080"; // throw Connection refused
} else {
url = "http://www.apache.org/";
}
final HttpGet request2 = new HttpGet(url);
httpclient.execute(request2, new FutureCallback<HttpResponse>() {
public void completed(final HttpResponse response2) {
System.out.println("completed, " + request2.getRequestLine() + "->" + response2.getStatusLine());
}
public void failed(final Exception ex) {
System.out.println("failed, " + request2.getRequestLine() + "->" + ex);
throw new RuntimeException();
}
public void cancelled() {
System.out.println(request2.getRequestLine() + " cancelled");
}
});
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
TimeUnit.SECONDS.sleep(1);
}
}
} finally {
httpclient.close();
}
exception in the next requests: java.util.concurrent.CancellationException: Request execution cancelled
I can confirm same behavior with version 4.1.5.
I must confess it is quite surprising to see an application uncontrolled exception shutting down the whole client unexpectedly. In the context of an application reusing same client instance in multiple places, means the application client gets completely unsuable, with catastrophic consequences for the service.
You can use the "isRunning" method to evaluate if the client is under this situation, and potentially try to recreate the client again. But it is definately incovenient to see the client being shutdown like this.
After exercising the client with different conditions (error responses, slow responses...), the only way to reproduce this is to point to an invalid endpoint where no server is running. This is the condition presented in the original example.
I think I found the issue here https://jar-download.com/artifacts/org.apache.httpcomponents/httpasyncclient/4.1.5/source-code/org/apache/http/impl/nio/client/InternalIODispatch.java
You can see onException doesn't have a try/catch block to properly handle exceptions from the application.
I have confirmed this issue is fixed in Httpclient5 5.1.3. So other than fixing your application code to avoid uncontrolled exceptions, the solution is to migrate into the new Httpclient5 lib version.
you can see doc in https://hc.apache.org/httpcomponents-client-5.1.x/migration-guide/migration-to-async-simple.html
and if you want to use CloseableHttpClient you must start it client.start();

How to deserialize ProblemDetails in ASP.NET Core 2.2

I have a C# client app that calls an ASP.NET Core REST service. If the REST service fails on the server it is configured to return a 'problem details' json response as per rfc7807, e.g.:
{
"type": "ServiceFault",
"title": "A service level error occurred executing the action FooController.Create
"status": 500,
"detail": "Code=ServiceFault; Reference=5a0912a2-df17-4f27-8e5a-0d4828022306; Message=An error occurred creating a record.",
"instance": "urn:foo-corp:error:5a0912a2-df17-4f27-8e5a-0d4828022306"
}
In the client app I would like to deserialize this json message to an instance of ProblemDetails as a convenient way of accessing the details. E.g.:
ProblemDetails details = await httpResp.Content.ReadAsAsync<ProblemDetails>();
However, the deserialization throws the following exception:
System.Net.Http.UnsupportedMediaTypeException: No MediaTypeFormatter
is available to read an object of type 'ProblemDetails' from content
with media type 'application/problem+json'.
ReadAsAsync<T> is unfamiliar with the application/problem+json media type, and does not have a formatter that can handle that type by default, hence the error
You can use the long approach and get the string first then use Json.Net
string json = await httpResp.Content.ReadAsStringAsync();
ProblemDetails details = JsonConvert.DeserializeObject<ProblemDetails>(json);
You can define a ProblemDetailsMediaTypeFormatter that will inherit from JsonMediaTypeFormatter.
public class ProblemDetailsMediaTypeFormatter : JsonMediaTypeFormatter
{
public ProblemDetailsMediaTypeFormatter()
{
SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/problem+json"));
}
}
Usage:
var problemDetails = await response.Content
.ReadAsAsync<ProblemDetails>(new [] { new ProblemDetailsMediaTypeFormatter() }, cancellationToken);

Passing String value from Angular $http post to Spring #RestController

I have a REST api endpoint like this -
#RequestMapping(value = "/createform/custom/name", method = RequestMethod.POST)
public String nameSubmit(#RequestBody String name) {
return "you have submitted this name ***** "+name;
}
From angular service I tried to make a REST call like this -
var data = 'name='+inputName;
$http.post(uploadUrl, data, {
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
}).then(
function(success){
alert(success.data);
},
function(error){
alert(error.status);
}
);
Now I always get a -1 HTTP status and control goes to error block. I also tried #RequestParam instead of #RequestBody but no luck. But if I try to access the service through curl or chrome postman , everything works fine. Only when I try through angular application I get stuck with -1 response.
It was a CORS issue. I tried the Spring proposed solutions first. But the "gs-rest-service-cors" jar was not found in Maven repository. Hence ended up writing a filter as shown here and things worked fine.

JAX-RS Apache Oltu server request with JSON body

I am trying to implement OAuth2 in my JAX-RS application, using Apache Oltu. I have found this:
https://github.com/apache/oltu/tree/trunk/oauth-2.0/integration-tests/src/test/java/org/apache/oltu/oauth2/integration/endpoints
#POST
#Consumes("application/x-www-form-urlencoded")
#Produces("application/json")
public Response authorize(#Context HttpServletRequest request) throws OAuthSystemException
{
OAuthTokenRequest oauthRequest = null;
OAuthIssuer oauthIssuerImpl = new OAuthIssuerImpl(new MD5Generator());
try {
oauthRequest = new OAuthTokenRequest(request);
} catch (OAuthProblemException e) {
OAuthResponse res = OAuthASResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST).error(e)
.buildJSONMessage();
return Response.status(res.getResponseStatus()).entity(res.getBody()).build();
}
This works fine with application/x-www-form-urlencoded. However I want to have support for application/json too. I can't find any documentation how I extend or implement this. Is anyone familiar with this problem?
Preferably I want to reuse OAuthTokenRequest
The #Consumes and #Produces annotations from the JAX-RS api have support for an Array of Strings by default. You can declare your REST endpoint like this to support multiple formats: #Consumes({"application/x-www-form-urlencoded", "application/json"})

Exception thrown when WebAuthenticationBroker receives an OAuth2 callback

The WebAuthenticationBroker doesn't seem to be able to handle navigation to my ms-app://. Just throws this ugly error as you will see below.
Steps
Call AuthenticateAsync(), including callback uri obtained at runtime: WebAuthenticationBroker.GetCurrentApplicationCallbackUri()
Go through authorize process, hit Allow.
Instead of returning, the broker shows the page Can't connect to service. We can't connect to the service you need right now. Unable to do anything, so I hit the Back button visible.
Debugger breaks on catch: "The specified protocol is unknown. (Exception from HRESULT: 0x800C000D)"
The callback for WebAuthenticationBroker.AuthenticateAsync() is received (according to Fiddler4 & the Event Viewer) but it throws the aforementioned exception as if it doesn't know how to interpret the ms-app:// protocol.
All examples imply my code should work but I think there's something less obvious causing an issue.
Code
private static string authorizeString =
"https://api.imgur.com/oauth2/authorize?client_id=---------&response_type=token";
private Uri startUri = new Uri(authorizeString);
public async void RequestToken() {
try {
var war = await WebAuthenticationBroker.AuthenticateAsync(
WebAuthenticationOptions.UseTitle
, startUri);
// Imgur knows my redirect URI, so I am not passing it through here
if (war.ResponseStatus == WebAuthenticationStatus.Success) {
var token = war.ResponseData;
}
} catch (Exception e) { throw e; }
}
Event Viewer log excerpts (chronological order)
For information on how I obtained this, read the following MSDN: Web authentication problems (Windows). Unfortunately this is the only search result when querying authhost.exe navigation error.
Information: AuthHost redirected to URL: <ms-app://s-1-15-2-504558873-2277781482-774653033-676865894-877042302-1411577334-1137525427/#access_token=------&expires_in=3600&token_type=bearer&refresh_token=------&account_username=------> from URL: <https://api.imgur.com/oauth2/authorize?client_id=------&response_type=token> with HttpStatusCode: 302.
Error: AuthHost encountered a navigation error at URL: <https://api.imgur.com/oauth2/authorize?client_id=------&response_type=token> with StatusCode: 0x800C000D.
Information: AuthHost encountered Meta Tag: mswebdialog-title with content: <Can't connect to the service>.
Thanks for reading, Stack. Don't fail me now!
Afaik, you need to pass the end URL to AuthenticateAsync even if you assume that the remote service knows it.
The way WebAuthenticationBroker works is like the following: you specify an "endpoint" URL and when it encounters a link that starts with this URL, it will consider the authentication process complete and doesn't even try navigating to this URL anymore.
So if you specify "foo://bar" as callback URI, navigating to "foo://bar" will finish the authentication, as will "foo://barbaz", but not "foo://baz".
Resolved! #ma_il helped me understand how the broker actually evaluates the redirect callback and it led me back to square one where I realized I assumed WebAuthenticationOptions.UseTitle was the proper usage. Not so. Up against Imgur's API using a token, it requires WebAuthenticationOptions.None and it worked immediately.
As an example to future answer-seekers, here's my code.
private const string clientId = "---------";
private static Uri endUri = WebAuthenticationBroker.GetCurrentApplicationCallbackUri();
private static string authorizeString = "https://api.imgur.com/oauth2/authorize?"
+ "client_id="
+ clientId
+ "&response_type=token"
+ "&state=somestateyouwant"
+ "&redirect_uri="
+ endUri;
private Uri startUri = new Uri(authorizeString);
public async void RequestToken() {
try {
WebAuthenticationResult webAuthenticationResult =
await WebAuthenticationBroker.AuthenticateAsync(WebAuthenticationOptions.None
, startUri
, endUri);
if (webAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success) {
string token = webAuthenticationResult.ResponseData;
// now you have the token
}
} catch { throw; }
}