I am using a Grails service closure to perform a async HTTP request to another web application. Using Grails 1.3.9, I am very limited here. The code runs inside a thread. It is called from a scheduled job and from several function calls. The error I get is below:
ERROR:
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
CODE:
Thread.start {
def http = new HTTPBuilder(grailsApplication?.config?.smsConfig?.smsServiceAddress);
try {
http.request(POST) {
body = bodyRequest;
requestContentType = ContentType.JSON
response.success = { resp ->
println "SUCCESS! ${resp.status}"
def user = RequestContextHolder.currentRequestAttributes().getSession().user
if (user != null) {
if (termin) {
termin.withTransaction {
try {
// do desired action
} catch (e) {
println(e);
}
}
}
}
}
response.failure = { resp ->
println "FAILURE request failed with status ${resp.status}, response body was [${resp.entity.content.text}]"
System.out << resp
}
}
}
//here error is caught
catch (e) {
log.error "Error: " + e;
}
}
I have tried adding this options to web.xml
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
and also this to WebXmlConfig.groovy
listener.add = true
listener.classNames = ["org.springframework.web.context.request.RequestContextListener"]
but both did not help
This is something that isn't well documented or can you send you spirals:
Try this:
/*
* Fix for No thread-bound request found: Are you referring to request attributes
*/
def webRequest = RequestContextHolder.getRequestAttributes()
if(!webRequest) {
def servletContext = ServletContextHolder.getServletContext()
def applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext)
webRequest = grails.util.GrailsWebMockUtil.bindMockWebRequest(applicationContext)
}
You will need spring test in your build.gradle
compile 'org.springframework:spring-test:2.5'
There is a grails 2 branch so follow the same class in the other branch if it is grails 2
Related
This is the exact exception in the error logs.
I have a requirement where I should be creating a set of service calls and wait till all of them are completed successfully before moving on to do a different set of service calls.
I have two services Service1 and Service2.
There are 2 instances of Service2 in 2 different servers and we have set up an F5(Load Balancer) to distribute the load evenly.
Let's say I have 10 service calls to be made from Service1 to Service2 at a time and F5 will share those 10 calls among the 2 servers. i.e. 5 Calls to Service2 of each server.
But I observed that if any one of those 10calls is taking lot of time to complete the work it should do(The work to be done in Service2 has some heavy lifting) then i get a socket exception thrown and entire process gets stopped.
However when I dont use the F5 load balancer and just use 1 instance of the Service2. Then however long the process takes for any of those 10 calls it doesn't throw any exception.
I am not sure if this is an issue with F5 configuration or with the way connections are made with the F5 from .Net code.
Please go through the below code to get some idea of what i am trying to do and let me know if any code change would help me resolve it.
for (int i=0 ; i< ReqList.Count;i++)
{
maxTasks++;
ClassA reqList = new ClassA();
reqList = ReqList[i];
List<ClassA> recsByReq = recs.Where(x => x.ReqId == reqList.ReqtId).ToList();
ClassC service2Input = new ClassC();
service2Input.DetaiList = listofRecs;
service2Input.RecList = recsByReq;
taskList.Add(_service2.Service2MethodCall(service2Input, service2Resource));
if(maxTasks == 10 || ReqList.Count == 10 || i==ReqList.Count-1)
{
Task.WaitAll(taskList.ToArray(),-1);
maxTasks = 0;
taskList.Clear();
}
}
The Service2MethodCall is where I am creating a HttpClient to make connections with the 2nd service i.e. Service2,
public class Service2: IService2 {
private ServiceClient GetService2(string resource)
{
return new ServiceClient(_service2BaseUrl, TimeSpan.FromMinutes(60))
{
Resource = resource,
};
}
public async Task Service2MethodCall(ClassC service2Input, string resource)
{
try
{
var client = GetService2(resource);
await client.PostAsync(JsonConvert.SerializeObject(service2Input).ToString());
}
catch (Exception ex)
{
throw new Exception("The Service encountered an error during the Service2 call for Req ID : " +
service2Input.RecsList.Find(x => x.ReqId != "").ReqId.ToString(), ex);
}
}
}
The PostAsync() method creates a new HttpClient with HttpClientHandler object for each of the call.
public async Task PostAsync(object data) {
using(var httpClientHandler = new HttpClientHandler()) {
httpClientHandler.ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) => {
if (sslPolicyErrors == SslPolicyErrors.None) {
return true; //Is valid
}
if (cert.GetCertHashString().ToUpper() == _acceptedThumbprint.ToUpper()) {
return true;
}
return false;
};
using(var client = new HttpClient(httpClientHandler)) {
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(ResponseFormatter.MediaType);
client.Timeout = Timeout.InfiniteTimeSpan;
Uri uri = BuildUri();
if (!String.IsNullOrWhiteSpace(SignatureKey)) {
client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization",
RequestFormatter.GenerateAuthHeaderEncodedUserSignature(uri, AuthUserName, SignatureKey, data));
}
//_logger.WriteUsage(client.BaseAddress.ToString());
HttpResponseMessage response = await RequestFormatter.PostAsync(client, uri, data);
string content = await response.Content.ReadAsStringAsync();
try {
response.EnsureSuccessStatusCode();
}#
pragma warning disable CS0168 // The variable 'rex' is declared but never used
catch (HttpRequestException rex)# pragma warning restore CS0168 // The variable 'rex' is declared but never used
{
//_logger.WriteUsage("Response for POST to: {0} did not yield a successful status code. Message: {1}" + uri.ToString() + content);
throw new ApiHttpException(response.StatusCode, content);
}
}
}
}
Is there some thing I can do within the code to avoid this situation once and for all?
I have a spring boot API in java which is using pact-jvm for pact verification.
We have a new client who wants to use the same API using a new path, which the gateway will take care of, but this causes issue for pacts, I want to intercept the request and modify the path of the request for new pacts to point to old path.
I was trying to refer some material online and found this :
https://medium.com/dazn-tech/pact-contract-testing-dealing-with-authentication-on-the-provider-51fd46fdaa78
The below code prints the updated value of the request, but the pact still fails with 404 error as if it is still using new path
requestFilter = { req ->
println "incoming request : $req"
if ("$req".contains('/new-context') ) {
req = "$req".replace('/new-context', '/old-context')
println "updated request : $req"
}
}
The problem in the above code was I was treating req as string and doing manipulations, but it is an HttpRequest object and the below code solved the issue for me:
requestFilter = { req ->
def uriText = req.getURI()
println "incoming request uri : $uriText"
if ("$uriText".contains('/new-context') ) {
def uriTextNew = "$uriText".replace('/new-context', '/old-context')
println "updated request uri : $uriTextNew"
URI newURI = new URI(uriTextNew)
req.setURI(newURI)
}
}
I have implemented a #OneWay JAX-RS service with Apache CXF ( a dropwizard application ). When called with invalid structure, causing an unmarshalling error in DocLiteralInInterceptor, http status code 200 is returned to client. To make the calling process recognize the fault, I need to return status 400 or 500, along with the error text from Unmarshalling Error.
I recognized that, after the error, the "in" interceptor chain is unwound ( interceptors handleFault-methods are called in reverse order ), so I installed an interceptor at the start of the "in"-chain ( last on unwinding ) with
public CustomSOAPInterceptor(String chainname) {
super(Phase.RECEIVE);
getBefore().add(PolicyInInterceptor.class.getName());
this.chainname=chainname;
}
Within my handleFault-Method I can seperate the fault message and recognize the unmarshall error. But I am not succeeding in setting the response.
I tried
Fault f = (Fault) e;
f.setStatusCode(Response.Status.BAD_REQUEST.getStatusCode());
and
Response response = Response
.status(Response.Status.BAD_REQUEST)
.entity(Response.Status.BAD_REQUEST.getStatusCode() + " " + f.getLocalizedMessage())
.build();
soapMessage.getExchange().put(Response.class, response);
and
message.put(Message.RESPONSE_CODE, Response.Status.BAD_REQUEST.getStatusCode());
Where is the response set and how can I overwrite it ?
Tx for any advice.
I know, its kind of late, but for those who are looking for a solution:
In my application, the following works:
public void handleFault(SoapMessage soapMessage) {
/* some code to test for specific error deleted */
Exchange exchange = soapMessage.getExchange();
Message outMessage = exchange.getOutMessage();
if (outMessage == null) {
Endpoint endpoint = exchange.get(Endpoint.class);
outMessage = endpoint.getBinding().createMessage();
exchange.setOutMessage(outMessage);
}
try {
EndpointReferenceType target = exchange.get(EndpointReferenceType.class);
Conduit conduit = exchange.getDestination().getBackChannel(soapMessage);
exchange.setConduit(conduit);
conduit.prepare(outMessage);
} catch (IOException ex) {
LOG.error(ex.getMessage(), ex);
}
Object resp = outMessage.get("HTTP.RESPONSE");
if (resp != null && resp instanceof HttpServletResponse) {
HttpServletResponse response = (HttpServletResponse) resp;
response.setStatus(Response.Status.BAD_REQUEST.getStatusCode());
}
soapMessage.getInterceptorChain().abort();
}
I have strange problem with my Game written in Unity (Mono). I have login functionality and then, after successfull login i'm sending some kind of keep-alive requests to ensure token is updated (I'm sending it every 30s).
The problem is, that after some time (sometimes it's 1 hour, sometimes 2.5 hours) all my requests have timeout status.
To be sure about my connection status I made some checks in code: I'm making simple GET to http://google.com and to main website of my API (not an API call. Just website GET). When I got timeout on API next time i figured out that:
After 1 timeout I have it always. Restarting application helps
I'm getting timeouts on API call and on GET request for base API website
Google is still responding with status 200 (no timeouts here)
Implementation:
On beginning i've been using RestSharp to handle requests, but the problem occured and there was a decision to throw RestSharp away and now we're using classic WebClient
class BetterWebClient : WebClient
{
private WebRequest _Request = null;
public TimeSpan? Timeout { get; set; }
protected override WebRequest GetWebRequest(Uri address)
{
this._Request = base.GetWebRequest(address);
if ( Timeout.HasValue )
{
_Request.Timeout = (int)Timeout.Value.TotalMilliseconds;
}
else
{
_Request.Timeout = 10*1000; //10s
}
if (this._Request is HttpWebRequest)
{
((HttpWebRequest)this._Request).AllowAutoRedirect = true;
}
return this._Request;
}
}
My HandleRequest function (which also calls Google and API website) looks like this:
public static void HandleRequest<TR>(string url, RestResponse<TR> executeGetRequest) where TR : new()
{
using (BetterWebClient w = new BetterWebClient() {Timeout = TimeSpan.FromSeconds(2)})
{
try
{
string downloadString = w.DownloadString("http://www.google.com");
Debug.Log("Google request: OK");
}
catch ( Exception )
{
Debug.LogError("Google request failed");
}
try
{
string downloadString = w.DownloadString("myAPIwebsite");
Debug.Log("WorldOfRescue.com request: OK");
}
catch ( Exception )
{
Debug.LogError("WorldOfRescue.com request failed");
}
}
var client = new BetterWebClient() {Timeout = TimeSpan.FromSeconds(5)};
client.Headers.Add("Accept", "application/json");
client.Headers.Add("Content-Type", "application/json");
try
{
string downloadString = client.DownloadString(url);
Debug.Log("Request for "+url+ " completed. Response: " + downloadString);
}
catch ( WebException e )
{
Debug.Log(e.Status);
throw;
}
catch ( Exception e )
{
Debug.Log(e.ToString());
throw;
}
finally
{
client.Dispose();
}
}
Do you have any idea why it happens? It looks like something is blocking me to send request to specific website, but in same time other website is working fine.
I'm using the Asp.Net WebClient to create an HTTP post.
The below code has try-catch block around the code which catches WebException:
try
{
using (MyWebClient wc = new MyWebClient())
{
wc.Headers[HttpRequestHeader.ContentType] = _lender.ContentType;
wc.Timeout = 200;
return _lender.GetResult(wc.UploadString(_lender.PostUri, _lender.PostValues));
}
}
catch (WebException ex)
{
return new ServiceError(ex.Status.ToString());
}
The main exceptions I'm looking for are timeouts. I've extended WebClient to allow me to set the timeout.
When I set the timeout to say 100ms, an exception is thrown as expected. I can get the WebException status as per the example (it returns "timeout"), however, I want to return status codes too.
If I extract the httpwebresponse using ex.Response I get a null value returned, when I was expecting an associated status code.
Why do I not get an HttpStatus.Request.Timeout?
I have the same problem and I realise a few things while I search for a solution.
WebExceptionStatus enum is not equivalent to http status code that the API you call returned. Instead it is a enum of possible error that may occour during a http call.
The WebExceptionStatus error code that will be returned when you receive an error (400 to 599) from your API is WebExceptionStatus.ProtocolError aka number 7 as int.
When you need to get the response body or the real http status code returned from the api, first you need to check if WebException.Status is WebExceptionStatus.ProtocolError. Then you can get the real response from WebExceptionStatus.Response and read its content.
Sometimes the timeout is handled by the caller (aka your code) so you do not have a response in that case. So you can look if WebException.Status is WebExceptionStatus.Timeout
This is an example:
try
{
...
}
catch (WebException webException)
{
if (webException.Status == WebExceptionStatus.ProtocolError)
{
var httpResponse = (HttpWebResponse)webException.Response;
var responseText = "";
using (var content = new StreamReader(httpResponse.GetResponseStream()))
{
responseText = content.ReadToEnd(); // Get response body as text
}
int statusCode = (int)httpResponse.StatusCode; // Get the status code
}
else if (webException.Status == WebExceptionStatus.ProtocolError)
{
// Timeout handled by your code. You do not have a response here.
}
// Handle other webException.Status errors. You do not have a response here.
}