JavaFX: Error-logging ChangeListener - java

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

Related

Unable to serialize instance variable of a non-serializable superclass from the serializable subclass

New to this topic and right now I'm stuck at a brick wall. I have 2 classes, parent class: Controller.java and subclass: GreenhouseControls.java. I need to serialize a GreenhouseControls object but also an instance variable (eventList) from its superclass Controller.java.
My serialization happens when an inner class of GreenhouseControls.java throws a custom ControllerException, which is caught in the main method. Before terminating the program, the GreenhouseControls object should be saved (including the field from its superclass).
Why is a NotSerializableException thrown by the inner class WindowMalfunction of GreenhouseControls? Anyone have any ideas, as I am seriously stuck?
What I tried is the following:
Implement serializable on Controller.java. This is because if the superclass is serializable, then subclass is automatically serializable, however this throws java.io.NotSerializableException: GreenhouseControls$WindowMalfunction, (WindowMalfunction is the inner class that throws the initial exception to begin the serialization processs).
Implement serializable on GreenhouseControls.java and implement custom serialization by overriding writeObject() and readObject() to save the field from the superclass. This approach yet again throws the same exception as the approach 1.
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
Controller.java
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
public class Controller {
// THIS IS THE VARIABLE I NEED TO SAVE
protected List<Event> eventList = new ArrayList<Event>();
public void addEvent(Event c) {
eventList.add(c);
}
public void run() throws ControllerException {
while (eventList.size() > 0)
// Make a copy so you're not modifying the list
// while you're selecting the elements in it:
for (Event e : new ArrayList<Event>(eventList))
if (e.ready()) {
System.out.println(e);
e.action();
eventList.remove(e);
}
}
public static void shutDown() { }
}
GreenhouseControls.java class (note I have removed the inner classes and other code from it and only left related info)
public class GreenhouseControls extends Controller implements Serializable {
private int errorcode = 0;
public class WindowMalfunction extends Event {
public WindowMalfunction(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
windowok = false;
throw new ControllerException("Window malfunction");
}
public String toString() {
return "Window malfunction";
}
}
public class PowerOut extends Event {
public PowerOut(long delayTime) {
super(delayTime);
}
public void action() throws ControllerException {
poweron = false;
throw new ControllerException("Power out");
}
public String toString() {
return "Power out";
}
}
// Various other inner classes that extend event exist
public static void serializeObject(GreenhouseControls gc) {
FileOutputStream fileOut;
ObjectOutputStream out;
try {
fileOut = new FileOutputStream("dump.out");
out = new ObjectOutputStream(fileOut);
out.writeObject(gc);
System.out.println("WERRROR code: " + gc.getError());
out.close();
fileOut.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
out.writeObject(super.eventList);
}
private void readObject(ObjectInputStream in) throws IOException,
ClassNotFoundException {
in.defaultReadObject();
Object obj = in.readObject();
List<Event> x = cast(obj);
super.eventList = x;
}
#SuppressWarnings("unchecked")
public static <T extends List<?>> T cast(Object obj) {
return (T) obj;
}
public int getError() {
return errorcode;
}
public Fixable getFixable(int errorcode) {
switch (errorcode) {
case 1:
return new FixWindow();
case 2:
return new PowerOn();
default:
return null;
}
}
public static void main(String[] args) {
GreenhouseControls gc = null;
try {
String option = args[0];
String filename = args[1];
if (!(option.equals("-f")) && !(option.equals("-d"))) {
System.out.println("Invalid option");
printUsage();
}
// gc = new GreenhouseControls();
if (option.equals("-f")) {
gc = new GreenhouseControls();
gc.addEvent(gc.new Restart(0, filename));
}
gc.run();
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Invalid number of parameters");
printUsage();
} catch (ControllerException e) {
String errormsg;
if (e.getMessage().equals("Window malfunction")) {
gc.errorcode = 1;
errormsg = "Window malfunction event occurred Error code: " + gc.errorcode;
} else {
gc.errorcode = 2;
errormsg = "Power out event occurred Error code: " + gc.errorcode;
}
logError(errormsg);
serializeObject(gc);
gc.displayEventList();
shutDown();
}
}
}
Event.java
public abstract class Event {
private long eventTime;
protected final long delayTime;
public Event(long delayTime) {
this.delayTime = delayTime;
start();
}
public void start() { // Allows restarting
eventTime = System.currentTimeMillis() + delayTime;
}
public boolean ready() {
return System.currentTimeMillis() >= eventTime;
}
public abstract void action() throws ControllerException;
Event has to be Serializable too.
Change
public abstract class Event {
to
public abstract class Event implements Serializable {

Java generics api architecture

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());
}

Creating a "default constructor" for inner sub-interfaces

Okay, the title is maybe hard to understand. I didn't find something correct.
So, basically I'm using Java 8 functions to create a Retryable API. I wanted an easy implementation of these interfaces, so I created an of(...) method in each implementation of the Retryable interface where we can use lambda expressions, instead of creating manually an anonymous class.
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public interface Retryable<T, R> extends Function<T, R>{
void retrying(Exception e);
void skipping(Exception e);
int trials();
#Override
default R apply(T t) {
int trial = 0;
while (true) {
trial++;
try {
return action(t);
} catch (Exception e) {
if (trial < trials()) {
retrying(e);
} else {
skipping(e);
return null;
}
}
}
}
R action(T input) throws Exception;
interface RunnableRetryable extends Retryable<Void, Void> {
static RunnableRetryable of(Consumer<Exception> retrying, Consumer<Exception> skipping, int trials, CheckedRunnable runnable) {
return new RunnableRetryable() {
#Override
public void retrying(Exception e) {
retrying.accept(e);
}
#Override
public void skipping(Exception e) {
skipping.accept(e);
}
#Override
public int trials() {
return trials;
}
#Override
public Void action(Void v) throws Exception {
runnable.tryRun();
return null;
}
};
}
#FunctionalInterface
interface CheckedRunnable extends Runnable {
void tryRun() throws Exception;
#Override
default void run() {
try {
tryRun();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
interface ConsumerRetryable<T> extends Retryable<T, Void> {
static <T> ConsumerRetryable of(Consumer<Exception> retrying, Consumer<Exception> skipping, int trials, CheckedConsumer<T> consumer) {
return new ConsumerRetryable<T>() {
#Override
public void retrying(Exception e) {
retrying.accept(e);
}
#Override
public void skipping(Exception e) {
skipping.accept(e);
}
#Override
public int trials() {
return trials;
}
#Override
public Void action(T t) throws Exception {
consumer.tryAccept(t);
return null;
}
};
}
#FunctionalInterface
interface CheckedConsumer<T> extends Consumer<T> {
void tryAccept(T t) throws Exception;
#Override
default void accept(T t) {
try {
tryAccept(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
interface SupplierRetryable<T> extends Retryable<Void, T> {
static <T> SupplierRetryable of(Consumer<Exception> retrying, Consumer<Exception> skipping, int trials, CheckedSupplier<T> supplier) {
return new SupplierRetryable<T>() {
#Override
public void retrying(Exception e) {
retrying.accept(e);
}
#Override
public void skipping(Exception e) {
skipping.accept(e);
}
#Override
public int trials() {
return trials;
}
#Override
public T action(Void v) throws Exception {
return supplier.tryGet();
}
};
}
#FunctionalInterface
interface CheckedSupplier<T> extends Supplier<T> {
T tryGet() throws Exception;
#Override
default T get() {
try {
return tryGet();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
interface FunctionRetryable<T, R> extends Retryable<T, R> {
static <T, R> FunctionRetryable of(Consumer<Exception> retrying, Consumer<Exception> skipping, int trials, CheckedFunction<T, R> function) {
return new FunctionRetryable<T, R>() {
#Override
public void retrying(Exception e) {
retrying.accept(e);
}
#Override
public void skipping(Exception e) {
skipping.accept(e);
}
#Override
public int trials() {
return trials;
}
#Override
public R action(T t) throws Exception {
return function.tryApply(t);
}
};
}
#FunctionalInterface
interface CheckedFunction<T, R> extends Function<T, R> {
R tryApply(T t) throws Exception;
#Override
default R apply(T t) {
try {
return tryApply(t);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
}
But as you can see, there's a lot of duplicate code in every of(...) methods. I could create a kind of "constructor" (that's not the correct word, because interfaces can't have a constructor) in the Retryable interface, but I don't know how. Does someone have an idea ?
The main problem is your API explosion. All these nested interfaces extending Retryable do not add any functionality, but require the user of this code to deal with them, once they are part of the API. Further, they are the cause of this code duplication, as each of these redundant interfaces requires its own implementation, whereas all implementations are basically doing the same.
After removing these obsolete types, you can simply implement the operations as delegation:
public interface Retryable<T, R> extends Function<T, R>{
void retrying(Exception e);
void skipping(Exception e);
int trials();
#Override default R apply(T t) {
try { return action(t); }
catch(Exception e) {
for(int trial = 1; trial < trials(); trial++) {
retrying(e);
try { return action(t); } catch (Exception next) { e=next; }
}
skipping(e);
return null;
}
}
R action(T input) throws Exception;
public static Retryable<Void, Void> of(Consumer<Exception> retrying,
Consumer<Exception> skipping, int trials, CheckedRunnable runnable) {
return of(retrying, skipping, trials, x -> { runnable.tryRun(); return null; });
}
#FunctionalInterface interface CheckedRunnable extends Runnable {
void tryRun() throws Exception;
#Override default void run() {
try { tryRun(); } catch (Exception e) { throw new RuntimeException(e); }
}
}
public static <T> Retryable<T, Void> of(Consumer<Exception> retrying,
Consumer<Exception> skipping, int trials, CheckedConsumer<T> consumer) {
return of(retrying, skipping, trials,
value -> { consumer.tryAccept(value); return null; });
}
#FunctionalInterface interface CheckedConsumer<T> extends Consumer<T> {
void tryAccept(T t) throws Exception;
#Override default void accept(T t) {
try { tryAccept(t); } catch (Exception e) { throw new RuntimeException(e); }
}
}
public static <T> Retryable<Void, T> of(Consumer<Exception> retrying,
Consumer<Exception> skipping, int trials, CheckedSupplier<T> supplier) {
return of(retrying, skipping, trials, voidArg -> { return supplier.tryGet(); });
}
#FunctionalInterface interface CheckedSupplier<T> extends Supplier<T> {
T tryGet() throws Exception;
#Override default T get() {
try { return tryGet(); }
catch (Exception e) { throw new RuntimeException(e); }
}
}
public static <T, R> Retryable<T, R> of(Consumer<Exception> retrying,
Consumer<Exception> skipping, int trials, CheckedFunction<T, R> function) {
return new Retryable<T, R>() {
#Override public void retrying(Exception e) { retrying.accept(e); }
#Override public void skipping(Exception e) { skipping.accept(e); }
#Override public int trials() { return trials; }
#Override public R action(T t) throws Exception {
return function.tryApply(t);
}
};
}
#FunctionalInterface interface CheckedFunction<T, R> extends Function<T, R> {
R tryApply(T t) throws Exception;
#Override default R apply(T t) {
try { return tryApply(t); }
catch (Exception e) { throw new RuntimeException(e); }
}
}
}
There is only one implementation class needed, which has to be able to deal with an argument and a return value, the others can simply delegate to it using an adapter function, doing either, dropping the argument or returning null, or both.
For most use cases, the shape of the lambda expression is appropriate to select the right method, e.g.
Retryable<Void,Void> r = Retryable.of(e -> {}, e -> {}, 3, () -> {});
Retryable<Void,String> s = Retryable.of(e -> {}, e -> {}, 3, () -> "foo");
Retryable<Integer,Integer> f = Retryable.of(e -> {}, e -> {}, 3, i -> i/0);
but sometimes, a little hint is required:
// braces required to disambiguate between Function and Consumer
Retryable<String,Void> c = Retryable.of(e->{}, e ->{}, 3,
str -> { System.out.println(str); });
It looks like you can factor some of this out in to a (possibly package-private) abstract class:
abstract class AbstractRetryable<T, R> implements Retryable<T, R> {
private final Consumer<Exception> retrying;
private final Consumer<Exception> skipping;
private final int trials;
AbstractRetryable(Consumer<Exception> retrying,
Consumer<Exception> skipping,
int trials) {
this.retrying = Objects.requireNonNull(retrying, "retrying");
this.skipping = Objects.requireNonNull(skipping, "skipping");
this.trials = trials;
}
#Override
public void retrying(Exception x) {
retrying.accept(x);
}
#Override
public void skipping(Exception x) {
skipping.accept(x);
}
#Override
public int trials() {
return trials;
}
}
The only issue with this is that you're using subinterfaces, so you can't create an anonymous class which both extends the abstract class and implements the subinterface.
You could then write more (again, possibly package-private) subclasses:
final class RunnableRetryableImpl
extends AbstractRetryable<Void, Void>
implements RunnableRetryable {
private final CheckedRunnable runnable;
RunnableRetryableImpl(Consumer<Exception> retrying,
Consumer<Exception> skipping,
int trials,
CheckedRunnable runnable) {
super(retrying, skipping, trials);
this.runnable = Objects.requireNonNull(runnable, "runnable");
}
#Override
public Void apply(Void ignored) {
try {
runnable.tryRun();
} catch (Exception x) {
// BTW I would consider doing this.
if (x instanceof RuntimeException)
throw (RuntimeException) x;
// I would also probably write a class like:
// class RethrownException extends RuntimeException {
// RethrownException(Exception cause) {
// super(cause);
// }
// }
// This way the caller can catch a specific type if
// they want to.
// (See e.g. java.io.UncheckedIOException)
throw new RuntimeException(x);
}
return null;
}
}
Or you could reduce the line count by using local classes:
static RunnableRetryable of(Consumer<Exception> retrying,
Consumer<Exception> skipping,
int trials,
CheckedRunnable runnable) {
Objects.requireNonNull(runnable, "runnable");
final class RunnableRetryableImpl
extends AbstractRetryable<Void, Void>
implements RunnableRetryable {
RunnableRetryable() {
// Avoid explicitly declaring parameters
// and passing arguments.
super(retrying, skipping, trials);
}
#Override
public Void apply(Void ignored) {
try {
runnable.tryRun();
} catch (Exception x) {
if (x instanceof RuntimeException)
throw (RuntimeException) x;
throw new RuntimeException(x);
}
return null;
}
}
return new RunnableRetryableImpl();
}
Personally, I think I would just write package-private implementations instead of the local classes but it certainly requires a fair amount of boiler-plate code.
Also, as a side note, when you are writing factories that return anonymous classes, you should use requireNonNull inside the method itself (as I did in my example of method). This is so that if null is passed to the method, the method throws the NPE instead of e.g. some call to retrying or skipping throwing the NPE some time later.

Keeping possible exceptions in Enum

I am working on some workflow and it is possible to raise many exceptions in that. I heard that we can keep all those possible exceptions in an Enum (Exception1, Exception2 ...) and use it. How can we do that using Enums in Java?
You can add the classes of exceptions with
enum EnumWithExceptions {
ENUM1(Exception1.class, Exception2.class),
ENUM2(Exception3.class);
private final Class<? extends Exception>[] exceptions;
private EnumWithExceptions(Class<? extends Exception>... exceptions) {
this.exceptions = exceptions;
}
public boolean matches(Exception e) {
for(Class<? extends Exception> e2: exceptions)
if (e2.isInstance(e)) return true;
return false;
}
}
} catch(Exception e){
if (ENUM1.matches(e)){
//do something
} else if(ENUM2.matches(e)) {
//do something
} else {
//do something
}
}
enum Fred {
SAM(AnException.class),
I(AnotherException.class),
AM(YetAnotherException.class)
;
private Throwable t;
Fred(Throwable throwable) {
this.t = throwable;
}
public Throwable getThrowable() {
return t;
}
}
...
throw Fred.SAM.getThrowable();
Why not store the exceptions in an ArrayList? Or if you want to name the index, you could use a HashMap.
import java.util.ArrayList;
import java.util.HashMap;
public final class ExceptionStorage {
private static int exceptionCount = 0;
private static HashMap<String, Exception> indexedExceptions = new HashMap<>();
private static ArrayList<Exception> exceptions = new ArrayList();
public static void addException(Exception e) {
exceptions.add(e);
}
public static void putException(Exception e) {
indexedExceptions.put("Exception" + (++exceptionCount), e);
}
public static ArrayList<Exception> getUnindexedExceptions() {
return this.exceptions;
}
public static HashMap<String, Exception> getIndexedExceptions() {
return this.indexedExceptions;
}
}
Obviously you would have to modify the code to use either ArrayList or HashMap, but I think this would be a better solution than using Enums.

Throw my own exceptions?

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 {
...
}
}

Categories