I have this code:
#SneakyThrows
public void startDatabase() throws NotBoundException, RemoteException {
entityRepository = new EntityRepositoryImpl(DatabaseManagerImpl.getInstance());
registrar = new RegistrarImpl(entityRepository);
String process = ManagementFactory.getRuntimeMXBean().getName();
registrar.register();
LOG.debug("Started database with process id: " + process);
}
In which it throws an exception NotBoundException, RemoteException adding the #SneakyThrows annotation makes the IDE report that both these two exceptions are not thrown by the method (anymore).
Does Lombok SneakyThrows actually stop an exception from propagating?
No, it does not prevent the exception from propagating.
#SneakyThrows can be used to sneakily throw checked exceptions without actually declaring this in your method's throws clause.
Reference: https://projectlombok.org/features/SneakyThrows
Related
I have below piece of code in my project. An exception is thrown at line # 4 still my product details are saved. I am having hard time to understand why does it save product details even after throwing the exception
I am also trying to understand if the exception thrown at line #4 is a checked or unchecked exception ? If i am throwing "throw new Exception("Details don't match")" it is a Runtime exception I am assuming?
class Product{
#Transactional
addDetails(){
try{
}
catch (Exception e) {
throw new Exception("Details dont match") //Line 4
}
productDAO.save(productDetails)
addAdditionalDetails(productDetails)
}
}
class ProductDAO {
#Transactional
public void save(Product productDetails){
entitiyManager.merge(productDetails)
}
}
I am also trying to understand if the exception thrown at line #4 is a
checked or unchecked exception?
Answer: java.lang.Exception is a checked exception.
If I am throwing "throw new Exception("Details don't match")" it is a
Runtime exception I am assuming?
Answer: No, it is not a RuntimeException. RuntimeException is those which extends java.lang.RuntimeException or its subclass.
In spring by Transaction is Rollback when a Runtime exception occurs. That means any exception thrown in a transaction which extends RuntimeException or its subclass will rollback it. But in your case, you are throwing Exception which is not a type of RuntimeException.
Solution:
I will suggest creating a Custom exception which extends RuntimeExction and throws it.
class UnmatchedDetailException extends RuntimeException{
UnmatchedDetailException(String msg){
super(msg);
}
}
And then throw the UnmatchedDetailException
throw new UnmatchedDetailException("Deatils not matched");
With default spring configurations, only un-checked runtime exceptions are rolled back. In order to customize this configuration, rollbackFor is used as a property in the #Transactional annotation.
For ex,
#Transactional(rollbackFor = { MyInvalidUserException.class,
MyApplicationException.class }) public void method() throws
MyInvalidUserException, MyApplicationException {
...
... }
Java 8
I have the following constructor I want to test using Mockito.
I want the test to throw an exception if a null is passed for the repository.
public PresenterImp(#Nonnull IRepository repository, IScheduler scheduler) {
super(schedulerFactory);
this.repository = Preconditions.checkNotNull(repository);
}
What would be the best way to do this? As my presenter is not a mock so I can’t use a when..
In my setup I do the following:
#Before
public void setup() throws Exception {
repository = Mockito.mock(IRepository.class);
iScheduler = Mockito.mock(IScheduler.class);
viewContract = Mockito.mock(ViewContract.class);
presenter = new PresenterImp(repository, iScheduler);
optInNotificationPresenter.attachView(viewContract);
}
Many thanks for any suggestions
Can do it as:
#Test(expected=NullPointerException.class )
public void testNullCheck() throws Exception
new PresenterImp(null, mock);
}
I have a Spring Boot application where I have methods in my Service layer like:
public List<PlacementDTO> getPlacementById(final int id) throws MctException {
List<PlacementDTO> placementList;
try {
placementList = placementDao.getPlacementById(id);
} catch (SQLException ex) {
throw new MctException("Error retrieving placement data", ex);
}
return placementList;
}
What is the best way to unit test that MctException will be thrown? I tried:
#Test(expected = MctException.class)
public void testGetPlacementByIdFail() throws MctException, SQLException {
when(placementDao.getPlacementById(15)).thenThrow(MctException.class);
placementService.getPlacementById(15);
}
However, this doesn't test the right that an exception is actually thrown.
I think you have to stub the placementDao.getPlacementById(15) call to throw the SQLException instead of your MctException, like this:
#Test(expected = MctException.class)
public void testGetPlacementByIdFail() throws MctException, SQLException {
when(placementDao.getPlacementById(15)).thenThrow(SQLException.class);
placementService.getPlacementById(15);
}
This way when you call your Service method placementService.getPlacementById(15); you know that your MctException will encapsulate the SQLException and therefore your test could expect the MctException exception to be thrown.
You may want to try out the ExepctionException rule feature of Junit. This would allow greater granularity in verification of your exception handling in your unit test than the expected exception annotation.
#Rule
public ExpectedException thrown= ExpectedException.none();
#Test
public void testGetPlacementByIdFail(){
thrown.expect(MctException.class);
thrown.expectMessage("Error retrieving placement data");
//Test code that throws the exception
}
As the above snippet show, you would also be able to test on various properties of the exception like its message.
Could you tell me please, is it normal practice to write a method (example: JUnit Test) that throws an Exception, for example:
class A {
public String f(int param) throws Exception {
if (param == 100500)
throw new Exception();
return "";
}
}
private A object = new A();
#Test
public void testSomething() throws Exception {
String expected = "";
assertEquals(object.f(5), expected);
}
In fact, method f() won't throw an exception for that parameter(5) but nevertheless I must declare that exception.
Yes it is completely fine, and if it does throw the exception the test will be considered as failed.
You need to specify that the method throws an Exception even if you know that the specific case does not (this check is done by the compiler).
In this case, what you expect is object.f(5) returns an empty string. Any other outcome (non-empty string or throwing an exception) would result in a failed test case.
A JUnit-Test is meant to test a given method for correct behavior. It is a perfectly valid scenario that the tested method throws an error (e.g. on wrong parameters). If it is a checked exception, you either have to add it to your test method declaration or catch it in the method and Assert to false (if the exception should not occur).
You can use the expected field in the #Test annotation, to tell JUnit that this test should pass if the exception occurs.
#Test(expected = Exception.class)
public void testSomething() throws Exception {
String expected = "";
assertEquals(object.f(5), expected);
}
In this case, the tested method should throw an exception, so the test will pass. If you remove the expected = Exception.class from the annotation, the test will fail if an exception occurs.
If the method you're calling throws a checked exception yes, you'll either need a try catch or to rethrow. It's fine to do this from the test itself. There are a variety of ways to test Exception using JUnit. I've tried to provide a brief summary below:
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
* Example uses Kent Beck - Test Driven Development style test naming
* conventions
*/
public class StackOverflowExample {
#Rule
public ExpectedException expectedException = ExpectedException.none();
#Test
// Note the checked exception makes us re-throw or try / catch (we're
// re-throwing in this case)
public void calling_a_method_which_throws_a_checked_exception_which_wont_be_thrown() throws Exception {
throwCheckedException(false);
}
/*
* Put the class of the specific Exception you're looking to trigger in the
* annotation below. Note the test would fail if it weren't for the expected
* annotation.
*/
#Test(expected = Exception.class)
public void calling_a_method_which_throws_a_checked_exception_which_will_be_thrown_and_asserting_the_type()
throws Exception {
throwCheckedException(true);
}
/*
* Using ExpectedException we can also test for the message. This is my
* preferred method.
*/
#Test
public void calling_a_method_which_throws_a_checked_exception_which_will_be_thrown_and_asserting_the_type_and_message()
throws Exception {
expectedException.expect(Exception.class);
expectedException.expectMessage("Stack overflow example: checkedExceptionThrower");
throwCheckedException(true);
}
// Note we don't need to rethrow, or try / catch as the Exception is
// unchecked.
#Test
public void calling_a_method_which_throws_an_unchecked_exception() {
expectedException.expect(Exception.class);
expectedException.expectMessage("Stack overflow example: uncheckedExceptionThrower");
throwUncheckedException();
}
private void throwCheckedException(boolean willThrow) throws Exception {
// Exception is a checked Exception
if (willThrow) {
throw new Exception("Stack overflow example: checkedExceptionThrower");
}
}
private void throwUncheckedException() throws NullPointerException {
// NullPointerException is an unchecked Exception
throw new NullPointerException("Stack overflow example: uncheckedExceptionThrower");
}
}
You can test that the exception is launched with this:
#Test(expected = ValidationException.class)
public void testGreaterEqual() throws ValidationException {
Validate.greaterEqual(new Float(-5), 0f, "error7");
}
I've created my own exception class:
public class ValidationException extends RuntimeException { ... }
I've declared it in EJB interface method:
public interface MyApi {
void save(MyDTO dto) throws ValidationException;
}
Now I've used it in the implementation:
#Stateless
#Local(MyApi.class)
public class MyService implements MyApi {
public void save(MyDTO dto) throws ValidationException {
...
throw ValidationException(errorMessages);
}
}
However, when I call that method:
#Path("/my")
#Stateless
public class MyChannel {
#Inject private MyApi myApi;
public void save(MyDTO dto) {
try{
myApi.save(dto);
} catch (ValidationException ex) {
// do sth with the exception
}
}
}
Instead of expected ValidationException, the EJBException is thrown with the following message:
0000167f BusinessExcep E CNTR0020E: EJB threw an unexpected (non-declared) exception during invocation of method "save" on bean
It surprised me, because the exception is declared in the interface and in the implementation. How else can I declare the exception, in order to be able to use it to communicate errors to the caller?
The whole mayhem happens on the WebSphere 8.5. I'm using EJB 3.0 and WebSphere libraries. The channel is JSON REST channel in the WAR module, which is wrapped in EAR module.
I believe the root of your problem lies in choosing to have your custom ValidationException extend RuntimeException. Within Java, RuntimeException or any subclass of RuntimeException does not have to be declared using a throws clause on a method signature. The intent of RuntimeException is that it is generally used in unrecoverable bug scenarios that are the result of something done incorrectly by the method caller, such as attempting to traverse beyond the end of an array (ArrayIndexOutOfBoundsException) or passing an invalid parameter (IllegalArgumentException).
Given that you would like to make your ValidationException part of the method signature and thereby require the calling client to handle the exception, I suggest the following change:
//Modify your exception so that it
//subclasses Exception (not RuntimeException):
public class ValidationException extends Exception { ... }
You will not have to modify the MyService interface, because the save method already declares that it throws the exception. But this small change will shift the way Java handles ValidationException so that when the exception is thrown, it will behave in the way you expect (and without the extraneous noise about an "undeclared" exception).
Use the #ApplicationException annotation. For example
#ApplicationException
public class ValidationException extends RuntimeException {
private static final long serialVersionUID = 7797343376699439504L;
}
You can use it with RuntimeException so you don't have to use throws declarations.