Best practice of handling multiple http status error code in java - java

What’s the best practice of handling multiple http status error code, For example, I want to handle all 4xx and 5xx status code, except 404.
I’ve my current implementation like below : (I’ve place only sample code)
if ( HTTP.STATUS == 500 || HTTP.STATUS == 502 || HTTP.STATUS == 503 || HTTP.STATUS == 400
|| HTTP.STATUS == 401 || HTTP.STATUS == 402 || HTTP.STATUS == 403) {
String status = “Failed to send”;
}
I know this is very ugly code, can anyone suggest best way of handling the error code between 4xx and 5xx except 404 using java program

This may not be a good solution for HTTP status codes, but with regards to matching many possible values, you can use a switch statement without break to stack them all:
String status = null;
switch (HTTP.STATUS) {
case 400:
case 401:
case 402:
case 403:
case 500:
case 502:
case 503:
status = “Failed to send”;
break;
default:
status = "All ok!";
}

As you are able to switch on Enums in Java, define an Enum for the range of possible codes e.g.
public enum HttpStatusCodeRange {
SUCCESS_RANGE, CLIENT_ERROR_RANGE, SERVER_ERROR_RANGE, UNKNOWN; }
Then create a utility to calculate the Enum for the particular code you get e.g.
public static HttpStatusCodeRange getRange(int code) {
if (code >= 200 && code < 300) {
return HttpStatusCodeRange.SUCCESS_RANGE;
}
if (code >= 400 && code < 500) {
return HttpStatusCodeRange.CLIENT_ERROR_RANGE;
}
if (code >= 500 && code < 600) {
return HttpStatusCodeRange.SERVER_ERROR_RANGE;
}
return HttpStatusCodeRange.UNKNOWN;
}
Then you can write fairly neat code to process your HTTP response codes e.g.
HttpStatusCodeRange range = HttpStatusCodeRangeUtil.getRange(response.getStatus());
switch (range) {
case SUCCESS_RANGE :
handleSuccess();
break;
case CLIENT_ERROR_RANGE :
handleClientError();
break;
case SERVER_ERROR_RANGE :
handleServerError();
break;
case UNKNOWN :
handleUnexpectedError();
break;
default :
handleUnknownError();
break;
}

It's better to send particular messages, for different HTTP status responses.
Look here:
http://racksburg.com/choosing-an-http-status-code/
You can also make some generic method like this:
public class GenericExceptionMapper implements ExceptionMapper<Throwable> {
#Override
public Response toResponse(Throwable ex) {
ErrorMessage errorMessage = new ErrorMessage();
setHttpStatus(ex, errorMessage);
errorMessage.setCode(AppConstants.GENERIC_APP_ERROR_CODE);
errorMessage.setMessage(ex.getMessage());
StringWriter errorStackTrace = new StringWriter();
ex.printStackTrace(new PrintWriter(errorStackTrace));
errorMessage.setDeveloperMessage(errorStackTrace.toString());
errorMessage.setLink(AppConstants.BLOG_POST_URL);
return Response.status(errorMessage.getStatus())
.entity(errorMessage)
.type(MediaType.APPLICATION_JSON)
.build();
}
private void setHttpStatus(Throwable ex, ErrorMessage errorMessage) {
if(ex instanceof WebApplicationException ) {
errorMessage.setStatus(((WebApplicationException)ex).getResponse().getStatus());
} else {
errorMessage.setStatus(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()); //defaults to internal server error 500
}
}
}

