Overloading the getCause() method in a throwable object - java

How would one go about overloading the getCause() method in a throwable object ?
I have the following but it doesn't seem to work as it says that it cannot be overloaded with a string.
public class MyException extends RuntimeException {
String cause;
MyException(String s) {
cause = s;
}
#Overwrite public String getCause() {
return cause;
}

It is illegal to have two methods that only differ in their return type. Suppose someone wrote:
Object obj = myException.getCause();
That is perfectly legal java, and the compiler has no way to figure out if it's the String version or the Throwable version.
Likewise you can't replace the superclass signature since this is also perfectly legal:
Throwable t = new MyException();
Throwable t0 = t.getCause();
//Returns String?!?!?!?

Accepted answer clears the point :
It is illegal to have two methods that only differ in their return
type
But if you have a situation where, getCause() should return the custom cause in MyException, in case original cause is null.
In that case, you can use initCause() to set the cause and override toString() method. So, when getCause() method will be called on object of MyException, it will show the message from customCause instead of null.
What is the use: In legacy system, if you have used getCause() on MyException object while logging, and now you want to add the custom cause to it without changing lot of code, here is the way.
public class MyException extends RuntimeException {
String customCause;
MyException(String s) {
super(s);
customCause = s;
}
#Override
public synchronized Throwable getCause() {
if (super.getCause() != null) {
return this;
} else {
this.initCause(new Throwable(customCause));
return this;
}
}
#Override
public String toString() {
String s = getClass().getName();
String message = getLocalizedMessage();
if (message == null) {
message = customCause;
}
return (message != null) ? (s + ": " + message) : s;
}
}
References:
https://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html#initCause(java.lang.Throwable)
https://docs.oracle.com/javase/7/docs/api/java/lang/Throwable.html

Related

Avoiding code duplication when checking for default responses

I have a Java program that calls an external API (RealApi in the code below) and sometimes I want to avoid calling this API and instead return pre-constructed responses (generated by FakeApi).
So, I ended up duplicating this kind of construct in most of my methods:
public Type1 m1(String s) {
try {
Type1 r = FakeApi.m1(s);
if (r != null) {
return r;
}
} catch (Exception e) {
// log error
}
return RealApi.m1(s);
}
What are some options to avoid duplicating this try/catch block everywhere? It's important that if FakeApi throws an exception or returns null, the RealApi must be called.
One option would be encapsulate the error checking behaviour into its own method:
public <T> T fakeOrReal(Supplier<T> fake, Supplier<T> real) {
try {
T r = fake.get();
if (r != null) {
return r;
}
}
catch (Exception e) {
// log error
}
return real.get();
}
You can then just call it with
public Type1 m1(String s) {
return fakeOrReal(() -> FakeApi.m1(s), () -> RealApi.m1(s));
}
This is not as simple as Thomas Preißler's answer but it will help you not repeat any method at all. So if you expand the interface, you have to modify only the concrete classes and not the linker which describes the actual behavior you want.
Create an interface that contains all the methods of RealApi:
interface Api {
Type1 m1(String s);
}
Then a class that does the actual call:
class ConcreteApi implements Api {
public Type1 m1(String s) {
return RealApi.m1(s);
}
}
Then create your FakeApi:
class TotallyFakeApi implements Api {
public Type1 m1(String s) {
return FakeApi.m1(s);
}
}
Now, the tricky part to avoid repeating yourself:
private static Object callImplementation(Api api, Method method, Object[] methodArgs) throws Exception {
Method actualMethod = api.getClass().getMethod(actualMethod.getName(), actualMethod.getParameterTypes());
return actualMethod.invoke(api, methodArgs);
}
Api fakeOrReal(Api fakeApi, Api realApi) {
return (Api) Proxy.newProxyInstance(
FakeApi.class.getClassLoader(),
new Class[]{Api.class},
(proxy, method, methodArgs) -> {
try {
Object r = callImplementation(fakeApi, method, methodArgs);
if (r != null) {
return r;
}
} catch (Exception e) {
// logError(e);
}
return callImplementation(realApi, method, methodArgs);
}
);
}
Get the actual implementation like this:
Api apiToUse = fakeOrReal(new TotallyFakeApi(), new ConcreteApi());

Generalize safe cast functions in Java

