I'm implementing a strategy pattern for exceptions handling
public class GlobalExceptionHandler {
private interface Strategy<T extends Exception> {
ErrorResponse extract(T e);
}
private static class ResponseStatusStrategy implements Strategy<ResponseStatusException> {
#Override
public ErrorResponse extract(ResponseStatusException e) {
return ErrorResponse.builder()
.status(e.getStatus())
.message(e.getReason())
.description(e.getReason())
.build();
}
}
private static class IllegalStateStrategy implements Strategy<IllegalStateException> {
#Override
public ErrorResponse extract(IllegalStateException e) {
return ErrorResponse.builder()
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.message(e.getMessage())
.description("")
.build();
}
}
....
I call this API like this:
Exception ex = ....; // function param
if (ex instanceof ResponseStatusException) {
errorResponse = new ResponseStatusStrategy().extract((ResponseStatusException) ex);
} else if (ex instanceof IllegalStateException) {
errorResponse = new IllegalStateStrategy().extract((IllegalStateException) ex);
} else {
errorResponse = new EmptyStrategy().extract(ex);
}
Is there a more efficient and beautiful way to implement this? Idea gets me hint that I even didn't use interface method: "method extract(T e) is never used".
It would be great to have API like this:
Strategy<???> strategy;
if (ex instanceof ResponseStatusException) {
strategy = new ResponseStatusStrategy();
} else if (ex instanceof IllegalStateException) {
strategy = new IllegalStateStrategy();
} else {
strategy = new EmptyStrategy();
}
errorResponse = strategy.extract(ex);
You are trying to solve an object creational problem. You want a particular Strategy class object based on the StatusException class. Create a new class with a factory pattern to return you the correct object. Here is some dummy code inspired from your code.
private interface Factory {
Strategy buildStrategy(Exception e);
}
private static class FactoryImpl implements Factory {
public Strategy buildStrategy(Exception e) {
if (e instanceof IOException) {
return new Strategy1();
} else {
return new EmptyStrategy();
}
}
}
private interface Strategy<T extends Exception> {
String extract();
}
private static class Strategy1 implements Strategy<IOException> {
#Override public String extract() {
return "Strategy1";
}
}
private static class EmptyStrategy implements Strategy<NamingException> {
#Override public String extract() {
return "EmptyStrategy";
}
}
public static void main(String[] args) {
var f = new FactoryImpl();
System.out.println(f.buildStrategy(new IOException()).extract());
System.out.println(f.buildStrategy(new NamingException()).extract());
}
Related
I have a Service which is responsible to gather some information through Providers. Depending on the information required, a certain Provider has to be used. For now the Provider is chosen upon a given Class. This example is simplified, but it should give a reasonable understanding of my setup
abstract class AbstractProvider {
private String provider = "MyProvider";
public String doSomethingAwsome() {
return provider;
}
}
class ProviderA extends AbstractProvider {
#Override
public String doSomethingAwsome() {
return super.doSomethingAwsome() + "_A";
}
}
class ProviderB extends AbstractProvider {
#Override
public String doSomethingAwsome() {
return super.doSomethingAwsome() + "_B";
}
}
class MyService {
private ProviderA providerA;
private ProviderB providerB;
MyService() {
providerA = new ProviderA();
providerB = new ProviderB();
}
public <T extends AbstractProvider> String doSomethingWithProvider(Class<T> providerClass) {
if (providerClass.equals(ProviderA.class)) {
return providerA.doSomethingAwsome();
} else if (providerClass.equals(ProviderB.class)) {
return providerB.doSomethingAwsome();
}
throw new IllegalArgumentException("No Provider found for Class: " + providerClass);
}
}
class Main {
public static void main(String[] args) {
MyService myService = new MyService();
String fromProviderA = myService.doSomethingWithProvider(ProviderA.class);
String fromProviderB = myService.doSomethingWithProvider(ProviderB.class);
System.out.printf("Provider A: %s, Provider B: %s", fromProviderA, fromProviderB);
}
}
Now I'm not happy with the solution in MyService.doSomethingWithProvider(). How would you implement this?
Is there a generic way of choosing the Provider? I dont like to use if-else clauses here.
Edit
Based on some suggestions, using a map seems better
class MyService {
private Map<Class<? extends AbstractProvider>, AbstractProvider> providers = new HashMap<>();
MyService() {
providers.put(ProviderA.class, new ProviderA());
providers.put(ProviderB.class, new ProviderB());
}
public <T extends AbstractProvider> String doSomethingWithProvider(Class<T> providerClass) {
if (providers.containsKey(providerClass)) {
return providers.get(providerClass).doSomethingAwsome();
}
new IllegalArgumentException("No Provider found for Class: " + providerClass)
}
}
Turing85 suggested to have a look at the Chain of Responsibility design pattern. Honestly I had to dig a little deeper for this one. The idea is quite easy to understand but getting my head around the implementation took me a little further.
So thanks for your input, I'm happy with this
abstract class AbstractProvider {
private String provider = "MyProvider";
public AbstractProvider nextProcessor;
public AbstractProvider(AbstractProvider nextProcessor) {
this.nextProcessor = nextProcessor;
}
public String doSomethingAwsome() {
return provider;
}
public abstract <T extends AbstractProvider> String doSomethingAwsome(Class<T> provider) throws IllegalArgumentException;
}
class ProviderA extends AbstractProvider {
public ProviderA (AbstractProvider nextProvider) {
super(nextProvider);
}
#Override
public String doSomethingAwsome() {
return super.doSomethingAwsome() + "_A";
}
#Override
public <T extends AbstractProvider> String doSomethingAwsome(Class<T> provider) throws IllegalArgumentException {
if (provider.equals(this.getClass())) {
return this.doSomethingAwsome();
} else if (nextProcessor != null) {
return nextProcessor.doSomethingAwsome(provider);
}
throw new IllegalArgumentException("No provider found for class: " + provider);
}
}
class ProviderB extends AbstractProvider {
public ProviderB (AbstractProvider nextProvider) {
super(nextProvider);
}
#Override
public String doSomethingAwsome() {
return super.doSomethingAwsome() + "_B";
}
#Override
public <T extends AbstractProvider> String doSomethingAwsome(Class<T> provider) throws IllegalArgumentException {
if (provider.equals(this.getClass())) {
return this.doSomethingAwsome();
} else if (nextProcessor != null) {
return nextProcessor.doSomethingAwsome(provider);
}
throw new IllegalArgumentException("No provider found for class: " + provider);
}
}
class MyService {
private AbstractProvider providerChain;
MyService() {
providerChain = new ProviderA(new ProviderB(null));
}
public <T extends AbstractProvider> String doSomethingWithProvider(Class<T> providerClass) {
return providerChain.doSomethingAwsome(providerClass);
}
}
I'm pretty sure you can do several more improvements here. Don't hesitate to give me your input
How to write this Java Class in C# Class format
public final class JsonParserResolver {
// PlacesApiJsonParser is an Interface
public static final PlacesApiJsonParser JSON_PARSER;
static {
boolean hasGson;
try {
Class.forName("com.google.gson.Gson");
hasGson = true;
} catch (ClassNotFoundException e) {
hasGson = false;
}
JSON_PARSER = hasGson ? new GsonPlacesApiJsonParser() : new
AndroidPlacesApiJsonParser();
}
private JsonParserResolver() {
throw new RuntimeException("No instances");
}
}
The class static member is resolving stuff automatically on Class instantiation. This is a very useful
Hold your horses this is where I am, I get a little stuck on the JSON_PARSER
namespace WorkSampleBookSearch
{
public final class JsonParserResolver
{
public static final PlacesApiJsonParser JSON_PARSER;
static {
boolean hasGson;
JSON_PARSER = hasGson? new GsonPlacesApiJsonParser() : new AndroidPlacesApiJsonParser();
}
private JsonParserResolver()
{
throw new RuntimeException("No instances");
}
}
}
I would like to generalize the following pattern:
setChangeListener = c -> {
try {
// do something dangerous
} catch (final IOException e) {
logger.error(e.getLocalizedMessage(), e);
}
};
I would like to use it like this:
errorLoggingSetChangeListener = c -> {
// do something dangerous
};
I was thinking about this:
public class ErrorLoggingSetChangeListener<T> implements SetChangeListener<T> {
private static final Logger logger = Logger.getLogger(ErrorLoggingSetChangeListener.class);
private final SetChangeListener<T> delegate;
#Override
public void onChanged(final SetChangeListener.Change<? extends T> change) {
try {
delegate.onChanged(change);
} catch (final Exception e) {
if (logger.isEnabledFor(Level.ERROR)) {
logger.error(e.getLocalizedMessage(), e);
}
}
}
public ErrorLoggingSetChangeListener(final SetChangeListener<T> delegate) {
super();
this.delegate = delegate;
}
}
But that is not possible, since ErrorLoggingSetChangeListener is not a Functional interface.
Any chance to convert this class to an Functional Interface?
This does not compile:
public interface ErrorLoggingSetChangeListener<T> extends SetChangeListener<T> {
static final Logger logger = Logger.getLogger(ErrorLoggingSetChangeListener.class);
#Override
default void onChanged(final SetChangeListener.Change<? extends T> change) {
try {
SetChangeListener.super.onChanged(change);
} catch (final Exception e) {
if (logger.isEnabledFor(Level.ERROR)) {
logger.error(e.getLocalizedMessage(), e);
}
}
}
}
This does also not compile:
errorLoggingSetChangeListener = new ErrorLoggingSetChangeListener<>(c -> {
throw new IOException();
});
The error message is
Unhandled exception [..]
.
This is similar to #JonnyAW's solution, but combines both classes into a single interface:
import javafx.collections.SetChangeListener;
#FunctionalInterface
public interface ErrorLoggingSetChangeListener<E> extends SetChangeListener<E> {
public void delegate(Change<? extends E> change) throws Exception ;
#Override
public default void onChanged(Change<? extends E> change) {
try {
delegate(change);
} catch (Exception exc) {
// just do a System.out.println here to demo we reach this block:
System.out.println("Custom error handling...");
exc.printStackTrace();
}
}
}
And here's a demo of using this:
import javafx.collections.FXCollections;
import javafx.collections.ObservableSet;
public class Test {
public static void main(String[] args) {
ObservableSet<String> set = FXCollections.observableSet();
ErrorLoggingSetChangeListener<String> listener = c -> {
if (c.wasAdded()) {
int i = Integer.parseInt(c.getElementAdded());
System.out.println("Value added: "+i);
}
};
set.addListener(listener);
set.add("42");
set.add("What do you get when you multiply 6 by 9?");
}
}
which generates the expected output:
Value added: 42
Custom error handling...
java.lang.NumberFormatException: For input string: "What do you get when you multiply 6 by 9?"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Integer.parseInt(Integer.java:615)
at Test.lambda$0(Test.java:10)
at ErrorLoggingSetChangeListener.onChanged(ErrorLoggingSetChangeListener.java:12)
at com.sun.javafx.collections.SetListenerHelper$SingleChange.fireValueChangedEvent(SetListenerHelper.java:163)
at com.sun.javafx.collections.SetListenerHelper.fireValueChangedEvent(SetListenerHelper.java:72)
at com.sun.javafx.collections.ObservableSetWrapper.callObservers(ObservableSetWrapper.java:128)
at com.sun.javafx.collections.ObservableSetWrapper.add(ObservableSetWrapper.java:269)
at Test.main(Test.java:17)
here is my implementation, that will compile:
ErrorLoggingSetChangeListener:
import javafx.collections.SetChangeListener;
public class ErrorLoggingSetChangeListener<T> implements SetChangeListener<T> {
private DangerousInterface<T> delegate;
public ErrorLoggingSetChangeListener(DangerousInterface<T> delegate) {
super();
this.delegate = delegate;
}
#Override
public void onChanged(Change<? extends T> change) {
try {
this.delegate.delegate(change);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
DangerousInterface:
public interface DangerousInterface<T> {
public void delegate(Change<? extends T> change) throws Exception;
}
Main:
SetChangeListener<String> listener = new ErrorLoggingSetChangeListener<>((test) -> {
//no errors here now
throw new Exception();
});
I got definitely no compile errors
EDIT: ok, I got the Problem, you need a new Interface that can actually throw something, now you can wrap it in onChanged
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 have a lot of classes UNO,HAV,MAS,KOS
I want to create a factory pattern.
validator.load("UNO").validate();
I need dynamically load classes into validator class and return an instance.
(dynamically set name of the class and return an instance)
My problem is: how can I return the instance of a class, if I have incompatible types?
I don't know what to write in return type of method.
The main problem in the Validator CLASS.
public SegmentAbstract load(String str) {
AND
return SegmentAbsClass.forName(identify);
Main class
try{
validator.load("UNO").validate();
}catch(Exception e){
System.out.print("No class ");
}
Abstract Class (SegmentAbstract)
public abstract class SegmentAbstract {
public abstract Boolean validate();
}
Class UNO
public class UNA extends SegmentAbstract{
public Boolean validate() {
System.out.print("UNO!!");
return true;
}
}
Class Validator
public class Validator {
public SegmentAbstract load(String str) {
String identify = str.substring(0, 3);
try {
return SegmentAbsClass.forName(identify);
}
catch(Exception e) {
return this;
}
}
}
Try this :
public interface Validator {
boolean validate(Object obj);
}
public final class ValidatorFactory {
private ValidatorFactory(){}
public static Validator load(String type){
try {
Class<?> clazz = Class.forName(type);
if (Arrays.asList(clazz.getInterfaces()).contains(Validator.class)){
return (Validator) clazz.newInstance();
}
throw new IllegalArgumentException("Provided class doesn't implement Validator interface");
} catch (Exception e) {
throw new IllegalArgumentException("Wrong class provided", e);
}
}
}
Maybe this will help???
I will do something like that:
// ISegment.java
public interface ISegment {
Boolean validate();
}
// Uno.java
public class Uno implements ISegment {
public Boolean validate() {
System.out.print("UNO!!");
return true;
}
}
// SegmentFactory.java
public final class SegmentFactory {
public static enum Supported {
UNO("uno", Uno.class), /* ... */, HAV("hav", Hav.class);
private final Class<?> clazz;
private final String name;
private Supported(final String name, final Class<?> clazz) {
this.name = name;
this.clazz = clazz;
}
public Class<?> getClazz() {
return clazz;
}
public static Supported for(final String name) {
for (final Supported s : values()) {
if (s.name.equals(name) {
return s;
}
}
return null; // a default one
}
}
public static ISegment create(final Supported supp) {
if (supp == null) {
return null;
}
return supp.getClazz.newInstance();
}
private SegmentFactory() {
// avoid instantiation
}
}
usage:
final ISegment sa = SegmentFactory.create(SegmentFactory.Supported.for("uno"));
sa.validate();
Not tested!!
Take a look here. Briefly, the idea is to create a map in your factory class (Map<String,String>, key is identifier, value is fully qualified class name), and add supported classes during initialization. Then you use reflection to instantiate an object in your factory method. Also, you can avoid reflection by using Map<String, SegmentAbstract> instead of Map<String,String> and adding public abstract getNewSegment() to your SegmentAbstract class.