how to return something from a Ninject Interceptor - ninject

I have written a common validator as part of Ninject interceptor. My requirement is that I have to return a response object, just like how any service method in my project returns, for consistency sake. By returning a response object also helps me to send back an appropriate validation message when the validator fails. How do I do that in the interceptor? I understood that the Intercept() returns nothing. I tried throwing an exception but I don't know where to catch it. Can someone help me?
public void Intercept(IInvocation invocation)
{
var validationFails = false;
if (validationFails)
{
// return an object
// response.ErrorMessage = "Validation Error"
// Or throw exception, but where should I catch it
throw new Exception(statusMessage);
}
else
{
invocation.Proceed();
}
}

Assign the ReturnValue and don't call Proceed when validation fails.
public class MyRequestHandler
{
Response ProcessRequest(string input) { return new Response(); }
}
public MyValidationInterceptor : IInterceptor
{
public void Intercept( IInvocation invocation )
{
if (NeedsValidation(invocation.Method) &&
!IsValidRequest((string)invocation.Arguments[0]))
{
invocation.ReturnValue =
new Response { ErrorMessage = "Validation Error" };
return;
}
invocation.Proceed();
}
}

I had to hook up my interceptor to business layer methods, instead of service methods, and am able to return proper return value as part of my response.

Related

How do I hook into micronaut server on error handling from a filter?

For any 4xx or 5xx response given out by my micronaut server, I'd like to log the response status code and endpoint it targeted. It looks like a filter would be a good place for this, but I can't seem to figure out how to plug into the onError handling
for instance, this filter
#Filter("/**")
class RequestLoggerFilter: OncePerRequestHttpServerFilter() {
companion object {
private val log = LogManager.getLogger(RequestLoggerFilter::class.java)
}
override fun doFilterOnce(request: HttpRequest<*>, chain: ServerFilterChain): Publisher<MutableHttpResponse<*>>? {
return Publishers.then(chain.proceed(request), ResponseLogger(request))
}
class ResponseLogger(private val request: HttpRequest<*>): Consumer<MutableHttpResponse<*>> {
override fun accept(response: MutableHttpResponse<*>) {
log.info("Status: ${response.status.code} Endpoint: ${request.path}")
}
}
}
only logs on a successful response and not on 4xx or 5xx responses.
How would i get this to hook into the onError handling?
You could do the following. Create your own ApplicationException ( extends RuntimeException), there you could handle your application errors and in particular how they result into http error codes. You exception could hold the status code as well.
Example:
class BadRequestException extends ApplicationException {
public HttpStatus getStatus() {
return HttpStatus.BAD_REQUEST;
}
}
You could have multiple of this ExceptionHandler for different purposes.
#Slf4j
#Produces
#Singleton
#Requires(classes = {ApplicationException.class, ExceptionHandler.class})
public class ApplicationExceptionHandler implements ExceptionHandler<ApplicationException, HttpResponse> {
#Override
public HttpResponse handle(final HttpRequest request, final ApplicationException exception) {
log.error("Application exception message={}, cause={}", exception.getMessage(), exception.getCause());
final String message = exception.getMessage();
final String code = exception.getClass().getSimpleName();
final ErrorCode error = new ErrorCode(message, code);
log.info("Status: ${exception.getStatus())} Endpoint: ${request.path}")
return HttpResponse.status(exception.getStatus()).body(error);
}
}
If you are trying to handle Micronaut native exceptions like 400 (Bad Request) produced by ConstraintExceptionHandler you will need to Replace the beans to do that.
I've posted example here how to handle ConstraintExceptionHandler.
If you want to only handle responses itself you could use this mapping each response code (example on #Controller so not sure if it works elsewhere even with global flag:
#Error(status = HttpStatus.NOT_FOUND, global = true)
public HttpResponse notFound(HttpRequest request) {
<...>
}
Example from Micronaut documentation.
Below code I used for adding custom cors headers in the error responses, in doOnError you can log errors
#Filter("/**")
public class ResponseCORSAdder implements HttpServerFilter {
#Override
public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, ServerFilterChain chain) {
return this.trace(request)
.switchMap(aBoolean -> chain.proceed(request))
.doOnError(error -> {
if (error instanceof MutableHttpResponse<?>) {
MutableHttpResponse<?> res = (MutableHttpResponse<?>) error;
addCorsHeaders(res);
}
})
.doOnNext(res -> addCorsHeaders(res));
}
private MutableHttpResponse<?> addCorsHeaders(MutableHttpResponse<?> res) {
return res
.header("Access-Control-Allow-Origin", "*")
.header("Access-Control-Allow-Methods", "OPTIONS,POST,GET")
.header("Access-Control-Allow-Credentials", "true");
}
private Flowable<Boolean> trace(HttpRequest<?> request) {
return Flowable.fromCallable(() -> {
// trace logic here, potentially performing I/O
return true;
}).subscribeOn(Schedulers.io());
}
}

