This is the easiest example of a complex issue. I haven't found the example of this problem anywhere in the entire internet. I'm validating the input in a validationMethod that return Boolean. Now, I need to use this method in calling class (run the flow if return is true, catch exception if return is false).
public class StringUtil{
public static boolean validateNumInput(String UserInput)
{
if(UserInput.matches("[0-9]+")){
return true;
} return false;
}
}
public class Main{
public static void main(String[] args){
String a="012*+";
try{
if(StringUtil.validateNumInput(a)){
System.out.println(StringUtil.validateNumInput(a));
}
}catch(Exception e){
System.out.println("Big problem");
}
}
}
According to the documentation, you can filter catch clauses with a Boolean predicate. So, your validation method would need to throw an exception which you could filter for in your catch clause. But if you're doing that, you might as well roll your own custom exception and not have to deal with the Boolean at all. The other alternative is, in your calling code, treat the return code as a return code and throw your own exception.
Option 1:
public class StringUtil{
public static boolean validateNumInput(String UserInput)
{
if(UserInput.matches("[0-9]+")){
return true;
}
throw new Exception ("Validation failed!");
}
}
public class Main{
public static void main(String[] args){
String a="012*+";
try{
if(StringUtil.validateNumInput(a)){
System.out.println(StringUtil.validateNumInput(a));
}
}catch(Exception e) when (e.Message == "Validation failed!") {
System.out.println("Big problem");
}
}
}
Option 2:
public class Main{
public static void main(String[] args){
String a="012*+";
try{
if(StringUtil.validateNumInput(a)){
System.out.println(StringUtil.validateNumInput(a));
} else {
throw new Exception ();
}
}catch(Exception e) {
System.out.println("Big problem");
}
}
}
Related
ASP.NET Core Web Api Middleware Converts Custom Exception into Base Exception
I have created a custom exception class and use it throw an exception. The middleware catches it but throws base exception instead of custom exception. I am not able to understand why it does not catch custom exception.
Custom Exception
public class CustomException : Exception
{
public int HttpStatusCode { get; private set; }
public CustomException()
{
}
public CustomException(int httpStatusCode, string message):base(message)
{
HttpStatusCode = httpStatusCode;
}
}
Middleware
public class ExceptionMiddleware
{
public readonly RequestDelegate _next;
public ExceptionMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task InvokeAsync(HttpContext httpContext)
{
try
{
await _next(httpContext);
}
catch(CustomException ex)
{
await HandleExceptionAsync(httpContext, ex);
}
catch(Exception ex)
{
await HandleExceptionAsync(httpContext, ex);
}
}
private static Task HandleExceptionAsync(HttpContext context, Exception ex)
{
int statusCode = (int)HttpStatusCode.InternalServerError;
if (ex is CustomException)
{
CustomException se = ex as CustomException;
statusCode = se.HttpStatusCode;
}
context.Response.ContentType = "application/json";
context.Response.StatusCode = statusCode;
return context.Response.WriteAsync(JsonConvert.SerializeObject(new InternalServerErrorResponse(ex.Message)));
}
}
Exception thrown
throw new CustomException(StatusCodes.Status422UnprocessableEntity, "User is already registered!");
When exception is thrown, middleware does not catch custom exception but base Exception. It always goes to the below code block
catch(Exception ex)
{
await HandleExceptionAsync(httpContext, ex);
}
Please advise.
You can use exception filter to handle exceptions and easily manipulate response.
public class ExceptionFilter : IExceptionFilter
{
public ExceptionFilter(IHostingEnvironment env, ILogger<JsonExceptionFilter> logger)
{
_env = env;
_logger = logger;
}
public void OnException(ExceptionContext context)
{
var error = new ApiResponse();
var exceptionName = context.Exception.GetType().Name;
var message = context.Exception.Message;
if (_env.IsDevelopment())
{
error.Message = context.Exception.Message;
error.Detail = context.Exception.StackTrace;
}
else
{
//Prevent To Show Exception Messages On Production
error.Message = "Server Error Occured";
error.Detail = "Something wrong happened";
}
context.Result = new ObjectResult(error)
{
//Manipulate Status Code
StatusCode = 500
};
}
}
And register to Startup.cs
public void ConfigureServices(IServiceCollection services){
services.AddMvc(options =>
{
//Catch the exceptions
options.Filters.Add<ExceptionFilter>();
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
you have to tell your app to use this middleware in configure method in your startup class like this -
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerManager logger){
app.ExceptionMiddleware();
}
I cannot catch the exception, instead a runtime error is thrown in the main method.
Any idea?
code below:
public class Test {
public static void main(String[] args) {
ArrayList myList = new ArrayList();
String[] myArray;
try{
while(true){
myList.add("My String");
}
}catch(RuntimeException re){
System.out.println("Caught a RuntimeException");
}catch(Exception re){
System.out.println("Caught a Exception");
}
System.out.println("Ready to use");
}
}
It will throw OutOfMemoryError which do not extend Exception. So you can not catch it by Exception.
public static void main(String[] args) {
ArrayList myList = new ArrayList();
try{
while(true){
myList.add("My String");
}
}catch(RuntimeException re){
System.out.println("Caught a RuntimeException");
}catch(Exception re){
System.out.println("Caught a Exception");
} catch (OutOfMemoryError e){
System.out.println("Out of memory");
}
System.out.println("Ready to use");
}
I'm looking to use JACKSON instead of grails JSON ,without changing the auto-scaffolded contollers.
Is it possible to seamlessly replace the current grails JSON converter with another one ?
Are there any classes to implement other then AbstractConverter...
Should be pretty simple. AbstractConverter is all you need to extend to do:
render result as JackSON
Something like this***:
*** taken from here: https://github.com/sjhorn/grails-jackson/blob/master/src/groovy/com/hornmicro/JackSON.groovy
class JackSON extends AbstractConverter {
Object target
public JackSON() {
}
public JackSON(Object target) {
this()
setTarget(target)
}
public void render(Writer out) throws ConverterException {
try {
ObjectMapper mapper = new ObjectMapper()
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
mapper.configure(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM, false)
mapper.configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, false)
mapper.writeValue(out, target)
} catch(e) {
throw new ConverterException(e)
}
try {
out.flush()
out.close()
} catch (Exception e) {
log.warn("Unexpected exception while closing a writer: " + e.getMessage())
}
}
public void render(HttpServletResponse response) throws ConverterException {
response.setContentType(GrailsWebUtil.getContentType("application/json", "UTF-8"));
try {
render(response.getWriter())
} catch (IOException e) {
throw new ConverterException(e)
}
}
public Object getWriter() throws ConverterException {
throw new ConverterException("Not Implemented")
}
public void convertAnother(Object o) throws ConverterException {
throw new ConverterException("Not Implemented")
}
public void build(Closure c) throws ConverterException {
throw new ConverterException("Not Implemented")
}
public ObjectMarshaller lookupObjectMarshaller(Object target) {
return null
}
public void setTarget(Object target) {
this.target = target
}
}
I have created a CustomException with a custom message and an error code.
public class CustomException extends RuntimeException{
private int errorCode;
public CustomException(String message,int errorCode){
super(message);
this.errorCode=errorCode;
}
public int getErrorCode(){
return this.errorCode;
}
public String getMessage(){
return "Message: "+super.getMessage()+" ErrorCode: "+this.errorCode;
}
}
When I add a null value in a list throw CustomException with the message "Null" and error Code 1. When I add an empty value the message for exception is "Empty" and error Code 2.
How I can capture and test error code in unit test?
I have done something like that:
public class MyListTester{
private Class exceptionType = CustomException.class;
#Test
public void testAddNonNullValue() {
exception.expect(exceptionType);
exception.expectMessage("Null");
list.add(null);
}
but I don't have acces to the error code
The trick is to use the expect method of the ExpectedException rule which takes a Matcher as parameter and to write a custom matcher for verifying the error code. Here is a complete example:
public class MyListTester {
#Rule
public ExpectedException exception = ExpectedException.none();
#Test
public void testAddNullValue() {
MyList list = new MyList();
exception.expect(CustomException.class);
exception.expectMessage("Null");
exception.expect(errorCode(1));
list.add(null);
}
#Test
public void testAddEmptyValue() {
MyList list = new MyList();
exception.expect(CustomException.class);
exception.expectMessage("Empty");
exception.expect(errorCode(2));
list.add(emptyValue);
}
private Matcher<? extends CustomException> errorCode(final int errorCode) {
return new CustomTypeSafeMatcher<CustomException>("errorCode " + errorCode) {
#Override
protected boolean matchesSafely(CustomException e) {
return e.getErrorCode() == errorCode;
}
};
}
}
Hi I have custom junit runner
public class InterceptorRunner extends BlockJUnit4ClassRunner {
#Retention(RetentionPolicy.RUNTIME)
#Target(ElementType.TYPE)
public #interface InterceptorClasses {
public Class<?>[] value();
}
public InterceptorRunner(Class<?> klass) throws InitializationError {
super(klass);
}
#Override
public Statement methodInvoker(FrameworkMethod method, Object test) {
InterceptorStatement statement = new InterceptorStatement(super.methodInvoker(method, test));
InterceptorClasses annotation = test.getClass().getAnnotation(InterceptorClasses.class);
Class<?>[] klasez = annotation.value();
try {
for (Class<?> klaz : klasez) {
statement.addInterceptor((Interceptor) klaz.newInstance());
}
} catch (IllegalAccessException ilex) {
ilex.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return statement;
}
#Override
public void run(RunNotifier notifier) {
FailListener listener = new FailListener();
notifier.addListener(listener);
super.run(notifier);
notifier.removeListener(listener);
}
}
and custom listener
public class FailListener extends RunListener {
#Override
public void testFailure(Failure failure) throws Exception {
System.out.println("test fails");
super.testFailure(failure);
}
public void testStarted(Description description) throws Exception {
System.out.println("Test started");
super.testStarted(description);
}
}
How can I log not only System.out.println("test fails"); but also Exception and some other information?
It seems to me that it possible to use failure, but I don't know how to.
The Failure object has a method getException().