I'm getting the following findbugs error:
"Method call passes null for nonnull parameter : Null passed for nonnull parameter of getApiStatus(ApiResponse)"
If the apiResponse is null in the CallApi method (not shown here for brevity's sake), it simply throws an exception that is caught in handleApiException and thrown again if we can't do anything else about the exception.
There is no way that a null value for apiResponse could be passed into getApiStatus() method at the botton of this code snippit. How can I tell findbugs that this is the case without doing yet another null check on top of the null check that is done in the apiService.CallApi method? I've tried using the NonNull annotation, but that didn't resolve the issue. Here's the code in question:
ApiResponse apiResponse = null;
try {
apiResponse = apiService.CallApi(apiURL, requestObject);
}
catch (ApiException ex) {
handleApiException(ex);
}
boolean apiStatus = getApiStatus(apiResponse);
Any Ideas?
My suggestion would be to NOT handle the exception, but to set this method as throws ApiException. And then handle it higher up the chain. If your code gets an exeption in that try block, then handles the exception in the catch, then apiResponse can easily be null. And will then go on to try the getApiStatus method, hence passing in a null.
public void yourMethod() throws ApiException {
ApiResponse apiResponse = apiService.CallApi(apiURL, requestObject);
boolean apiStatus = getApiStatus(apiResponse);
// Whatever else you need to do here.
}
Your only other option is to put the apiStatus call below the apiResponse one inside the try block, like so:
ApiResponse apiResponse = null;
try {
apiResponse = apiService.CallApi(apiURL, requestObject);
boolean apiStatus = getApiStatus(apiResponse);
} catch (ApiException ex) {
handleApiException(ex);
}
Or, as you say, do a null check before calling getApiStatus, but that's not as preferable as the options above.
In your code, the getApiStatus(apiResponse) will be called regardless of the ApiException occurring or not.
You should have this instead:
try {
ApiResponse apiResponse = apiService.CallApi(apiURL, requestObject);
// line bellow will not execute if CallApi throws ApiException
boolean apiStatus = getApiStatus(apiResponse);
}
catch (ApiException ex) {
handleApiException(ex);
}
// lines bellow will execute after try-catch block above
// regardless of the ApiException occurring or not
If CallApi throws an exception, then it will be handled and control will continue to getApiStatus, without apiResponse ever being assigned anything other than the initial null.
Related
I have this catch statement:
catch (NotFoundException ex) {
ex.getError().setTitle(NOT_FOUND);
throw new NotFoundException(resource, id, ex.getError());
}
How can I mock this exception? I've tried this
when(service
.filter(eq(any()), eq(any()), eq(any())))
.thenThrow(new NotFoundException(anyString(), anyString()));`
But it gives me a null exception error because of this line:
ex.getError().setTitle(NOT_FOUND);
The constructor is:
public NotFoundException(String resource, String id, Error error) {
this.resource = resource;
this.ids = Collections.singletonList(id);
this.error = error;
}
And I can't get the exception variable to set the title, or find an way to mock it.
Thanks for you help!
.thenThrow(new NotFoundException(anyString(), anyString()));
This isn't allowed: anyString() only stands directly in for the call in when and verify. In your call to filter, simply use any() rather than eq(any()), but you're otherwise using matchers in the correct place.
Furthermore, it looks like your system-under-test assumes that ex.getError() is non-null; it is likely that you'll need to pass in a useful Error instance as constructor parameter into the NotFoundException you create.
.thenThrow(new NotFoundException("foo", "bar", new Error(/* ... */)))
Naturally, if your Error is difficult to create or work with, you might use a mock(Error.class) instead.
We have the following snippet of code in Spring-Boot:
#Value("${service.image.cloud.host}")
String imgUrl;
private final ImageValidationProperties imageValidationProperties;
public ImageResponse getImageslistFromCloud(String image, Integer cloud) {
String imageNumber = "0RC";
String url = imgUrl;
if (cloud != null) {
imageNumber = imageValidationProperties.getImagesFromCloud(cloud);
url = imageValidationProperties.getUrlFromCloud(cloud);
}
log.debug("Request images", imageNumber);
ResponseEntity<ImageResponse> imgResponse = null;
try {
RestTemplate template = new RestTemplate();
imgResponse = template.getForEntity(url.concat(imageNumber).concat(imgUrl), ImageResponse.class);
return imgResponse.getBody();
}
catch (Exception e) {
log.error("error: {}", e);
return imgResponse.getBody();
}
}
My supervisor told me that it could throw a Null Pointer Exception which is not handled, but I dont understand how it could be fixed. I have used try and catch already so I am not sure what could go wrong.
Someone has idea what could be wrong? I apperciate any help :)
#Value property is null because your Class doesn't have a Bean, try to annotate your class with #Service, #Component or even use a #Bean annotation.
Your catch block will throw a NullPointerException if template.getForEntity resulted in an HTTP error (e.g. if the resource could not be found). In this case imgResponse is still null and you call the getBody() method on it. Instead you should return null or use Optional as return type and return Optional.empty().
You should also avoid to catch the very common Exception and be more specific about the exceptions you want to catch.
In try block you instantiated imgResponse field.But, In catch block you directly returned response by using imgResponse.getBody(); statement. Which will possibly throw NullPointerException.
One best way to avoid NullPointerException is to use java.util.Optional. Which could potential save to break your code at runtime.
I think the problem is with imgResponse.getBody() in the catch block. imgResponse is still null in the catch block, which will throw NPE when imgResponse.getBody() is called.
Another place is: you need to initialize the variable imageValidationProperties as well, otherwise its method call will result in null pointer exception
(imageNumber = imageValidationProperties.getImagesFromCloud(cloud);
url = imageValidationProperties.getUrlFromCloud(cloud);)
I'm trying to get the same result as when I use #Valid in object parameter from a Controller. When the object is invalid an exception (MethodArgumentNotValidException) is throw by my ExceptionHandlerController who has #RestControllerAdvice.
In my case I want to validate an object, but I only can validate it in service layer. The object have bean validation annotations, so I'm trying to programmatically throw MethodArgumentNotValidException for my ExceptionHandlerController handle it, but I'm not having success.
So far I have this:
private void verifyCard(CardRequest card) {
BeanPropertyBindingResult result = new BeanPropertyBindingResult(card, "card");
SpringValidatorAdapter adapter = new SpringValidatorAdapter(this.validator);
adapter.validate(card, result);
if (result.hasErrors()) {
try {
throw new MethodArgumentNotValidException(null, result);
} catch (MethodArgumentNotValidException e) {
e.printStackTrace();
}
}
}
The first parameter is from type MethodParameter and I'm not been able to create this object. Is it the best way to handle my problem?
EDIT 1:
I can't remove the try/catch block. When I remove it I get compile error. How to work around?
You have already handled it by the catch block, you should remove try-catch to your global handler catch it.
then specify the method like below
private void verifyCard(CardRequest card) throws MethodArgumentNotValidException
MethodArgumentNotValidException is a subclass of Exception. This means that it's "checked": To throw it out of your verifyCard(..) method, you have to declare that verifyCard(..) can throw it:
private void verifyCard(CardRequest card) throws MethodArgumentNotValidException {
// your code
}
If you have lombok dependency in your project, you can also fake compiler by using #SneakyThrows annotation.
https://projectlombok.org/features/SneakyThrows
throw new MethodArgumentNotValidException(null, result);
Above constructor will not work as method parameter is necessary.
Valid constructor (reference) is:
MethodArgumentNotValidException(MethodParameter parameter, BindingResult bindingResult);
Hence, in your case:
throw new MethodArgumentNotValidException(new MethodParameter(
this.getClass().getDeclaredMethod("verifyCard", YourClassName.class), 0), errors);
I have actual method below:
public ResponseEntity<Message> catEnter(#PathVariable("catId") BigInteger catId, #RequestBody Catrequest catReq, HttpServletRequest request) throws CatDataException, InvalidCatExcecatption {
Message message = new Message();
try {
message = catManager.submitData(catReq.getMessage(), catId, request);
} catch (IOException e) {
throw new CatDataAppException(e.getMessage());
}
return (ResponseEntity<Message>) restResponse(message, request.getMethod());
// Getting null pointer exception in above line
}
I am using mockito for my test code as below:
#Test
public void submitData() throws Exception {
Message mes = new Message();
mes.setCode("00");
mes.setMessage("hi");
ResponseEntity<Message> responseentity = ((ResponseEntity<Message>) catController.catEnter(BigInteger.valueOf(3431), catRequest, mockRequest));
}
I'm getting null pointer exception, Message going as a null, even I set the value explicitly?
Here:
You pass mockRequest when making that call to your production code:
ResponseEntity<Message> responseentity = ... catController.catEnter(... mockRequest));
And your production call does:
return (ResponseEntity<Message>) restResponse(message, request.getMethod());
So the only conclussion: mockRequest is null!
So, first make sure that the passed variable is not null; like:
Request mockedRequest = mock(Request.class);
Or, use the #Mock annotation in case that mockedRequest is a field in your test class.
On top of that; you probably want to do some mock-specification, like:
when(mockedRequest.getMethod()).thenReturn( whatever )
But beyond that, you are lacking a lot of the fundamental basics of Java:
naming conventions: variable names go camelCase, like entityResponse. And typically, tests are named like testCatEnter to express the method that is tested.
You have casts ... where they are not required.
You have quite some code there ... that is unused, like the mes declaration in your test method.
Long story short: I have the feeling that you are overburdening yourself dramatically. First learn the basics; then go for the advanced Mockito stuff.
I have a super simple line:
JSONObject params = new JSONObject("{\"values\": { \"barcode\": \"testing\" } }");
Android studio tells me that this line 'throws JSONException', but why? I must be doing something stupid here. Any help is appreciated
JSONException is a checked exception. This means that you need to have code in place to deal with it. You need to either catch the exception or let it bubble up by declaring throws JSONException on your method.
This is the case for all checked exceptions in Java (all exception except those that extend RuntimeException).
In your case, since the String is constant and correct, I would do
} catch ( JSONException e) {
// should never happen
throw new IllegalArgumentException("unexpected parsing error",e);
}
This will convert the JSONException (if for some reason it does happen after all) into an (unchecked) RuntimeException.
public JSONObject(String source) throws JSONException {
this(new JSONTokener(source));
}
You are using above method/constrcutor to create your JSONObject and its saying in its signature that it throws JSONException so you can't simply do what you have done ,
JSONObject params = new JSONObject("{\"values\": { \"barcode\": \"testing\" } }");
You need to enclose above line in Java try- catch since method signature is clearly specifying a checked Exception so you need to handle that in try catch.
try{
JSONObject params = new JSONObject("{\"values\": { \"barcode\": \"testing\" } }");
}catch(JSONException ex){
//eat or rethrow your exception
}
You have to note that there are other JSONObject constructors which doesn't specify any checked exceptions so you can use those in a simple line, like you did but the one you are trying to use specifies a checked exception so you need to handle that - otherwise your code won't compile.