1 2 3 Previous Next 44 Replies Latest reply on Feb 12, 2010 11:23 AM by kenglxn

    Implementing the same of @RequestParameter in WELD

    agori

      I think you are aware of this Seam annotation, and I am trying to re-implement the same of @RequestParameter in WELD. I am implementing using with CDI producers and InjectionPoint as Gavin exemplified here.


      I found this problems:


      1. injection needs a further annotation. Is possible to avoid @Inject in some way? I am just curious, it's not a real issue obviously.


      2. basic type are not proxable, so If I inject a parameter in a session scoped bean, the value is injected once per session and not once per request.
      This is because I can't use @RequestScoped in producer method:


       @Produces @HttpParam("") @RequestScoped
         String getParamValue(ServletRequest request, InjectionPoint ip) {
            return request.getParameter(ip.getAnnotation(HttpParam.class).value());
         }
      
      



      This code throws an exception because WELD couldn't inject InjectionPoint in a non Dependent scoped producer.

        • 1. Re: Implementing the same of @RequestParameter in WELD
          meetoblivion

          So assuming you do this instead:




           @Produces @HttpParam("")
             String getParamValue(ServletRequest request, InjectionPoint ip) {
                return request.getParameter(ip.getAnnotation(HttpParam.class).value());
             }



          What happens when you decorate your injection point




          @Inject @RequestScoped @HttpParam("someParam") String someParam;



          I haven't thought about it too much, but even if the containing element is SessionScoped, this should reflect the current param value.

          • 2. Re: Implementing the same of @RequestParameter in WELD
            nickarls

            My guesses



            • The @Inject is needed unless you write an extension that handles it (gavins post is from pre-330)

            • The ServletContext needs to come from somewhere in your producer (trivial to write a producer for it, though)

            • You can't do @Inject @RequestScoped, an injected bean will have the scope it has by definition

            • Number of injections don't count, a requestscoped instance will always be...per request



            Please show the full stack trace for the InjectionPoint-dependent-producer problem...

            • 3. Re: Implementing the same of @RequestParameter in WELD
              gavin.king

              It is possible to write a portable extension that adds the @Inject annotation to everything annotated @RequestParameter.

              • 4. Re: Implementing the same of @RequestParameter in WELD
                meetoblivion

                Nicklas Karlsson wrote on Jan 02, 2010 22:21:


                You can't do @Inject @RequestScoped, an injected bean will have the scope it has by definition



                Now I'm a bit more confused.


                Now we can produce something very generic, e.g.




                @Produces
                public SomeObject produceSomeObject() { 
                ....
                }





                And we can produce something very specific




                @Produces @SomeQualifier("Something")
                @SessionScoped
                public SomeObject produceSomeQualifierSomeOjbect() { 
                ....
                }





                And we can mark the Scoping based on the containing component, if I understand correctly




                @ApplicationScoped
                public class SomeOtherObject {
                
                @Produces @SomeOtherQualifier
                public SomeObject produceSomeQualifierSomeOjbect() { 
                ....
                }
                
                }
                




                and my understanding based on the resolution rules, none of these will result in a problem w/ resolution




                @Inject SomeObject someObject;
                @Inject @ApplicationScoped @SomeQualifier SomeObject someObject2;
                @Inject @SessionScoped @SomeQualifier("Something") SomeObject someObject3;
                @Inject @ApplicationScoped @SomeOtherQualifier SomeObject someObject4;



                or am I wrong?


                My other confusion, if you @Inject @RequestScoped something, in multiple inject points, are they the same instance or a different instance?

                • 5. Re: Implementing the same of @RequestParameter in WELD
                  matt.drees

                  You should not put scope annotations (e.g. @RequestScoped) at an injection point.  They will be ignored. (Or maybe Weld should issue a warning message.)


                  The resolution rules determine which bean to inject based on the type and qualifiers of the injection point; the scope is determined solely from the bean (not the injection point).

                  • 6. Re: Implementing the same of @RequestParameter in WELD
                    meetoblivion

                    I figured they'd get ignored.  For some reason, I decided to try a bit of short hand, e.g.:




                    @ApplicationScope
                    public class SomeBean {
                    @Inject @SomeQualifier SomeObject someObject2;
                    }





                    but either way, you should be able to decorate a Producer with the Scope rules, correct?  What would happen then if you Inject something that is produced only in RequestScoped into a SessionScoped object?  It should resolve, correct?

                    • 7. Re: Implementing the same of @RequestParameter in WELD
                      gavin.king

                      A producer, just like any other bean, can have a scope. Beans are the only things that can have scopes. Injection points are not beans.

                      • 8. Re: Implementing the same of @RequestParameter in WELD
                        meetoblivion

                        I think the point I'm trying to make is that




                        @SessionScoped
                        public class SomeAppBean{
                        @Inject @HttpParam("username") String username;
                        ...
                        }
                        
                        @Produces
                        @RequestScoped
                        @HttpParam("")
                        public String produceHttpParam(InjectionPoint ip) {
                        ...
                        }





                        The reference to String username should be dynamic, e.g. not just created once per session, right?  Or does this get mucked up because String is not proxied (or is it?)

                        • 9. Re: Implementing the same of @RequestParameter in WELD
                          gavin.king

                          Well, that is not actually a legal injection point, and Weld should have given you an exception, according to spec section 5.4.1.

                          • 10. Re: Implementing the same of @RequestParameter in WELD
                            agori

                            Gavin King wrote on Jan 03, 2010 18:44:


                            Well, that is not actually a legal injection point, and Weld should have given you an exception, according to spec section 5.4.1.


                            If I understand well, this is because a primitive typed field should be proxified (because it's request scoped and belongs to a session scoped bean), and this is impossible. Am I right?


                            So how to implement @RequestParameter as a portable extension? I think in Seam I can inject a parameter into a session scoped bean...

                            • 11. Re: Implementing the same of @RequestParameter in WELD
                              meetoblivion

                              And I take it that marking it @Dependent will make it SessionScoped.


                              What about the idea of having a producer that produces the Map of request parameters?  Or wrapping that somehow?

                              • 12. Re: Implementing the same of @RequestParameter in WELD
                                matt.drees

                                So how to implement @RequestParameter as a portable extension?

                                So, I think there are two ways you could go about this.  One is to use the same producer method definition in John's example, but at the injection point
                                use CharSequence (which is proxiable) instead of String (which is not).  To be concrete:


                                class MySessionScopedBean {
                                  @Inject @HttpParam("foo") CharSequence foo; //this is a proxy
                                
                                  public void ping() {
                                    String foo = this.foo.toString();
                                    //this foo is not a proxy
                                    ...
                                  }
                                
                                }
                                



                                The other approach, which I would opt for, is to have the producer method bean scoped @Dependent instead of @RequestScoped, and at the injection point use Instance<String> instead of String.  So:


                                @Produces
                                @Dependent
                                @HttpParam("")
                                public String produceHttpParam(InjectionPoint ip) {
                                  ...
                                }
                                
                                
                                class MySessionScopedBean {
                                  @Inject @HttpParam("foo") Instance<String> foo;
                                
                                  public void ping() {
                                    String foo = this.foo.get();
                                    ...
                                  }
                                
                                }
                                
                                



                                I'd go with the second approach, myself.

                                • 13. Re: Implementing the same of @RequestParameter in WELD
                                  meetoblivion

                                  In the second, since it's @Dependent, wouldn't it become SessionScoped?  I think the underlying issue is that it needs to be refreshed when the page URL has a new get/post param.

                                  • 14. Re: Implementing the same of @RequestParameter in WELD
                                    matt.drees

                                    In the second, since it's @Dependent, wouldn't it become SessionScoped?

                                    So, the Instance<String> instance is itself effectively session scoped, because it's a dependent object of MySessionScopedBean.  However the instances it generates (via foo.get()) are each the result of a call to the @Dependent context, which is guaranteed to be a new instance of the bean (spec section 6.4).  In this case, new instances come from the producer method.  So, no, the http param value won't be inappropriately cached.

                                    1 2 3 Previous Next