Glassfish 3: Calling method on ejb in ServletContextListener.contextDestroyed method leads to exception - glassfish

I have an #Singleton ejb which will be called in a ServletContextListener contextInitialized and contextDestroyed method. The call in the contextDestroyed method leads to an Exception:
javax.ejb.EJBException: Attempt to invoke when container is in STOPPED
It looks as if the contextDestroyed method is called after the container went down leaving
me with no chance to access any resources like my ejb.
Does anyone know if there is any way to know about application shutdown before the container
is down?
Thanx in advance.
Cheers, Sven

You could use the #PreDestroy annotation on a method directly in your #Singleton bean. Thus marked, the method will be called before the bean destruction, during the application shutdown.

Related

Hangfire cannot find registered service

I have an issue with Hangfire, most likely because of my ignorance about some topics.
I have a host/plugins infrastructure, where each plugin is loaded at runtime and it register its interfaces.
public void ConfigureServices(IServiceCollection services, IConfigurationRoot Configuration)
{
services.AddTransient<IManager, Manager>();
services.AddTransient<IAnotherManager, AnotherManager>();
this.AddControllers(services);
}
Some plugin may add jobs using Hangfire, which are also set during runtime
public void ScheduleJobs()
{
RecurringJob.AddOrUpdate<IManager>(n => n.SayHello(), Cron.Monthly);
}
The issue I have is, while any service registered directly in the host is correctly resolved in hangfire,
all the interfaces (ex IManager) that are defined in external assemblies aren't found.
I added a customer JobActivator where I'm passing the IServiceCollection and I can actually see that those external services are registered (and I can use them anywhere else but from Hangfire), but still
in the JobActivator, when Hangfire tries to resolve the external service, it fails.
public override object ActivateJob(Type type)
{
// _serviceCollection contains the IManager service
var _provider = _serviceCollection.BuildServiceProvider();
// this will throw an Exception => No service for type '[...].IManager' has been registered.
var implementation = _provider.GetRequiredService(type);
return implementation;
}
In the same example, if I use the Default JobActivator, then the exception I get is System.MissingMethodException: Cannot create an instance of an interface.
I could enqueue the job using the Class instead of the Interface, but that's not the point and anyway if the Class has services injected, those will not be resolved as well.
What am I missing?
The problem has been solved. The solution is to add a specific IoC Container for hangfire. I used Unity. In that way dependencies are resolved correctly.
Thanks Matteo for making it clear that HF requires its own IoC container. This link makes the point too:
Hangfire needs to have it's own container with dependencies registered independently of the global UnityContainer. The reason for this is twofold; Hangfire's dependencies need to be registered with the PerResolveLifetimeManager lifetime manager. This is so that you don't get concurrency issues between workers that have resolved a dependency to the same instance. For example; with the normal HierarchicalLifetimeManager, two workers needing the same repository dependency may resolve to the same instance and share a common db context. The workers are meant to each have their own db contexts. Secondly, when the OWIN bootstrapper is run, the global UnityContainer may or may not be initialised yet and Hangfire is unable to take in a reference to the container. So giving Hangfire it's own managed container is a clear separation of purpose and behaviour in how our dependencies are resolved.

Windsor IOC in a non-Http WCF application - error initialising IOC kernel

I have a problem trying to initialise my IOC container in a WCF application. The application is non HTTP based using WAS.
When I start the application I get this error message...
Kernel was null, did you forgot to call DefaultServiceHostFactory.RegisterContainer
I have seen other answers to this solution which say to do the following...
Add a Factory definition to the ServiceHost definition e.g.
Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, Castle.Facilities.WcfIntegration"
Create a class in th App_Code folder with a static method called AppInitialize(). This method should then automatically be called and you can use it to register your container.
I have done this but my AppInitialize method is not called and I am still getting the error above.
Thanks.

Local stateless EJB injection within singleton startup EJB

is this possible somehow? Following scenario:
statelesse local EJB with name A
singleton startup EJB with name B
B contains a reference to A
I tried but my application server (WAS) fails on application startup with the error that A was not found. The console log also makes clear that A was not started at the moment the B is loaded but some other stateless EJBs are started before B. Making A also a singleton EJB and letting B depond on A via annotation #DependsOn({"A"}) produced an error, too, stating that dependent bean A was not found. Using A in a web module works fine.
Any ideas what' I do wrong? Thx for any help!
Steffen Harbich
If A is in a different module/application as B, then you need to ensure that the module of A is configured to start before the module of B. You can either use initialize-in-order in application.xml, or use module starting weights in the admin console.

Are CDI event observer methods compatible with EJBs?

I have a Singleton EJB (javax.ejb.Singleton version. sigh.) which has a CDI observer method on it. When I try to deploy this to glassfish 3.1 the server fails to deploy the EAR file without any real explanation - simply saying there was an exception during deployment without any more details.
SEVERE: Exception while loading the app
SEVERE: Exception while shutting down application container
....
SEVERE: Exception while shutting down application container : java.lang.NullPointerException
This is the CDI event listener :
public void updateFromGranule(#Observes #CloudMask GranuleAvailableEvent granuleEvent) {
LOG.info("updating cloud map");
update(granuleEvent.getGranule(), CloudMask.class);
fireUpdate();
}
If I change the Singleton bean to just be an #ApplicationScoped bean the app deploys fine. Similarly, if I remove the CDI event observer method the application deploys fine.
I actually need the class to be an EJB singleton because I want the transaction, thread safety etc. of EJBs, so just leaving this as a #ApplicationScoped POJO isn't much use to me. The problem doesn't seem to be limited to Singleton beans though - I've experimented by changing the annotation to #Stateless and #Stateful and I get the same issue.
It seems to me that this might be a bug in Weld, perhaps Weld and EJB are fighting about how they proxy that method - presumably EJB needs to add an interceptor class and wrap that method to ensure thread safety, and Weld is trying to do something else to make the event listener work?
Am I misunderstanding something here, and should CDI event handlers simply not be used on EJBs (in which case there should be better error messages from glassfish) - or is this actually just a bug in the CDI or EJB implementation?
I think this is the answer :
CDI observer methods must apparently either be static or declared in the local interface of an EJB if the EJB declares a local interface. Normally if you try to declare an observer method that isn't in the local interface you get an exception from Weld like this :
org.jboss.weld.exceptions.DefinitionException: WELD-000088 Observer method must be static or local business method: [method] public org.stain.ObserverBean.testMethod(EventClass) on public#Singleton class org.stain.ObserverBean
For some reason glassfish does not report this exception properly when loading my EAR file and simply says Exception while loading the app.
Adding the method to the local interface (or removing the interface declaration on the class) fixes the problem and allows the application to load normally.
I noticed the same problem with the latest version of weld. But if you add the #LocalBean annotation it will work with #Singleton and #Singleton #Startup.

SEVERE: java.lang.NullPointerException

When i try to run my index.jsp page which calls WebClient.jsp page, where i define my InitialContext() method, and implement my Bean in class AccountBean.java shows ..
SEVERE: java.lang.NullPointerException........
I use Glassfish v3, jdk1.6, eclipse Helios.
I can't give too specific an answer, but my recommendation for this issue is to make sure that every object you are trying to use is guaranteed to be pointing to an instance of the object.