Spring 4 AOP #Aspect isn't triggering for #RestController - spring-mvc

I have created an Aspect which performs a basic id comparison to ensure that a user belongs to a the same group that created the entity being requested. I have had success attaching my aspect to #Service methods, but it doesn't make sense on the service layer, and I need it to be attached to #RestController methods instead. When I attempt to do this, everything seems good, but my Aspect never triggers, and the logs are silent.
pom.xml
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.1.7.RELEASE</version>
</dependency>
spring context
<context:annotation-config/>
<context:component-scan base-package="my.pkg"/>
<aop:aspectj-autoproxy/>
<aop:config proxy-target-class="true"/>
Aspect
#Aspect
#Component
public class MyAspect {
#Pointcut("within(#org.springframework.stereotype.Controller *)")
public void controller() {}
#Pointcut("within(#org.springframework.web.bind.annotation.RestController *)")
public void restController() {}
#Pointcut("args(java.security.Principal,..)")
public void principalArgPointcut() {}
#Around("(controller() || restController()) && principalArgPointcut()")
public Object validate(ProceedingJoinPoint point) throws Throwable {
doValidationBefore();
Object result = point.proceed();
doValidationAfter();
return result;
}
}
where "doValidationBefore()" and "doValidationAfter()" will throw an exception if validation fails.
And finally, my RestController
#RestController
#RequestMapping("/my-path")
public class MyController {
#RequestMapping(value = "/{entityId}", method = RequestMethod.GET)
public #ResponseBody
ResponseEntity<MyEntity> getEntityDetails(Principal principal, #PathVariable("entityId") Long entityId) {
return new ResponseEntity(HttpStatus.OK);
}
}
Some things to note:
This exact aspect works when I change the execution pattern to match services and place it in my service package.
The Aspect and the RestController are in the same context
I use IDEA IDE, and when I use the "navigate to advised methods" icon on the Aspect, the method I'm testing IS listed in the list of methods.
None of the methods listed in "navigate to advised methods" are working
Things I have tried:
I added 3 libraries to my pom.xml: org.aspectj:aspectjrt:1.8.6,
org.aspectj:aspectjtools:1.8.6, cglib:cglib:2.2.2. None of these made
any difference.
I tried defining my Aspect and PointCuts directly in the context xml and removing the annotations, no difference.
I have tried setting my execution pattern to apply to ALL methods, and it still did not trigger.
I tried adding an interface for my RestController, no change.
I would love some help here, as I've been trying to solve this for quite some time now. I know it must be possible.

As it turns out, my Aspect and my Controllers were NOT, in fact, in the same context.
While I believed my Controllers to be included in the context scanning of my web-context.xml, they were actually being scanned in WEB-INF/servlet-context.xml
Once I moved my Aspect configuration to WEB-INF/servlet-context.xml, my Aspect began to trigger as expected.
Thanks for all those who contemplated my problem.

Figure out for sure where your service is being configured in spring. If you have I there is an icon that you can click to navigate to the spring bean config. Then ensure that the aspect is configured in the same file.
If they are definitely defined in the same file, look next that the aop pointcut advice matches the method on which you're expecting it to fire. Again, Idea has an icon next to the pointcut that will navigate to matching methods.

Related

ASP.NET Core MVC application dependency injection issue when using BaseController

Recently i tried to create a MVC application using ASP.NET Core 2.0 and i had some values defined in appsettings.json,
"MySettings": {
"WebApiBaseUrl": "http://localhost:6846/api/"
}
In order to read these values i have added
services.Configure<MySettingsModel>(Configuration.GetSection("MySettings"));
above line in ConfigureServices method in Startup.cs
and in my home controller i have added
private readonly IOptions<MySettingsModel> appSettings;
public HomeController(IOptions<MySettingsModel> app)
{
appSettings = app;
}
MySettingsModel class is just a model with property same as key define in appsettings.json.
by this method i'm able to read the value of this key.
Now my issue is that i want to use this key in many controllers so i don't want to repeat this code in every controller so what i did was i created a BaseConntroller, added its constructor and i got my values there. But when i inherit other controllers with my BaseController , it throws me an error and tells me to generate it's constructor, so basically it tells me to add constructor in every controller which is what i wanted to avoid.
How can i achieve this?
You can see the image for the error
And these are the potential fixes that it shows me.
This is just basic C# inheritance. Derived classes must re-implement constructors on base classes (at least the ones you want or need). The only exception is the empty constructor, which is implicit. In other words, you simply need:
public class HomeController : BaseController
{
public HomeController(IOptions<MySettingsModel> app)
: base(app)
{
}
And, of course, you need to change the accessibility of the base class field to protected instead of private. Otherwise, derived classes will not be able to access it.
Of course, this doesn't really save you that much. However, there's no free lunch here. Like I said, this is a limitation of C#, itself, so you have no choice. Although, it's worth mentioning, that while this can sometimes be annoying, it's actually a kind of useful feature of C#. You can look at any class and see exactly what constructors it has available, without having to trace down all its ancestors.
Actually, there is a good solution here:
https://stackoverflow.com/a/48886242/2060975
I am mostly using this method.
[Authorize]
[ApiController]
public abstract class ApiControllerBase : ControllerBase
{
private IOptions<AppSettings> _appSettings;
protected IOptions<AppSettings> appSettings => _appSettings ?? (_appSettings = (IOptions<AppSettings>)this.HttpContext.RequestServices.GetService(typeof(IOptions<AppSettings>)));
...
}
I hope it helps someone:)

