[Fix] Fixed Strolch exception i18n hierarchy

This commit is contained in:
Robert von Burg 2024-03-25 10:18:43 +01:00
parent a7258f0d06
commit 393659ff19
Signed by: eitch
GPG Key ID: 75DB9C85C74331F7
6 changed files with 99 additions and 122 deletions

View File

@ -24,6 +24,7 @@ import java.util.Locale;
import java.util.ResourceBundle;
import com.google.gson.JsonObject;
import li.strolch.exception.StrolchException;
import li.strolch.exception.StrolchUserMessageException;
import li.strolch.model.Tags;
import li.strolch.model.i18n.I18nMessageToJsonVisitor;
@ -229,10 +230,8 @@ public class ServiceResult {
json.addProperty(EXCEPTION_MSG, getExceptionMessageWithCauses(this.throwable, false));
json.addProperty(THROWABLE, formatException(this.throwable));
if (this.throwable instanceof StrolchUserMessageException
&& ((StrolchUserMessageException) this.throwable).hasI18n())
json.add(I_18_N, ((StrolchUserMessageException) this.throwable).getI18n()
.accept(new I18nMessageToJsonVisitor()));
if (this.throwable instanceof StrolchException ex && ex.hasI18n())
json.add(I_18_N, ex.getI18n().accept(new I18nMessageToJsonVisitor()));
}
if (!json.has(I_18_N) && this.i18nMessage != null)

View File

@ -26,14 +26,12 @@ public class StrolchAccessDeniedException extends StrolchException {
private final Certificate certificate;
private final Restrictable restrictable;
private final I18nMessage i18n;
public StrolchAccessDeniedException(Certificate certificate, Restrictable restrictable, I18nMessage i18n,
Throwable cause) {
super(i18n.getMessage(), cause);
super(i18n, cause);
this.certificate = certificate;
this.restrictable = restrictable;
this.i18n = i18n;
}
public Certificate getCertificate() {
@ -43,8 +41,4 @@ public class StrolchAccessDeniedException extends StrolchException {
public Restrictable getRestrictable() {
return restrictable;
}
public I18nMessage getI18n() {
return this.i18n;
}
}

View File

@ -15,16 +15,17 @@
*/
package li.strolch.exception;
import java.util.Locale;
import li.strolch.utils.I18nMessage;
import java.util.Locale;
import java.util.ResourceBundle;
/**
* @author Robert von Burg <eitch@eitchnet.ch>
*/
public class StrolchException extends RuntimeException {
private I18nMessage i18n;
protected I18nMessage i18n;
public StrolchException(String message, Throwable cause) {
super(message, cause);
@ -36,6 +37,41 @@ public class StrolchException extends RuntimeException {
public StrolchException(I18nMessage i18n) {
super(i18n.getMessage(Locale.getDefault()));
this.i18n = i18n;
if (i18n.hasException())
initCause(i18n.getException());
}
public StrolchException(I18nMessage i18n, Throwable cause) {
super(i18n.getMessage(Locale.getDefault()), cause);
this.i18n = i18n;
}
public StrolchException(ResourceBundle bundle, String key) {
this(new I18nMessage(bundle, key));
}
public StrolchException(ResourceBundle bundle, String key, String prop, Object value) {
this(new I18nMessage(bundle, key).value(prop, value));
}
public StrolchException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2,
Object value2) {
this(new I18nMessage(bundle, key).value(prop1, value1).value(prop2, value2));
}
public StrolchException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2, Object value2,
String prop3, Object value3) {
this(new I18nMessage(bundle, key).value(prop1, value1).value(prop2, value2).value(prop3, value3));
}
public StrolchException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2, Object value2,
String prop3, Object value3, String prop4, Object value4) {
this(new I18nMessage(bundle, key)
.value(prop1, value1)
.value(prop2, value2)
.value(prop3, value3)
.value(prop4, value4));
}
public boolean hasI18n() {
@ -54,4 +90,9 @@ public class StrolchException extends RuntimeException {
this.i18n = i18n;
return this;
}
public StrolchException cause(Throwable cause) {
initCause(cause);
return this;
}
}

View File

@ -1,78 +1,40 @@
package li.strolch.exception;
import li.strolch.utils.I18nMessage;
import java.util.Locale;
import java.util.ResourceBundle;
import li.strolch.utils.I18nMessage;
public class StrolchUserMessageException extends StrolchException {
private I18nMessage i18n;
public StrolchUserMessageException(I18nMessage i18n) {
super(i18n.getMessage(Locale.getDefault()));
this.i18n = i18n;
if (i18n.hasException())
initCause(i18n.getException());
super(i18n);
}
public StrolchUserMessageException(I18nMessage i18n, Throwable cause) {
super(i18n.getMessage(Locale.getDefault()), cause);
this.i18n = i18n;
super(i18n, cause);
}
public StrolchUserMessageException(ResourceBundle bundle, String key) {
this(new I18nMessage(bundle, key));
super(bundle, key);
}
public StrolchUserMessageException(ResourceBundle bundle, String key, String prop, Object value) {
this(new I18nMessage(bundle, key) //
.value(prop, value));
super(bundle, key, prop, value);
}
public StrolchUserMessageException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2,
Object value2) {
this(new I18nMessage(bundle, key) //
.value(prop1, value1) //
.value(prop2, value2));
super(bundle, key, prop1, value1, prop2, value2);
}
public StrolchUserMessageException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2,
Object value2, String prop3, Object value3) {
this(new I18nMessage(bundle, key) //
.value(prop1, value1) //
.value(prop2, value2) //
.value(prop3, value3));
super(bundle, key, prop1, value1, prop2, value2, prop3, value3);
}
public StrolchUserMessageException(ResourceBundle bundle, String key, String prop1, Object value1, String prop2,
Object value2, String prop3, Object value3, String prop4, Object value4) {
this(new I18nMessage(bundle, key) //
.value(prop1, value1) //
.value(prop2, value2) //
.value(prop3, value3) //
.value(prop4, value4));
}
public StrolchUserMessageException cause(Throwable cause) {
initCause(cause);
return this;
}
public boolean hasI18n() {
return this.i18n != null;
}
public I18nMessage getI18n() {
return this.i18n;
}
public void setI18n(I18nMessage i18n) {
this.i18n = i18n;
}
public StrolchUserMessageException i18n(I18nMessage i18n) {
this.i18n = i18n;
return this;
super(bundle, key, prop1, value1, prop2, value2, prop3, value3, prop4, value4);
}
}