I have a Java class that does nothing else than safely cast a number of objects to their expected classes, and returns a descriptive error message if the cast fails. They all look like this:
public static RequirementId castToRequirementID(Object value) throws WrongObjectTypeException {
Class<?> expectedClass = RequirementId.class;
Class<?> actualClass = value.getClass();
if(actualClass == expectedClass) {
RequirementId requirementID = (RequirementId) value;
return requirementID;
}
String errorMessage = "Value was of wrong type";
throw new WrongObjectTypeException(errorMessage, expectedClass, actualClass);
}
public static RequirementProjectInformation castToRequirementProjectInformation(Object value) throws WrongObjectTypeException {
Class<?> expectedClass = RequirementProjectInformation.class;
Class<?> actualClass = value.getClass();
if(actualClass == expectedClass) {
RequirementProjectInformation requirementProjectInformation = (RequirementProjectInformation) value;
return requirementProjectInformation;
}
String errorMessage = "Value was of wrong type";
throw new WrongObjectTypeException(errorMessage, expectedClass, actualClass);
}
As you can see, these functions are mostly identical, except for the fact that I need to change the expectedClass in the first line of each function, and the cast in the fourth line of each function. That makes me want to generalize this in some way, for example:
public static MongoDB_ObjectAddress safelyCast(Object value, Class<?> expectedClass) throws WrongObjectTypeException {
Class<?> actualClass = value.getClass();
if(actualClass == expectedClass) {
expectedClass castedObject = (expectedClass) value;
return castedObject;
}
String errorMessage = "Value was of wrong type";
throw new WrongObjectTypeException(errorMessage, expectedClass, actualClass);
}
However, the above statement does not work since I can't use expectedClass in place of the actual class name in the declaration and the cast.
Is there some clever way to do this? Or is this simply impossible in Java?
You can use the Class.cast method:
public static <T> T safelyCast(Object value, Class<T> expectedClass) throws WrongObjectTypeException {
if (expectedClass.isInstance(value)) {
return expectedClass.cast(value);
} else {
String errorMessage = "Value was of wrong type";
throw new WrongObjectTypeException(errorMessage, expectedClass, value.getClass());
}
}
I must say I don't see much point in this WrongObjectTypeException, it doesn't give you more information than the ClassCastException you would get normally.

Is it right way for handling exceptions using Apache ExceptionUtils.getRootCause?

Is it possible, that below condition in "My code" will be fulfilled(true)? I belive that no, beacuse getRootCause returns object casted to Throwable. So it should check, if Throwable is a subtype of MyOwnException, which is not true. So, in general, it is wrong way to use getRootCause to handle exceptions, is not it?
MyOwnException part
public class MyOwnException extends Exception {
// ....
}
Apache's ExceptionUtils.getRootCause
public static Throwable getRootCause(Throwable throwable) {
List list = getThrowableList(throwable);
return (list.size() < 2 ? null : (Throwable)list.get(list.size() - 1));
}
My code
try {
// do something
} catch (Exception e) {
try {
Throwable exc = ExceptionUtils.getRootCause(e);
if (exc instanceof MyOwnException) {
// do something
}
}
}
instanceof will check against the actual run-time type of an object instance. It does not matter what the declared compile-time type of the variable that holds the object is.
So your condition works: If the root cause is a MyOwnException then your if block's body will execute.

Is there a nicer (java8?) way to collect the "cause stack" of an exception?