Something like so perhaps:
if (status == 404) {
// handle 404
} else {
String sstatus = '' + status;
switch (sstatus.charAt(0)) {
case '4':
// handle 4xx
break
case '5':
...

Related

Log failed tesg case and continue with loop

I am reading the test data from excel sheet and iterating the record.
On every iteration I am asserting the response in restassured.
Here is the code:
if (rbac == true && isallowed == var)
System.out.println("Test case is pass because rbac status and allowed status are matched");
else if (rbac == false && isallowed == false) {
assertEquals(403, response.statusCode());
System.out.println("Test case is pass because rbac status and allowed status are matched (false)");
}
else if (rbac == false && isallowed == true)
Assert.fail("Test case fail because rbac status is false but allowed status is true.");
else
Assert.fail("Test case fail");
Now I want
Pass and failure test cases record will get logged in report.
Test will continue if any record during test case will get failed until last record.

Using Java Stream in specific case with mapping and filtering response codes

My question is regarding lambda with JAVA8 and use of the filters.
It is done via Selenium of Java for testing for different response codes.
How can I use Lambda in greatest possible way to transform following function with Streams?
The code which I wanted to refactor is as follows into Streams , lambda of Java 8:
for (int i = 0; i < links.size(); i++) {
if (!(links.get(i).getAttribute("href") == null) && !(links.get(i).getAttribute("href").equals(""))) {
// Find HTTP Status-Code
try {
statusCode = getResponseCode(links.get(i).getAttribute("href").trim());
} catch (IOException e) {
e.printStackTrace();
}
// Check broken link
if (statusCode== 404) {
System.out.println("Broken of Link# "+i+" "+links.get(i).getAttribute("href"));
}
else if (statusCode== 400) {
System.out.println("Bad Request# "+i+" "+links.get(i).getAttribute("href"));
}
else if (statusCode== 401) {
System.out.println("Unauthorized# "+i+" "+links.get(i).getAttribute("href"));
}
else if (statusCode== 403) {
System.out.println("Forbidden# "+i+" "+links.get(i).getAttribute("href"));
}
else if (statusCode== 500) {
System.out.println("Internal server error# "+i+" "+links.get(i).getAttribute("href"));
}
}
}
What I have for now is:
List<AbstractMap.SimpleImmutableEntry<String,Integer>> variablename =
links.stream().map(WebElement::getAttribute("href"));
I was trying to do something along the lines of filtering out everything that is not 500,403,401,400,404 and only keeping the mapping or a Pair of that like (linkString, responseCode), but I am having a bit of troubles exactly how I could do it properly with Lambda?
EDIT1:
I didn't meant to put everything via stream, just to make as much use of it as I can in this example
It's fairly simple if you take it piece by piece, so:
// create a set of codes you want to include
Set<Integer> acceptableCodes = new HashSet<>(Arrays.asList(404, 400, 401, 403, 500));
// for (int i = 0; i < links.size(); i++) {
links.stream()
// convert to the href value as that's all we need later on
.map(link -> link.getAttribute("href"))
// filter out anything without a href
// if (!(links.get(i).getAttribute("href") == null) && !(links.get(i).getAttribute("href").equals(""))) {
.filter(href -> href != null)
.filter(href -> !href.equals(""))
// filter out non-matching status codes
.filter(href -> acceptableCodes.contains(getResponseCode(href))
.map(link -> new LinkWithCode(href , getResponseCode(href))
.collect(toList());
Putting it together without the comments so you can read it easier:
Set<Integer> acceptableCodes = new HashSet<>(Arrays.asList(404, 400, 401, 403, 500));
links.stream()
.map(link -> link.getAttribute("href"))
.filter(href -> href != null)
.filter(href -> !href.equals(""))
.filter(href -> acceptableCodes.contains(getResponseCode(href))
.map(link -> new LinkWithCode(href , getResponseCode(href))
.collect(toList());
LinkWithCode is a class you'll need to create to hold the link and the status code. This assumes getResponseCode isn't a heavyweight operation as it's happening twice.
Caveat: I haven't tested this or put it in an IDE so you might have some tidy up to do.

How do I do a SIP telephone call

I want to constract a telephone-caller inside my java application. For this pupose I used a JAIN-SIP library. After the first INVITE the system needs Proxy-Authentication. The second invite is conscructed with the help of "AuthenticationHelperImpl.class":https://gitorious.org/0xdroid/external_nist-sip/source/1e0f37693341071f316852c8e05a08deef2b7fc4:java/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java#L311, includes Proxy-Authentication header and lloks like:
INVITE sip:+11111111111#fpbx.de;maddr=fpbx.de SIP/2.0
Call-ID: 1c609509a43b721ab11c396c1e6ea9e7#192.168.17.107
CSeq: 2 INVITE
From: "77735hk6iu" <sip:77735hk6iu#fpbx.de>
To: "+111111111111111" <sip:+11111111111#fpbx.de>
Via: SIP/2.0/UDP 192.168.17.107:34567;rport;branch=z9hG4bK-383337-5bc4fd6b7a616843fce9eaa243bcb10e
Max-Forwards: 70
Contact: <sip:77735hk6iu#192.168.17.107:5060>
Content-Type: application/sdp
Proxy-Authorization: Digest username="77735hk6iu",realm="fpbx.de",nonce="VLaIxVS2h5muPS30F2zLdXHjup6ELyen",uri="sip:+111111111111#fpbx.de:5060;maddr=fpbx.de",response="47ea578c6b01c99fd3ed2b41c60983df"
Content-Length: 61
v=0
o=- 130565705777141827 1 IN IP4 192.168.17.107
s=call
After that I receive at the beginning code 100 message ("your call is very important for us") followed with 408 code message ("Request Timeout").
What I did to imporve the situation:
tried different phone number formats: 004930208488480,
04930208488480, 049, 0049, sdfhajfkhsk. For all these numbers I
become the same combination on messages.
tried to use port in request uri
tried to remove maddr from request uri.
tried to fullfill the message body with codek settings.
to set and remove rport from via header
If you now what I'm doing wrong, please, help me.
Thank you in advance.
I think, Maybe your Proxy-Authorization header is wrong. Maybe you is miscalculated. I wanted to share my resolve.
authUser is your phoneNumber. (for example: 77735hk6iu )
authPass is your user's password.
msg is your invite request.(Headers !)
AccountManagerImpl accountManagerImp = new AccountManagerImpl(authUser, AuthPass);
AuthenticationHelperImpl authenticationHelperImpl = new AuthenticationHelperImpl(accountManagerImp);
try {
this.authentication = authenticationHelperImpl.handleChallenge(msg, (SIPClientTransaction)trans);
AuthenticationHelperImple.java Class :
public AuthorizationHeader handleChallenge(Response challenge, ClientTransaction challengedTransaction) throws SipException {
SIPRequest challengedRequest = ((SIPRequest) challengedTransaction.getRequest());
ListIterator authHeaders = null;
if (challenge.getStatusCode() == Response.UNAUTHORIZED) {
authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME);
}
else {
if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) {
authHeaders = challenge.getHeaders(ProxyAuthenticateHeader.NAME);
}
else {
throw new IllegalArgumentException("Unexpected status code ");
}
}
if (authHeaders == null) {
throw new IllegalArgumentException("Could not find WWWAuthenticate or ProxyAuthenticate headers");
}
WWWAuthenticateHeader authHeader = null;
while (authHeaders.hasNext()) {
authHeader = (WWWAuthenticateHeader) authHeaders.next();
String realm = authHeader.getRealm();
this.uri = challengedRequest.getRequestURI();
this.requestMethod = challengedRequest.getMethod();
this.requestBody = (challengedRequest.getContent() == null) ? "" : new String(challengedRequest.getRawContent());
if (this.accountManager instanceof SecureAccountManager) {
UserCredentialHash credHash = ((SecureAccountManager) this.accountManager).getCredentialHash(challengedTransaction,
realm);
if (credHash == null) {
logger.logDebug("Could not find creds");
throw new SipException("Cannot find user creds for the given user name and realm");
}
this.authorizationHeader = this.getAuthorization(requestMethod, uri.toString(), requestBody, authHeader, credHash);
}
else {
UserCredentials userCreds = ((AccountManager) this.accountManager).getCredentials(challengedTransaction, realm);
if (userCreds == null) {
throw new SipException("Cannot find user creds for the given user name and realm");
}
// sipDomain = userCreds.getSipDomain();
// we haven't yet authenticated this realm since we were
// started.
this.authorizationHeader = this.getAuthorization(requestMethod, uri.toString(), requestBody, authHeader, userCreds);
}
}
return this.authorizationHeader;
}
getAuthorization function :
public AuthorizationHeader getAuthorization(String method,
String uri,
String requestBody,
WWWAuthenticateHeader authHeader,
UserCredentials userCredentials) throws SecurityException {
String response = null;
String qopList = authHeader.getQop();
String qop = (qopList != null) ? "auth" : null;
String nc_value = "00000001";
String cnonce = "xyz";
try {
response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(),
userCredentials.getUserName(), authHeader.getRealm(),userCredentials.getPassword(), authHeader.getNonce(), nc_value, // JvB added
cnonce, // JvB added
method, uri, requestBody, qop,logger);
}
catch (NullPointerException exc) {
throw new SecurityException("The received authenticate header was malformatted: " + exc.getMessage());
}
AuthorizationHeader authorization = null;
try {
if (authHeader instanceof ProxyAuthenticateHeader) {
if (this.headerFactory != null) {
authorization = headerFactory.createProxyAuthorizationHeader(authHeader.getScheme());
}
else {
authorization = new ProxyAuthorization();
authorization.setScheme(authHeader.getScheme());
}
}
else {
if (this.headerFactory != null) {
authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme());
}
else {
authorization = new Authorization();
authorization.setScheme(authHeader.getScheme());
}
}
authorization.setUsername(userCredentials.getUserName());
authorization.setRealm(authHeader.getRealm());
authorization.setNonce(authHeader.getNonce());
authorization.setParameter("uri", uri);
authorization.setResponse(response);
if (authHeader.getAlgorithm() != null) {
authorization.setAlgorithm(authHeader.getAlgorithm());
}
if (authHeader.getOpaque() != null) {
authorization.setOpaque(authHeader.getOpaque());
}
// jvb added
if (qop != null) {
authorization.setQop(qop);
authorization.setCNonce(cnonce);
authorization.setNonceCount(Integer.parseInt(nc_value));
}
authorization.setResponse(response);
} catch (ParseException ex) {
throw new RuntimeException("Failed to create an authorization header!");
}
return authorization;
}
Finally, your this.authentication variable is ProxyAuthorizationHeader. You must put this.authentication in your INVITE message. And than you will sent SipMessage from transaction or dialog to JAIN-SIP stack.
Good Luck !
The problem was partly solved when a removed "maddr=fpbx.de" from request URI and from proxy-auth. uri
fpr this a used handleCahllenge method with boolean arguments:
inviteTid = authenticationHelper.handleChallenge(response, tid, sipProvider, 15, **true**);
But I still don't know how I can a acchieve sponaneous telephone number.
The 100 message is hop-by-hop, that is to say it just means the next hop got your request. Other messages will typically be end-to-end (so, if you got a 180 Ringing, that typically means the endpoint being called sent the 180). A 408 typically shows up when one of the hops sent the INVITE but never got a response (and your SIP stack might be generating that internally when it doesn't get a provisional response in a reasonable timeframe -- usually about 32 seconds with the default SIP timers).
I don't know your network setup, but there are several private IPs in that message (of the 192.168.x.x variety). If I had to guess, your first hop is sending the 100 back to the IP/port it received it from, but the next response is following the Via headers (as it should), and the hop after you isn't respecting the rport parameter, so the response is getting lost. Alternately, your NAT is poorly configured and is closing the hole it created for the INVITE too quickly.
If you have a proxy on the edge of your network that this message is going out, it is either putting bad Via headers on the message (possibly with the internal IP instead of the external IP) or it is sending the INVITE to the wrong place (causing it to never get a response), and the 408 is coming from it.

HtmlUnit webpage status code

I am trying to get the web status for a given page. However when its a 404 error, the page does not return the status code, rather it throws and error.
int status= webClient.getPage("website").getWebResponse().getStatusCode();
System.out.println( status);
Any Ideas?
I am looking to see when sites time out, however for testing purposes I malformed the url of the desired website to see if I can even see a 404.
According to this
You can do this:
webclient.setThrowExceptionOnFailingStatusCode(False)
****EDIT ***
This does print out your status code:
WebClient webClient = new WebClient();
webClient.setThrowExceptionOnFailingStatusCode(false);
int status = webClient.getPage("http://google.co.uk/ffffff").getWebResponse()
.getStatusCode();
System.out.println(status);
Prints out 404 - your status code.
Alternatively, you can continue to allow the FailingHttpStatusCodeException to be thrown (true). Then within the catch clause get the error status code.
...
int status = 0;
Object page = null;
try {
page = webClient.getPage(webRequest);
webClient.close();
if (page instanceof UnexpectedPage) {
status = ((UnexpectedPage) page).getWebResponse().getStatusCode();
} else if (page instanceof HtmlPage) {
status = ((HtmlPage) page).getWebResponse().getStatusCode();
}
// do something else ...
} catch (FailingHttpStatusCodeException | IOException e) {
if (e instanceof FailingHttpStatusCodeException) {
status = ((FailingHttpStatusCodeException) e).getStatusCode();
}
// do something else ...
}

Problem attempting to make a post to an odata server using odata4j in android/java

I'm attempting to use the odata4j lib to make an OData post to a client's server. I'm doing this by creating a custom CursorWrapper to get the type of each column. It seems that no matter what I do, I'm getting a '406 Not Acceptable' error.
The odata4j javadocs aren't the greatest and there is a severe lack of examples both at the odata4j site as well as from general google searches. I'm not even sure how to log what is being posted to the OData server (I'm sure that would make the error clear). There doesn't seem to be an obvious function to get the xml post to a string.
So, my question is a 2 part question:
1. How do you log the the transactions from the odata4j lib?
2. What, if anything, is wrong in my logic to make an OData post using odata4j?
I'm including a code snippet below. Any help would be greatly appreciated.
// Create the ODataConsumer with the appropriate credentials
OClientBehavior basicAuth = new BasicAuthenticationBehavior(Config.dbfile +
"\\" + Config.username, Config.password);
ODataConsumer consumer = ODataConsumer.create(url, basicAuth);
// Make sure there are results in the cursor
if ( cursorWrapper.moveToFirst() ){
// create the new product
OCreateRequest<OEntity> newMaterial =
consumer.createEntity( "ESvcOrderTrans" );
// Iterate through each cursor's row
while (cursorWrapper.isAfterLast() == false) {
// Iterate through each cursor's columns
for ( int i=1; i < cursorWrapper.getColumnCount(); i++ ){
// Determine type of key
switch ( cursorWrapper.getType(i) ){
case CustomCursorWrapper.FIELD_TYPE_INTEGER :
if (cursorWrapper.isNull(i)){
createRequest.properties(OProperties.null_(
cursorWrapper.getColumnName(i),
"Edm.Int32"));
} else {
createRequest.properties( OProperties.int32(
cursorWrapper.getColumnName(i),
cursorWrapper.getInt(i)));
}
break;
case CustomCursorWrapper.FIELD_TYPE_STRING :
if (cursorWrapper.isNull(i)){
createRequest.properties(OProperties.null_(
cursorWrapper.getColumnName(i),
"Edm.String"));
} else {
createRequest.properties(OProperties.string(
cursorWrapper.getColumnName(i),
cursorWrapper.getString(i)));
}
break;
case CustomCursorWrapper.FIELD_TYPE_FLOAT :
if (cursorWrapper.isNull(i)){
createRequest.properties(OProperties.null_(
cursorWrapper.getColumnName(i),
"Edm.Double"));
} else {
createRequest.properties(OProperties.decimal(
cursorWrapper.getColumnName(i),
cursorWrapper.getFloat(i)));
}
break;
case CustomCursorWrapper.FIELD_TYPE_BLOB :
if (cursorWrapper.isNull(i)){
createRequest.properties(OProperties.null_(
cursorWrapper.getColumnName(i),
"Edm.Binary"));
} else {
createRequest.properties(OProperties.binary(
cursorWrapper.getColumnName(i),
cursorWrapper.getBlob(i)));
}
break;
case CustomCursorWrapper.FIELD_TYPE_NULL :
break;
}
}
// Execute the OData post
newMaterial.execute();
// Move to the next cursor
cursorWrapper.moveToNext();
}
}
To log all http traffic:
ODataConsumer.dump.all(true);
Let me know what you find out.
Hope that helps,
- john

Categories