I have a requirement of exception handling for all methods, suppose that I have a project and within the project, the StaleStateException is thrown, and I need to handle it, I want to do it like this:
class Util() {
public static void handle(XXXX method) {
try{
//invoke method
} catch(StaleStateException e) {
//do something
}
}
}
How can I implement this method?
Here is another way to do this:
public class Methods {
public static void someMethodToPass(String s){
System.out.println("Invoked, Here is the argument: " + s);
}
public static void invokerMethod(Method m) throws InvocationTargetException, IllegalAccessException {
m.invoke(null,"Some argument");
}
public static void main(String[] args) {
try {
invokerMethod(Arrays.stream(Methods.class.getMethods()).filter(m -> m.getName().equals("someMethodToPass")).findFirst().get());
} catch (InvocationTargetException | IllegalAccessException e) {
e.printStackTrace();
}
}
}
Function<InputType, Void> = input -> {
// do stuff
System.out.println(input.toString());
}
class Util() {
public static void handle(Function<InputType, Void> method) {
try{
input.apply(input);
} catch(StaleStateException e) {
//do something
}
}
}
Related
I'm trying to return the stats object.
But I'm getting
local variables referenced from an inner class must be final or
effectively final
on stats = statistics; How can I return the object but make sure .close(); is run?
public static Statistics getStatistics(String environmentName) {
Container container = getContainer(environmentName);
Statistics stats = new Statistics();
try {
dockerClient().statsCmd(container.getId()).exec(new ResultCallback<Statistics>() {
#Override
public void onStart(Closeable closeable) {
}
#Override
public void onNext(Statistics statistics) {
stats = statistics;
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onComplete() {
}
#Override
public void close() throws IOException {
}
}).close();
} catch (IOException e) {
e.printStackTrace();
}
return stats;
}
You want to call getStatistics and immediately use the resulting stats. This is called synchrone usage.
But in effect one can only asynchroneously being informed by the callback that the statistics are finally arrived.
So change:
f(String env) {
Statistics stats = getStatistics(env);
g(stats);
}
to
f(String env) {
retrievStatistics(env);
}
public static void retrieveStatistics(String environmentName) {
Container container = getContainer(environmentName);
stats = null;
try {
dockerClient().statsCmd(container.getId()).exec(new ResultCallback<Statistics>() {
Statistics stats;
#Override
public void onNext(Statistics statistics) {
g(statistics);
stats = statistics; // Alternative when using onComplete instead.
}
#Override public void onStart(Closeable closeable) {}
#Override public void onError(Throwable throwable) { }
#Override public void onComplete() {
g(stats); // Or this
}
#Override public void close() throws IOException { }
}).close();
} catch (IOException e) {
e.printStackTrace();
}
}
A busy wait loop as you did, is suboptimal.
You can try to use java.util.concurrent.CompletableFuture (java 8).
In this case:
public static Statistics getStatistics(String environmentName) {
Container container = null;
CompletableFuture<Statistics> future = new CompletableFuture<>();
try {
dockerClient().statsCmd(container.getId()).exec(new ResultCallback<Statistics>() {
#Override
public void onStart(Closeable closeable) {
}
#Override
public void onNext(Statistics statistics) {
if (!future.isDone()) {
future.complete(statistics);
}
}
#Override
public void onError(Throwable throwable) {
future.completeExceptionally(throwable);
}
#Override
public void onComplete() {
if (!future.isDone()) {
future.complete(null);
}
}
#Override
public void close() throws IOException {
}
}).close();
} catch (IOException e) {
e.printStackTrace();
}
try {
// wait until statistics resolved
return future.get();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
}
Alternatively, if the exec code is synchronous, you can use AtomicReference, for example, as a temporal container. The approach will be similar to CompletableFuture example above, but with less overhead
You're creating an anonimous inner class:
new ResultCallback<Statistics>() { #Override public void onStart(Closeable closeable) { } #Override public void onNext(Statistics statistics) { stats = statistics; } #Override public void onError(Throwable throwable) { } #Override public void onComplete() { } #Override public void close() throws IOException { } }).close();
The problem is that you're defining the stats in the method which is unnecessary because you're defining it again in the anonymous inner class #Override public void onNext(Statistics statistics) { stats = statistics; }
Instead, try to declare the variable directly in the class and initialize in null. Inside function only redefine it in the anonymous class.
I've been trying to create a general trycatch method like this:
public static void tryCatchAndLog(Runnable tryThis) {
try {
tryThis.run();
} catch (Throwable throwable) {
Log.Write(throwable);
}
}
However I get an unhandled exception if I try to use it like this:
tryCatchAndLog(() -> {
methodThatThrowsException();
});
How can I implement this so that the compiler knows that tryCatchAndLog will handle the Exception?
Try this :
#FunctionalInterface
interface RunnableWithEx {
void run() throws Throwable;
}
public static void tryCatchAndLog(final RunnableWithEx tryThis) {
try {
tryThis.run();
} catch (final Throwable throwable) {
throwable.printStackTrace();
}
}
Then this code compiles:
public void t() {
tryCatchAndLog(() -> {
throw new NullPointerException();
});
tryCatchAndLog(this::throwX);
}
public void throwX() throws Exception {
throw new Exception();
}
Change Runnable to custom interface that is declared to throw Exception:
public class Example {
#FunctionalInterface
interface CheckedRunnable {
void run() throws Exception;
}
public static void main(String[] args) {
tryCatchAndLog(() -> methodThatThrowsException());
// or using method reference
tryCatchAndLog(Example::methodThatThrowsException);
}
public static void methodThatThrowsException() throws Exception {
throw new Exception();
}
public static void tryCatchAndLog(CheckedRunnable codeBlock){
try {
codeBlock.run();
} catch (Exception e) {
Log.Write(e);
}
}
}
"Added more details"
I want to Mock a certain void method but i'm not quite sure how to. I read about EasyMock but i don't know what to do when it's a void method, This is my main class;
Main class
public class Main {
Updater updater = new Updater(main.getID(), main.getName(),....);
try {
updater.updateContent(dir);
}
i want to mock updater.updateContent(dir); so that i can skip the try
Updater class
private String outD;
public void updateContent(final String outDir) throws Exception {
outD = outDir;
if (...) {
....;
}
}
... private void methods
This is my test class so far,
public class MainTest {
#Before
public void setUp() {
}
#Test
public void testMain() {
try {
try {
Updater updater = EasyMock.createNiceMock(Updater.class);
updater.updateContent("/out");
EasyMock.expectLastCall().andThrow(new RuntimeException());
EasyMock.replay(updater);
updater.updateContent("/out");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
(edited) thanks.
For methods returning void you must record the behavior this way:
Updater updater = EasyMock.createNiceMock(Updater.class);
updater.updateContent("someDir"); // invoke the easy mock proxy and
// after invoking it record the behaviour.
EasyMock.expectLastCall().andThrow(new RuntimeException()); // for example
EasyMock.replay(updater);
updater.updateContent("someDir"); // will throw the RuntimeException as recorded
Expect you have the following Main class
public class Main {
private Updater updater;
private int updatedContentCount; // introduced for the example
public Main(Updater updater) {
this.updater = updater;
}
public void updateContent() {
try {
updater.updateContent("/out");
updatedContentCount++;
} catch (Exception e) {
// skip for this example - normally you should handle this
}
}
public int getUpdatedContentCount() {
return updatedContentCount;
}
}
and your updater's API looks like this
public class Updater {
public void updateContent(String dir) throws Exception {
// do something
}
}
Then a test of the Main class would be something like this:
public class MainTest {
private Updater updater;
private Main main;
#Before
public void setUp() {
updater = EasyMock.createNiceMock(Updater.class);
main = new Main(updater);
}
#Test
public void testUpdateCountOnException() throws Exception {
updater.updateContent("/out");
EasyMock.expectLastCall().andThrow(new RuntimeException());
EasyMock.replay(updater);
main.updateContent();
int updatedContentCount = main.getUpdatedContentCount();
Assert.assertEquals(
"Updated count must not have been increased on exception", 0,
updatedContentCount);
}
}
The MainTest tests if the updateCount is handled correctly on an exception of the Updater.
I need to know how to handle the exceptions in a situation like below. Please assist me,
public interface DCommand {
public Object execute(Class_A car);
}
public class Class_B {
public void getMessage() throws Exception {
throw new Exception("Test error");
}
}
public class Class_A {
Class_B cb = null;
public Class_B getClass_b() {
cb = new Class_B();
return cb;
}
public Object testAction(DCommand command) {
Object returnObject = null;
try {
return (Boolean) command.execute(this);
} catch (Exception e) {
System.out.println("ERROR IN CLASS B" + e.getLocalizedMessage());
}
return returnObject;
}
}
====================== simiulating ============================
public class Test {
public static void main(String[] args) {
Class_A c = new Class_A();
boolean a = (Boolean) c.testAction(new DCommand() {
#Override
public Object execute(Class_A car) {
try {
car.getClass_b().getMessage();
return true;
} catch (Exception ex) {
System.out.println("Error in the simulator.");
}
return false;
}
});
}
}
When I run the above code I need to catch the exception thrown by the Class_B in the Class_A where prints the "ERROR IN CLASS A".
Problem is that you are throwing a type of Exception in your Class B's getMessage method. Instead you should define your own exception by extending java.lang.Exception.
public class ClassBException extends Exception {
public ClassBException(String msg) {
super(msg);
}
}
And then use ClassBException to be thrown in Class B's getMessage method like this
public class Class_B {
public void getMessage() throws ClassBException {
throw new Exception("Test error");
}
}
Now you need to a have separate catch block for ClassBException at any place you are calling Class B's getMessage method.
Add this Methode to class A:
public void runGetMessage()
{
try{
cb.getMessage();
}catch(Exception e){
System.out.println("Error in CLASS A.");
}
}
And change the Execute methode to:
public Object execute(Class_A car) {
try {
car.getClass_b();
car.runGetMessage();
return true;
} catch (Exception ex) {
System.out.println("Error in the simulator.");
}
return false;
}
I found some posts about java/reflection on this site. But still can't understand something. Could anyone tell where's error in my code? (need to print "HELLO!")
Output:
java.lang.NoSuchMethodException: Caller.foo()
Here's my Main.java:
import java.lang.reflect.*;
class Main {
public static void main(String[] args) {
Caller cal = new Caller();
Method met;
try {
met = cal.getClass().getMethod("foo", new Class[]{});
met.invoke(cal);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
class Caller {
void foo() {
System.out.println("HELLO!");
}
}
getMethod() only finds public methods. Either change the access modifier of the Caller#foo() method to public, or use getDeclaredMethod() instead.
import java.lang.reflect.*;
public static void main(String[] args) {
public static void main(String[] args) {
try {
Class c = Class.forName("Caller");
Object obj = c.newInstance();
Method m = c.getMethod("foo");
m.invoke(obj);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
public class Caller {
public void foo() {
System.out.println("HELLO!");
}
}