Get error stream from IOException - java

I am using library which issues HTTP request by calling
java.net.URL.getInputStream()
In the small portion of requests, it throws IOException. Message of this exception indicates that HTTP Error 500 has been processed.
I am concerned if I am able to get connection error stream from exception. I know that 500 indicates error in the requested API, but I would like to get as many information about error as possible.
I know that
java.net.URL.getInputStream()
is shorthand for
java.net.URL.getConnection().getInputStream()
and I could get error stream from java.net.HttpUrlConnection - but as library does this, it is not available for me.
The library is google geocoder for java, maven artifact
<dependency>
<groupId>com.google.code.geocoder-java</groupId>
<artifactId>geocoder-java</artifactId>
<version>0.16</version>
</dependency>
This is different from question that this question has been marked as duplicate of, as this is not about handling error from java.net.HttpConnection in general, but only in specific case where all I can do is only catching exception - if it is possible to obtain error stream from exception somehow.

Related

Get body detail message from throwable and assert that that exact message was returned when exception was thrown

I have a spring app that calls external APIs (I don't have control over this external project and its code). I am writing integration tests in my spring project. The test invoke those APIs. One of the API is throwing an exception for certain inputs:
On the tests, I am catching exception as:
Throwable throwable = catchThrowable(() -> TestHelper.createProduct(...));
assertThat(throwable)
.isInstanceOf(CustomException.class)
.hasMessageContaining(PRODUCT_CREATE_ERROR)
.hasCause(null);
I tried printing throwable.getMessage() and this is what it prints:
An internal error occurred: status code: [400], status text: [Bad Request],
headers: [[Transfer-Encoding:"chunked", Content-Type:"application/json; charset=utf-8", Server:"Kestrel", X-Powered-By:"ASP.NET", Date:"Fri, 10 Sep 2017 22:38:37 GMT"]],
body: [{"status":400,"detail":"Cannot create product."}]
I want to be able to capture the message "Cannot create product", I see in the message above and use that to confirm that this error message was returned, something like:
throwable.
.hasMessageContaining(capturedMessage)
Is there a way to get this message "Cannot create product.", I see in the body detail above (from exception.getMessage)
If I do something like: .hasMessageContaining("An internal error occurred"), it works, but I also want to be able to do something similar for the err text "Cannot create product.". How can I retrieve that specific text and say that this error was returned?
Give a try to hasStackTraceContaining, that should do the job.

Best way to handle badly written external exception?

I have an external service I'm calling that just returns 500's with the SAME exception each time no matter the issue.
For example(my api to their service):
Action: Fetch image that does not exist
IMGException: Status code: 500, ErrMsg: File not found
Action: Fetch image that does exist but there are server side issues
IMGException: Status code: 500, ErrMsg: Cannot grab img at this time
Action: Fetch image that does exist but is expired
IMGException: Status code: 500, ErrMsg: Img is expired
What would be the best way to handle this? I was catching them and giving them more descriptive messages to throw to my #ExceptionHandler for logging, etc. Should I just throw them and never catch them since I cannot dependably predict what the exception is caused from and therefore cannot correctly change the status code or message?
You can parse the ErrMsg and throw your own exceptions. But Since the response is from an external service, you can as well include the message from external service in the response to your API in a separate field like ExternalMessage.
This will help the users in case the response from external API changes and you end up throwing a different exception.
I recommend you to simply rethrow these exceptions with the information that the server sends to you and add any information you have. But do not add new information based on what you recieved (with if's, for example), because if they change something your code will just be deprecated.
Of course, never show crypt messages to your final user. In this case add some generic message with instructions about what they can do.

Hibernate - handling SQLException

All,
I am working on a project to upgrade hibernate from 4.1.4.FINAL to 5.2.17.FINAL. We have a bunch of Sybase stored procedures executed using org.hibernate.jdbc.Work. These stored procedures raise errors with some valid error codes like 20010. The error messages raised are caught and used to display on the UI. Here is the Sybase syntax to raise errors.
raiserror 20005 'Invalid'
I see that the new version of hibernate delegates SQL exceptions to convert to a specific exception in the JDBCException hierarchy. See -
org.hibernate.exception.internal.StandardSQLExceptionConverter
If it doesn't find a specific exception then it creates GenericJDBCException with a default message set. For example see
org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.coordinateWork -
Here the SQL exception is caught and the convert method is called with message 'error executing work'. So genericJDBCException.getMessage() will give this message.
I know that GenericJDBCException.getSQLException().getMessage() will give the actual sql exception message. But it is not feasible to change the existing code.
Is there a way to add our own delegate so that I can check the error code and return an exception with the message in SQLException. Or is there any better way to handle this?
Thanks

Catch a specific Elasticsearch exception from a BulkRequest

I use Java to index some documents with a BulkRequestinto Elasticsearch 1.4.2.
Some of these docs only need to be written when they are not already in the index, so I set the CREATE-opType like this:
indexRequestBuilder.opType(IndexRequest.OpType.CREATE)
Now the docs which were already in the index fail in the BulkResponse.
Error message bulkItemResponse.getFailureMessage():
DocumentAlreadyExistsException[...]
I want to ignore this class of exception but retry writing the docs for all other type of exceptions.
So how can I catch just the DocumentAlreadyExistsException?
I can get the Failure with bulkItemResponse.getFailure(), but I cannot find any information about the type of the Exception beside the error message.
I could look in the error-message for the exception name, but this may be rather fragile with new Elasticsearch versions:
if(bulkItemResponse.getFailureMessage().startsWith("DocumentAlreadyExistsException[")
Is there a better way?
This cant be possible. The bulk request is actaully executed on the server side and not client side. And hence all it can do is to sent the stacktrace back and not the Exception object.

Is there a neater way to analyse the AuthenticationException for the error code?

Is there a neater way to check the javax.naming.AuthenticationException (or spring) for the main failure reason? The different errors are desciribed in LDAP Wiki (Binding Errors).
The AuthenticationException provides no sufficient API to determine easily the error code. The only content is the exception message.
[LDAP: error code 49 - 80090308:
LdapErr: DSID-0C090334,
comment: AcceptSecurityContext error, data 773, vece]
The identifing block is the "data 773" – standing for the error ERROR_PASSWORD_MUST_CHANGE. But it feels very odd to me to check for message.contains("data 773")! Is there any better way to check the error code?
The snippet which throws the AuthenticationException is written with the org.springframework.security.ldap.DefaultSpringSecurityContextSource.
InitialLdapContext context = (InitialLdapContext) contextFactory
.getReadWriteContext(principal, password);
Unfortunately this is the only way I've seen it handled because the failure codes produced by the LDAP service I have experience with (Active Directory) always encodes the failure code in the message. Don't feel too bad even though it isn't a nice way to do things.
As far as I know, there is no better implementation for this. You could try providing a whole translation for the ldap error codes in an external file and use them to translate.

Categories