Null pointer in my Facade :( - java

I've written a task manager, and well it;'s a long story... all in Java by the way. So I wrote a Facade which you can see below there is a problem with the HashMap and I suspect that the values which I attempt to add into the HashMap during the construction aren't going so well. The method that is triggering the null pointer exception is the create method. the input parameters to the method have been verified by me and my trusty debugger to be populated.
any help here would be great... I'm sure I forgot to mention something so I'll reply to comments asap as I need to get this thing done now.
package persistence;
import java.util.UUID;
import java.util.HashMap;
import persistence.framework.ComplexTaskRDBMapper;
import persistence.framework.IMapper;
import persistence.framework.RepeatingTaskRDBMapper;
import persistence.framework.SingleTaskRDBMapper;
public class PersistanceFacade {
#SuppressWarnings("unchecked")
private static Class SingleTask;
#SuppressWarnings("unchecked")
private static Class RepeatingTask;
#SuppressWarnings("unchecked")
private static Class ComplexTask;
private static PersistanceFacade uniqueInstance = null;
#SuppressWarnings("unchecked")
private HashMap<Class, IMapper> mappers;
public PersistanceFacade() {
mappers = new HashMap<Class, IMapper>();
try {
SingleTask = Class.forName("SingleTask");
RepeatingTask = Class.forName("RepeatingTask");
ComplexTask = Class.forName("ComplexTask");
mappers.put(SingleTask, new SingleTaskRDBMapper());
mappers.put(RepeatingTask, new RepeatingTaskRDBMapper());
mappers.put(ComplexTask, new ComplexTaskRDBMapper());
}
catch (ClassNotFoundException e) {}
}
public static synchronized PersistanceFacade getUniqueInstance() {
if (uniqueInstance == null) {
uniqueInstance = new PersistanceFacade();
return uniqueInstance;
}
else return uniqueInstance;
}
public void create(UUID oid, Object obj) {
IMapper mapper = (IMapper) mappers.get(obj.getClass());
mapper.create(oid, obj);
}
#SuppressWarnings("unchecked")
public Object read(UUID oid, Class type) {
IMapper mapper = (IMapper) mappers.get(type);
return mapper.read(oid);
}
public void update(UUID oid, Object obj) {
IMapper mapper = (IMapper) mappers.get(obj.getClass());
mapper.update(oid, obj);
}
#SuppressWarnings("unchecked")
public void destroy(UUID oid, Class type) {
IMapper mapper = (IMapper) mappers.get(type);
mapper.destroy(oid);
}
}

For Class.forName("RepeatingTask") to return a class you must have a class persistence.RepeatingTask. But in your comment you say that obj.getClass() returns domain.RepeatingTask so it looks to me like you have 2 "RepeatingTask" classes or domain.RepeatingTask is a sub type.

My guess is that your problem lies in the constructor:
try {
SingleTask = Class.forName("SingleTask");
RepeatingTask = Class.forName("RepeatingTask");
ComplexTask = Class.forName("ComplexTask");
mappers.put(SingleTask, new SingleTaskRDBMapper());
mappers.put(RepeatingTask, new RepeatingTaskRDBMapper());
mappers.put(ComplexTask, new ComplexTaskRDBMapper());
}
catch (ClassNotFoundException e) {}
You silently ignore the ClassNotFOundException. If you add logging to the catch I expect it to tell you that the class SingleTask is not found, as I expect that you did not put those classes in the default package.
Given your reply to comments these classes are in the domain. package, so you could try to change to:
try {
SingleTask = Class.forName("domain.SingleTask");
RepeatingTask = Class.forName("domain.RepeatingTask");
ComplexTask = Class.forName("domain.ComplexTask");
mappers.put(SingleTask, new SingleTaskRDBMapper());
mappers.put(RepeatingTask, new RepeatingTaskRDBMapper());
mappers.put(ComplexTask, new ComplexTaskRDBMapper());
}
catch (ClassNotFoundException e) {
log.warn("Cannot load class", e);
}
Btw, adding logging to your code will help to find the reasons behind unexpected behaviour.

Class.forName("SingleTask"); is throwing a ClassCastException, so mappers does not get populated. Since you are ignoring ClassCastExeption in your constructor you have missed that error, it seems.

Related

Use java operator :: dynamically

I have the following implementation:
private SomeWritter someWritter(String someArgument) {
SomeWritter.Builder builder = SomeWritter.builder(someArguments);
builder = builder.addColumn("colName1", TargetClass::getArg1)
builder = builder.addColumn("colName2", TargetClass::getArg2)
return builder.build();
}
private Builder<T> addColumn(String colName, ToDoubleFunction<T> getter){
//implementation goes here
}
my issue is that I need to iterate over the addColumns call, something among these lines:
private void SomeWritter(String someArgument) {
SomeWritter.Builder builder = SomeWritter.builder(someArguments);
for (Field field : getFilteredFieldsFromClass(TargetClass.class)) {
builder = builder.addColumn(field.getName(), [SOMEHOW GET THE REF TO GETTER HERE])
}
return builder.build();
}
in order to get the refference to the getter, I tryed to do
TargetClass.class.getMethod("getArg1", ...);
this works, but I have a Method, not a ToDoubleFunction.
I need to somehow get that ToDoDoubleFunction, programatically, I want to do the same that the TargetClass:: does, dinamically, not harcoded. any ideas ?
import java.lang.reflect.Field;
public class Main {
static class Example{
double arg1;
int arg2;
}
interface Foo<T>{
double toDouble(T example);
}
public static void addColumn(Foo<Example> foo){
//do nothing
}
public static void main(String[] args) {
final var example = new Example();
for(Field field: Example.class.getDeclaredFields()){
addColumn(example1 -> {
try {
return (double) field.get(example1);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
});
}
}
}
That code iterates over all fields of the Example class and uses the reflection inside a lambda.
Side Note. Intellij can replace method references with lambda when you click alt+enter when cursor is on them (Windows).

How to test void method with no parameters?

I have method that is called by another service and it just change one of the field for some rows in database. Method looks like this:
void errorOrders() {
List<Orders> orders = OrderDAO.getErrorOrders(); //select only fields with status 'error'
orders.forEach(order -> order.setStatus(OrderStatus.NEW);
//some logging etc.
}
Is there any way to unit test this method? Can I inject myself inside this method and check if orders status was changed?
Cheers!
I would recommend you refactor your class to make your code testable. Ideally you would inject the dependency that represents the OrderDAO:
class ErrorChecker {
private final OrderDAO orderDAO;
public ErrorChecker(OrderDAO orderDAO) {
this.orderDAO = orderDAO;
}
public void errorOrders() {
List<Orders> orders = orderDAO.getErrorOrders();
orders.forEach(order -> order.setStatus(OrderStatus.NEW);
}
}
Then your test code would look like:
#Test
void testErrorOrders() {
Order order1 = mock(Order.class);
Order order2 = mock(Order.class);
OrderDAO orderDAO = mock(OrderDAO.class);
when(orderDAO.getErrorOrders()).thenReturn(List.of(order1, order2));
ErrorChecker errorChecker = new ErrorChecker(orderDAO);
errorChecker.errorOrders();
verify(order1).setState(OrderStatus.NEW);
verify(order2).setState(OrderStatus.NEW);
}
There are ways to mock static methods but I would recommend refactoring to inject the dependencies as it has many other benefits beside testability.
If you need to leave the method as static then you can still mock it (in v3.4+ of Mockito):
#Test
void testErrorOrders() {
try (MockedStatic mocked = mockStatic(OrderDAO.class)) {
mocked.when(OrderDAO.getErrorOrders()).thenReturn(List.of(order1, order2));
ErrorChecker errorChecker = new ErrorChecker(orderDAO);
errorChecker.errorOrders();
mocked.verify(order1).setState(OrderStatus.NEW);
}
}
#ismail and #khelwood already provided good answers.
If you mock the Object, you can control/see what happens to it
If you change an Object, where you can access the state via public methods, use those
If you change an Object whose state you cannot access with normal code, use Java Reflections to look at member variables.
If you set up Objects, that pass their data to streams and other output, you can put some additional streams etc in between. Use inheritance and reflection if necessary
Simple example of using Reflection on a shielded class:
package stackoverflow.simplefieldaccess;
public class ShieldedClass {
private int mStatus;
public ShieldedClass() {
mStatus = 666;
}
public void setStatus(final int pStatus) {
mStatus = pStatus; // usually with ints be careful and do checks here, but for the sake of simplicity we leave that out
}
#Override public String toString() {
return getClass().getSimpleName() + "[status:" + mStatus + "]";
}
}
Code to access it via reflection in a few ways:
package stackoverflow.simplefieldaccess;
import java.lang.reflect.Field;
import jc.lib.lang.reflect.JcFieldAccess;
public class SimpleFieldAccess {
public static void main(final String[] args) throws NoSuchFieldException, SecurityException {
final ShieldedClass so = new ShieldedClass();
System.out.println("Object.status before change: " + so);
so.setStatus(667);
System.out.println("Object.status after change: " + so);
System.out.println();
System.out.println("Accessing Object.status via Reflection...");
final Class<? extends ShieldedClass> cls = so.getClass();
final Field fieldToChance = cls.getDeclaredField("mStatus");
{
System.out.println("\nBad read access");
try { // will result in java.lang.IllegalAccessException
System.out.println("\tReading Object.status fiels via Reflection: " + fieldToChance.getInt(so));
throw new IllegalStateException("UNEXOECTED ERROR!");
} catch (final java.lang.IllegalAccessException e) {
System.out.println("\tAs expected: IllegalAccessException");
}
}
{
System.out.println("\nBad write access");
try { // will result in java.lang.IllegalAccessException
fieldToChance.set(so, Integer.valueOf(1337));
System.out.println("\tObject.status after change: " + so);
} catch (final java.lang.IllegalAccessException e) {
System.out.println("\tAs expected: IllegalAccessException");
}
}
{
System.out.println("\nGood manual read and write access");
final boolean isFieldOriginallyAccessible = fieldToChance.isAccessible();
try { // will result in java.lang.IllegalAccessException
if (!isFieldOriginallyAccessible) fieldToChance.setAccessible(true);
System.out.println("\tReading Object.status field via Reflection: " + fieldToChance.getInt(so));
fieldToChance.set(so, Integer.valueOf(4321));
System.out.println("\tObject.status after change: " + so);
} catch (final java.lang.IllegalAccessException e) {
e.printStackTrace();
} finally {
if (!isFieldOriginallyAccessible) fieldToChance.setAccessible(false);
}
}
{
System.out.println("\nGood automated read and write access");
try (JcFieldAccess fa = new JcFieldAccess(fieldToChance)) { // will result in java.lang.IllegalAccessException
System.out.println("\tReading Object.status field via Reflection: " + fieldToChance.getInt(so));
fieldToChance.set(so, Integer.valueOf(123));
System.out.println("\tObject.status after change: " + so);
} catch (final java.lang.IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
For reflections, when I want to access fields, I use my homebrew class that makes it easier to get access to the field and afterwards restore it to normal (last example above uses this):
package jc.lib.lang.reflect;
import java.io.Closeable;
import java.lang.reflect.AccessibleObject;
public class JcFieldAccess implements Closeable {
private final AccessibleObject mField;
private final boolean mIsAccessible;
public JcFieldAccess(final AccessibleObject pField) {
mField = pField;
mIsAccessible = mField.isAccessible();
if (!mIsAccessible) mField.setAccessible(true);
}
#Override public void close() {
if (mIsAccessible) return;
if (mField != null) mField.setAccessible(false);
}
}
The trick with this util class is that when used in a try-resource block, its close() method will get called automatically, whether the block fails or not. It's the same as having the close() or in this case setAccessible(false) call in the finally block, with some extra checks.
Let the class be:
class HandleErrorOrders {
private OrderDAO orderDAO;
HandleErrorOrders(final OrderDAO orderDAO) {
this.orderDAO = orderDAO;
}
public void errorOrders() {
List<Orders> orders = OrderDAO.getErrorOrders(); //select only fields with status 'error'
orders.forEach(order -> order.setStatus(OrderStatus.NEW);
//some logging etc.
}
}
You need to use assert methods to check end state.
To test, write something like:
class HandleErrorOrdersTest {
#Mock
private OrderDAO orderDAO;
#InjectMocks
private HandleErrorOrders handleErrorOrders;
#Test
void testErrorOrders() {
Order order1 = mock(Order.class);
Order order2 = mock(Order.class);
when(orderDAO.getErrorOrders()).thenReturn(List.of(order1, order2));
ErrorChecker errorChecker = new ErrorChecker(orderDAO);
errorChecker.errorOrders();
//asset checks
Assert.assertEquals(OrderStatus.NEW, order1.getStatus());
Assert.assertEquals(OrderStatus.NEW, order2.getStatus());
//verification checks
Mockito.verify(orderDAO).getErrorOrders();
}
}

Unable to instantiate sub class with parameter

I keep getting the error: java.lang.NoSuchMethodException: com.production.workflow.MyWorkflow.<init>(com.production.model.entity.WorkflowEntity)
I have a constructor that is expecting WorkflowEntity so I'm not able to figure out why it's saying NoSuchMethod. Is there something about constructor inheritance that is preventing this from instantiating?
My instantiation factory:
public static Workflow factory(WorkflowEntity workflowEntity) {
try {
Class<?> clazz = Class.forName(workflowEntity.getClassName()).asSubclass(Workflow.class);
Constructor c = clazz.getConstructor(WorkflowEntity.class);
Object workflowClass = c.newInstance(clazz);
return (Workflow) workflowClass;
} catch (Exception e) {
e.printStackTrace();
logger.severe("Unable to instantiate "+workflowEntity.getClassName()+" class: " + e.getLocalizedMessage());
}
return null;
}
Workflow class:
public class MyWorkflow extends Workflow {
//no constructors
Extended class:
abstract public class Workflow {
protected static final Logger logger = Logger.getLogger(Workflow.class.getName());
private WorkflowEntity entity;
protected WorkflowProcess workflowProcess;
#Autowired
private WorkflowProcessService workflowProcessService;
/* Don't use this one */
public Workflow() { }
/* Default constructor */
public Workflow (WorkflowEntity entity) {
this.entity = entity;
//get first workflow process
//#todo this should factor in rule, for multiple starting points
for (WorkflowProcessEntity workflowProcessEntity : entity.getWorkflowProcesses()) {
workflowProcess = WorkflowProcess.factory(workflowProcessEntity);
break;
}
}
There are two problems in your code:
Constructors are not automatically inherited by subclasses. You need to add the MyWorkflow(WorkflowEntity) constructor to the MyWorkflow class.
Your new instance call needs to be made with the workflowEntity instance (and not the class instance you are giving it now)
Here:
class MyWorkflow extends Workflow {
public MyWorkflow() {
super();
}
public MyWorkflow(WorkflowEntity entity) {
super(entity);
}
}
public static Workflow factory(WorkflowEntity workflowEntity) {
try {
Class<?> clazz = Class.forName(workflowEntity.getClassName())
.asSubclass(Workflow.class);
Constructor<?> c = clazz.getConstructor(WorkflowEntity.class);
Object workflowClass = c.newInstance(workflowEntity);
return (Workflow) workflowClass;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
Consider the builder pattern instead of the factory pattern. Here is an example that builds a WorkFlow that takes a WorkflowEntity constructor parameter and builds a workFlow that does not take a WorkFlowEntity pattern (just showing multiple options available via a builder).
public class WorkFlowBuilder
{
private WorkflowEntity constructorParameter;
private Class workflowClass;
public WorkFlowBuilder(Class desiredWorkflowClass)
{
if (desiredWorkflowClass != null)
{
workflowClass = desiredWorkflowClass;
}
else
{
throw new IllegalArgumentException("blah blah blah");
}
}
public void setConstructorParameter(final WorkflowEntity newValue)
{
constructorParameter = newValue;
}
public WorkFlow build()
{
Object workflowObject;
if (constructorParameter != null)
{
Constructor constructor = workflowClass.getConstructor(WorkflowEntity.class);
Object workflowObject;
workflowObject = constructor.newInstance(workflowEntity);
}
else
{
workflowObject = workflowClass.newInstance();
}
return (WorkFlow)workflowObject;
}
}
Use this as follows:
WorkFlowBuilder builder = new WorkFlowBuilder(MyWorkFlow.class);
WorkflowEntity entity = new WorkFlowEntity();
WorkFlow item;
entity... set stuff.
builder.setConstructerParameter(entity)
item = builder.build();
I think you just want to pass in the workflowEntity into the constructor on the newInstance call, instead of the typed Class.
Constructors lost their outside visibility during inheritance.
You need to redefine it in MyWorkflow.
This is done so because sub classes may not support the super class creation process. So super object constructors does not make sense to sub classes and it's even unsafe if they were visible outside.
You should also remove the default constructor if your class can be used if instantiated without WorkflowEntity. Just remove it from Workflow and do not add to MyWorkflow.
UPD
You should also consider using generics to avoid class casting.
public Workflow create(WorkflowEntity workflowEntity) throws
ClassNotFoundException, NoSuchMethodException, SecurityException
, InstantiationException, IllegalAccessException
, IllegalArgumentException, InvocationTargetException {
Class<? extends Workflow> clazz = Class.forName(workflowEntity.getClassName()).asSubclass(Workflow.class);
Constructor<? extends Workflow> c = clazz.getConstructor(WorkflowEntity.class);
Workflow workflowClass = c.newInstance(clazz);
return workflowClass;
}
class WorkflowEntity {
public String getClassName() {
return "className";
};
}
class Workflow {
Workflow(WorkflowEntity entity) {
};
}
class MyWorkflow extends Workflow {
MyWorkflow(WorkflowEntity entity) {
super(entity);
}
}

Dynamic variables with given type

I have written a small class, which reads out annotation from methods.
Now I want to extend that class to make it more dynamic.
My class uses at the moment following code for reading out the annotation:
ExtendedCommandAnnotation e = foo.getClass()
.getAnnotation(ExtendedCommandAnnotation.class);
String startTag = e.annoPropStartTag();
That is the simple case with fixed annotation.
In the new version I haven't any fixed annotation. I will get the annotation 'ExtendedCommandAnnotation' in a variable.
So the code above will be edited to:
String className= "ExtendedCommandAnnotation";
??? e = foo.getClass().getAnnotation(Class.forName(className));
String startTag = e.annoPropStartTag();
I don't know what I shall put instead of the ???. I tried it with Annotation, but then I can't get the properties with the defined methods.
Is there any way to get this working?
My annotation "class":
#Retention( RetentionPolicy.RUNTIME )
public #interface ExtendedCommandAnnotation
{
String annoPropUseTab() default "0";
String annoPropStartTag() default "";
String annoPropEndTag() default "";
}
EDIT:
Finally I get something like that:
String[] cmdMethNames = this.getAvailableCommandNames();
Class<?> annotationClass = Class.forName(this.annotationClassName);
for( Method meth : cmdMeth )
{
HashMap<String, String> tempAnno = new HashMap<String, String>();
if (meth.isAnnotationPresent((Class<? extends Annotation>) annotationClass))
{
Annotation anno = meth.getAnnotation((Class<? extends Annotation>) annotationClass);
[...]
}
[...]
}
But the cast to (Class<? extends Annotation>) make following warning: "Type safety: Unchecked cast from Class< capture#4-of ? > to Class< ? extends Annotation >"
If you don't know the annotation in advance, you can't know that it's got an annoPropStartTag() method, can you? So you can't tell the compiler how to bind to that method...
If you want to basically find a method with that name at execution time, you'll currently need to use reflection.
You might want to consider having some sort of "base" annotation type which contains all the methods you need in the general case, and then derive all the other annotation types from that.
/* Foo.java */
#ExtendedCommandAnnotation(annoPropStartTag = "hello")
public class Foo {
}
/* ExtendedCommandAnnotation.java */
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
#Retention( RetentionPolicy.RUNTIME )
public #interface ExtendedCommandAnnotation {
String annoPropUseTab() default "0";
String annoPropStartTag() default "";
String annoPropEndTag() default "";
}
/* Main.java */
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
public class Main {
public static void main(String[] args) {
doOriginalImplementation(); // Prints "hello"
doReflectionImplementation(); // Prints "hello"
}
public static void doOriginalImplementation() {
Foo foo = new Foo();
ExtendedCommandAnnotation e = foo.getClass().getAnnotation(ExtendedCommandAnnotation.class);
String startTag = e.annoPropStartTag();
System.out.println(startTag);
}
public static void doReflectionImplementation() {
Foo foo = new Foo();
Annotation[] annotations = foo.getClass().getAnnotations();
// or the statement below, depends on what you intent to do:
// Annotation[] annotations = foo.getClass().getDeclaredAnnotations();
Class classOfExtendedCommandAnnotation = null;
Annotation annotationOnClassFoo = null;
for (Annotation a : annotations) {
Class classA = a.annotationType();
if ("ExtendedCommandAnnotation".equals(classA.getName())) {
classOfExtendedCommandAnnotation = classA;
annotationOnClassFoo = a;
break;
}
}
Method methodAnnoPropStartTag = null;
if (classOfExtendedCommandAnnotation != null) {
try {
methodAnnoPropStartTag = classOfExtendedCommandAnnotation.getMethod("annoPropStartTag");
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
if (methodAnnoPropStartTag != null) {
try {
String startTag = (String) methodAnnoPropStartTag.invoke(annotationOnClassFoo);
System.out.println(startTag);
} catch (ClassCastException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}
}
}
In my solution, the class ExtendedCommandAnnotation need not to be present at compile time. However, the class Foo must be present. The solution could be modified a little bit so that the class Foo need not to be present too.

Java Exception Handling via Strategy Pattern?

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.

Categories