How do I inject Jersey beans into Quartz job in Weld? - java

I have a pure JAX-RS application both in Glassfish and in jetty-servlet. I'm trying to inject some beans into Quartz job.
I've annotated Job fields with #javax.inject.Inject, but I also believe I need to make Job factory available to container, or vice versa - I'm somewhat lost here what end to start with.
How do I accomplish it?

Hi Victor without some more detail regarding your application I am going to assume you're running in a servlet container. There is no way to do it using a "pure" JAX-RS application.
However I would recommend you use CDI (Weld or OpenWebBeans). You can then use Deltaspike to enable the request context inside your Quartz job get a reference to a request scoped bean.
Enabling Weld in your servlet container is quite simple
A guide on enabling the request context outside of an HTTP request is available here
By default you cannot inject #RequestScoped beans into your quartz job (there is no HTTP request hence no request context). To work around this you can either enable the request context by following the link above OR (and probably my approach) inject #Dependent scoped beans (which do the work) into your JAX RS beans (essentially wrappers), you can then easily get references to the #Dependent scoped beans inside your quartz job.
Here is my web.xml and pom.xml for running Weld and Jersey inside jetty, you will need jetty-plus, jetty-jndi and Weld dependencies.
Here is some info about getting JNDI setup within jetty, however I do not use this method as I start jetty as an embedded container within a SE application, here is a code snippet of what I do:
String[] configurationClasses =
{
"org.eclipse.jetty.webapp.WebInfConfiguration",
"org.eclipse.jetty.webapp.WebXmlConfiguration",
"org.eclipse.jetty.webapp.MetaInfConfiguration",
"org.eclipse.jetty.webapp.FragmentConfiguration",
"org.eclipse.jetty.plus.webapp.EnvConfiguration",
"org.eclipse.jetty.webapp.JettyWebXmlConfiguration"
};
WebAppContext webapp = new WebAppContext();
webapp.setConfigurationClasses(configurationClasses);
webapp.setDescriptor("/path/to/webapp/WEB-INF/web.xml");
webapp.setContextPath("/");
webapp.setResourceBase("/path/to/webapp");
webapp.setClassLoader(Thread.currentThread().getContextClassLoader());

Related

How to add a EJB Interceptor programmatically?

I'm trying to add a Interceptor in a EJB at runtime programmatically via CDI extensions.
This EJB exposes a Remote interface for remote calls. But I'm trying to add this Interceptor in the implementation class of this EJB adding the #Interceptors annontation like in this other SO question (CDI Extensions - Add Interceptors in ProcessAnnotatedType phase)
I think the CDI Extension only executes after the EJB are already registered because the Interceptor is never called.
But, for test purpose I have successfully register and execute an Interceptor programmatically in a simple CDI Bean.
The problem is when I'm try to register in a EJB.
Am I missing something?
Edit:
I'm using Wildfly 8
I think the key problem here is the difference between #Interceptors (EJB ones) and #Interceptor (CDI ones). CDI does not govern EJB container hence adding the EJB annotation (#Interceptors) in CDI extension won't necessarrily kick EJB logic into effect - EJB container might have started at that moment and it won't know of the annotation. Furthermore the CDI extension would add this annotation to the AnnotatedType which is a structure EJB probably won't make use of. On the other hand, all this really depends on the application server as it is responsible for CDI/EJB integration hence as a "bonus" the behavior might differ between AS.
CDI extension is something which allows you to hook into CDI bootstrap lifecycle, therefore you are able to use/enable/add CDI interceptors. I would try going that way instead. BTW even the SO question you referred to speaks of beans.xml/#Priority for enablement which means it uses CDI interceptors and not EJB ones.
Also, an EJB bean should automatically become CDI bean therefore you can attach CDI interceptor to it without changing the bean itself.

Determine WAR context root from MDB

I have a JavaEE ear containing an ejb and war being deployed to GlassFish v3.1.2.2. The war contains a Jersey/Atmosphere application that is using CDI. Within the war, I have an MDB that is asynchronously receiving events it will broadcast using Atmosphere. The message I need to broadcast using Atmosphere needs to includes some links to other resources in the web application.
In order to build those links, like in other places in the code, I would like to use UriBuilder. To do so, I need access to the application's deployed context root, so I can invoke UriBuilder.fromPath(contextRoot)
This Java EE 7 article implies I can inject a ContextServlet into a CDI bean this way:
#Inject ServletContext context;
But this does not work for my MDB. I'm also only on JavaEE6 w/ Glassfish v3.
How can I access the ServletContext from an MDB hosted in my war?
I ended up solving this with the following.
Installed the deltaspike servlet module since I'm on GlassFish v3.1.2.2 which does not have CDI 1.1 which includes a provider for ServletContext out of the box.
Followed the MDB piece of this article to convert my JMS message to a CDI event and then observed that CDI event from a pure CDI bean that had the ServletContext injected in order to build out the required URLs for the Atmosphere message.

Is it possible to use #WebService, #Stateless and #Singleton altogether in one EJB 3 bean?

