The Question
Given that the archive we deploy is an "implicit bean archive" (see below), using #javax.inject.Inject to inject a #javax.annotation.ManagedBean into another managed bean work in WildFly 8.1.0, but it won't work in GlassFish 4.0.1-b08 nor GlassFish 4.1-b13. GlassFish crash with this message:
WELD-001408: Unsatisfied dependencies for type...
Do I misunderstand the following outlined specifications or do GlassFish have a bug?
CDI 1.1 Part 1
CDI 1.1 (JSR-346) section 12.1 "Bean Archives" says:
An explicit bean archive is an archive which contains a beans.xml file
[..]. An implicit bean archive is any other archive which contains one
or more bean classes with a bean defining annotation [..].
If then, my archive has no beans.xml descriptor file, I will still be able to use beans that have a "bean defining annotation". Question is, what is a bean defining annotation?
The CDI specification section 2.5 "Bean defining annotations" says:
Any scope type is a bean defining annotation.
So that's pritty clear and that's all there is to it according to this section of the CDI specification. If I deploy an archive with no beans.xml descriptor file in it, then I can #Inject beans as long as they have an explicitly declared scope, #javax.enterprise.context.RequestScoped for example. It works in both WildFly and GlassFish. However..
Managed Beans
The subset specification that all specifications within the Java EE technology stack must adhere to, Managed Beans (JSR-316), has a "base model" in which #javax.annotation.ManagedBean do define a managed bean. The managed beans specification doesn't say that #ManagedBean makes the bean a plausible injection target for an injection point (i.e., field or parameter). The specification do say that the beans "can be used anywhere in a Java EE application" (section MB.1.2 "Why Managed Beans?") which in my ears sound like they should be injectable too.
Java EE 7 Umbrella specification
The Java EE 7 specification (JSR-342) has this to say in section EE.5.24 "Support for Dependency Injection":
Containers must support injection points annotated with the
javax.inject.Inject annotation only to the extent dictated by CDI. Per
the CDI specification, dependency injection is supported on managed
beans.
There are currently three ways for a class to become a managed bean:
Being an EJB session bean component.
Being annotated with the ManagedBean annotation.
Satisfying the conditions described in the CDI specification.
Classes that satisfy at least one of these conditions will be eligible
for full dependency injection support as described in the CDI
specification.
There you go: #ManagedBean has "full dependency injection support". Not half or just a little bit of support. Yet, I'm not that sure exactly what "dependency injection support" is. But I think that the paragraph that follows describe it well enough:
Component classes listed in Table EE.5-1 that satisfy the third
condition above, but neither the first nor the second condition, can
also be used as CDI managed beans if they are annotated with a CDI
bean-defining annotation or contained in a bean archive for which CDI
is enabled. However, if they are used as CDI managed beans (e.g.,
injected into other managed classes), the instances that are managed
by CDI may not be the instances that are managed by the Java EE
container.
Basically, what this paragraph says is that the second condition is CDI managed beans that may be injected into other managed classes (because the exception beans "can also").
The umbrella specification and the managed beans specification has both made it somewhat clear that the CDI specification has the last word.
CDI 1.1 Part 2
The #ManagedBean annotation is only found mentioned in the CDI specification two times, both of which occur in chapter 11 which speaks of life cycle CDI events that a CDI extension can observe. Section 11.5.7 is one of the hits and define a ProcessInjectionPoint event. A managed bean may use dependency injection - no surprise there. However, section 11.5.8 define a ProcessInjectionTarget event. Here's what the specification has to say about the ProcessInjectionTarget event:
The container must fire an event for every Java EE component class
supporting injection that may be instantiated by the container at
runtime, including every managed bean declared using #ManagedBean, EJB
session or message-driven bean, bean, interceptor or decorator.
This phrase says undoubtedly that a #ManagedBean may be used as target for an injection point without adding the notion of scope types (#Dependent is always default).
As stated earlier, injecting a #ManagedBean from an implicit bean archive work in WildFly and as far as I can understand, this is required by all Java EE specifications just quoted. So I think it is GlassFish that has a bug. But the CDI spec never said a word about #ManagedBean in section 2.5 "Bean defining annotations", and as always, I'm a nervewreck when reading through overlapping Java EE specifications, so I thought I should ask before I go and file a "critical" bug to the GlassFish team.
EDIT 2014-08-22
Filed a GlassFish bug: https://java.net/jira/browse/GLASSFISH-21169.
This is not a complete answer as confusion will inevitably arise when we try to put together and make sense out of all specifications. I just wanted to say that CDI 1.2 has made a clarification about what exactly a bean defining annotation is (see section "2.5.1. Bean defining annotations"). CDI 1.2 give a list:
The set of bean defining annotations contains:
#ApplicationScoped, #SessionScoped, #ConversationScoped and #RequestScoped annotations,
all other normal scope types,
#Interceptor and #Decorator annotations,
all stereotype annotations (i.e. annotations annotated with #Stereotype),
and the #Dependent scope annotation.
It should be added that what defines a "normal scope type" (second bullet point) is a custom scope annotated #NormalScope.
Related
This doesn't seem right. I was doing some cleanup of my code and I just noticed this. Every ajax request is firing the constructor and #PostConstruct of my #ViewScoped bean. Even a simple database pagination is firing it.
I understood that #ViewScoped is longer than #RequestScoped and that it shouldn't be reconstructed on every request. Only after a complete page reload by GET.
In other words, your #ViewScoped bean behaves like a #RequestScoped bean. It's been recreated from scratch on every postback request. There are many possible causes for this, most of which boils down that the associated JSF view is not available anymore in the JSF state which in turn is by default associated with the HTTP session.
Provided that you can assure that the HTTP session itself is not the root cause of the problem, i.e. when #SessionScoped works absolutely fine, then walk through the below list of possible causes. Otherwise, if the HTTP session itself is also trashed and recreated on every single request, then you need to take a step back and look at session cookie and server configuration. Any cause related to a broken HTTP session is at least beyond the context of JSF.
You're using Mojarra 2.1.17 or older, and the view contains EL expressions which bind a view scoped bean property to a tag attribute which is evaluated during view build time. Examples are JSTL <c:if>, <c:forEach>, etc or JSF <ui:include>, <x:someComponent id="#{...}", <x:someComponent binding="#{...}">, etc. This is caused by a bug in Mojarra (issue 1496). See also Why does #PostConstruct callback fire every time even though bean is #ViewScoped? JSF
This is already fixed in Mojarra version 2.1.18. If you can't upgrade to a newer version, the workaround is to disable partial state saving as below in web.xml, see also JSTL in JSF2 Facelets... makes sense?
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
Or when you want to target a specific set of JSF views only:
<context-param>
<param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
<param-value>/foo.xhtml;/bar.xhtml;/folder/baz.xhtml</param-value>
</context-param>
Important to mention is that binding the value of JSF component's id or binding attribute to a view scoped bean property is a bad practice. Those should really be bound to a request scoped bean property, or an alternative should be sought. See also How does the 'binding' attribute work in JSF? When and how should it be used?
You're using Mojarra 2.2.0, only that version has a (yet unknown) bug in maintaining the view scope which is already fixed in 2.2.1, see also issue 2916. Solution is to upgrade to a newer version.
The #ViewScoped annotation is imported from the wrong package. JSF offers two #ViewScoped annotations, one from javax.faces.bean package for JSF managed beans annotated with #ManagedBean, and another one from javax.faces.view package for CDI managed beans annotated with #Named. When the bean scope annotation does not match the bean management annotation, then the actual bean scope will become the bean management framework's default scope, which is #RequestScoped in JSF managed beans and #Dependent in CDI managed beans.
You need to ensure that you have either of the following constructs and don't mix them, see also #ViewScoped bean recreated on every postback request when using JSF 2.2.
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class CorrectJSFViewScopedBean implements Serializable {
import javax.inject.Named;
import javax.faces.view.ViewScoped;
#Named
#ViewScoped
public class CorrectCDIViewScopedBean implements Serializable {
The view is (accidentally?) marked transient via <f:view transient="true">. This basically turns on "stateless JSF", which is new since Mojarra 2.1.19. Hereby the JSF view simply won't be saved in the JSF state at all and logical consequence is that all referenced view scoped beans can't be associated with the JSF view anymore. See also What is the usefulness of statelessness in JSF?
The web application is configured with com.sun.faces.enableRestoreView11Compatibility context param set to true in an incorrect attempt to "avoid" ViewExpiredException. With this context param, the ViewExpiredException will never be thrown, but the view (and all associated view scoped beans) will just be recreated from scratch. However, if that happens on every request, then this approach actually hides another problem: the views expire way too soon. This indicates a possible problem in maintaining the JSF view states and/or the HTTP session. How to solve/configure that properly, head to javax.faces.application.ViewExpiredException: View could not be restored.
The web application's runtime classpath is polluted with multiple different versioned JSF API or impl related classes. This causes a corruption/mismatch in the identifiers/markers for the JSF view state. You need to make sure you don't have multiple JSF API JAR files in webapp's /WEB-INF/lib. In case you're using Maven, make carefully sure that you mark server-provided libraries as <scope>provided</scope>. See also "Installing JSF" section in our JSF wiki page and the answer to this related question: How to properly install and configure JSF libraries via Maven?.
When you're using PrimeFaces <p:dialog>, then make sure that the <p:dialog> has its own <h:form> and that it is not nested in another <h:form>. See also p:fileUpload inside p:dialog losing #ViewScoped values.
When you're combining PrimeFaces FileUploadFilter with PrettyFaces, then make sure that the FileUploadFilter also runs on PrettyFaces-rewritten/forwarded requests. See also ViewScoped bean rebuilt when FileUploadListener called using PrettyFaces and How to use PrimeFaces p:fileUpload? Listener method is never invoked or UploadedFile is null / throws an error / not usable.
When you're using PrettyFaces, a badly configured rewrite rule which redirects CSS/JS/image resources to a JSF page tied to a #ViewScoped bean will also give misleading behavior. See also CDI ViewScope & PrettyFaces: Multiple calls to #PostConstruct (JSF 2.2).
This is a followup question to some questions on stackoverflow.com:
JSTL c:forEach causes #ViewScoped bean to invoke #PostConstruct on every request
Why does #PostConstruct callback fire every time even though bean is #ViewScoped? JSF
However, we're using Mojarra 2.1.22 but our Seam 3 CDI #ViewScoped annotated beans always become reconstructed, that is the method annotated with #PostConstruct is executed and we get an new bean on every AJAX request.
All I keep hearing for a few months (it's February 2014 now) is that Mojarra 2.1.18+ has many of these bugs fixed and that the view-scoped bean should survive AJAX requests when the view is using this bean from a <c:forEach items="#{mySeam3CdiViewScopedBean.items}" ... >.
Here are a few bugs:
https://java.net/jira/browse/JAVASERVERFACES-1665
https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-928 (<- see the last comment by dwightd - I cannot confirm it!)
https://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-787
https://java.net/jira/browse/JAVASERVERFACES-2688
The only difference to the examples I mentioned at the top is that we're using Seam 3.1 Faces CDI #ViewScoped (+ #Named) and not "native" JSF #ViewScoped (+ #ManagedBean).
Question:
Is Seam 3 Faces (3.1 Final) the reason why it isn't working?
(How can we find out? It's not easy to translate what we have to a test case... maybe someone knows?)
PS: I know this is more of a forum question, but I have hopes that the people here dealing with JSF 2 but not necessarily Seam 3 (Faces) could give their feedback.
A few remarks about your questions :
Using JSTL loop in JSF is not recommended since it's not managed in JSF lifecycle. Using facelets ui:repeat is the good practice
Seam 3 is deprecated, you should avoid using it as you won't have any support if the problem comes from here.
You have two solutions (by order of preference) :
Switch to JSF 2.2x (and CDI 1.1) which integrates native CDI compliant #ViewScoped. You can easily do this by using JBoss Wildlfy 8 or Oracle Glassfish 4 servers.
If you cannot switch JSF, forget Seam Faces and switch to Deltaspike (the descendant of Seam 3 and CODI). It provides a CDI scope for the JSF #ViewScoped
But in both case, try to get rid of JSTL in your JSF pages, it is a source of a lot of strange issues.
We're using the Grails spring security plugin:
http://grails.org/plugin/spring-security-core
I simply want to change the default access decision manager from the default AffirmativeBased to UnanimousBased. I do not see it documented anywhere in the plugin manual:
http://grails-plugins.github.io/grails-spring-security-core/docs/manual/
Does anyone know if it's possible to change this?
I added one additional voter, "myVoter" which is detected and working fine.
grails.plugins.springsecurity.voterNames = [
'myVoter', 'authenticatedVoter', 'roleVoter',
]
Based on Burt Beckwith's "Hacking the Grails Spring Security Plugin" [http://www.slideshare.net/gr8conf/hacking-the-grails-spring-security-plugins], it should be possible to simply provide a different implementation of the accessDecisionManager bean. Something like this:
accessDecisionManager(org.springframework.security.access.vote.UnanimousBased)
in resources.groovy
When I tried this, I had trouble with the constructor syntax in the bean definition. The access decision manager wants a list of voters in the constructor and I couldn't quote figure out how to get my voters defined in config.groovy as parameters to the constructor. I was about to derive my own decision manager (with parameterless constructor) from UnanimousBased when I stumbled upon the source code for AuthenticatedVetoableDecisionManager in the Grails Spring Security Plugin. This class splits the voters in half... anything deriving from AuthenticatedVoter will immediately fail if any are denied (e.g. AUTHENTICATED_FULLY family), but all other voters will pass if any are granted (e.g. RoleVoter). I wanted the AuthenticatedVoter functionality for my custom voter so I simply derived from AuthenticatedVoter (making sure to override all of the interface methods so I didn't accidentally get any base class functionality) and stuck with the default decision manager.
I am migrating an application to Java EE 7 and would like to CDI 1.1. But I don't get the meaning of bean-discovery-mode="annotated". The
CDI 1.1 specification is not very helpful. At least I have not found any useful paragraph. Did I miss it?
This example runs perfectly with bean-discovery-mode="all" and injects an instance of LoggingClass:
public class LoggingClass {
public Logger logger = Logger.getLogger("ALOGGER");
}
#Test
public class MMLoggerProducerIT extends Arquillian {
#Inject private LoggingClass lc;
}
But if I change from bean-discovery-mode="all" to bean-discovery-mode="annotated" the container is not able to inject an instance into the field lc.
How do I have to annotate LoggingClass to use bean-discovery-mode="annotated" correctly?
When using bean-discovery-mode="annotated" only classes with a bean defining annotation are discovered. All other classes are ignored. Any scope type is a bean defining annotation. If a scope type is declared on a bean class, then the bean class is said to have a bean defining annotation [spec]. The 1.1 spec is not completely clear here. Only classes with a #NormalScope scope or #Dependent pseudo scope are discovered, #javax.inject.Singleton and all other #Scope (pseudo) scopes are ignored.
Note that the definition of a "bean defining annotation" changed in CDI 1.2 and is now very well defined:
The set of bean defining annotations contains:
#ApplicationScoped, #SessionScoped, #ConversationScoped and #RequestScoped annotations,
all other normal scope types,
#Interceptor and #Decorator annotations,
all stereotype annotations (i.e. annotations annotated with #Stereotype),
and the #Dependent scope annotation.
As a practical matter, bean-discovery-mode="ALL" turns on scanning of all classes in an archive. This is called an "explicit archive".
Omitting beans.xml, or setting bean-discovery-mode="ANNOTATED", makes the archive an implicit archive. In this case, the container will scan for beans with annotated scope types.
This explains why LoggingClass isn't injected when you set bean-discovery-mode="ANNOTATED". As documented in the Java EE 7 Tutorial:
CDI can only manage and inject beans annotated with a scope type in an implicit archive.
Edit: so just to be absolutely clear, you need to add a scope type to LoggingClass. So something like this:
#SessionScoped
public class LoggingClass {
public Logger logger = Logger.getLogger("ALOGGER");
}
In Java EE 7 and CDI 1.1, we removed the requirement to include the beans.xml deployment descriptor to turn on CDI for an archive, bringing CDI 1.1 in line with most other Java EE APIs where deployment descriptors are optional. It also removed the binary on/off nature of including beans.xml or not. You can control which files are scanned by the container with the settings in bean-discovery-mode.
See the JavaEE tutorial on packaging CDI applications here:
http://docs.oracle.com/javaee/7/tutorial/cdi-adv001.htm#CACDCFDE
I also agree with the answer form #rmuller. But I want to point out that there is still different behavior on application servers Payara and Wildfly.
See the following example with a normal not scoped class but having a #EJB injection:
public class SomeClass {
#EJB
MyService myService;
...
}
If you provide a beans.xml file with:
.... version="1.2" bean-discovery-mode="annotated"....
Payara 4.1 will treat the class SomeClass NOT as a CDI bean and will NOT inject the service EJB.
This is clear to me that it behaves as stated in the specification.
But Wildfly 10 treats the class as an CDI bean and injects the service EJB which is not expected. To get this working the beans.xml file should look like this:
.... version="1.2" bean-discovery-mode="all"....
It's amazing that the two most common application servers are different here in behavior.
Hi
I am new to Spring Security 3 and was trying out #PostFilter on a method declared in an Interface but the returned Collection is not getting filtered.
Here is the code:
public interface IProductService {
#PostFilter("(!filterObject.customersOnly) or (filterObject.customersOnly and hasRole('ROLE_USER'))")
Collection<Category> getCategories();
}
customerOnly is a boolean attribute in a domain object Category.
I've added the following element on xyz-security.xml:
<global-method-security pre-post-annotations="enabled" />
Could someone help me understand what am i missing?
Thanks
The typical causes for this are:
AspectJ and/or CGLIB JARs are not in your classpath.
You have the annotation on an interface OR on a class (review the Spring AOP docs to determine which is supported for which AOP implementation).
You have added the Spring Security configuration to a different ApplicationContext than where you have declared your secured beans (for example, you are trying to secure a bean in your *-servlet.xml file, when your Spring Security configuration is declared by the ContextLoaderListener).
You have removed or altered the declaration so that the annotated bean is not processed by the same ApplicationContext where Spring Security is configured.
If none of these suggestions applies, please enable DEBUG logging and watch application startup to see if the bean annotation is processed at all.
As an aside, I have had many readers report similar flavors of this problem - the source code for this sample does work, but in all cases it has been true that readers have subsequently changed one of the above 4 items, causing the sample code to "break" ;)