View File

@ -40,7 +40,8 @@ public class ExceptionHelper {
public static String getCallerMethod(int depth) {
return StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE) //
.walk(frames -> frames.map((StackWalker.StackFrame sf) -> sf.getClassName() + "." + sf.getMethodName())
.walk(frames -> frames
.map((StackWalker.StackFrame sf) -> sf.getClassName() + "." + sf.getMethodName())
.skip(depth)
.findFirst()).orElse("UnknownClass.unknownMethod!");
}
@ -61,8 +62,7 @@ public class ExceptionHelper {
* in such a case
* </p>
*
* @param t
* the {@link Throwable}
* @param t the {@link Throwable}
*
* @return the exception as string
*/
@ -80,11 +80,9 @@ public class ExceptionHelper {
* in such a case
* </p>
*
* @param t
* the {@link Throwable}
* @param withClassName
* if true, then exception class name is prepended to the exception message, if the exception message is null,
* then this param is ignored
* @param t the {@link Throwable}
* @param withClassName if true, then exception class name is prepended to the exception message, if the exception
* message is null, then this param is ignored
*
* @return the exception as string
*/
@ -104,8 +102,7 @@ public class ExceptionHelper {
* in such a case
* </p>
*
* @param t
* the {@link Throwable}
* @param t the {@link Throwable}
*
* @return the exception as string
*/
@ -123,15 +120,15 @@ public class ExceptionHelper {
* in such a case
* </p>
*
* @param t
* the {@link Throwable}
* @param withClassName
* if true, then exception class name is prepended to the exception message, if the exception message is null,
* then this param is ignored
* @param t the {@link Throwable}
* @param withClassName if true, then exception class name is prepended to the exception message, if the exception
* message is null, then this param is ignored
*
* @return the exception as string
*/
public static String getExceptionMessageWithCauses(Throwable t, boolean withClassName) {
if (t == null)
return "(null)";
if (t.getCause() == null)
return getExceptionMessage(t, withClassName);
@ -142,13 +139,12 @@ public class ExceptionHelper {
/**
* Formats the given {@link Throwable}'s stack trace to a string
*
* @param t
* the throwable for which the stack trace is to be formatted to string
* @param t the throwable for which the stack trace is to be formatted to string
*
* @return a string representation of the given {@link Throwable}'s stack trace
*/
public static String formatException(Throwable t) {
String ls = System.getProperty(PROP_LINE_SEPARATOR);
String ls = System.lineSeparator();
if (!ls.equals(UNIX_LINE_SEP))
System.setProperty(PROP_LINE_SEPARATOR, UNIX_LINE_SEP);
try {
@ -165,8 +161,7 @@ public class ExceptionHelper {
/**
* Formats the given {@link Throwable}'s message including causes to a string
*
* @param t
* the throwable for which the messages are to be formatted to a string
* @param t the throwable for which the messages are to be formatted to a string
*
* @return a string representation of the given {@link Throwable}'s messages including causes
*/
@ -177,11 +172,9 @@ public class ExceptionHelper {
/**
* Formats the given {@link Throwable}'s message including causes to a string
*
* @param t
* the throwable for which the messages are to be formatted to a string
* @param withClassName
* if true, then exception class name is prepended to the exception message, if the exception message is null, *
* then this param is ignored
* @param t the throwable for which the messages are to be formatted to a string
* @param withClassName if true, then exception class name is prepended to the exception message, if the exception
* message is null, * then this param is ignored
*
* @return a string representation of the given {@link Throwable}'s messages including causes
*/
@ -196,8 +189,7 @@ public class ExceptionHelper {
/**
* Returns the root cause for the given {@link Throwable}
*
* @param throwable
* the {@link Throwable} for which to get the root cause
* @param throwable the {@link Throwable} for which to get the root cause
*
* @return the root cause of the given {@link Throwable}
*/
@ -213,8 +205,7 @@ public class ExceptionHelper {
/**
* Returns {@link #getExceptionMessage(Throwable, boolean)} for the root cause of the given {@link Throwable}
*
* @param throwable
* the throwable for which to get the message of the root cause
* @param throwable the throwable for which to get the message of the root cause
*
* @return {@link #getExceptionMessage(Throwable, boolean)} for the root cause of the given {@link Throwable}
*/
@ -225,8 +216,7 @@ public class ExceptionHelper {
/**
* Walks the causes for the given {@link Throwable} and sees if the given cause exists
*
* @param throwable
* the {@link Throwable} for which to find the given cause type
* @param throwable the {@link Throwable} for which to find the given cause type
*
* @return true if the cause was found, false if not
*/

View File

@ -8,6 +8,7 @@ import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import li.strolch.exception.StrolchElementNotFoundException;
import li.strolch.exception.StrolchException;
import li.strolch.exception.StrolchNotAuthenticatedException;
import li.strolch.exception.StrolchUserMessageException;
import li.strolch.model.i18n.I18nMessageToJsonVisitor;
@ -139,34 +140,24 @@ public class ResponseUtil {
if (svcResult.isOk())
return Response.ok().entity(json).type(MediaType.APPLICATION_JSON).build();
Status status;
if (t instanceof AccessDeniedException) {
status = Status.FORBIDDEN;
} else if (t instanceof PrivilegeModelException) {
status = Status.INTERNAL_SERVER_ERROR;
} else if (t instanceof PrivilegeException) {
status = Status.UNAUTHORIZED;
} else if (t instanceof StrolchElementNotFoundException) {
status = Status.NOT_FOUND;
} else {
status = Status.INTERNAL_SERVER_ERROR;
}
Status status = switch (t) {
case AccessDeniedException ignored -> Status.FORBIDDEN;
case PrivilegeException ignored -> Status.UNAUTHORIZED;
case StrolchElementNotFoundException ignored -> Status.NOT_FOUND;
case null, default -> Status.INTERNAL_SERVER_ERROR;
};
return Response.status(status).entity(json).type(MediaType.APPLICATION_JSON).build();
}
public static Response toResponse(Throwable t) {
if (t instanceof StrolchNotAuthenticatedException)
return ResponseUtil.toResponse(Status.UNAUTHORIZED, t);
if (t instanceof AccessDeniedException)
return ResponseUtil.toResponse(Status.FORBIDDEN, t);
if (t instanceof StrolchElementNotFoundException)
return ResponseUtil.toResponse(Status.NOT_FOUND, t);
if (t instanceof PrivilegeModelException)
return ResponseUtil.toResponse(Status.INTERNAL_SERVER_ERROR, t);
if (t instanceof PrivilegeException)
return ResponseUtil.toResponse(Status.FORBIDDEN, t);
return toResponse(Status.INTERNAL_SERVER_ERROR, t);
return switch (t) {
case StrolchNotAuthenticatedException ignored -> toResponse(Status.UNAUTHORIZED, t);
case AccessDeniedException ignored -> toResponse(Status.FORBIDDEN, t);
case StrolchElementNotFoundException ignored -> toResponse(Status.NOT_FOUND, t);
case PrivilegeException ignored -> toResponse(Status.FORBIDDEN, t);
case null, default -> toResponse(Status.INTERNAL_SERVER_ERROR, t);
};
}
public static Response toResponse(Status status, String msg) {
@ -180,13 +171,13 @@ public class ResponseUtil {
public static Response toResponse(Status status, Throwable t) {
JsonObject response = new JsonObject();
if (t instanceof StrolchUserMessageException ex && ((StrolchUserMessageException) t).hasI18n()) {
response.add("i18n", ex.getI18n().accept(new I18nMessageToJsonVisitor()));
} else {
Throwable rootCause = getRootCause(t);
if (rootCause instanceof StrolchUserMessageException ex &&
((StrolchUserMessageException) rootCause).hasI18n()) {
response.add("i18n", ex.getI18n().accept(new I18nMessageToJsonVisitor()));
switch (t) {
case StrolchException ex when ex.hasI18n() ->
response.add("i18n", ex.getI18n().accept(new I18nMessageToJsonVisitor()));
case null, default -> {
Throwable rootCause = getRootCause(t);
if (rootCause instanceof StrolchUserMessageException ex && ex.hasI18n())
response.add("i18n", ex.getI18n().accept(new I18nMessageToJsonVisitor()));
}
}