handle checked exception in RxJava 2 - java

I have some issue when I try to catch exception.
I have some method like this (legacy method) :
public String myLegacyMethod throws MyException() {
//do something or throw MyException in case of error
}
and I need to send a Single of this part and my solution is:
public Single<String> reactiveMethod() {
try {
String s = myLegacyMethod();
return Single.just(s);
} catch (Exception e) {
//log exception
return Single.error(e);
}
}
are there a way to handle an exception in reactive way? or maybe transform reactiveMethod in non-blocking code?
thanks for your answers.

You can use fromCallable in 2.x if MyException extends Exception:
public Single<String> reactiveMethod() {
return Single.fromCallable(() -> myLegacyMethod());
}

Related

How to unit test the catch exception statement?

How do I test the catch statement below? My coverlay is failing and I am not sure how to cover this line.
public Method execute(#NonNull final String test) throws ServiceException {
try {
object = javaClient.fetchInfo(test);
} catch (ClientException | InternalServerError e) {
throw serviceExceptionAdapter.apply(e);
}
return object;
}
This is currently what I have in my test file:
#BeforeEach
void setup() {
this.serviceExceptionAdapter = mock(ExceptionAdapter.class);
this.mockJavaClient = mock(JavaClient.class);
proxy = new Proxy(mockJavaClient, serviceExceptionAdapter);
}
#Test
void test_InternalServerError() {
when(mockJavaClient.fetchInfo(any())).thenThrow(InternalServerError.class);
when(serviceExceptionAdapter.apply(any())).thenThrow(ServiceException.class);
assertThrows(ServiceException.class, () -> proxy.execute(test));
verify(serviceExceptionAdapter, times(1)).apply(any());
}
I have to guess a little bit, as you didn't provide a full working example. From what I see in your catch block
} catch (ClientException | InternalServerError e) {
throw serviceExceptionAdapter.apply(e);
}
you expect the return value of your .apply(e) function to be an exception and throw that exception. In your test however, your mocked serviceExceptionAdapter doesn't return an Exception, but throws one instead:
when(serviceExceptionAdapter.apply(any()))
.thenThrow(ServiceException.class);
If my interpretations are correct, your code should work if you change the mentioned line in the test to the following:
when(serviceExceptionAdapter.apply(any()))
.thenReturn(new ServiceException(...));

JUnit test not catching exception

