please advise on the below scenario
How can I handle Http Status code
try {
validateUser(a,b);
} catch(HttpException he){
response = new ResponseEntity<>(status code);
}
....
validateUser(String a, String b) throws HttpException {
if(some condition) {
throw new HttpException(); // I want throw set status code to 401 so that I can catch it up there in catch block
}
}
import java.xml.ws.http.HTTPException;
try {
validateUser(a,b);
} catch(HTTPException he){
response = new ResponseEntity<>(HttpStatus.valueOf(he.getStatusCode()));
}
private void validateUser(String a, String b) throws HTTPException {
if(some condition) {
throw new HTTPException(HttpStatus.UNAUTHORIZED.value());
}
}
Related
In my Java project SonarQube says that an expression is always false. However I cannot see why. This is the code in question:
BaseException baseException = null;
for (SpaceInfo i: spaceInfos) {
try {
processSingle(i.getSpaceKey(), i.getContentType());
} catch (BaseException e) {
baseException = BaseException.chain(baseException, e);
}
}
// Here sonar say that this condition will always evaluate to false.
if (baseException != null) {
throw baseException;
}
However in my opinion if the processSingle method throws a BaseException then baseException should not be null and therefore the expression should not evaluate to false.
The processSingle method is declared as follows:
private void processSingle(String spaceKey, String contentType) throws BaseException
And there are definitely cases in which the processSingle method will throw a BaseException. So I think that Sonar is mistaken. Or is there something going on here that I am not seeing?
Update:
This is what BaseException.chain() does:
public static BaseException chain (BaseException a, BaseException b) {
if (a == null) { return b; }
a.setNextException(b);
return a;
}
And this is the code of processSingle:
private void processSingle(String spaceKey, String contentType) throws BaseException {
assert ContentTypes.Page.equals(contentType) || ContentTypes.BlogPost.equals(contentType);
Content content;
try {
content = createEmptyContent(spaceKey, contentType);
} catch (Exception e) {
throw new MessageToContentProcessorProcessSingleException(contentType, spaceKey, e);
}
BaseException baseException = null;
try {
contentCreator.addMetadata(content);
} catch (BaseException e) {
baseException = BaseException.chain(baseException, e);
}
Pair<List<AttachmentInfo>, FailedToSaveAttachmentException> pair = contentCreator.saveAttachments(messageParser.getContent(), content);
List<AttachmentInfo> attachments = pair.getLeft();
baseException = BaseException.chain(baseException, pair.getRight());
try {
String html = htmlGenerator.generateHtml(attachments, messageParser.getContent());
contentCreator.updateBodyOfContent(content, html);
} catch (BaseException e) {
baseException = BaseException.chain(baseException, e);
}
if (baseException != null) {
throw new MessageToContentProcessorProcessSingleException(contentType, spaceKey, baseException);
}
}
Just for testing/curiosity, I would try:
} catch (BaseException e) {
baseException = e;
}
this would show if Sonar thinks the exception can be thrown or not. Or if it is getting confused by the chain method or assignment statement (assigning to basseException but using it (still null) on the right side of assignment).
I know this is changing the logic, just for testing
even try (but I do not believe this would trick Sonar)
} catch (BaseException e) {
var tmp = BaseException.chain(baseException, e);
baseException = tmp;
}
Try changing chain() to help SonarQube:
public static BaseException chain (BaseException a, BaseException b) {
if (a == null) {
return b;
} else {
a.setNextException(b);
return a;
}
}
thinking about it, hardly possible to be the problem - almost trivial that a is not null here
I would try and see if it works:
BaseException baseException;
for (SpaceInfo i: spaceInfos) {
try {
processSingle(i.getSpaceKey(), i.getContentType());
baseException = null;
} catch (BaseException e) {
baseException = BaseException.chain(baseException, e);
}
}
Can this func. not be prettified?
Can the the catch clause be left empty, I have heard it's frowned up on.
apiClient.accountList() is where the exception can occur.
public Optional<Account> getAccount(String accountUuid) throws ApiException {
try {
for (Account account : apiClient.accountList()) {
if (account.getUuid().equals(accountUuid)) {
return Optional.of(account);
}
}
} catch (ApiException e) {
return Optional.empty();
}
return Optional.empty();
}
If you're very motivated to avoid the duplicate return statement, a simple tweak to the control-flow should do it. As mentioned in the comments, logging exceptions is often a good idea.
public Optional<Account> getAccount(String accountUuid) throws ApiException {
Optional<Account> result = Optional.empty();
try {
for (Account account : apiClient.accountList()) {
if (account.getUuid().equals(accountUuid)) {
result = Optional.of(account);
break;
}
}
}
catch (ApiException e) { /* Log exception */ }
return result;
}
You can use Stream, assuming getUuid does not throw an ApiException.
public Optional<Account> getAccount(String accountUuid) throws ApiException {
try {
return apiClient.accountList().stream()
.filter(account -> account.getUuid().equals(accountUuid))
.findAny();
} catch (ApiException e) {
/* Log exception */
return Optional.empty();
}
}
Actually instead of collection returning methods like accountList() it more and more makes sense to use Streams, accountStream().
I put a simple retry because the operation can rarely fail. The simplified code is below. The method putObject can accidentally throw an exception, in this case the retry should allow to invoke this method again. Is it possible to write a JUnit test for this?
I know that with Mockito library we can force to throw an Exception invoking a method but how to force this exception to be thrown only once?
public class RetryExample {
Bucket bucket = new Bucket();
static int INTERNAL_EXCEPTION_CODE = 100;
class AException extends RuntimeException {
private static final long serialVersionUID = 1L;
int statusCode;
public int getStatusCode() {
return statusCode;
}
}
class Bucket {
public void putObject(String fileName, byte[] data) throws AException {
System.out.println("PutObject=" + fileName + " data=" + data);
}
}
public void process(String fileName, byte[] data) throws AException {
try {
retryOperation((f, d) -> bucket.putObject(f, d), fileName, data);
} catch (Exception ex) {
throw new AException("Failed to write data", ex);
}
}
private <T, U> void retryOperation(BiConsumer<T, U> biConsumer, T t, U u) {
int retries = 0;
boolean retry = false;
AException lastServiceException = null;
do {
try {
biConsumer.accept(t, u);
} catch (AException e) {
lastServiceException = e;
int statusCode = e.getStatusCode();
if (statusCode == INTERNAL_EXCEPTION_CODE) {
throw e;
} else {
break;
}
}
retries++;
if (retries >= 3) {
retry = false;
}
} while (retry);
if (lastServiceException != null) {
throw lastServiceException;
}
}
Test Class:
public class RetryExampleTest {
...
#Test
public void test() {
RetryExample retryExample = new RetryExample();
String fileName = "TestFile";
byte[] data = simulatedPayload(10000);
try {
retryExample.process(fileName, data);
} catch (Exception e) {
fail("Exception thrown=" + e);
}
}
According to the Mockito documentation you can set different behavior for consecutive method calls.
when(mock.someMethod("some arg"))
.thenThrow(new RuntimeException())
.thenReturn("foo");
In case of a void method you can do something similar (Mockito documentation)
doThrow(new RuntimeException())
.doNothing()
.when(mock).doSomething();
I think you can use a global data object to store the times of throw Exceptions, so in the Mockito library invoke the Exception method just taken the global data object to record the times. It would be simple. Just all by your control.
When I create custom Call class I can't return Response, because Response class is final. Is there any workaround for this?
public class TestCall implements Call<PlacesResults> {
String fileType;
String getPlacesJson = "getplaces.json";
String getPlacesUpdatedJson = "getplaces_updated.json";
public TestCall(String fileType) {
this.fileType = fileType;
}
#Override
public Response execute() throws IOException {
String responseString;
InputStream is;
if (fileType.equals(getPlacesJson)) {
is = InstrumentationRegistry.getContext().getAssets().open(getPlacesJson);
} else {
is = InstrumentationRegistry.getContext().getAssets().open(getPlacesUpdatedJson);
}
PlacesResults placesResults= new Gson().fromJson(new InputStreamReader(is), PlacesResults.class);
//CAN"T DO IT
return new Response<PlacesResults>(null, placesResults, null);
}
#Override
public void enqueue(Callback callback) {
}
//default methods here
//....
}
In my unit test class I want to use it like this:
Mockito.when(mockApi.getNearbyPlaces(eq("testkey"), Matchers.anyString(), Matchers.anyInt())).thenReturn(new TestCall("getplaces.json"));
GetPlacesAction action = new GetPlacesAction(getContext().getContentResolver(), mockEventBus, mockApi, "testkey");
action.downloadPlaces();
My downloadPlaces() method look like:
public void downloadPlaces() {
Call<PlacesResults> call = api.getNearbyPlaces(webApiKey, LocationLocator.getInstance().getLastLocation(), 500);
PlacesResults jsonResponse = null;
try {
Response<PlacesResults> response = call.execute();
Timber.d("response " + response);
jsonResponse = response.body();
if (jsonResponse == null) {
throw new IllegalStateException("Response is null");
}
} catch (UnknownHostException e) {
events.sendError(EventBus.ERROR_NO_CONNECTION);
} catch (Exception e) {
events.sendError(EventBus.ERROR_NO_PLACES);
return;
}
//TODO: some database operations
}
After looking at retrofit2 Response class more thoroughly I've found out that there is a static method that do what I need. So, I simply changed this line:
return new Response<PlacesResults>(null, placesResults, null);
to:
return Response.success(placesResults);
Everything works now.
try
{
if(ruleName.equalsIgnoreCase("RuleName"))
{
cu.accept(new ASTVisitor()
{
public boolean visit(MethodInvocation e)
{
if(rule.getConditions().verify(e, env, parentKeys, astParser, file, cu)) // throws ParseException
matches.add(getLinesPosition(cu, e));
return true;
}
});
}
// ...
}
catch(ParseException e)
{
throw AnotherException();
}
// ...
I need to catch thrown exception in the bottom catch, but I cannot overload method via throws construction. How to do with that, please advice? Thanks
Create custom exception, write try catch block in anonymous class and catch it in your catch block.
class CustomException extends Exception
{
//Parameterless Constructor
public CustomException () {}
//Constructor that accepts a message
public CustomException (String message)
{
super(message);
}
}
now
try
{
if(ruleName.equalsIgnoreCase("RuleName"))
{
cu.accept(new ASTVisitor()
{
try {
public boolean visit(MethodInvocation e)
{
if(rule.getConditions().verify(e, env, parentKeys, astParser, file, cu)) // throws ParseException
matches.add(getLinesPosition(cu, e));
return true;
}
catch(Exception e){
throw new CustomException();
}
});
}
// ...
}
catch(CustomException e)
{
throw AnotherException();
}
As suggested already, an unchecked exception could be used. Another option is to mutate a final variable. Eg:
final AtomicReference<Exception> exceptionRef = new AtomicReference<>();
SomeInterface anonymous = new SomeInterface() {
public void doStuff() {
try {
doSomethingExceptional();
} catch (Exception e) {
exceptionRef.set(e);
}
}
};
anonymous.doStuff();
if (exceptionRef.get() != null) {
throw exceptionRef.get();
}