5

Within a JSP it is possible to use CDI managed beans using EL expressions such as ${myBean.myAttribute}. No problem here.

I would like to use "regular injection" (i.e. without using EL expressions) with @Inject in JSP files, for example : <%! @Inject MyBean myBean; %> then later <%= myBean.getMyAttribute() %>. Even if that example can be achieved using EL expressions, some other use cases cannot.

This does not seem to be completely supported by app servers:
- JBoss 6.0.0, JBoss 6.1.0, Resin 4.0.22: OK, it works just fine.
- JBoss 7.0.1, GlassFish 3.x (several versions were tested): FAILS, myBean remains null.

It should work fine in a JSP since :
(1) it works fine in servlets according to the various concerned specifications and
(2) JSP get translated to servlet during runtime.

Do you guys know if what I'm trying to do is supported or not? Any inside/implementation information maybe?

Hash
  • 4,647
  • 5
  • 21
  • 39
Florian Beaufumé
  • 1,751
  • 2
  • 22
  • 34
  • 3
    I don't know if it is (or should be) supported, but I know that doing this in a JSP is just a bad idea. JSPs are meant to generate markup. They're not supposed to contain Java scriptlets for years. Do what you want to do in a regular servlet, and dispatch to the JSP. Only use the EL and JSP tags in the JSPs. – JB Nizet Sep 12 '11 at 09:32
  • 4
    Using servlets and/or MVC frameworks can help in some situations depending on the application requirements. But sometimes adding a servlet only to pass a service bean reference to a JSP is overkill, and may be considered an anti-pattern. What I'm really interested in here is understanding the CDI behavior for JSP, even if there are alternative solutions. :) – Florian Beaufumé Sep 13 '11 at 08:47

3 Answers3

3

Interesting question, if you hadn't been testing it, I would have bet some money on the fact the it does not work ;-)

CDI builds on managed beans (JSR 316). The corresponding definition is pretty relaxed (on purpose):

From the spec:

A Managed Bean can be declared by annotating its class with the javax.annotation.ManagedBean annotation. A Managed Bean must not be: a final class, an abstract class, a non-static inner class. A Managed Bean may not be serializable, unlike a regular JavaBean component.

In the basic component model, Managed Beans must provide a no-argument constructor, but a specification that builds on Managed Beans, such as CDI (JSR-299), can relax that requirement and allow Managed Beans to provide constructors with more complex signatures,

What's probably happening is that the container scans the classpath and happens to find the compiled JSP servlets. It's a while since I last saw one, but I remember that the code is generated and everything (including scriptlets) lands in doGet() or doPost()...!? So, even though they formally do not disqualify in terms of the definition, I doubt that a JSP scriplet is anything that you want to consider a managed bean. It feels terribly wrong, honestly ;-)

I'm following the CDI / Weld / Seam mailing lists since quite a while, and don't recall that JSP has ever been mentioned. Same with googling this connection.

As a consequence you should not rely on CDI working with scriptlets. IMHO this behaviour has more of a side effect than of something intenional and can be dropped in future releases without notice (or even without being noticed :-)

So, +1 for the proposal of JB Nizet: Use servlets with CDI, but not JSPs.

UPDATE: I tried to help, not to create confusion ;-) My point is: IMHO it feels really really wrong to use CDI in JSPs, but I did not find anything in the relevant specs that proves this. All I can say is that JSPs are never mentioned anywhere - which kind of supports my gut feeling (and fits the observation that some implementations do consider it, others don't).

Jan Groth
  • 14,039
  • 5
  • 40
  • 55
  • 1
    I did not understand your affirmation that "CDI builds on managed beans". In fact, CDI [makes JSF managed beans not necessary](http://stackoverflow.com/q/2930889/287976) and does not require the `@ManagedBean` annotation in its managed beans - one class [just need a default constructor](http://tinyurl.com/66vkjxp) to be a bean. Also, the Weld reference states that [servlets are beans](http://docs.jboss.org/weld/reference/1.0.0/en-US/html/1.html) so I would bet that JSP-generated servlets would support injection (not taking in account whether it is good or bad). – brandizzi Sep 12 '11 at 21:24
  • 2
    No no, you are mixing JSF `javax.faces.bean.ManagedBean` with CDI `javax.annotation.ManagedBean` - a unfortunate ambiguity. [This Weld documentation chapter](http://docs.jboss.org/weld/reference/1.0.0/en-US/html/1.html) is a good start for (re-)evaluating CDI, please do also check the cited JSR 316... Yes, servlet are beans, that's beyond doubt. But I honestly don't know if **generated servlets** fits into that scheme - like I wrote before. – Jan Groth Sep 13 '11 at 04:48
  • Not all JSP scripting elements end up in doGet/doPost, JSP "declarations" (i.e. "<%! ... %>" stuff) define class attributes or methods. That's the right fit for @Inject attributes. Appart from this clarification, Jan, I do not understand your logical implication and why you say that "they formally do not qualify". – Florian Beaufumé Sep 13 '11 at 08:59
1

I don't think there is a portable @Inject available out-of-box for JSP, but it should be possible to implement it (at the container level) the same way it works with servlets.

And while I agree that's it not the best way to utilize CDI, technically I don't see any reason against it. For example, AFAIK @Inject in servlets transparently uses ThreadLocal proxies, why not use this feature in JSP's?

Tair
  • 3,779
  • 2
  • 20
  • 33
0

Try this :-

<%!
    @Inject
    private UserService userService;
%>

It's working for me :)

Note: Use bracket <%! %> instead of <% %>.

Victory
  • 1,184
  • 2
  • 11
  • 30