Well, i'm trying to use RequestedScoped beans inside a Quartz Job, see:
public class JobRoboFtp implements Job {
#Inject
private AcervoVideoService acervoVideoService;
#Inject
private ConfiguracaoService configuracaoService;
#Inject
private FtpManager ftpManager;
But i got always:
No active contexts for scope type javax.enterprise.context.RequestScoped
Well, If i change this Services to #Dependent scope everything works but i would like to use RequestedScope. There is any way ?
Since you didn't say much about versions, I am going to assume some of the latest versions of Weld 2.x (or even 3.x) - then there is a way. I also assume you are talking about SE environment, as otherwise request scope would auto-activate during requests.
If we are talking CDI 1.2 (Weld 2.x) then you need to add explicit dependency on Weld API and make use of it. The dependency is org.jboss.weld:weld-api and the functionality you are looking for is #ActivateRequestContext interceptor binding. If you are looking for a link to Weld docs, its here - note that this was added in Weld 2.4!
The principle is simple - it intercepts method calls and activated context when entering the method, then destroys it when you exit the method.
#ActivateRequestContext
public void myMethod() {
// any content in here will have request context ACTIVE
doAwesomeThings();
}
If we are talking about CDI 2.0/Weld 3.x - then the very same approach was adapted by CDI (Weld version works there as well). You can read about it here.
Related
i Have a job which needs both a dao and 1 factory class
something like this
https://pastebin.com/kK7VcbW1
My question is how to inject them , i get this exception when the code reaches the dao calling getSomething in the Factory class
In the abstractDao i #Inject entityManager which i get from an #ApplicationScoped EnttityManagerProducer its getEntityManager is #RequestScoped
org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:691)
at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:89)
at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:164)
at org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)
at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)
at org.jboss.weld.bean.proxy.ProxyMethodHandler.invoke(ProxyMethodHandler.java:99)
at org.jboss.weldx.persistence.EntityManager$1070085530$Proxy$_$$_WeldClientProxy.createQuery(Unknown Source)
at com.org.dao.impl.ConcreteDAOImpl.getByName(ConcreteDAOImpl.java:18)
at com.org.dao.impl.ConcreteDAOImp$Proxy$_$$_WeldClientProxy.getByName(Unknown Source)
at com.org.FactoryImpl.getObj(FactoryImpl.java:33)
(the real classes i replaced for the sake of the example)
I tried putting the annotations on both class and interface level i dont know which is preferrable
This type of functionality is built in out of the box with Apache Deltaspike, you can read about the scheduler module. The problem as you're aluding to is that by default, contexts are not started automatically when outside of Java EE. To do that, you need to manually start one. In CDI 2.0 this can be done by adding #ActivateRequestContext to a method/class and a request scope will be started for the duration of that method.
Prior to CDI 2.0, its platform specific. DeltaSpike solves the issue much cleaner.
Env:
Wildfly 8.2.0 Final
JDK 8
Java EE 7
Please note that by 'POJO' i am referring to the classes that serve the other classes i.e other than value objects, entities.
This question was on back of my head for some time. Just wanted to put it out.
Based on CDI and Managed Beans specs and various other books/articles, its pretty clear that CDI injection starts with a 'managed' bean instance. By 'managed' i mean servlet, EJBs etc. which are managed by a container. From there, it injects POJOs (kind of crawl through layers) till every bean gets its dependencies. This all makes very sense to me and i see very little reason why developers ever need to use "new" to create an instance of their dependent POJO's.
One scenario that comes to my mind is when developer would like to have logic similar to
if(something) {
use-heavy-weight-A-instance
} else {
use-heavy-weight-B-instance
}
But, that also can be achieved via #Produces.
Here is one scenario that i verified to be true in wildfly 8.2.0 Final i.e. CDI is not able to inject bean when the JSP has
<%!
#Inject
BeanIntf bean;
%>
But, the alternative to use a servlet works fine.
That said, would like to know if there is any scenario(s) where a developer has to use 'new'. As i understand, by using 'new', developer owns the responsibility of fulfilling dependencies into that bean and all its dependent beans, and their dependent beans etc..
Thanks in advance,
Rakesh
When using CDI or other container you don't use new, because you expect a bunch of service coming from the container.
For CDI these main services are:
Injection of dependent beans (get existing instance or create a new
instance)
Lifecycle callback management (#PostConstruct and
#PreDestroy)
Lifecycle management of your instance (a #RequestScoped bean will make container produce an instance leaving until the end of request)
Applying interceptors and decorators on your instance
Registering and managing observers methods
Registering and managing producers methods
Now, on some rare occasion, you may want to add a part of these services to a class you instantiate yourself (or that another framework like JPA instantiate for you).
BeanManager bm = CDI.current().getBeanManager();
AnnotatedType<MyClass> type = bm.createAnnotatedType(MyClass.class);
InjectionTarget<MyClass> it = bm.getInjectionTargetFactory(type).createInjectionTarget(null);
CreationalContext<MyClass> ctx = bm.createCreationalContext(null);
MyClass pojo = new MyClass();
injectionTarget.inject(instance, ctx); // will try to satisfied injection points
injectionTarget.postConstruct(instance); // will call #PostConstruct
With this code you can instantiate your own MyClass containing injection points (#Inject) and lifecycle callbacks (#PostConstruct) and having these two services honored by the container.
This feature is used by 3rd party frameworks needing a basic integration with CDI.
The Unmanaged class handle this for you, but still prevent you to do the instantiation ;).
I'm working on a Java EE application, primarily JAX-RS with a JSF admin console, that uses CDI/Weld for dependency injection with javax.enterprise.context.ApplicationScoped objects. Minor debugging issues aside, CDI has worked beautifully for this project.
Now I need some very coarse-grained control over CDI-injected object lifecycles. I need the ability to:
Remove an injected object from the application context, or
Destroy/delete/clear/reset/remove the entire application context, or
Define my own #ScopeType and implementing Context in which I could provide methods to perform one of the two above tasks.
I'm fully aware that this is across, if not against, the grain of CDI and dependency injection in general. I just want to know
Is this remotely possible?
If yes, what is the easiest/simplest/quickest/foolproofiest way to get the job done?
Weld Reference Documentation Section 2.1.2
Keep in mind that once a bean is bound
to a context, it remains in that
context until the context is
destroyed. There is no way to manually
remove a bean from a context. If you
don't want the bean to sit in the
session indefinitely, consider using
another scope with a shorted lifespan,
such as the request or conversation
scope.
Custom scope example Porting the veiwscoped jsf annonation to cdi
If you really don't want to take the path of the Custom scope type.. You can use a non-portable method by using BeanManager.getContext method and cast this context in a weld AbstractSharedContext to have access to the beanstore or the cleanUp() method of the context.
Check this thread on how to get a BeanManager instance for your environment
A custom scope which might fit your needs is available at https://github.com/openknowledge/openknowledge-cdi-extensions/tree/master/openknowledge-cdi-scope/src/main/java/de/openknowledge/cdi/scope Maybe you have to adjust the implementation a bit.
Out of the box there is only the Conversation scope that gives you total control on its lifecycle. But you can create your own scope if conversation doesn't suit your needs.
Creating a scope is a tough job, but you can go to weld code and look how conversation was implemented.
In CDI 1.1 there is a javax.enterprise.context.spi.AlterableContext interface, which allows you to individually destroy a bean instance. All normal scopes (request, conversation, session) are alterable.
AlterableContext ctxConversation = (AlterableContext) beanManager.getContext(ConversationScoped.class);
for (Bean<?> bean : beanManager.getBeans(Object.class)) {
Object instance = ctxConversation.get(bean);
if (instance != null) {
ctxConversation.destroy(instance);
}
}
The beanManager here is a javax.enterprise.inject.spi.BeanManager instance. You can get it via JNDI lookup:
InitialContext.doLookup("java:comp/BeanManager");
or via CDI static method:
CDI.current().getBeanManager();
, but be aware of the issues with the static method in some Weld versions:
javax.enterprise.inject.spi.CDI implementation does not support multiple deployments;
CDI.current().getBeanManager() returns a beanmanager from a different deployment.
EJBs seem to be loaded lazily - whenever accessed.
However, I want to initialize them eagerly - i.e. whenever the container starts-up. How is this achieved (in JBoss in particular)
This topic gives some hints, but isn't quite satisfactory.
As of EJB 3.1, singleton beans can be notified of module start and stop:
#Singleton
#Startup
public class StartupBean {
#PostConstruct
private void postConstruct() { /* ... */ }
#PreDestroy
private void preDestroy() { /* ... */ }
}
Prior to EJB 3.1, there is no standard, EJB-only solution. I'd suggest adding a WAR to your EAR and using a servlet-context-listener.
According to Adam Bien's Real World Java EE Patterns - Rethinking Best Practices (see a summary of the patterns) and the Service Starter pattern, it is indeed as bkail suggests
with Java EE 6 = EJB 3.1 use #Singleton with #Startup (and perhaps also with #DependsOn)
prior to that the only standard and portable way is to use the Servlet API, e.g. a HttpServlet starting the EJBs in its init() method and load-on-startup set to 1 in web.xml.
I've got a NullPointerException using EJB3 in a J2SE environment (without EJB3 container)
Briefly, I've got a stateless bean implementing an interface.
When I call it in another class like in a main, a NullPointerException is triggered.
Sample:
#stateless
#Local(IMyInterface.class)
public class myBean implements IMyInterface{...}
public class Main{
#EJB
IMyInterface myInterface;
public static void main(String[] args){
Result result = myInterface.myBeanMethod(); // Exception happens here
}
}
I guess I miss some initialization stuff because the EJB is null when I first try to use it...
Thanks for your help,
EJBs can't work without a container. The dependencies (#EJB) are injected if the beans are instantiated by the container. If you are the one instantiating them, it is your responsibility to set the dependencies.
Furthermore, you are trying to use a non-static variable from a a static method - this won't even compile.
While you can use JPA (which is part of EJB 3) "Entity Beans" (actually, POJOs) in a J2SE environment, you can't use Session Beans without a container and you can't benefit from injection of resources using the #Resource or the more specialized #EJB and #WebServiceRef annotations in a non-managed environment, i.e. a container. In other words, only managed components support injection (Servlets, JSF Managed beans, EJB components, etc).
So, in your case, you'll need to:
Deploy your Session Bean in a Java EE container (like JBoss, GlassFish, WebLogic, etc)
Lookup the remote EJB using explicitly its global JNDI name. The code will look like that:
Foo foo = (Foo) new InitialContext().lookup("FooEJB");
A few additional remarks:
With EJB 3.0, the global JNDI name is container dependent so I can't tell you what it will be exactly (EJB 3.1 finally introduced "portable global JNDI names").
You'll need to set up the JNDI environment (which is container dependent) for the lookup either by providing a jndi.properties on the class path or by using the InitialContext(Hashtable) constructor.
You'll need to provide the application server "client library" on the class path of the client (which is obviously specific to each product).
Search for previous questions or open a new one if you need more specific guidance.