UPDATE: Here's the full test:
#Test(expected = NullPointerException.class)
public void testMissingData() throws Exception{
Resource<ObjectDataModel, Content, Status> resource = builder.build(content, argA1Response,
argA2Response, objFilterParam, argA3Response);}
And here's the build method:
public Resource<ObjectDataModel, Content, Status> build(Content argContent,
ResponseA1 argA1Response,
ResponseA2 argA2Response, String argObjectTypeFilter,
ResponseA3 argA3Response) {
try {
viewDataModel.setObjectType(this.buildObjectType(filteredObjectType,
argA1Response.getData().getDataObject().getCategories().get(0).getObjectTypes().get(0)));
}
catch (Exception e) {
String msg = "Exception occoured while buildng the Object Data Model";
LOG.error(msg, e);
}
// we have the required information gathered to return
return Resource.okFromDataAndContent(viewDataModel, argContent);
}
And here's the buildObjectType() method:
private ObjectType buildObjectType(ObjectTypes argA1ProductType,
PendingObjectTypes argA2ProductType) {
ProductType objectType = new ObjectType();
List<Plan> plans = argA1ObjectType.getPlan();
List<PendingObjectSummary> objPlans = argA1ObjectType.getData();
if (objectType.getData() == null) {
objectType.setData(new ArrayList<>());
}
PendingObjectSummary tempPlan = null;
for (Plan currPlan : plans) {
tempPlan = plans.stream()
.filter(plan -> plan.getObjId().equals(currPlan.getObjId()))
.findFirst()
.orElseThrow(NullPointerException::new);
}
return objectType;
}
I'm using an Optional to test for null and I can confirm that the exception is being thrown -- but JUnit isn't catching it. Here's the test case:
#Test(expected = NullPointerException.class)
public void testMissingData() throws Exception{
Object<> response = fixture.create();
assertNotNull(response);
assertNotNull(response.getData());
assertNull(resource.getData().getObjectType());
}
In my create method I'm simply iterating over a bunch of objects to try and find one that matches my ID; if not found then throw a NullPointerException:
for (Object currObj : objects) {
tempObj = myOtherCollection.stream()
.filter(obj -> obj.getId().equals(currObj.getId()))
.findFirst()
.orElseThrow(NullPointerException::new);
}
The JUnit output clearly isn't catching the exception - here's the output:
java.lang.AssertionError: Expected exception: java.lang.NullPointerException
And my tomcat logs are definitely throwing the exception here:
18:48:30.015 [main] ERROR com.myCompany.src.ModelBuilder - Exception occoured while buildng the Data Model
java.lang.NullPointerException: null
at java.util.Optional.orElseThrow(Optional.java:290)
The only issue I can see is that maybe where I assign tempObj that the code is wrong. Am I missing anything obvious? Thanks for any helpful tips.
You are catching the nullpointer exception so the exception is not propagated to your test.
see
try {
viewDataModel.setObjectType(this.buildObjectType(filteredObjectType,
argA1Response.getData().getDataObject().getCategories().get(0).getObjectTypes().get(0)));
}
catch (Exception e) {
String msg = "Exception occoured while buildng the Object Data Model";
LOG.error(msg, e);
}
If you want to test for an exception you could throw an exception in your error handling (for example a custom ObjectCreationExcepion) and assert that that one is thrown, like
try {
viewDataModel.setObjectType(this.buildObjectType(filteredObjectType,
argA1Response.getData().getDataObject().getCategories().get(0).getObjectTypes().get(0)));
}
catch (Exception e) {
String msg = "Exception occoured while buildng the Object Data Model";
LOG.error(msg, e);
throw new ObjectCreationException(msg);
}
and in your test
#Test(expected = ObjectCreationException.class)
public void testMissingData() throws Exception{
Object<> response = fixture.create();
}
#Test(expected = ObjectCreationException.class) only handles exceptions that are not handled within the tested code OR the test itself.
So what you could do is
public Resource<ObjectDataModel, Content, Status> build(Content argContent,
ResponseA1 argA1Response,
ResponseA2 argA2Response, String argObjectTypeFilter,
ResponseA3 argA3Response) throws NullPointerExceptions // << notice thrwoing declatration
{ // do some stuf}
and then in test you can handle it like you where trying by
public void testMissingData() throws Exception{
Resource<ObjectDataModel, Content, Status> resource = builder.build(content, argA1Response,
argA2Response, objFilterParam, argA3Response);
}

Throwing exception from CompletableFuture

I have the following code:
// How to throw the ServerException?
public void myFunc() throws ServerException{
// Some code
CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
try {
return someObj.someFunc();
} catch(ServerException ex) {
// throw ex; gives an error here.
}
}));
// Some code
}
someFunc() throws a ServerException. I don't want to handle this here but throw the exception from someFunc() to caller of myFunc().
Your code suggests that you are using the result of the asynchronous operation later in the same method, so you’ll have to deal with CompletionException anyway, so one way to deal with it, is
public void myFunc() throws ServerException {
// Some code
CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
try { return someObj.someFunc(); }
catch(ServerException ex) { throw new CompletionException(ex); }
});
// Some code running in parallel to someFunc()
A resultOfA;
try {
resultOfA = a.join();
}
catch(CompletionException ex) {
try {
throw ex.getCause();
}
catch(Error|RuntimeException|ServerException possible) {
throw possible;
}
catch(Throwable impossible) {
throw new AssertionError(impossible);
}
}
// some code using resultOfA
}
All exceptions thrown inside the asynchronous processing of the Supplier will get wrapped into a CompletionException when calling join, except the ServerException we have already wrapped in a CompletionException.
When we re-throw the cause of the CompletionException, we may face unchecked exceptions, i.e. subclasses of Error or RuntimeException, or our custom checked exception ServerException. The code above handles all of them with a multi-catch which will re-throw them. Since the declared return type of getCause() is Throwable, the compiler requires us to handle that type despite we already handled all possible types. The straight-forward solution is to throw this actually impossible throwable wrapped in an AssertionError.
Alternatively, we could use an alternative result future for our custom exception:
public void myFunc() throws ServerException {
// Some code
CompletableFuture<ServerException> exception = new CompletableFuture<>();
CompletableFuture<A> a = CompletableFuture.supplyAsync(() -> {
try { return someObj.someFunc(); }
catch(ServerException ex) {
exception.complete(ex);
throw new CompletionException(ex);
}
});
// Some code running in parallel to someFunc()
A resultOfA;
try {
resultOfA = a.join();
}
catch(CompletionException ex) {
if(exception.isDone()) throw exception.join();
throw ex;
}
// some code using resultOfA
}
This solution will re-throw all “unexpected” throwables in their wrapped form, but only throw the custom ServerException in its original form passed via the exception future. Note that we have to ensure that a has been completed (like calling join() first), before we query the exception future, to avoid race conditions.
For those looking for other ways on exception handling with completableFuture
Below are several ways for example handling Parsing Error to Integer:
1. Using handle method - which enables you to provide a default value on exception
CompletableFuture correctHandler = CompletableFuture.supplyAsync(() -> "A")
.thenApply(Integer::parseInt)
.handle((result, ex) -> {
if (null != ex) {
ex.printStackTrace();
return 0;
} else {
System.out.println("HANDLING " + result);
return result;
}
})
.thenAcceptAsync(s -> {
System.out.println("CORRECT: " + s);
});
2. Using exceptionally Method - similar to handle but less verbose
CompletableFuture parser = CompletableFuture.supplyAsync(() -> "1")
.thenApply(Integer::parseInt)
.exceptionally(t -> {
t.printStackTrace();
return 0;
}).thenAcceptAsync(s -> System.out.println("CORRECT value: " + s));
3. Using whenComplete Method - using this will stop the method on its tracks and not execute the next thenAcceptAsync
CompletableFuture correctHandler2 = CompletableFuture.supplyAsync(() -> "A")
.thenApply(Integer::parseInt)
.whenComplete((result, ex) -> {
if (null != ex) {
ex.printStackTrace();
}
})
.thenAcceptAsync(s -> {
System.out.println("When Complete: " + s);
});
4. Propagating the exception via completeExceptionally
public static CompletableFuture<Integer> converter(String convertMe) {
CompletableFuture<Integer> future = new CompletableFuture<>();
try {
future.complete(Integer.parseInt(convertMe));
} catch (Exception ex) {
future.completeExceptionally(ex);
}
return future;
}
Even if other's answer is very nice. but I give you another way to throw a checked exception in CompletableFuture.
IF you don't want to invoke a CompletableFuture in another thread, you can use an anonymous class to handle it like this:
CompletableFuture<A> a = new CompletableFuture<A>() {{
try {
complete(someObj.someFunc());
} catch (ServerException ex) {
completeExceptionally(ex);
}
}};
IF you want to invoke a CompletableFuture in another thread, you also can use an anonymous class to handle it, but run method by runAsync:
CompletableFuture<A> a = new CompletableFuture<A>() {{
CompletableFuture.runAsync(() -> {
try {
complete(someObj.someFunc());
} catch (ServerException ex) {
completeExceptionally(ex);
}
});
}};
I think that you should wrap that into a RuntimeException and throw that:
throw new RuntimeException(ex);
Or many be a small utility would help:
static class Wrapper extends RuntimeException {
private Wrapper(Throwable throwable) {
super(throwable);
}
public static Wrapper wrap(Throwable throwable) {
return new Wrapper(throwable);
}
public Throwable unwrap() {
return getCause();
}
}
public static void go() {
CompletableFuture<String> a = CompletableFuture.supplyAsync(() -> {
try {
throw new Exception("Just because");
} catch (Exception ex) {
throw Wrapper.wrap(ex);
}
});
a.join();
}
And then you could unwrap that..
try {
go();
} catch (Wrapper w) {
throw w.unwrap();
}