asp.net MVC : use unitOfWork inside custom AuthenticationAttribute when ActionFilters are not per-request?

I have implemented IAuthenticationFilter to create a custom one. in the constructor I use structureMap to get instance of my IUnitOfWork. this authentication logic is to check user status in the database and ....
IUnitOfWork uow;
public CustomAuthenticatationAttribute()
{
this.uow = ObjectFactory.GetInstance<IUnitOfWork>();
}
I have configured structureMap to serve IUnitOfWork HttpContextScoped.
x.For<IUnitOfWork>().HttpContextScoped().Use(() => new MyDbContext());
but then something strange happened. I deleted the user in one action, but when the AuthenticationFilter is executed on another action, the instance of unitOfWork still returns the user ! I searched the web for hours and I come to this :
Are ActionFilterAttributes reused across threads? How does that work?
in short , it says that Filters are cached and used across requests !
Now I'm confused . how to deal with this ? shall I give up using unitOfWork and get back to using(var context = ....) ? or there is a correct way of using unitOfWork inside Filters .
I found a solution here
https://gist.github.com/ivanra/9019273
It replaces the DefaultFilterProvider and I prefer to avoid that if possible.
The solution you found with suppressing caching in the FilterProvider is actually the same solution that the MVC integration libraries for both Autofac and Simple Injector use.
But the caching behavior of attributes is just one of the many reasons why doing dependency injection in attributes is actually a bad idea.
The best solution is IMO to move to passive attributes if you can, or at least encapsulate the attributes logic and its dependencies into a component and don't do anything more than resolving and executing that component in the OnActionExecuting method. For instance:
public class CustomAuthenticatationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
var action =
ObjectFactory.GetInstance<IActionFilter<CustomAuthenticatationAttribute>>();
action.OnActionExecuting(this, context);
}
}

Specify run time parameter dependency in Unity

