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.
Related
I'm trying to get an understanding of which concrete types are providing the implementations of interfaces in an IOC (dependency injection) container. My implementation works fine when there are no delegates involved. However, I'm having trouble when a delegate method is passed as the type factory, as I can't get Mono.Cecil to give me the concrete type or a method reference to the factory back. I'm specifically in this case trying to build a component that can work with the IServiceCollection container for .Net ASP.Net REST APIs. I've created a 'minimised' set of code below to make it easy to explain the problem.
Consider the following C# code:
interface IServiceProvider {}
interface IServiceCollection {}
class ServicesCollection : IServiceCollection {}
interface IMongoDBContext {}
class MongoDBContext : IMongoDBContext
{
public MongoDBContext(string configName) {}
}
static class Extensions
{
public static IServiceCollection AddSingleton<TService>(this IServiceCollection services, Func<IServiceProvider, TService> implementationFactory) where TService : class
{
return null;
}
}
class Foo
{
void Bar()
{
IServiceCollection services = new ServicesCollection();
services.AddSingleton<IMongoDBContext>(s => new MongoDBContext("mongodbConfig"));
}
}
When successfully locating the 'services.AddSingleton' as a MethodReference, I'm unable to see any reference to the MongoDBContext class, or its constructor. When printing all the instructions .ToString() I also cannot seem to see anything in the IL - I do see the numbered parameter as !!0, but that doesn't help if I can't resolve it to a type or to the factory method.
Does anyone have any ideas on how to solve this?
Most likely your code is looking in the wrong place.
C# compiler will try to cache the conversion of lambda expression -> delegate.
if you look in sharplab.io you'll see that the compiler is emitting an inner class '<>c' inside your Foo class and in that class it emits the method '<Bar>b__0_0' that will be passed as the delegate (see opcode ldftn).
I don't think there's an easy, non fragile way to find that method.
That said, one option would be to:
Find the AddSingleton() method call
From there start going back to the previous instructions trying to identify which one is pushing the value consumed in 1 (the safest way to do that would be to consider how each instruction you are visiting changes the stack). In the code I've linked, it would be IL_0021 (a dup) of Bar() method.
From there, do something similar to 2, but now looking for the instruction that pushes the method reference (a ldftn) used by the ctor of Func<T, R>; in the code linked, it would be IL_0016.
Now you can inspect the body (in the code linked, Foo/'<>c'::'<Bar>b__0_0')
Note that this implementation has some holes though; for instance, if you call AddSingleton() with a variable/parameter/field as I've done (services.AddSingleton(_func);) you'll need to chase the initialization of that to find the referenced method.
Interestingly, at some point Cecil project did support flow analysis (https://github.com/mono/cecil-old/tree/master/flowanalysis).
If you have access to the source code, I think it would be easier to use Roslyn to analyze it (instead of analyzing the assembly).
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:)
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.
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);
}
}
I am trying to get Ninject working with a WebForms application that already has a custom PageBase object. But, I don't know for sure if I can use Ninject's PageBase object alongside another, custom PageBase. I've been searching for a while now to see if I could find an answer to this problem, or to learn how to do it, but all I've found is this:
I've hacked together an alternative using a shared base class that
derives from Page. It looks roughly like this
public abstract class PageBase : Page
{
public IKernel Kernel { get; private set; }
public PageBase() { Kernel = ...; }
public void Page_Init() { Kernel.Inject(this); }
}
This will allow you to property and method injection on any pages that
inherit from PageBase. Note that the constructor is incomplete --
you'll have to access the kernel in some static fashion. You should
be able to read it from the HttpApplication somehow.
(source: http://groups.google.com/group/ninject/browse_thread/thread/317fc48387399aa6, linked from Ninject with ASP.Net webforms and MVC):
This looks like it might work for me because it appears that I could apply this code to the existing, custom PageBase. But, I am hung up on the part in which the author says, "... the constructor is incomplete -- you'll have to access the kernel in some static fashion."
Does anyone have any idea what that sentence means, and how one might go about accessing the Ninject kernel in a static fashion?
You do not need to derive from a Ninject page base. You can alternatively use the NinjectHttpModule.
https://github.com/ninject/ninject.web/blob/master/src/Ninject.Web/NinjectHttpModule.cs