Throws own exception from validate in android simple framework

I am using Simple XML in my project and have following problem
Source code
#Root (name = "Test")
#Order (elements = { "UserName", .... })
public class Test
{
#Element
public String UserName;
#Validate
public void validate() throws Exception
{
if(UserName.length() > 10) {
throw new Exception("User ID is invalid");
}
}
};
In the main code I write something like this
try {
serializer.read(REQ.class, reader);
}
catch(Exception ex) {
Log.i(TAG, ex.getMessage()); <--- HERE I GET MESSAGE: null, not the one I throws.
}
Question
Look like I can't catch exception which I throws, like validate function get my exception and replace it with it's own one. So am I right and what I can do to throw my own exception?
Thank you G.BlakeMeike you were right, the solution is follow:
try {
serializer.read(REQ.class, reader);
}
catch(Exception ex) {
Log.i(TAG, ex.getCause().getMessage());
}

EasyMock to test SecurityException

I am trying to use easyMock to write a test, that tests SecurityException in the following code.
eg. for NumberFormatException I use the below.
EasyMock.expect(mockEntityManager.find(UserProfile.class,"abc")).andThrow(new
NumberFormatException());
Any ideas on what to expect to throw SecurityException?
public Object getAsObject(FacesContext facesContext, UIComponent
uiComponent, String s) {
EntityManager entityManager = (EntityManager)Component.getInstance("entityManager");
if (s == null || s.equals("null")) {
return null; } else {
try {
long i = Long.parseLong(s);
return entityManager.find(UserProfile.class, i);
} catch (NumberFormatException e) {
logger.error(e);
} catch (SecurityException e) {
logger.error(e);
} }
return null; }
I have the feeling that you haven't written that code, and that's why you're wondering what might throw SecurityException. The answer is nothing, as long as you're using a good implementation of EntityManager.
The documented version of EntityManager.find()enter link description here doesn't throw SecurityException. BUT if you're running that code inside a J2EE app server that uses a custom version of EntityManager, it could be that it throws that exception... But I don't think it should.
Thanks for your responses..here is what I did to expect SecurityException.
MyClass abc = new MyClass();
EasyMock.expect(mockEntityManager.find(MyClass.class,111L)).andThrow(new SecurityException());
EasyMock.replay(mockEntityManager);
Object target = abc.getAsObject(mockFacesContext, mockUiComponent,"111");
Assert.assertEquals(null, target);

Categories