1 2 3 Previous Next 44 Replies Latest reply on Feb 12, 2010 11:23 AM by kenglxn Go to original post
      • 30. Re: Implementing the same of @RequestParameter in WELD
        meetoblivion

        Matt Drees wrote on Jan 04, 2010 05:40:


        As Gavin said, it'd be helpful if you post the full code.


        I'm not sure what more code you're expecting, I did already.  It takes 4 classes to run the basic Injection example - annotation, producer, consumer (injection point) and primitive type wrapper;  I also included the facelet that prints out the results.

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

          Nicklas Karlsson wrote on Jan 04, 2010 09:53:


          Is that running code? I would assume there is no injection into servlet listeners and you would have to get the manager from JNDI and fire it yourself?



          Well, I think it should run in an EE 6 environment.  The spec requires support injection in servlet listeners.  So it should run in glassfish.  I don't think jboss will run it yet, since jboss 6 m1 doesn't support servlet 3.

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

            John Ament wrote on Jan 04, 2010 13:21:

            I did already. 


            Well, you had posted what you started with.  You didn't post what changes you made as a result of the suggestions here.  But it's not really import if your http param injection code is working correctly now.  Is it?

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

              Matt Drees wrote on Jan 04, 2010 16:01:


              Well, you had posted what you started with.  You didn't post what changes you made as a result of the suggestions here.  But it's not really import if your http param injection code is working correctly now.  Is it?



              So I want to point out that what I'm trying to get working is this (from above):





              The reference to String username should be dynamic, e.g. not just created once per session, right?

              I'm not sure I've seen anything in this thread that actually tries to explain how that might work.  The problem is not trying to get a reference to the ServletRequest, I've gotten around that.

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

                John Ament wrote on Jan 05, 2010 01:39:


                So I want to point out that what I'm trying to get working is this (from above):


                The reference to String username should be dynamic, e.g. not just created once per session, right?




                So, Strings can't be dynamic.  They're immutable and final.  If you inject a String, it will remain as it is for the duration of your component's life.
                In CDI, injection occurs at instance creation time (like Guice, Spring and others) and not at method invocation time (like Seam).  So while Seam can make a String appear dynamic, CDI can't.  (For good reasons, too.)


                So, instead of String, you need to inject something else.  Like RequestParameter.

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

                  Matt Drees wrote on Jan 05, 2010 02:26:


                  So, instead of String, you need to inject something else.  Like RequestParameter.


                  Yep, that's why I'm trying to use RequestParameter in my code above, but it doesn't work.

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

                    Ok, so can you post the stacktrace you get and also post your version of RequestParameter, as well as whatever you're using to provide a ServletRequest?  I assume you haven't changed MyBean, HttpParam, and the facelet template.  I also assume you've gotten rid of RequestParamProducer and ParamHolder.

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

                      Matt Drees wrote on Jan 05, 2010 02:26:


                      In CDI, injection occurs at instance creation time (like Guice, Spring and others) and not at method invocation time (like Seam).  So while Seam can make a String appear dynamic, CDI can't.  (For good reasons, too.)



                      Could you explain what are these good reasons?

                      • 38. Re: Implementing the same of @RequestParameter in WELD
                        swd847

                        Performance.


                        In seam every component invokation involoved looking up and injecting every @In member with an interceptor, which could kill performance in some situations.

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

                          Also, it allows concurrent calls on a bean.  Seam's injection model fundamentally requires single-threaded access to components that use @In.  Even then, re-entrancy can cause unexpected results.



                          For what it's worth, if anyone really wanted seam-style injection in CDI, they could implement it with an interceptor.

                          • 40. Re: Implementing the same of @RequestParameter in WELD
                            pmuir

                            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.


                            Just checked, it does :-)

                            • 41. Re: Implementing the same of @RequestParameter in WELD
                              pmuir

                              Matt Drees wrote on Jan 04, 2010 15:18:



                              Nicklas Karlsson wrote on Jan 04, 2010 09:53:


                              Is that running code? I would assume there is no injection into servlet listeners and you would have to get the manager from JNDI and fire it yourself?



                              Well, I think it should run in an EE 6 environment.  The spec requires support injection in servlet listeners.  So it should run in glassfish.  I don't think jboss will run it yet, since jboss 6 m1 doesn't support servlet 3.


                              JBoss M1 does support injection into Servlet listeners. Matt, why is it dependent on Servlet 3? Have I missed a trick about how to implement this in Servlet 3?

                              • 42. Re: Implementing the same of @RequestParameter in WELD
                                swd847

                                Back to the original topic, the reason why the example is not working is because the RequestParamProducer.produceHttpParam is @Dependant scoped (the default). This means that the object is effictivly session scoped if you are injecting it into a session scoped bean.


                                Also as only @Dependent scoped producer allow you to get a reference to the InjectionPoint changing the scope will not fix it either. One massively overkill solution is to write a PE that registers a separate producer for every distinct instance of @RequestParam it encounters, the other way would just be to initilise RequestParam with the name of the parameter, and just do the lookup whenever anyone calls getValue.


                                Also you could make RequestPram generic and by examining the field.getGenericType() in the producer method perform basic conversions to Integer etc.

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

                                  I chose a mix:


                                  @Inject Parameter<String> id;
                                  



                                  where a PE reannotate fields with @Inject annotation and Parameter class, adding a @Param("id") annotation behind the scenes.



                                  But this approach only works for primitive types (Integer, String, etc...). Instead I would like to inject every type:



                                  @Inject @Param("uid") @Converter(...) User user;
                                  



                                  For this use case I need to register a producer bean for every annotated field (with @Pram, @Inject, and not Parameter type).
                                  But I could have also this situation:


                                  @Inject @Param("uid1") @Converter(...) User user1;
                                  @Inject @Param("uid2") @Converter(...) User user2;
                                  



                                  Here we have two producer with @Param qualifier and type User. This throw an ambiguous resolution exception.


                                  At this point I have to add annotations with a PE tot resolve the ambiguities.


                                  This is quite hard to do ;). I would like to use the Reannotated utility that are in the Weld extension sources, but they are still undocumented and I didn't give a deep look.




                                  • 44. Re: Implementing the same of @RequestParameter in WELD
                                    kenglxn

                                    This really isn't a problem.
                                    You just put the injection into a RequestScoped bean. If you need to get Something from a SessionScopedBean, then inject it as well.




                                    @Qualifier
                                    @Retention(RUNTIME)
                                    @Target({TYPE, METHOD, FIELD, PARAMETER})
                                    public @interface HttpParam {
                                        public String value() default "";
                                    }





                                    public class HttpParamProducer {
                                    
                                        @Inject
                                        FacesContext facesContext;
                                    
                                        @Produces
                                        @HttpParam
                                        String getHttpParameter(InjectionPoint ip) {
                                            String name = ip.getAnnotated().getAnnotation(HttpParam.class).value();
                                            if ("".equals(name)) name = ip.getMember().getName();
                                            return facesContext.getExternalContext()
                                                    .getRequestParameterMap()
                                                    .get(name);
                                        }
                                    }




                                    @RequestScoped
                                    public class TrackProducer {
                                    
                                        @Inject @HttpParam
                                        String trackId;
                                    
                                        @Inject
                                        SpotifyWeb spotifyWeb;
                                    
                                        @Produces
                                        @Named("trackReqParam")
                                        String getTrack() {
                                            return spotifyWeb.wrap(trackId);
                                        }
                                    }



                                    In this example spotifyWeb is a SessionScoped bean.
                                    Works well using Weld 1.0.1-CR1

                                    1 2 3 Previous Next