To sum up my failing project: My #ServerEndpoint class is packaged in a WAR together with the beans.xml file. My WAR in turn is packaged in a EAR and this EAR file is what gets deployed to a GlassFish 4 server that internally use Tyrus.
Should it be possible?
The WebSocket specification says:
Websocket endpoints running in the Java EE platform must have full
dependency injection support as described in the CDI specification.
Websocket implementations part of the Java EE platform are required to
support field, method, and constructor injection using the
javax.inject. Inject annotation into all websocket endpoint classes,
as well as the use of interceptors for these classes.
The only thing I can understand of this paragraph is that injecting an Enterprise JavaBean into a WebSocket should be no rocket science. However, for me, whatever I do, it fails to work. I feel that most intuitively one should only need to prefix a server endpoint instance field with the #EJB or #Inject annotation, but no one of these annotations work. The variable will be null.
Already a known problem?
One Internet source says a bit cryptically that "due to a bug" he must use constructor injection. I saw that he had added the annotation #Named to the server endpoint. I used the famous copy paste pattern and did exactly what he did, with and without the #Named annotation, and it still don't work. In fact, my #Inject annotated constructor is never even called!
The Tyrus user guide says that one can mix together anyone of the famous session bean declaration annotations with the server endpoint (#Stateful, #Stateless and #Singleton). So I did, still the injection fails to happen. It doesn't matter if I use the annotation #Inject or #EJB.
And that is strange, because the book Java EE 7 Developer Handbook claims to have a working example on page 27 and page 28 based on the same approach. Author Peter Pilgrim annotates his server endpoint #Stateless. He then uses #Inject to do the injection. He says:
In Java EE 7 we must also declare [our server endpoint] as a stateless
EJB with #Stateless in order to inject [another EJB] as a dependency.
(This is a consequence of Java for WebSocket 1.0 specification.) Note
that we can use #javax.annotation.Inject from CDI.
Okay so he says we must use a #Stateless annotation, and "notes" that one can use #Inject. For me, it sounds utterly strange that we "must" use a #Stateless annotation on a server endpoint which according to the specification, is everything else than stateless (!). I've read elsewhere on the Internet that using #Inject instead of #EJB should be one fix. Peter "notes" that "we can use" #Inject but it smells fishy, as if he never got #EJB to work at all and now tries to flee responsibility.
Well, whatever the reason ("bug" or "consequence of the specification"), I couldn't get my dependency injection to work whatever vivid mix of annotations I used on the endpoint class itself or on the instance field.
The ultimate fix
Is to programmatically use a JNDI lookup, but it looks ugly and should be avoided.
(just restating what I wrote into comment to get this question from "unanswered" list)
You should checkou out Tyrus CDI sample/test.
It demonstrates list what you can do with current implementation. We are always open for new test cases, but there are some issues with the spec itself - standard Request scopes don't work for WebSocket runtime, because it handles messages outside of servlets service/doFilter methods. See WEBSOCKET_SPEC-196 and WEBSOCKET_SPEC-197.
For me. annoting the websocket with #Stateful and EJB object declaration with #EJB did the work.
#Stateful
#ServerEndpoint(value = "/profileregistration")
public class ProfileRegistrationEndpoint {
#EJB
private ProfileRegistration profileRegEJB;
....
}
Related
I'm in the process of converting a rather large Grails 2 application to Grails 4. It uses the Shiro plugin, which I have upgraded to version 4.3 (compile "org.grails.plugins:grails-shiro:4.3"). In one large GSP (which has always worked OK), the Shiro taglib is now causing the following error:
Error executing tag <shiro:isLoggedIn>: No SecurityManager accessible to the calling code, either bound to the org.apache.shiro.util.ThreadContext or as a vm static singleton. This is an invalid application configuration.
The SecurityManager is initialized OK in Bootstrap.groovy, and in another simple test page, shiro:isLoggedIn works fine. So my question is why might the SecurityManager not be available in this use of the taglib? What should I be looking out for?
I'm not a Grails person, but one common reason folks see this problem is that the ShiroFilter did not process the request (or the filter is not configured early enough in the chain).
What happens is the ShiroFilter creates a Subject (the user) and associates it and the SecurityManager with the request thread. Other API (like the tag lib) would use that Subject and/or SecurityManager.
Check your servlet filters, maybe compare them with the old version with the new version and see what has changed.
G'day John, I look after the grails shiro plugin. That error occurs in the taglib because for some reason I'm trying to track down, the ThreadContext doesn't appear to be available. That means the SecurityUtils goes looking for a static security Manager which isn't normally set in web applications.
So basically it's a bug, and hopefully I'll fix it shortly (help welcome).
If I in my AppHostBase descendant (web api project ) use container.AutoWire(this), it will result in a NullReferenceException in the ServiceStack code, if I am using a web project, thus starting it with the CreateHostBuilder(args).Build().Run(); in the main method.
The error is reproduced in this Github project: https://github.com/tedekeroth/ServiceStackAutoWireTest
The error occurs in AppHostBase.Netcore.Cs, line 158:
If I remove the container.AutoWire(this); in TestAppHost.cs, the error goes away, but then the dependency injection does not work, meaning the Logger in TestAppHostproperty is not assigned:
I am not sure why this happens or what I can do about it. I'd appreciate some input, thanks.
Setup
Visual Studio 2019
Target framework: .NET 5.0 (Console Application)
Project SDK: Microsoft.NET.Sdk.Web
ServiceStack 5.11.0
The IOC AutoWire API attempts to autowire all public property dependencies of an object which is definitely something you should never attempt to do with the AppHost which encapsulates the configuration and behavior of your ServiceStack App where indiscriminatingly overriding every public property is going to leave it in a corrupted state.
Registering your AppHost in the IOC shouldn't be necessary as it's available everywhere via the HostContext.AppHost singleton. It's also a bad idea trying to reference any type defined in your Host Project, (the AppHost being the canonical example) since it creates a circular reference to your Host project in your App logic dependencies which shouldn't have any references back to its Host project, your Host project is supposed to reference all your projects .dll's, configure your App's and all its dependencies, not the other way around.
Should you need access to any Plugins it's recommended to use the GetPlugin<T>() API in your Service for optional plugins or AssertPlugin<T>() for required plugins. If you need to resolve any deps manually you can use TryResolve<T>() API in your Service class. For any of your App's custom config I'd recommend registering them in a custom AppConfig class for your Services to access like any other dependencies.
Otherwise if you really need access to the AppHost you can use the HostContext.AppHost singleton. If you absolutely need to have the AppHost in the IOC, just register it as a normal singleton, i.e. don't try to autowire it:
container.Register<IAppHost>(c => this);
However as mentioned earlier I'd strongly advise against it, have everything your App needs in a custom class (e.g. AppConfig) that is accessed like a normal dependency.
I have a piece of code that encapsulates functionality that isn't specific to Orchard. However i need to make it available in Orchard via dependency injection. So, I built up an Autofac Module that registers all components (types), but I can't find a way to inform Orchard's Autofac Container about it.
From what i red, there are two ways to add a module to a container:
By supplying the module at to the ContainerBuilder (usually at start-up),
Or by updating the already built Container at runtime with a ContainerBuilder
I can approach the problem in the first way, but I rather do a variant of the second if there is such?
Just add a class deriving from Autofac.Module to your Orchard module and that's it. It will get automatically picked by Orchard during the container construction.
Piotr Szmyd's answer is fundamentally correct, but here's some more detail:
Your Orchard Module is the new .csproj that you've added to the Orchard.sln
Add Autofac as a reference to that csproj (make sure you use the version included with Orchard - not nuget. See here for more details about that problem)
Then add a class that derives from Autofac.Module and which implements Load(ContainerBuilder).
e.g.
using System;
using Autofac;
namespace MyCustom.Module.Namespace
{
public class LoaderModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<MyClass>().As<IMyInterface>();
}
}
}
As an additional note:
The Autofac registration code only gets invoked at application startup time.
If you are running with the site sitting locally in IIS and the code in VS, then the dynamic compilation nature of Orcahrd means that when you recompile the code, the application doesn't stop.
So in order for this Autofac registration code to be hit (and also for any channges to it to take effect) you have to iisreset to kill the application, so that it reloads the Autofac Registrations.
I am trying to properly use Ninject to inject log4net logging into my MVC3 application. I am using the Ninject.MVC3 package, so I have the NinjectMVC3 class that automatically extends the App_Start method and contains the RegisterServices method that binds all dependencies. I also have the Ninject.Extensions.Logging.Log4Net package, but I don't know how to use it. I already know how to configure log4net in my web.config, but don't know how to use this extension for DI.
I have read all the following articles/posts, but none of them seem to define how to properly setup a project for DI logging.
At http://dotnetdarren.wordpress.com/2010/07/29/logging-in-mvc-part-4-log4net/, Darren
provides a great article, but doesn't seem to deal with DI (at least I don't see it).
At Using Ninject to fill Log4Net Dependency,
Remo Gloor states here that the extensions should provide all that's needed for implementation, but it doesn't show the code of how to instantiate it.
The documentation for ninject.extensions.logging at https://github.com/ninject/ninject.extensions.logging/wiki/Using is very limited at best. I have re-read it many times, and still don't see how to use bind the injection in the NinjectMVC3 class, or concrete examples of how to call the logger from my controller class for example.
At the most promising article, Moosaka provides some great code at Ninject.Extensions.Logging.Log4net unexpected behavior, but when I try it, I get a compile error in the LoggerFactory at ILogger logger = new Logger(type); stating "Cannot access protected constructor 'Logger' here". Also, he states to "Tuck this whole mess away into a separate class library". Does that mean as a whole separate project?
I'm just getting lost in all the differing options and dated posts and would like any input on how to use Dependancy Injection with Ninject and Log4Net in my MVC3 project. Also, if it matters, all of my Ninject code is in my domain project, but the logging needs done from both the domain and web project (and mocked in my unit tests). Any help is appreciated.
You shouldn't have to configure anything except the normal log4net config.
All you have to do is to inject a ILogger wherever you want to log.
https://github.com/ninject/ninject.extensions.logging/wiki/Using
I started web development using JSF, after studying JSP and Servlets for a while.
When you create a JSF web application you always(may be often but I am not sure if it always or not) have to create beans.xml and you don't write anything in it. But, if that file doesn't exist the JSF web app will not work.
What is the reason behind that?
Why we need that file?
Please, detailed explanation.
Adding to the answer of Micheal; CDI is not only useful in combination with JSF because of the injection support, but also because of its support to be used with EL (expression language). This is a feature JSF heavily depends upon.
In fact, CDI beans can almost entirely replace JSF managed beans and therefor you'll find lots of examples using them and a good amount of JSF books advising their use. For JSF applications CDI beans have e.g. the following advantages:
Can inject smaller scopes into larger scopes. E.g. request scoped GET parameters can be injected into a session scoped bean. This is not possible with JSF managed beans.
Can take advantage of the conversation scope; a scope that spawns multiple different pages.
Very unfortunate is that in JSF 2.0 and 2.1 the extremely handy view scope is not supported by CDI beans by default, although extensions like Seam can add these. (update: in JSF 2.2 there's a new view scope that does work with CDI beans)
All in all the confusion between JSF Managed beans and CDI beans is such that there's a JSF spec issue for this, see http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-976
The presence of a beans.xml file signals the servlet container that the application uses JSR-299 (Contexts and Dependency Injection) - without it, the application's classes will not be scanned for CDI annotations either and dependency injection will not be performed. If you don't use CDI (e.g. you only use plain JSF managed beans), you don't need beans.xml. If you do, you can use the file (instead of annotations) to define CDI configurations - this allows you, for example, to provide a test configuration where some dependencies are replaced with mocks.
From Getting Started with Contexts and Dependency Injection and JSF 2.x
When the application is deployed the server looks for CDI managed beans. In a Java EE 7 application, the classes on the path are scanned for CDI annotations by default. In a Java EE 6 application, the classes are scanned for CDI annotations if the module contains a beans.xml file.