I have two methods with ActionResult return types yet one of them is giving back a single Employee object and still works. Why is that?

I've just wrote a controller class in a Blazor application and I don't undersand something.
I have a method GetEmployee:
[HttpGet("{employeeId:int}")]
public async Task<ActionResult<Employee>> GetEmployee(int employeeId)
{
try
{
var result = await employeeRepsitory.GetEmployee(employeeId);
if (result == null)
{
NotFound();
}
return result;
}
catch (Exception)
{
return StatusCode(StatusCodes.Status500InternalServerError,
"Error retrieving data from the database");
}
}
The return type is an ActionResult<Employee> but clearly in my method I'm returning an Employee. Because the employeeRepsitory.GetEmployee(employeeId) method gives back a single Employee which is stored in a variable "result".
I have an other method GetEmployees :
[HttpGet]
public async Task<ActionResult<IEnumerable<Employee>>> GetEmployees()
{
try
{
return Ok(await employeeRepsitory.GetEmployees());
}
catch (Exception)
{
return StatusCode(StatusCodes.Status500InternalServerError,
"Error retrieving data from the database");
}
}
Where I put my object in an Ok() ActionResult. If I didn't wrap await employeeRepsitory.GetEmployees() in an Ok() then I have compillation error because I'm not giving back ActionResult. But how does that GetEmployee(int employeeId) method is not giving me compilation error yet I'm clearly giving back an Employee object and not an ActionResult. Thank you for your answers.

Do an action when an error occurs RxJava

I need to create a folder when it doesn't exist. In my case, the only way to do so is to capture the error and handle it to create the folder wanted.
But all i can find is
public static Observable<Boolean> folderExists(final Context context, final String targetPath, final String currentpath) {
Application application = Application.get(context);
//i browse the folder to get all the items
return browseFolderObservable(context,currentpath)
.subscribeOn(application.defaultSubscribeScheduler())
.doOnError(new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
BsSdkLog.d("Error no file found");
}
})
.map(new Func1<ArrayList<Item>, Boolean>() {
#Override
public Boolean call(ArrayList<Item> items) {
if(items.isEmpty()) {
BsSdkLog.d(" No items");
return false;
}else {
for(int i=0;i<items.size();i++)
{
Item item=items.get(i);
BsSdkLog.d(item.toString());
}
BsSdkLog.d("Right-here");
return true;
}
}
});
}
I want to call the method that i have that creates the folder when the error occurs but i don't know how to do that.
I'm new to this so i'd really appreciate the help
Thanks
The basic principe looks like this. I used the Java NIO library for testing.
The method 'createFolder' just wraps creating a folder. The test 'name' invokes the Single and checks for an Exception. If it is an IOException it will return a fallback value. You may do something different in there. You just provide a fallback single. If it is an error different from IOException, it will return the error.
#Test
void name() throws Exception {
final String TO_CREATE = "/home/sergej/Downloads/Wurstbrot";
this.createFolder(TO_CREATE)
.onErrorResumeNext(throwable -> { // handle Exception:
// Validate Exception
if (throwable instanceof IOException) {
// Return fallback
return Single.just(Paths.get("/home/sergej/Downloads/"));
}
return Single.error(throwable);
})
.test()
.await()
.assertValueCount(1)
.assertValue(path -> path.endsWith(TO_CREATE))
.assertNoErrors();
}
private Single<Path> createFolder(String p) {
return Single.defer(() -> { // may throw some IOException
Path path = Paths.get(p);
if (!Files.exists(path)) {
Path createdDirectory = Files.createDirectory(path); // will throw if already exists
return Single.just(createdDirectory);
}
// Or just return Path, because it already exists???
return Single.error(new IOException("Already exists"));
});
}

