# JAVA Exception Handling

## **Introduction**

Exception handling in a web application using Spring Security and Jersey can be effectively managed through **Jersey's ExceptionMapper** and **Spring MVC's @ControllerAdvice**. This allows you to map exceptions to specific HTTP responses, giving you control over how errors are handled and presented to the client.

## How This Maps to OWASP Top 10

Exception handling, especially when combined with session management, maps to several OWASP Top 10 security concerns, including:

* **A01:2021 - Broken Access Control**: Proper exception handling can prevent unauthorized access by ensuring that access violations are handled gracefully.
* **A02:2021 - Cryptographic Failures**: Exception handling can help manage errors related to cryptographic operations.
* **A07:2021 - Identification and Authentication Failures**: Managing session timeouts and regenerating session IDs helps mitigate authentication failures.
* **A09:2021 - Security Logging and Monitoring Failures**: Proper logging of exceptions can aid in monitoring and responding to security incidents.

## How It Works

* **Exception Mapping**: Use **ExceptionMapper** in Jersey to map different exceptions to specific HTTP responses. This ensures that your application handles errors gracefully and consistently.
* **Global Exception Handling**: Spring provides a **@ControllerAdvice** annotation to handle exceptions globally across all controllers. Combining this with Jersey can provide a robust exception handling mechanism.
* **Generic Exception Handling**: Implement a generic exception handler to catch all unmanaged runtime exceptions.

## Example of Exception Handling with Spring MVC and Jersey

### **1. Define Custom Exceptions**

```java
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

public class UnauthorizedException extends RuntimeException {
    public UnauthorizedException(String message) {
        super(message);
    }
}
```

### **2. Implement ExceptionMapper for Custom Exceptions**

```java
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class ResourceNotFoundExceptionMapper implements ExceptionMapper<ResourceNotFoundException> {
    @Override
    public Response toResponse(ResourceNotFoundException exception) {
        return Response.status(Response.Status.NOT_FOUND)
                       .entity(exception.getMessage())
                       .build();
    }
}

@Provider
public class UnauthorizedExceptionMapper implements ExceptionMapper<UnauthorizedException> {
    @Override
    public Response toResponse(UnauthorizedException exception) {
        return Response.status(Response.Status.UNAUTHORIZED)
                       .entity(exception.getMessage())
                       .build();
    }
}
```

### **3. Implement a Generic ExceptionMapper**

This ensures that any unmanaged exception can be controlled.

```java
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;

@Provider
public class GenericExceptionMapper implements ExceptionMapper<Exception> {
    @Override
    public Response toResponse(Exception exception) {
        return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
                       .entity("An unexpected error occurred: " + exception.getMessage())
                       .build();
    }
}
```

### **4. Register Exception Mappers in Jersey Configuration**

```java
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;

@Component
public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        packages("com.example.yourapp");
        register(ResourceNotFoundExceptionMapper.class);
        register(UnauthorizedExceptionMapper.class);
        register(GenericExceptionMapper.class);
    }
}
```

### **5. Use Exceptions in Your Resource Class**

```java
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/api")
public class MyResource {
    
    @GET
    @Path("/data")
    @Produces(MediaType.APPLICATION_JSON)
    public String getData() {
        // Simulate an error
        throw new ResourceNotFoundException("Data not found");
    }

    @GET
    @Path("/secure-data")
    @Produces(MediaType.APPLICATION_JSON)
    public String getSecureData() {
        // Simulate an unauthorized access
        throw new UnauthorizedException("Unauthorized access");
    }
}
```

### **6. Create a Controller**

Define a controller with methods that might throw exceptions.

```java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class MyController {

    @GetMapping("/hello")
    public String hello(@RequestParam String name, Model model) {
        if (name == null || name.isEmpty()) {
            throw new IllegalArgumentException("Name is required");
        }
        model.addAttribute("name", name);
        return "hello";
    }
}
```

### **7. Create a View**

Create a Thymeleaf template for the view.

```html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Hello</title>
</head>
<body>
    <h1 th:text="'Hello, ' + ${name} + '!'"></h1>
</body>
</html>
```

### **8. Implement Global Exception Handling in Spring MVC**

Use `@ControllerAdvice` to handle exceptions globally.

```java
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

@ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(IllegalArgumentException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Error handleIllegalArgumentException(IllegalArgumentException ex, WebRequest request) {
        return new Error("Invalid request: " + ex.getMessage());
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Error handleAllOtherExceptions(Exception ex, WebRequest request) {
        return new Error("An unexpected error occurred: " + ex.getMessage());
    }
}
```

### **9. Create an Error Model**

Define a model to represent error messages.

```java
public class Error {
    private String message;

    public Error(String message) {
        this.message = message;
    }

    public String getMessage() {
        return message;
    }
}
```

### **10. Create an Error View**

Create a Thymeleaf template for the error view.

```html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Error</title>
</head>
<body>
    <h1 th:text="${error.message}"></h1>
</body>
</html>
```

### **11. Run Your Application**

Start your Spring Boot application, and it will handle exceptions globally using the `GlobalExceptionHandler`.

#### How It Works

* **Controller**: The `MyController` class handles requests and throws exceptions if the input is invalid.
* **Global Exception Handling**: The `GlobalExceptionHandler` class catches exceptions and maps them to appropriate HTTP responses.
* **Error Model and View**: The `Error` model and corresponding view display error messages to the user.

## Key Points for Developers

* **Consistency**: Ensures that exceptions are handled consistently across your application.
* **User-Friendly Errors**: Provides meaningful error messages to clients.
* **Separation of Concerns**: Separates exception handling logic from business logic.
* **Generic Exception Handling**: Catch all unmanaged runtime exceptions with a generic exception handler.

## Summary and Key Takeaways

Exception handling is an essential part of building robust web applications. Using Spring MVC's `@ControllerAdvice`, Jersey's `ExceptionMapper`, and custom exceptions, you can handle errors gracefully and consistently, providing a better user experience and maintaining clean code.

## Reference Links

* [Jersey ExceptionMapper Documentation](https://eclipse-ee4j.github.io/jersey.github.io/documentation/latest/representations.html#d0e4155)
* [Spring Security Documentation](https://spring.io/projects/spring-security)
* [Spring @ControllerAdvice](https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/bind/annotation/ControllerAdvice.html)
* [OWASP Top 10](https://owasp.org/www-project-top-ten/)