We have a BaseException extends Exception in our project, and basically all our other exceptions derive from this class. I want to change some methods that deal with the "cause stack" at runtime.
As starting point, I wrote the following method:
class BaseException extends Exception {
...
/**
* Helper: creates a list containing the complete "cause stack" of this exception.
* Please note: the exception on which this method is called is part of result!
*
* #return a {#link List} of all "causes" of this exception
*/
List<Throwable> getAllCauses() {
Throwable cause = this;
List<Throwable> causes = new ArrayList<>();
while (cause != null) {
causes.add(cause);
cause = cause.getCause();
}
return causes;
}
This gets the job done, although it is not perfect (name isn't exactly great, and single layer of abstraction is violated, too) .
But still: is there a "more elegant" way of collecting this result? Especially given the fact that it would helpful to directly return a Stream<Throwable>.
( I am mainly wondering if there is a java8 lambda/idiom that could help here )
This article should be of help. In particular,
Stream<Throwable> causes(Throwable t){
if (t == null) return Stream.empty();
return Stream.concat(Stream.of(t), causes(t.getCause()));
}
Here is my implementation that implemented by Spliterator as below:
public static <T> Stream<T>
iterateUntil(T seed, UnaryOperator<T> generator, Predicate<T> proceed){
return stream(new AbstractSpliterator<T>(Long.MAX_VALUE, Spliterator.ORDERED){
private T value = seed;
public boolean tryAdvance(Consumer<? super T> action){
if(!proceed.test(value)) return false;
action.accept(value);
value = generator.apply(value);
return true;
}
}, false);
}
Then you can implements your getCauses as below and it drop the recursive calls:
List<Throwable> getAllCauses() {
return iterateUntil(this, Throwable::getCause, Objects::nonNull)
.collect(toList());
}
Using some enumeration seems more appropriate to me, then something like
class BaseException extends Exception {
...
Enumeration<Throwable> getCauses() {
return new Enumeration<Throwable>() {
private Throwable current = BaseException.this;
public boolean hasMoreElements() {
return current != null;
}
public Throwable nextElement() {
Throwable c = current;
current = current.getCause();
return c;
}
}
}
With Java 8 you can also create a new interface with a default method doing the trick and then use that interface in any of your exception class (slightly better than subclassing Exception?).

Mockito defining 'when' invokes the answer

I need to mock a JDBC update statement, and I want to make sure that the update string sent is the correct one. I have a MockConnectionManager that has the following method defined for defining the expected query strings:
public void setUpdateExpectedQuery(String ...expectedQueryStrings) throws SQLException {
Statement mockStatement = mock(Statement.class);
when(mockConnection.createStatement()).thenReturn(mockStatement);
when(mockStatement.executeUpdate(anyString())).then(new Answer<String>() {
#Override
public String answer(InvocationOnMock invocationOnMock) throws Throwable {
String str = Arrays.toString(invocationOnMock.getArguments());
throw new RuntimeException("Update string is not as expected: " + str);
}
});
for(String expected : expectedQueryStrings) {
when(mockStatement.executeUpdate(expected)).then(new Answer<Void>() {
#Override
public Void answer(InvocationOnMock invocationOnMock) throws Throwable {
// Do something, just don't throw an exception here.
return null;
}
});
}
}
I want that if an unexpected query string was encountered an exception will be thrown. The query strings we expect are below as mentioned in the Mockito wiki (http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#2).
For some reason, when executing the test and just calling the setUpdateExpectedQuery, an exception is thrown.
MockConnectionManager connectionManager = (MockConnectionManager) context.getBean("connectionManager");
connectionManager.setUpdateExpectedQuery("INSERT WHATEVER INTO WHENEVER");
The same exception as written in the first Answer: java.lang.RuntimeException: Update string is not as expected: [INSERT WHATEVER INTO WHENEVER]
How is this possible? is calling 'when' actually invokes the method? I never saw it happening in other cases...
I suspect the problem is that your calls within the loop (when you call mockStatement.executeUpdate(expected)) match your earlier mock of when(mockStatement.executeUpdate(anyString())).
Remember that the way the mock knows what you're calling within the when is because you're calling it - imagine translating when(mockStatement.executeUpdate(anyString())) into:
int result = mockStatement.executeUpdate(anyString());
OngoingStubbing<Integer> tmp = when(result);
tmp.then(...);
It may be that you just need to have a single when(...) call. So:
public void setUpdateExpectedQuery(String ...expectedQueryStrings)
throws SQLException {
final Set<String> capturedQueries = new HashSet<>
(Arrays.asList(expectedQueryStrings);
Statement mockStatement = mock(Statement.class);
when(mockConnection.createStatement()).thenReturn(mockStatement);
when(mockStatement.executeUpdate(anyString())).then(new Answer<String>() {
#Override
public String answer(InvocationOnMock invocationOnMock) throws Throwable {
String query = (String) invocationOnMock.getArguments[0];
if (capturedQueries.contains(query)) {
return null;
}
throw new RuntimeException("Update string is not as expected: " + query);
}
});
}

Categories