WSO2 API Manager - Handle Authentication failure with Custom Authenticator

I'm implementing a custom Authentication Handler for wso2-am following this guide https://docs.wso2.com/display/AM190/Writing+Custom+Handlers
But it's not clear how to handle the case when my authentication handler returns false. The sample code of the handleRequest is
public boolean handleRequest(MessageContext messageContext) {
try {
if (authenticate(messageContext)) {
return true;
}
} catch (APISecurityException e) {
e.printStackTrace();
}
return false;
}
If I try calling an API with valid credentials everything goes well (the method returns true) and I get an "HTTP 200 OK" response. If I try with invalid credentials the method returns false but I get an HTTP 202 ACCEPTED" response. I would like to receive another response code (for example 400). How do I handle this authentication failure path?
Thank you.
Ideally you need to call handleAuthFaliure method with message context.
private void handleAuthFailure(MessageContext messageContext, APISecurityException e)
When you call that method please create APISecurityException object(as listed below) and pass it. Then error code and error messages will be picked from there and automatically send error to client(by default we return 401 for security exceptions and if defined then send defined error code and message).
public class APISecurityException extends Exception {
private int errorCode;
public APISecurityException(int errorCode, String message) {
super(message);
this.errorCode = errorCode;
}
public APISecurityException(int errorCode, String message, Throwable cause) {
super(message, cause);
this.errorCode = errorCode;
}
public int getErrorCode() {
return errorCode;
}
}
Hope this will work for you.
Thanks
sanjeewa.

Struts2 more than one action in one class

I'm using Struts2. I have two web forms that have the same code. I would like to eliminate one form. Here is the structure of my Struts project.
\Web Pages
form.jsp
\WEB-INF
\Content
error.jsp
form.jsp
success.jsp
\Source Packages
\action
MyAction.java
MyAction.java
package action;
import com.opensymphony.xwork2.ActionSupport;
import org.apache.struts2.convention.annotation.*;
public class MyAction extends ActionSupport {
#Action(value = "foo", results = {
#Result(name = "input", location = "form.jsp"),
#Result(name = "success", location = "success.jsp"),
#Result(name = "error", location = "error.jsp")
})
public String execute() throws Exception {
if (user.length() == 1) {
return "success";
} else {
return "error";
}
}
private String user = "";
public void validate() {
if (user.length() == 0) {
addFieldError("user", getText("user required"));
}
}
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
}
I tried to eliminate form.jsp under \Web Pages by adding a new action method to MyAction.java.
#Action(value="bar", results = {
#Result(name = "success", location = "form.jsp"),
})
public String another() {
return "success";
}
But I got the following error when I go to http : //localhost .../bar.action
HTTP Status 404 - No result defined for action action.MyAction and result input
Your MyAction has an implementation of validate(), which means it is validation aware.
What's happening is that you're calling another, but validate() is kicking in (as it's in the interceptor stack). Validation is failing, and therefore sending to INPUT result, which is not defined in another.
You should
Add #SkipValidation to the another method if you don't want validation there
Add the INPUT result to another() if you want a default input result
On a more general note, when you get that kind of error (No result defined for action X and result input) it usually means you're either having validation errors, parameter population errors (eg: an exception in preparable).