My understanding is that
#Stateful
#ConversationScoped
is allowed, and is normal usage.
With the new JSF 2.2 ViewScoped (javax.faces.view.ViewScoped) annotation, which is documented to be fully compatible with CDI scope annotations, does this mean that:
#Stateful
#ViewScoped
Is a viable combination?
#Stateful is an EJB annotation, so technically your bean will be a stateful EJB bean, not a CDI bean. And it will only work in a full-blown application server.
In case of (only) JSF 2.2 + CDI use:
#javax.inject.Named // to expose a bean in the EL context
#javax.faces.view.ViewScoped // to make it view scoped
Also don't mix up the latter annotation with #javax.faces.bean.ViewScoped, it once took me a while to find the issue.
There's a nice example.
keep in mind that with #stateful, every time you inject it you will get a new concrete instance, because you're indicating storing state with that annotation. also the EJB layer concept of session is not the same as the JSF layer concept of session, and confusing the two can create all sorts of issues for you.
JSF session is tied to a specific client maintained by either a cookie or url-rewriting (container configuration).
EJB session is tied to a specific method execution (#Stateless) or a concrete instance (#Stateful).
unless you need to have durable serialization and state maintenance within the EJB, stateful is not going to give you want you want. you're best bet will be to separate the transactional aspects into a #Stateless and store your state in a #ViewScoped that gets passed into the #Stateless methods.
Related
I am new to CDI. While reading, I am always encountering contextual objects, non contextual objects. What does they mean?
For example the below link
http://docs.jboss.org/weld/reference/latest/en-US/html/beanscdi.html#d0e881
Message-driven and entity beans are by nature non-contextual objects
and may not be injected into other objects
The context of a CDI framework is basically a big map of objects*. You can add objects to the context or make the CDI framework create objects from your service classes by using any CDI configuration method (spring xml beans/annotations like #Component/#Service).
Once you have the context you can get objects from it: (Spring: getBean(name))
Now you can configure dependencies between the objects/beans in the context, and the CDI will make sure any object you get from the context will have its dependencies set. This is the dependency injection part.
Non-contextual objects are simply not added to the context and the CDI framework does not know about them. Usually only service classes are part of the CDI context.
* Not really a map though, objects can be accessed by name, by type and other ways. The default is you get the same object each time you ask by the same name (singleton), although you may configure the CDI to create a new object each time you ask (prototype).
A context in CDI is some span during execution of your program when contextual objects can be used.
It defines when CDI container creates, destroys and how it links instances of those objects together.
Non-contextual objects are those that are not tied to any CDI context.
MDBs are one example, they are managed by EJB container and not intended to be used as ordinary objects.
Entities come and go as you interact with a DB via JPA, so they also cannot be tied to a context.
Another example is any object whose instances you create manually.
Is there a way to store some bean inside the conversation context? I.e for each new conversation, a new separate bean is created belonging to it.
The easiest way to do what you want is to declare a ConversationScoped managed bean or EJB where JSF2 manages the scope.
There are some good explanations here:
http://docs.oracle.com/javaee/6/tutorial/doc/gjbbk.html
http://www.ibm.com/developerworks/java/library/j-jsf2fu-0710/index.html#cdi
http://www.theserverside.com/tip/Dependency-Injection-in-Java-EE-6-Conversations-Part-4
http://www.andygibson.net/blog/article/cdi-conversations-part-1/
http://www.andygibson.net/blog/tutorial/pattern-for-conversational-crud-in-java-ee-6/
http://blog.goyello.com/2011/06/08/jee6-cdi-and-conversation-scope/
... any of which will do a better job than I will. The very short version is that you annotate a bean - which can be a plain POJO that follows the bean conventions - with the #ConversationScoped annotation. You then #Inject a Conversation object, which you can use to begin() and end() conversations. Inject this #ConversationScoped bean into other things. The Conversation.begin and Conversation.end methods control its lifecycle.
There's a bit much code to just post here, but the above links should help.
An alternative to #ConversationScoped POJO managed beans can be #Stateful #ConversationScoped EJBs. They can be really handy when you need EJB services in a conversation.
For some of the conceptual background and detail read the CDI/Weld reference on scopes - and the rest of the CDI/Weld manual. It's really well written and really good.
Im trying to get my head around CDI and EJB and the Entity Boundary Control (ECB) pattern. My understanding of the ECB pattern is that the Boundary is the start and end of the transaction boundary. Further to that, CDI doesn't provide transaction support like an EJB does.
So if I want to implement the ECB pattern successfully, then the following are true;
I can Implement the Boundary portion with EJB's (i.e. #stateless, #stateful, #singleton) and the Control layer with CDI or EJB's.
I can Implement the Boundary and Control portion with CDI but implement transaction support in the Boundary similar to (http://smokeandice.blogspot.com/2009/12/cdi-and-declarative-transactions.html)
I can not implement the Boundary with CDI and then start using EJB's in the Control layer.
Thanks
I sucessfully implement the ECB pattern in JavaEE 6 using EJB's solely for the Boundaries and CDI for the Controllers. A typical stack in my architecture uses
Stateless EJB's annotated with JAX-RS annotations to implement a REST service as Boundary
CDI managed beans for business logic in the #Dependent scope as Controller
CDI managed beans in the #Dependent scope for Data Access Objects which use JPA's EntityManager to interact with a database
JPA entity beans
The stateless EJB's which form the Boundary are always annotated with #TransactionAttribute(REQUIRED) which is the default. I do not use other transaction attributes. Doing so, you can ensure that every interaction with the Boundary takes place in exactly one transaction.
By using only the #Dependent scope for the CDI managed beans, you can ensure that every thread has its own instance of that beans. So you have never more than one thread accessing a CDI managed bean at the same time. Doing so prevents you from the typical concurrency issues.
Using a combination of more heavy weight, pooled EJB's for the Boundary and lightweight CDI managed beans for the rest of the application performs very well for me.
Usually I'm using #RequestScoped or #SessionScoped (from javax.enterprise.context) to inject objects (for instance in faces beans) using #Inject.
I am also using EJBs. As I understood, a set of stateless EJB copies (pool) is used to be injected to objects. The reason there are many copies is to ensure one instance of EJB isn't accessed concurrently. When speaking about stateful EJBs (again as I understood), one instance of such is bound to concrete injection point. And they are injected using #EJB (the stateless ones too).
Frequently I can see on the web examples of using #Stateless or #Stateful in conjunction with #Scoped. What is the meaning of them?
Edit: (trying to clarify as no one responded to this moment):
I'm especially interested whether such scoped annotations change anyhow (and if they - how) moment of creation of EJB's instance.
For my understanding: if I have, #EJB annotated field, object of proper class is injected there. If such EJB is stateless, container simply take free instance from the pool of pre-created instances. Pool can be resized if necessary. It is stateless, because object isn't guaranteed to be preserved across method calls of our class (i.e. class which has field containing reference to EJB).
We can also use stateful EJB and in that case one instance is preserved during method calls. As I think, it will be simply injected once per object creation. (There is also singleton EJB, which is shared between all objects).
I can't find the purpose of #Scoped annotations for EJB here.
Edit 2:
One can use such combination of annotations if class is to be injected via EJB and DI (by #Inject) mechanisms. This is rather, however, special case and not elegant. I am asking if you know any other reasons.
Edit 3:
Please see my comment under arjan's answer.
A #Stateless or #Singleton bean may be explicitly scoped to prevent its scope being automatically modified to a scope that may be illegal. E.g. both these bean types are not allowed to be #RequestScoped. See this link for some more info: http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html/CDI.html
#Stateful makes a lot of sense to be (explicitly) scoped. Namely, without a scope you as a programmer have to take care to call the #Remove annotated method. This can be troublesome to guarantee, since such a bean is typically not used in a single method where you can call the #Remove method in a finally block. With a scope, the bean is exactly removed when the scope ends.
Furthermore, without a scope you can't always use injection to obtain a reference to a stateful bean's stub. Namely, every time the injection happens, you'll get a new instance. This is particularly troublesome when injecting a stateful bean in a request scoped (JSF) backing bean, where you have the intent to preserve the stateful bean across a couple of requests.
Then, in combination with #Named, you can also use a session bean directly as a backing bean to flatten your application layers (see e.g. http://jaxenter.com/java-ee-6-overview-35987-2.html). Obviously you want an explicit scope in that case. Now flattening your layers may not be a best practice in larger applications, but for smaller applications and/or people just beginning with Java EE there is definitely a wish to put business logic directly into the backing bean. It's then required that backing beans have access to the same kind of services (mainly transactions) that 'business beans' normally have.
Finally, Gavin King (CDI spec lead) has suggested to always use #Inject instead of #EJB. The only exception concerns remote EJBs, where #EJB is still used.
Part of the confusion around EJB and CDI is that CDI is a new component model in Java EE and still relatively new. Although they integrate fairly well with each other, they are still two different component models and not all best practices have been thought out yet. Reza Rahman (EG member, EJB book writer, and author of CDI implementation CanDI) has suggested that the EJB model could possibly be retrofitted in the future as a set of CDI services. Indeed, in Java EE 7 a step is being made by separating the transactional services from EJB and making them available via (CDI) annotations.
I have a #SessionScoped? DAO that's being injected into a Stripes framework Interceptor constructor that seems to be found from the interceptor (on subsequent calls) but is not being injected into a service in the same request (and session). Why isn't the same instance (initialized in the interceptor) being reused in the service (which is in a different package in the same project)?
Making the DAO a #Singleton does the trick, but is unacceptable as the DAO stores information that must remain consistent throughout a user's session on an application that has multiple users who would be sharing the same DAO instance.
If the Interceptor is not a session-scoped object, then you'll need to inject Provider<YourDaoType> into the Interceptor. This is the common pattern to use when an object with a long life depends on another object with a shorter life.
ok, I've figured it out. I changed the #SessionScoped to a bind(DAO.class).in(ServletScopes.SESSION) statement with which the injection works. As far as I understand, these should be equivalent, but in my case they're producing different results.
One aspect that was troubling me along the way was that Stripes built the interceptor that injected the DAO on startup causing errors as this happened outside the scope of a session (which the DAO is #SessionScoped. ActionBeanContext context information is needed to initialize the DAO session context which I set in an AbstractActionBean setContext method that is called during the construction of the action bean.
Thanks for your interest and help.