I'm using EJB 3 and JBoss AS 6.0.0.Final. I have a stateless session bean with the annotations #Stateless and #WebService. When I add the annotation #Singleton, the deployment is in error showing the message:
...name=ServiceBean, service=ejb3 is already installed
What can I do to avoid the deployment error?
You can use #WebService and #Stateless or #WebService and #Singleton in the same bean which makes perfectly sense if you want to expose a POJO as both a web service and EJB.
Don't see much sense in using #Stateless and #Singleton in the same bean. When you use #Singleton, you are creating an EJB with all the EJB capabilities (transaction management, security, etc) exactly as with #Stateless. The only difference is how the container manages the EJB lifecycle:
#Stateless: the EJB instance is created immediately after the first request and when the request ends, the EJB is pooled and ready for reuse if another request comes in. However, if all the pooled instances are being used in the moment another request comes in for the same bean, the container creates a new instance of the same to serve that new request.
#Singleton: the EJB instance is created after the first request (by default - see #Startup to override this behavior) comes in and that will be the only instance created by the container. If another request wants to use the same EJB, the container will never create a new instance of it - the instance previously created will be used. It is like a #Stateless EJB with a pool size of 1 :) Aspects like concurrency are important when using these, but this is probably out of the scope of this post.

How to get a 'JBoss service' with CDI in JMX with AS6?

I'm currently migrating a JBoss service class from AS5.1 to AS6 (not going to AS7 for a variety of reasons).
For AS5.1, the service implements a {serviceName}MBean and has a jboss-service.xml with attribute values. It's packaged in a jboss-sar, which is packaged in an EAR to be deployed. When deployed, the service fields are populated with the values from jboss-service.xml, and the service is automatically registered into JMX.
I would like to achieve the same thing using AS6, but would like the service to support CDI - so I'd like its new #Inject injection points to be satisfied. I need these to be satisfied in the object registered with JMX, so that methods called via JMX can reference injected fields, but I'm struggling to achieve this.
I've had to package the service in a jar, instead of a jboss-sar, for classloader reasons, but let's say it's otherwise unchanged. When deployed to AS6, all works as before - service goes into JMX, values from XML propagate to the object. However, the instance created does not have its CDI injection points satisfied, and neither does the object registered in JMX.
If I annotate the service class with #Startup and #javax.ejb.Singleton, but keep its interface and the jboss-service.xml, the object registered into JMX still does not have its CDI injection points satisfied. However if I programmattically deregister that bean, and re-register the instance in a #PostConstruct method, then the bean in JMX DOES have its injection points satisfied. However that bean no longer has the values specified in the jboss-service.xml.
So how can I get the best of both worlds? CDI and the usual JBoss service behaviour? What is the correct way to implement a JBoss service with CDI? I've been unable to find documentation on this. Hope someone can help.
Thanks,
Ben
As a worst-case fallback, you should be able to use the CDI extension API to get your service to be injected. I don't think you would need to write a fully-fledged extension, but if you have an initialisation hook in the service object, you can do this (lifted with minor editing from the docs, not compiled or tested):
public static <T> void inject(T object) {
BeanManager beanManager = (BeanManager)new InitialContext().lookup("java:comp/BeanManager");
AnnotatedType<T> type = beanManager.createAnnotatedType(object.getClass());
InjectionTarget<T> it = beanManager.createInjectionTarget(type);
CreationalContext ctx = beanManager.createCreationalContext(null);
it.inject(object, ctx);
it.postConstruct(object);
}
Basically, any object to that method will get injected. All the usual CDI annotations should work. Hopefully.
As mentioned in the comments above, it seems Tom's right - there's no 'nice' way of created a CDIed, JMX bean in one go, you either have to put your JMX bean in CDI, as is suggested above, or put you CDIed bean into JMX. We tried the former, but it appears the BeanManager isn't bound to JNDI at the point the service starts up.
So instead we went with CDI bean -> JMX. We're creating the services as Singleton EJBs, so their injection points are satisfied, and they then get registered/unregistered to JMX in their PostConstruct/PreDestroy methods, using German Escobar's excellent CDI portable extension (germanescobar.net/2010/01/cdi-portable-extension-jmx.html, community.jboss.org/thread/148750 is also helpful).
May try to use ApplicationScoped beans and get them to start by observing a ContainerInitialized(?) event, however, as we don't need all the features of an EJB. Haven't tried that yet, mind...

Implementing servlet lifecycle methods in a Spring web application?

I am implementing a web application using Spring. I am using Spring's ContextLoaderListener, to load up my application contexts, and Spring's DispatcherServlet, to load the relevant beans from {name}-servlet.xml, which refer to the beans in the main application context. I want to be able to integration test these Spring configurations outside of the container to validate everything is wired up correctly before I deploy to Tomcat. However my application requires some scheduled background processing when running in the container. In a regular HttpServlet I would simply implement init() and destroy(). All the suggestions I have read suggest using an InitializingBean for that kind of initialization.
However, if I use an InitializingBean, afterPropertiesSet() gets called whether I am inside the container or in integration tests - and outside the container, I don't have access to the resources that background task needs. Is there a better way to perform the tasks I would normally perform in init() and destroy() so that they will only run when deployed as a webapp?
Have you considered using a test spring config file that overrides the bean implementing your background process?
This way everything else in the spring configuration would work normally except for the one overridden bean.

Categories