[TL;DR]
The problem is, in AWrapper and AType I have to duplicate pretty much whole function, where there is always the syntax:
public [TYPE/void] METHOD([OPT: args]) throws TestFailedException {
[OPT: TYPE result = null;]
long startTime = System.currentTimeMillis();
while (true) {
try {
beforeOperation();
[OPT: result =] ((WrappedType) element).METHOD([OPT: args]);
handleSuccess();
break;
} catch (Exception e) {
handleSoftFailure(e);
if (System.currentTimeMillis() - startTime > TIMEOUT) {
handleFailure(e);
break;
} else {
try {
Thread.sleep(WAIT_FOR_NEXT_TRY);
} catch (InterruptedException ex) {
}
}
}
}
[OPT: return result;]
}
Lets say I have 2 classes I don't own:
public class IDontOwnThisType {
public void doA(String string) { System.out.println("doA"); }
public String doB(); {System.out.println("doB"); return "doB";}
public OtherTypeIDoNotOwn doC() {System.out.println("doC"); return new OtherTypeIDoNotOwn();}
}
public OtherTypeIDoNotOwn {
public void doD() { System.out.println("doD"); }
public String doE() { System.out.println("doE); }
public OtherTypeIDoNotOwn doF(String string) {System.out.println("doF"); return new OtherTypeIDoNotOwn();}
}
So, I have an interface:
public interface OperationManipulator {
void beforeOperation(); //called before operation
void handleSuccess(); //called after success
void handleSoftFailure(Exception e); //called after every failure in every try
void handleFailure(Exception e) throws TestFailedException; //called after reaching time limit
}
Then interface that extends above one, "mimicking" methods of external classes, but throwing custom exception:
public interface IWrapper<T extends IType> extends OperationManipulator {
public void doA(String string) throws TestFailedException;
public String doB() throws TestFailedException;
public T doC() throws TestFailedException;
}
Then we have IType, which also extends OperationManipulator:
public interface IType<T extends IType> extends OperationManipulator {
public void doD() throws TestFailedException;
public String doE() throws TestFailedException;
public T doF(String string) throws TestFailedException;
}
Then, we have abstract implementations of above interfaces:
public abstract class AType<T extends IType> implements IType{
Object element; // I do not own type of this object, cant modify it.
Class typeClass;
long TIMEOUT = 5000;
long WAIT_FOR_NEXT_TRY = 100;
public AType(Object element) {
this.element = element;
elementClass = this.getClass();
}
/* ... */
}
Then, we override functions from the interfaces, excluding OperationManipulator interface:
Function not returning anything version:
#Override
public void doD() throws TestFailedException {
long startTime = System.currentTimeMillis();
while (true) {
try {
beforeOperation();
((OtherTypeIDoNotOwn) element).doD();
handleSuccess();
break;
} catch (Exception e) {
handleSoftFailure(e);
if (System.currentTimeMillis() - startTime > TIMEOUT) {
handleFailure(e);
break;
} else {
try {
Thread.sleep(WAIT_FOR_NEXT_TRY);
} catch (InterruptedException ex) {
}
}
}
}
Function returning normal reference version:
#Override
public String doE() throws TestFailedException {
String result = null;
long startTime = System.currentTimeMillis();
while (true) {
try {
beforeOperation();
result = ((OtherTypeIDoNotOwn) element).doE();
handleSuccess();
break;
} catch (Exception e) {
handleSoftFailure(e);
if (System.currentTimeMillis() - startTime > TIMEOUT) {
handleFailure(e);
break;
} else {
try {
Thread.sleep(WAIT_FOR_NEXT_TRY);
} catch (InterruptedException ex) {
}
}
}
}
return result;
}
And function returning object of type parameter:
#Override
public T doF(String string) throws TestFailedException {
T result = null;
long startTime = System.currentTimeMillis();
while (true) {
try {
beforeOperation();
OtherTypeIDoNotOwn temp = ((OtherTypeIDoNotOwn) element).doF(string);
result = (T) elementClass.getDeclaredConstructor(Object.class).newInstance(temp);
handleSuccess();
break;
} catch (Exception e) {
handleSoftFailure(e);
if (System.currentTimeMillis() - startTime > TIMEOUT) {
handleFailure(e);
break;
} else {
try {
Thread.sleep(WAIT_FOR_NEXT_TRY);
} catch (InterruptedException ex) {
}
}
}
}
return result;
}
The same goes for AWrapper, but the differences are:
constructor have class argument of stored type
object is cast to IDoNotOwnThisType instead of OtherTypeIDoNotOwn. Functions of this object also may return OtherTypeIDoNotOwn.
IDoNotOwnThisType is type that AWrapper is wrapping.
OtherTypeIDoNotOwn is type that AType is wrapping.
Then, we have implementation of these abstract classes:
public class AssertingType extends AType<AssertingType> {
public AssertingType(Object element) {
super(element);
}
#Override
public void beforeOperation() {
//System.out.println("Asserting type before operation!");
}
#Override
public void handleSuccess() {
//TODO: add to log file and log to output
System.out.println("Asserting type success!");
}
#Override
public void handleFailure(Exception e) throws TestFailedException {
//TODO: add to log file, log to output and throw exception
System.out.println("Asserting type failure!");
e.printStackTrace();
throw new TestFailedException();
}
#Override
public void handleSoftFailure(Exception e) {
//TODO: add to log file, log to output
System.out.println("Asserting type soft failure!");
e.printStackTrace();
}
}
And:
public class AssertingWrapper extends AWrapper<AssertingType> {
public AssertingWrapper (Object driver) {
super(driver, AssertingType.class);
}
#Override
public void beforeOperation() {
//TODO
System.out.println("Asserting wrapper success!");
}
#Override
public void handleSuccess() {
//TODO: add to log file and log to output
System.out.println("Asserting wrapper success!");
}
#Override
public void handleFailure(Exception e) throws TestFailedException {
//TODO: add to log file, log to output and throw exception
System.out.println("Asserting wrapper failure!");
throw new TestFailedException();
}
#Override
public void handleSoftFailure(Exception e) {
//TODO: add to log file, log to output
System.out.println("Asserting wrapper soft failure!");
e.printStackTrace();
}
}
So, we can use it like that:
AssertingWrapper wrapper = new AssertingWrapper(new IDoNotOwnThisType());
AssertingType type = wrapper.doC();
AssertingType type2 = type.doF();
Output:
Asserting wrapper before operation!
doC
Asserting wrapper success!
Asserting type before operation!
doF
Asserting type success!
The full working code is here:
LIVE
The problem is, I have always to write while, try catch etc in AType and AWrapper, can I somehow reduce code duplication? In the example i provided just 3 functions per class, but in my real code I have 50+ methods. Can I somehow wrap these functions so thepart that is repeating is not duplicated?
Your problem appears to be quite complicated, and I cannot claim to have been able to successfully wrap my mind around it, but I will give it a try, because it appears to be a very interesting problem and because I happen to have some experience in dealing with situations that yours appears similar to.
Please excuse me if my answer turns out to be completely off the mark due to a misunderstanding on my part.
So, what it appears that you are looking for is a general purpose solution for injecting your own code before and after an invocation where the invocation may be to any method, accepting any number of parameters, and returning any kind of return value.
In java there exists a dynamic proxy facility, which you can find under java.lang.reflect.Proxy.
With it, you can do the following:
ClassLoader classLoader = myInterfaceClass.getClassLoader();
T temp = (T)Proxy.newProxyInstance( classLoader, new Class<?>[] { myInterfaceClass },
invocationHandler );
The invocationHandler is supplied by you, and it is of the following form:
private final InvocationHandler invocationHandler = new InvocationHandler()
{
#Override
public Object invoke( Object proxy, Method method, Object[] arguments )
throws Throwable
{
/* your pre-invocation code goes here */
/* ... */
/* invoke original object */
Object result = method.invoke( myObject, arguments );
/* your post-invocation code goes here */
/* ... */
/* return the result (will probably be null if method was void) */
return result;
}
};
So, I think you might be able to use that to solve your problem with the minimum amount of code.
Neither the creation of a dynamic proxy nor the call to method.invoke() perform terribly well, (you know, reflection is somewhat slow,) but if you are using it for testing, it should not matter.
Related
The project has the test Test_FindYNetNewsViaGoogle.java
public class Test_FindYNetNewsViaGoogle extends TestBase {
#Test
public void testGoToYNNHomeUrl(){
app.google().goToGoogleHome();
app.google().search("class_name");
app.google().enterSite(webElement2);
assertThat(app.browser().whatSiteIsOpened(), equalTo("urlYNetNews"));
}
}
A test scenario includes performance of app.google().search("www.ynetnews.com") that is located in GoogleHelper.class
public class GoogleHelper extends HelperBase{
private final String googleHomeUrl = "https://www.google.com/";
public GoogleHelper(WebDriver wd) {super(wd);}
public void goToGoogleHome() {
String curUrl = wd.getCurrentUrl();
if (googleHomeUrl.equals(curUrl)) {return;}
wd.navigate().to(googleHomeUrl);
}
#StaleElementAnnotation(retries = 2, seconds = 1)
public void search(String search) {
WebElement we_search = wd.findElemnt(By.className(search));
click(we_search);
}
public void click(WebElement search) {
// was refresh page
throw new StaleElementReferenceException("test exception");
}
public void enterSite(WebElement url){
click(url.locator));
}
}
I special write throw the StaleElementReferenceException exception, in order to image that after the previous step there were refresh of page.
So, to resolve this I need to change search(String) to
public void search(String search) {
int count = 0;
while (count < DEFAULT_RETRIES) {
try {
++count;
return searchService(search);
} catch (StaleElementReferenceException e) {
Thread.sleep(1000);
}
}
return null;
}
private void searchService(String search) {
WebElement we_search = wd.findElemnt(By.className(search));
click(we_search);
}
This okay if you have few those methods. But if there are many of it. So I think that there is solve in which we can invoke some Listener that can call in this case our initial method by surrounded it with as above written.
I have not found any TestNg listeners can give only test method name where was throw the exception. In my case it is Test_FindYNetNewsViaGoogle.testGoToYNNHomeUrl() and not GoogleHelper.click(WebElement search).
Please assist me!
First, you need to have a static method to retry the required methods. Maybe you can add this to your GoogleHelper class.
public static void retry(Runnable method, int maxTries, long seconds) throws InterruptedException {
int count = 0;
while (count < maxTries) {
try {
++count;
method.run();
} catch (RuntimeException e) {
TimeUnit.SECONDS.sleep(seconds);
}
}
}
Now you could use the above method in your test.
public class Test_FindYNetNewsViaGoogle extends TestBase {
#Test
public void testGoToYNNHomeUrl(){
app.google().goToGoogleHome();
GoogleHelper.retry(() -> app.google().search("class_name"), 2 , 1);
app.google().enterSite(webElement2);
assertThat(app.browser().whatSiteIsOpened(), equalTo("urlYNetNews"));
}
}
Assuming I have to read from a file, and then construct a java object out of it.
PersonData p = new PersonData();
p.setName(readTokenAsString());
p.setAge(AgeConverter.createFromDateOfBirth(readTokenAsString())); // this throws a checked exception if the date of birth is mal-formed.
//... a list of methods that throws exception as AgeConverter
Behavior I want: If one attribute has problem, just ignore it and keep process other attributes.
Solution I can think of:
try {
p.setAge1(...);
} catch (Exception e) {
//log and ignore
}
try {
p.setAge2(...);
} catch (Exception e) {
//log and ignore
}
//repeat for each attribute
Question:
Is there better way to do this to avoid repetition? Functional style maybe?
a) What's the best approach if I cannot modify PersonData class.
b) What's the best approach if I can rewrite PersonData class.
Given your current declaration, I would do it as follows.
Define a #FunctionalInterface to which you can pass your I/O logic:
#FunctionalInterface
public interface CheckedSupplier<T> {
T getValue() throws Exception;
}
Define an utility method that consumes the #FunctionaInterface:
public static final <T> T getValueWithDefault(CheckedSupplier<T> supplier, T defaultValue) {
try {
return supplier.getValue();
} catch (Exception e){
return defaultValue;
}
}
Use the utility method as follows:
PersonData p = new PersonData();
p.setName(getValueWithDefault(() -> readTokenAsString(), "default"));
p.setAge(getValueWithDefault(() -> AgeConverter.createFromDateOfBirth(readTokenAsString()), 0));
This should do the trick regardless of weather you want modify the PersonData class or not.
If you use Java 8 you can do something like this. Create your own functional interface with one method that throws Exception
public interface MyConsumer<T> {
public void process(T t) throws Exception;
}
And create a static method to use that interface
public static <T> void setAndLogException(T value, MyConsumer<T> consumer) {
try {
consumer.process(value);
} catch (Exception e) {
// log exception
}
}
And then using it like setAndLogException(AgeConverter.createFromDateOfBirth(readTokenAsString()), p::setAge);
You can also use solution provided by this: https://stackoverflow.com/a/28659553/6648303
This solution won't complain at compile phase about checked Exceptions.
It would be something like this:
public static void ignoringExc(RunnableExc r) {
try { r.run(); } catch (Exception e) { }
}
#FunctionalInterface public interface RunnableExc { void run() throws Exception; }
and then:
PersonData p = new PersonData();
ignoringExc(() -> p.setName(readTokenAsString()));
...
I have a legacy class C1, implementing interface I, that may throw some exceptions.
I want to create a class C2, also implementing interface I, that is based on an instance of C1, but catches all exceptions and does something useful about them.
Currently my implementation looks like this:
class C2 implements I {
C1 base;
#Override void func1() {
try {
base.func1();
} catch (Exception e) {
doSomething(e);
}
}
#Override void func2() {
try {
base.func2();
} catch (Exception e) {
doSomething(e);
}
}
...
}
(Note: I could also make C2 extend C1. This does not matter for the current question).
The interface contains many functions, so I have to write the same try... catch block again and again.
Is there a way to reduce the amount of code duplication here?
You can make a Proxy, it could actually be generic
interface I1 {
void test();
}
class C1 implements I1 {
public void test() {
System.out.println("test");
throw new RuntimeException();
}
}
class ExceptionHandler implements InvocationHandler {
Object obj;
ExceptionHandler(Object obj) {
this.obj = obj;
}
#Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
return method.invoke(obj, args);
} catch (Exception e) {
// need a workaround for primitive return types
return null;
}
}
static <T> T proxyFor(Object obj, Class<T> i) {
return (T) Proxy.newProxyInstance(obj.getClass().getClassLoader(), new Class[] { i },
new ExceptionHandler(obj));
}
}
public class Test2 {
public static void main(String[] args) throws Exception {
I1 i1 = ExceptionHandler.proxyFor(new C1(), I1.class);
i1.test();
}
}
I have defined my own expection class:
public class ProduktException extends Exception {
public ProduktException(String msg){
//null
}
public static void throwProduktNotCreatedException() throws ProduktException {
throw new ProduktException("Cannot be created!");
}
public static void throwProduktNotDeletedException () throws ProduktException {
throw new ProduktException("Cannot be deleted!");
}
}
My Problem is I do not know how to throw them when I try:
try {
...
} catch(ProduktNotDeletedException e) {
e.toString();
}
That does not work... But I want to have these structure! What is wrong?
I appreaciate your answer!!!
UPDATE:
My Problem is, I do not want to create several Exception Klasses I want to have all Exceptions in one class. Is there possibly a solution for that?
If you need to differentiate between different kinds of exceptions, just create 2 different exceptions, maybe something like:
public class ProduktException extends Exception
{
public ProduktException(String msg){
//null
}
}
Then have:
public class ProduktNotDeletedException extends ProduktException
{
....
}
and
public class ProduktNotCreatedException extends ProduktException
{
....
}
Then you can catch one or the other, or both.
try {
...
} catch(ProduktNotDeletedException e1) {
e1.toString();
} catch(ProduktNotCreatedException e2) {
e2.toString();
}
EDIT:
For a single class what I mean is:
public class ProduktException extends Exception {
boolean notDeleted;
boolean notCreated;
public ProduktException(String msg){
super(msg);
}
public boolean isNotDeleted() {
return(notDeleted);
}
public boolean isNotCreated() {
return(notCreated);
}
public static void throwProduktNotCreatedException() throws ProduktException {
ProduktException e = new ProduktException("Cannot be created!");
e.notCreated = true;
throw e;
}
public static void throwProduktNotDeletedException () throws ProduktException {
ProduktException e = new ProduktException("Cannot be deleted!");
e.notDeleted = true;
throw e;
}
}
Then in your try/catch:
try {
...
} catch(ProduktException e) {
e.toString();
if(e.isNotCreated()) {
// do something
}
if(e.isNotDeleted()) {
// do something
}
}
You need to either catch ProduktException, e.g.
try {
...
} catch (ProduktException e) {
e.toString();
}
or declare subtypes, e.g.
public ProduktNotDeletedException extends ProduktException
You'll probably want to pass the message in the constructor up, so add the following in your constructor:
super(msg);
The Syntax given below.
class RangeException extends Exception
{
String msg;
RangeException()
{
msg = new String("Enter a number between 10 and 100");
}
}
public class MyCustomException
{
public static void main (String args [])
{
try
{
int x = 1;
if (x < 10 || x >100) throw new RangeException();
}
catch(RangeException e)
{
System.out.println (e);
}
}
}
What you could do if you don't want to create multiple subclasses of your ProduktException for each different type of exception you need to throw is to include a code in the exception which will let you know what is wrong. Something like this:
public class ProduktException extends Exception {
private Code exceptionCode;
private String message
public ProduktException(Code code, String msg){
this.message = msg;
this.exceptionCode = code;
}
//Getters and setters for exceptionCode and message
}
Code can be an enum so that your application can know that each code corresponds to a specific "problem" (product not created, product not deleted, etc.). You can then throw your exceptions like this
throw new ProduktException(Code.PRODUCT_NOT_CREATED,
"Error while creating product");
And when you catch it you can differentiate based on the code.
catch (ProduktException ex) {
if (ex.getExceptionCode().equals(Code.PRODUCT_NOT_CREATED)) {
...
}
else {
...
}
}
I cooked up a class ExceptionHandler<T extends Exception, OptionalReturnType> (see below) to eliminate some (what I view as) boilerplate code which was cluttering up actual implementation, while still providing a hook for explicit Exception handling if desired in the future. For the most part, in my application (essential a scientific computation), there is no such thing as recovery from exceptions - I need a log of the problem so I can fix it, but otherwise I'm just going to re-run once the problem is corrected.
Do other people do this (at least, in my specific application situation)? Is it dumb to do so (if yes, some explanation as to why would be nice)?
ExceptionHandler:
public abstract class ExceptionHandler<ExceptionType extends Exception,OptionalReturn> {
public abstract OptionalReturn handle(ExceptionType e);
//assorted boilerplate ExceptionHandling, e.g.:
public static <ET extends Exception> ExceptionHandler<ET, ?> swallower(final boolean printStackTrace, final String string) {
return new ExceptionHandler<ET,Object>() {
#Override public Object handle(ET e) {
if(printStackTrace) { e.printStackTrace(); }
if(string!=null && !string.isEmpty()) { System.err.println(string); }
return null;
}
};
}
public static <ET extends Exception> ExceptionHandler<ET, ?> swallower() { return swallower(false,null); }
}
example use (which I'm in the process of chopping down so I'm actually not writing quite so much):
public class Getter<From> implements Function<Future<? extends From>, From> {
private ExceptionHandler<InterruptedException,?> IEH;
private ExceptionHandler<ExecutionException,?> EEH;
public static final ExceptionHandler<InterruptedException,?> IEH_SWALLOWER = ExceptionHandler.swallower(true,"Returning null.");
public static final ExceptionHandler<ExecutionException,?> EEH_SWALLOWER = ExceptionHandler.swallower(true,"Returning null.");
private Getter() { this(IEH_SWALLOWER,EEH_SWALLOWER); }
private Getter(ExceptionHandler<InterruptedException,?> IEH, ExceptionHandler<ExecutionException,?> EEH) {
this.IEH = IEH;
this.EEH = EEH;
}
public static <T> Getter<T> make() { return new Getter<T>(); }
public static <T> Getter<T> make(ExceptionHandler<InterruptedException,?> IEH, ExceptionHandler<ExecutionException,?> EEH) {
return new Getter<T>(IEH, EEH);
}
#Override public From apply(Future<? extends From> from) {
if (from==null) throw new NullPointerException("Null argument in call with Getter.");
return getter(from, IEH, EEH);
}
private static <T> T getter(Future<T> src, ExceptionHandler<InterruptedException,?> IEH, ExceptionHandler<ExecutionException,?> EEH) {
try { return src.get(); }
catch (InterruptedException e) { IEH.handle(e); }
catch (ExecutionException e) { EEH.handle(e); }
return null;
}
}
which is used with the Guava libraries to do some embarrassingly-parallel calculations, and makes the actual Iterable transformation of Futures into something like Iterables.transform(futureCollection,Getter.make()) instead of tangle of inner-classes and exception handling.
I find the code honestly hard to follow and understand. It's full of static which is usually a bad sign in OO design and it's hard to follow with the generics.
Wouldn't something simpler like this work as well?
private static <T> T getter(Future<T> src) {
try { return src.get(); }
catch (InterruptedException e) { handle( "some text"); }
catch (ExecutionException e) { handle( e ) }
return null;
}
You can implement as many handle method as necessary in a base class (or in a static utility class) and use them in the catch block as necessary. Methods will be selected based on the signature, so if you want to print the text, you pass the string, if you want the stack trace you pass the exception (or both). Which leads to the combinations:
handle( String msg )
handle( Exception e )
handle( Exception e, String msg )
This solution has less if, which is usually a good sign as well.
But I have maybe missed a point, given that the code you published is just an excerpt of the whole code.
Have a look otherwise at this question, which is also related: Pluggable Error Handling Strategy
EDIT
If the solution I proposed above is too simple for your need, here are two other ways:
public class AbstractGetter<From> implements Function<Future<? extends From>, From> {
private abstract handleInterrupt( Exception e );
private abstract handleExecution( Exception e );
private static <T> T getter(Future<T> src ) {
try { return src.get(); }
catch (InterruptedException e) { handleInterrupt(e) }
catch (ExecutionException e) { handleExecution(e) }
return null;
}
}
And you implement the X concrete class that correspond the various exception handling strategies. That's essentially the template pattern.
You can still use delegation, but at a more coarse-grained level. Instead of providing individual handler, you provide a handler strategy. That's kind of variation of the strategy pattern then.
public interface ErrorStrategy
{
public void handleInterrupt(Exception e);
public void handleExecution(Exception e);
}
public class Getter<From> implements Function<Future<? extends From>, From> {
ErrorStrategy handler = new DefaultErrorStrategy(). // default one
public Getter<From>()
{
}
public Getter<From>( ErrorStrategy h )
{
this.handler = h.
}
private static <T> T getter(Future<T> src ) {
try { return src.get(); }
catch (InterruptedException e) { handler.handleInterrupt(e) }
catch (ExecutionException e) { handler.handleExecution(e) }
return null;
}
}
You can create the X error handling strategies that you need.
I think it's a good solution, but it could benefit from an ExceptionHandlerFactory and some xml files.