I am creating a integration tool for TeamCity to Rally and using the Java REST API. When I try to create an object of type "build" I get an exception thrown by the restAPI with a 302 "temporarily moved" error.
How do I handle this? I cannot see any settings in the Rally RestAPI that turns on or off redirects and the API is not handling the redirect.
Any suggestions?
Here is the code that is being issued. The create call to the restAPI throws an exception. The two calls to def.getWorkspace().getRef and def.getRef() return the URLs for the workspace and build definition entries which this build record is associated with (the string is the "_ref" attribute from those entities).
try {
JsonObject obj = new JsonObject();
obj.addProperty("workspace", def.getWorkspace().getRef());
obj.addProperty("buildDefinition",def.getRef());
obj.addProperty("duration",1.05);
obj.addProperty("message", "Message for the build");
obj.addProperty("number","TEST0000");
obj.addProperty("start", isoFormat.format(new Date()));
obj.addProperty("status","Passed");
obj.addProperty("uri", "http://teamcity.com");
CreateRequest request = new CreateRequest("build", obj);
request.setFetch(new Fetch("FormattedID,Name"));
CreateResponse response = restAPI.create(request);
} catch (Exception e) {
LOG.error("Could not create object of type: " + type, e);
}
Have you successfully been able to create other objects/artifacts? Do you know if you have a Proxy server? It's possible that the 302 is coming from an intermediate Proxy rather than Rally. If you have a proxy, you can do:
restAPI.setProxy("https://myproxy","myproxyuser","myproxypassword");
To setup a proxy for your REST connection. Aside from that, a couple of comments:
Valid values for "Status" are [SUCCESS, FAILURE, INCOMPLETE, UNKNOWN, NO BUILDS]
There's no need to do a setFetch on a CreateRequest - the Fetch parameter is only used for Queries.
I hope this helps.
Related
I am trying to create soap web service client by one client WSDL file by using Apache Axis 2 and tomcat 6.
I successfully generated client, but when I am calling methods to get data I am getting error.
WSDL location: https://staging2.myhcl.com/MedicalClaim/Service.svc?wsdl
Error:
Unable to sendViaPost to url[http://staging2.myhcl.com/MedicalClaim/Service.svc]
java.net.SocketTimeoutException: Read timed out
My doubt is mentioned below:
We are sending request with GET or POST methods that how we can know in SOAP web service?
When above mentioned error used to come?
Rather than Apache Axis 2, what other generating client can we use for this WSDL file?
You might need to check how much time it is taking at Skeleton end.I have done SOAP some time back and i have faced same issue.Below code might help you
private HttpURLConnection getConnection(String endPoint) {
try {
URL url = new URL(endPoint);
URLConnection connection = url.openConnection();
connection.setConnectTimeout(20000); // 20 sec connection timeout
connection.setReadTimeout(60000); // 60 sec read timeout
HttpURLConnection httpConnection = (HttpURLConnection) connection;
httpConnection.setRequestMethod("POST");
OutputStream out = httpConnection.getOutputStream();
return httpConnection;
} catch (MalformedURLException e) {
e.printStackTrace();
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
But ensure that your service(Skeleton) is not taking much time to process the request.You can use SoapUI to find out how much time it is taking to return the response.Accordingly you can set the timeout value.
Here comes answers of your doubts:
1.You can set POST/GET in HttpURLConnection object.
2.The error specified can come if the connection is idle for long and the Service is not returning any result.Use SoapUI to check the reply from Service.
3.wsdl2java and java2wsdl with Apache Axis2 is a good option for this purpose.Also xmlbeans has an inbuilt converter, which is quite handy to use.
I'm trying to upload a file using the Apache Http Client's PUT method. The code is as below;
def putFile(resource: String, file: File): (Int, String) = {
val httpClient = new DefaultHttpClient(connManager)
httpClient.getCredentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(un, pw))
val url = address + "/" + resource
val put = new HttpPut(url)
put.setEntity(new FileEntity(file, "application/xml"))
executeHttp(httpClient, put) match {
case Success(answer) => (answer.getStatusLine.getStatusCode, "Successfully uploaded file")
case Failure(e) => {
e.printStackTrace()
(-1, e.getMessage)
}
}
}
When I tried running the method, I get to see the following error:
org.apache.http.NoHttpResponseException: The target server failed to respond
at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:101)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:252)
at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:281)
at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:247)
at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:219)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:298)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:633)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:454)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
I do not know what has gone wrong? I'm able to do GET requests, but PUT seems not to work! Any clues as to where I should look for?
Look on the server. If GET Works, but PUT does not, then you have to figure out the receiving end.
Also, you may want to write a simple HTML File that has a form with PUT Method in it to rule out your Java Part.
As a sidenode: Its technically possible that something in between stops the request from going through or the response reaching you. Best setup a dummy HTTP Server to do the testing against.
Maybe its also a timeout issue, so the server takes to long to process your PUT.
The connection you are trying to use is a stale connection and therefore the request is failing.
But why are you only seeing an error for the PUT request and you are not seeing it for the GET request?
If you check the DefaultHttpRequestRetryHandler class you will see that by default HttpClient attempts to automatically recover from I/O exceptions. The default auto-recovery mechanism is limited to just a few exceptions that are known to be safe.
HttpClient will make no attempt to recover from any logical or HTTP protocol errors (those derived from HttpException class).
HttpClient will automatically retry those methods that are assumed to be idempotent. Your GET request, but not your PUT request!!
HttpClient will automatically retry those methods that fail with a transport exception while the HTTP request is still being transmitted to the target server (i.e. the request has not been fully transmitted to the server).
This is why you don't notice any error with your GET request, because the retry mechanism handles it.
You should define a CustomHttpRequestRetryHandler extending the DefaultHttpRequestRetryHandler. Something like this:
public class CustomHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler {
#Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if(exception instanceof NoHttpResponseException) {
return true;
}
return super.retryRequest(exception, executionCount, context);
}
}
Then just assign your CustomHttpRequestRetryHandler
final HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setRetryHandler(new CustomHttpRequestRetryHandler());
And that's it, now your PUT request is handled by your new RetryHandler (like the GET was by the default one)
I'm creating an HTTP API using ASP.NET Web API. I've noticed that if an exception occurs that I haven't handled, that behaviour is very different to if I deliberately throw an HttpResponseException. This will make it hard for clients to reliably handle an error and display the "reason" message.
Eg consider this code:
[HttpPost]
public void ThisWillThrowAnError()
{
try
{
var i = 0;
var b = 1 / i; // cause divide by zero exception for testing
}
catch (Exception ex)
{
HttpResponseMessage message = new HttpResponseMessage();
message.ReasonPhrase = "Error: " + ex.Message;
throw new HttpResponseException(message);
}
}
This creates a response which has the error in an HTTP header and the response code set to 500:
Error: This request could not be processed. Attempted to divide by zero.
The actual response body is empty.
However if I remove the try/catch block, or if an exception occurs for which I do not manually throw an HttpResponseException, I get totally different behaviour. Although the status code is still 500, the header message just says "Internal Server Error" and the message is encoded in a JSON format like this:
{
"Message": "An error has occurred.",
"ExceptionMessage": "Attempted to divide by zero.",
"ExceptionType": "System.DivideByZeroException",
"StackTrace": " at ProjectName.Controllers (etc....)"
}
I think I prefer the latter as it gives you more info for debugging but it removes the ability to customise the message or provide a user-readable message for the problem.
Why is WebAPI inconsistent with how it handles exceptions? Am I doing something myself to cause this inconsistency? It just seems rather messy and difficult to work with and may mean that the calling application will have to be coded to handle two different types of error response :(
When creating error responses, consider using HttpRequestMessage.CreateErrorResponse to create error responses that are consistent with the ones WebAPI sends.
This blog post should hopefully help:
http://blogs.msdn.com/b/youssefm/archive/2012/06/28/error-handling-in-asp-net-webapi.aspx
I would use message handlers. A message handler is a class that receives an HTTP request and returns an HTTP response. So you can basically change response structure in one place, and have same response for success and failure, and for all requests in your Web Api. You can read about it in my blog post: https://www.vladopandzic.com/asp-net-web-api/building-consistent-responses-asp-net-web-api/
I have a web service that runs perfectly when i reference it from within the project solution. As soon as i upload it to the remote server, it starts blowing up. Unfortunately, the only error message I get is on the client side "faultexception was unhandled by user code". Inside of the web service, I have exceptions handled in all of the methods, so I'm pretty sure it's getting caught somewhere, but I don't know how to see it. I suspect that the problem is permissions related, but I can't see where it's happening.
I tried placing an error message into object returns, but it's still not making it out; something like this:
public bool SetDirectReports(ADUser user)
{
try
{
var adEntry = new DirectoryEntry(string.Format("LDAP://<GUID={0}>", user.Guid), "administrator", "S3cur1ty");
if (adEntry.Properties["directReports"].Count > 0)
{
user.DirectReports = new List<ADUser>();
foreach (string directReport in adEntry.Properties["directReports"]) //is being returned as full distinguished name
{
var dr = new DirectoryEntry(string.Format("LDAP://{0}", directReport), "administrator", "S3cur1ty");
user.DirectReports.Add(GetUserByGuid(dr.NativeGuid));
}
return true;
}
else
{
user.DirectReports = new List<ADUser>();
return false;
}
}
catch (Exception ex)
{
user.HasError = true;
user.ErrorMessage = "Error setting direct reports: " + ex.Message;
return false;
}
}
but its' still not catching. I was hoping for a better approach. I'm not sure if I could add something that would output the exception to the console or what. Any help would be appreciated. TIA
P.S. this isn't necessarily the method thats crashing, there's a web of them in the service.
You should dump all of your exceptions to a log file on the server side; exposing error information to the client is a potential security risk, which is why it's turned off by default.
If you really want to send exception information to the client, you can turn it on. If you are using a WCF service you should set the "includeExceptionDetailsInFaults" property on for the service behavior, as described in this MSDN article on dealing with unhandled exceptions in WCF. Once you do so, you will have a property on the FaultException called Detail that should itself be a type of Exception.
For better error handling you should also take a look at typed faults using the FaultContract and FaultException<> class; these have the benefit that they don't throw the channel into a faulted state and can be handled correctly:
try
{
// do stuff here
}
catch (Exception ex)
{
var detail = new CustomFaultDetail
{
Message = "Error setting direct reports: " + ex.Message
};
throw new FaultException<CustomFaultDetail>(detail);
}
If you are using an ASP.NET Web Service, you should set the customErrors mode to "Off" in your web.config. This will send back the entire exception detail as HTML, which the client should receive as part of the SOAP exception that it receives.
The error your are seeing ("faultexception was unhandled by user code") is happening because this is a remote exception and it is standard behavior to only display exceptions on the local computer by default. In order to make it work how you intend, you need to change the customErrors section of the web.config and set it to Off
UPDATE: I found a related question: c# exception not captured correctly by jquery ajax
(Three years later..)
Here's the solution I came up with, along with some sample WCF code, and Angular code to catch, and display the exception message:
Catching exceptions from WPF web services
Basically, you just need to wrap your WCF service in a try..catch, and when something goes wrong, set a OutgoingWebResponseContext value.
For example, in this web service, I've slipped in an Exception, which will make my catch code set the OutgoingWebResponseContext value.
It looks odd... as I then return null, but this works fine.
public List<string> GetAllCustomerNames()
{
// Get a list of unique Customer names.
//
try
{
throw new Exception("Oh heck, something went wrong !");
NorthwindDataContext dc = new NorthwindDataContext();
var results = (from cust in dc.Customers select cust.CompanyName).Distinct().OrderBy(s => s).ToList();
return results;
}
catch (Exception ex)
{
OutgoingWebResponseContext response = WebOperationContext.Current.OutgoingResponse;
response.StatusCode = System.Net.HttpStatusCode.Forbidden;
response.StatusDescription = ex.Message.Replace("\r\n", "");
return null;
}
}
What is brilliant about this try..catch is that, with minimal changes to your code, it'll add the error text to the HTTP Status, as you can see here in Google Chrome:
If you didn't have this try..catch code, you'd just get an HTTP Status Error of 400, which means "Bad Request".
So now, with our try..catch in place, I can call my web service from my Angular controller, and look out for such error messages coming back.
$http.get('http://localhost:15021/Service1.svc/getAllCustomerNames')
.then(function (data) {
// We successfully loaded the list of Customer names.
$scope.ListOfCustomerNames = data.GetAllCustomerNamesResult;
}, function (errorResponse) {
// The WCF Web Service returned an error
var HTTPErrorNumber = errorResponse.status;
var HTTPErrorStatusText = errorResponse.statusText;
alert("An error occurred whilst fetching Customer Names\r\nHTTP status code: " + HTTPErrorNumber + "\r\nError: " + HTTPErrorStatusText);
});
Cool, hey ?
Incredibly simple, generic, and easy to add to your services.
Shame some readers thought it was worth voting down. Sorry about that.
You have several options:
1) If you are using WCF, throw a FaultException on the server and catch it on the client. You could, for instance, implement a FaultContract on your service, and wrap the exception in a FaultException. Some guidance to this here.
2) You could use the Windows Server AppFabric which would give you more details to the exception within IIS. (requires some fiddling to get it working, though)
3) Why not implement some sort of server-side logging for the exceptions? Even if to a file, it would be invaluable to you to decipher what is really happening. It is not a good practice (especially for security reasons) to rely on the client to convey the inner workings of the server.
I'm using the WebChannelFactory<> to create a channel and interact with a WCF REST Service.
When there is an error, I want to retrieve the response from the channel to read the error message from the body of the response. But I cannot figure out how to get the response stream.
Here is my code:
using (var cf = new WebChannelFactory<T>(new Uri(url)))
{
var channel = cf.CreateChannel();
using (new OperationContextScope(channel as IContextChannel))
{
WebOperationContext.Current.OutgoingRequest.Headers
.Add("x-st-authtoken", HttpUtility.UrlDecode(Constants.General_AuthorizedToken));
WebOperationContext.Current.OutgoingRequest.Headers
.Add("x-st-tesskey", HttpUtility.UrlDecode(Constants.General_SessionKey));
try
{
a(channel);
}
catch (Exception ex)
{
throw new Exception("Status: " + ((int)WebOperationContext.Current.IncomingResponse.StatusCode).ToString());
}
}
}
In the catch statement, I want to include the data from the Response body...
It seems like an obvious thing, but I can't seem to find any information on the internet or anything.
Is there any specific reason for you to use ChannelFactory to interact with the REST service. I think it is easier to use HttpWebRequest object to invoke the REST service and there you can get the respone stream when an error is throw on the server.
Also check out RestSharp API through which you can achieve your task to read the response stream.
I believe it will throw a WebException.
so if you explicitly catch that type you can get use the WebException.Response property (which is an HttpWebReponse) on the exception and you can get the content from its stream.