I have a class which needs a string as a parameter in its constructor but this parameter will be decided by the calling code. At the same point of time, the life time of this class has to be tied to per HTTP request. So, I created a custom PerWebRequestTimelineManager and used that for my target type in the config file. But since the string in the constructor has to be dynamically determined, I cannot use the ConstructorInjection via the config file. I can use an abstract factory to solve the problem of dynamic dependency, but I am not sure about the implementation: Can you check the code below and validate the approach. Specifically the RegisterType and Resolve calls seem a bit out of place though the successive Resolve calls across the application will be able to retrieve the same instance.:
public class PerformanceTracerFactory : IPerformanceTracerFactory
{
private readonly IPerformanceTracer tracer;
public IPerformanceTracer CreateInstance(string operationTitle)
{
_container.RegisterType<IPerformanceTracer, PerformanceTracer>(new InjectionConstructor(operationTitle));
return _container.Resolve<IPerformanceTracer>();
}
}
Relevant portion of config file:
<register type="IPerformanceTracer" mapTo="PerformanceTracer">
<lifetime type="PerWebRequest"/>
</register>
<register type="IPerformanceTracerFactory" mapTo="PerformanceTracerFactory"/>
I have another question. In case if the above way of configuring and injecting the dependency using code is correct, then I think I do not need the config entries. I can always use the suitable overload to push the custom lifetime manager. In case, I would want to achieve the same thing using only config file, then how do I code the solution?
If you use a container-based factory you don't have to register/resolve your IPerformanceTracer in each call.
Register the mapping IPerformanceTracer --> PerformanceTracer once in your config file and use a ParameterOverride when you resolve your interface.
public IPerformanceTracer CreateInstance(string operationTitle)
{
return _container.Resolve<IPerformanceTracer>(new ParameterOverride("nameOfTheParameterInTheConstructorOfPerformanceTracer", operationTitle);
}

javax.ejb.EJBException: Illegal non-business method access on no-interface view

I'm using EclipseLink on GlassFish 3.1.1 and I'm trying to understand this exception:
javax.ejb.EJBException: Illegal non-business method access on no-interface view
at org.mycompany.myproject.session.__EJB31_Generated__MyBeanFacade__Intf____Bean__.getEntityManager(Unknown Source)
at org.mycompany.myproject.session.AbstractFacade.edit(AbstractFacade.java:28)
at org.mycompany.myproject.controller.EditMyBeanServlet.doPost(EditMyBeanServlet.java:199)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:754)
Notice that the stack trace indicates that the problem is triggered in the Netbeans generated AbstractFacade.getEntityManager method.
Any idea what the heck is going on or any tips to troubleshoot? I'm guessing that either the transaction or caching state in the EJB is weird when this happens because sometimes calling the edit method works fine. I'm calling the EJB methods from a Servlet. The exception occurs when trying to save changes to an entity.
The error you get most likely indicates that your code is trying to call the protected method anyway. This is not allowed for no-interface views on an EJB. You are only allowed to call public methods.
There's a small mismatch here between the normal Java class rules and the EJB rules. For a no-interface view, a proxy is created based on the original class type (typically a dynamic sub-class of it). This thus means that protected and package private methods are visible for code in the same package, and as far as the Java compiler is concerned, your code is allowed to call those.
But as mentioned, this is not allowed by the EJB rules, and thus an exception is thrown.
You can reproduce this easily by injection a bean like the following:
#Stateless
public class FooBean {
public void callMe() {
}
protected void doNotCallMe() {
}
}
Inject this somewhere (e.g. Servlet in same package) and try to call doNotCallMe(). You'll see the same exception. Call callMe() and everything will be fine.
I think I may have found a solution and possibly a bug in third party software. It seems like GlassFish 3.1.1 / EJB 3.1 / EclipseLink can't handle method overloading correctly. I've got a method defined in my EJB named edit that overloads (not overrides) the method from the parent abstract class. There is a method named edit in the abstract parent of the EJB that takes a generic type and then I've got a method named edit in the EJB which takes a List. If I rename the method to something else so that it is no longer overloading then the exception goes away!
Code:
public abstract class AbstractFacade<T> {
protected abstract EntityManager getEntityManager();
public void edit(T entity) {
...
and
#Stateless
public class MyEntityFacade extends AbstractFacade<MyEntity> {
protected EntityManager getEntityManager() { return em; )
public void edit(List<MyEntity> entities) {
...
Note: I noticed if I make the getEntityManager method public instead of protected I'll get a TransactionRequiredException instead of an EJBException.
What is weird is i had same problme with on inner class of my EJB.
While trying to call private method of parent or accessing on injected EJB, i faced some problems.
I had visibility on most of things but finally a runtie, things goes wrong.
Finally, i decided to retrieve my parent class throught JNDI, thus i could call public method without troubles. Meanwhile i could call still private methods on my parents class, i still have to remember that it will fail.

HandlerMethod given a HttpRequest?

I have an interceptor in which i want to do some intercepting logic based on the annotation on a controller method (Not on controller class). Say want to restrict the access to that controller method for certain users only. Is there any way to get the Handler method (Yes not the handler class) in the HandlerInterceptor?
I'm afraid not. You would have to group the desired methods in one (or a few) classes and base your check on the class, rather than method.
I guess you can parse the annotations yourself and match the paths, or try to see what spring does to do so in its classes, but that would be more complicated and error-prone.
You can try (but I haven't used it, so I don't know if it works) the #Interceptors annotation on your methods (saw it here)
You can do this in Spring 3.1 now with something like this:
public class ApiSecurityInterceptor implements HandlerInterceptor {
#Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
HandlerMethod method = (HandlerMethod) handler;
Api methodAnnotation = method.getMethodAnnotation(Api.class);
if (methodAnnotation != null) {
// this method is an #Api, we check the credentials
// you can do other things with annotation parameters at this point too
}
}
}
Then map it in servlet-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
...
<mvc:interceptors>
<bean class="com.orderpipe.prototype.server.web.interceptors.ApiSecurityInterceptor"/>
</mvc:interceptors>
Then in your actual controller:
#Controller
#RequestMapping(value = "/api-service")
public class AccountApiController {
#Api(type=CredentialType.OAUTH)
#RequestMapping(value="get", method = RequestMethod.GET)
public String get(Model model) {
// secured method via oauth, for example
// in a simpler example, you'd not have the parameter for credential type.
}
}
I use it to implement special servlet paths that implement different security mechanisms to the normal app, for example /api uses oAuth credentials.
I have the same need.
I consider an inconsistency that Spring MVC promotes the use of controller methods to handle requests, but the HandlerInterceptor interface does not supply the handler method that's going to handle the request as a parameter; only the controller object.
Requests are handled at the method level and it's the method execution what you need to intercept and for doing that efficiently you need to gain access to the method meta-information, for example, custom annotations declared at method level or its arguments.
The HandlerInterceptor.preHandle signature shoud be:
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handlerInstance, Method handlerMethod)
throws Exception;
So that you can do something like this:
hadlerMethod.getAnnotation(MyCustomAnnotation.class);
GOT IT?
In my case, I wanted to implement indexed-paremeter mapping; something STRIPES FRAMEWORK has (or flash scoping).
Do I have to resort to AspectJ to implement my cross-cutting functionality? DISSAPOINTING!
Firstly this is against MVC architectural pattern. MVC architecture is an architectural pattern that desires to
isolate "domain logic" (the application logic for the user) from the user interface (input and presentation), permitting independent development, testing and maintenance of each (separation of concerns).
See here
And controller has a great work in it.It desires decoupling, focusing on design porpose, and etc. I hope software developers don't give up GRASP :/

Resources