1 2 Previous Next 23 Replies Latest reply on Nov 16, 2009 12:52 AM by Francisco Jose Peredo Noguez

    How to reach HttpServletRequest and HttpServletResponse from bean?

    Francisco Jose Peredo Noguez Master

      I guess the subject says it all:


      How to reach HttpServletRequest and HttpServletResponse from a Weld bean? (Remember, no JSF dependent tricks please)


      If I were in Seam I guess I would use: ServletContexts.getInstance().getRequest() to obtain the HttpServletRequest.


      Also, in Seam with JSF I would get the HttpServletResponse... using FacesContext.getCurrentInstance().getExternalContext().getResponse() ...but that would be a dependency with JSF...


      Is there an way to do this with Weld out-of-the-box? Or do I need to create my own way?

        • 1. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
          Arbi Sookazian Master

          Good question, but I have a feeling you must use the Servlet API...

          • 2. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
            Nicklas Karlsson Master
            @Produces HttpServletRequest getRequest() {
              return FacesContext....
            

            • 3. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
              Gavin King Master

              Write a servlet filter that binds these objects to the current thread, at the beginning of the request, and cleans them up at the end of the request.


              Are you seriously using, in 2009, a web framework that makes it good practice to access these objects directly??

              • 4. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                Nicklas Karlsson Master

                OK, that it of course more clean but sometimes I can live with myself if I do a quick and dirty look at some request header by accessing it directly ;-)

                • 5. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                  Francisco Jose Peredo Noguez Master

                  Nicklas Karlsson wrote on Nov 15, 2009 07:42:


                  @Produces HttpServletRequest getRequest() {
                    return FacesContext....
                  




                  Thanks, but remember, no JSF for me ( in the weekend ;-) )...

                  • 6. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                    Francisco Jose Peredo Noguez Master

                    Gavin King wrote on Nov 15, 2009 08:09:


                    Write a servlet filter that binds these objects to the current thread, at the beginning of the request, and cleans them up at the end of the request.


                    Yes, that is what I thought, but I was hoping that your would tell me that Weld already had such a filter included... or that I could use a @Produces inside the filter to expose this... or I don't know, some kind of Weldish solution for this... ;-)



                    Are you seriously using, in 2009, a web framework that makes it good practice to access these objects directly??


                    I am trying to port Numberguess to JSP using only what is available in: Weld+Tomcat6(Servlets/JSP)+JSTL+Scala I guess I am trying to create a very basic equivalent
                    of Spring-MVC... but hopefully more elegant because it will be Weld based ;-)

                    • 7. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                      Gavin King Master

                      We're trying to discourage direct access to these objects from beans. We think it's better if your web framework acts as an intermediating layer here. But, of course, it's easy to write a servlet filter and a producer method (or portable extension) that makes these objects available for injection.


                      But, I personally would keep direct access to HttpServletRequest and friends inside the servlet. Remember that with CDI, you won't be needing to get and set request, session and application attributes directly, except in special circumstances.

                      • 8. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                        Francisco Jose Peredo Noguez Master

                        Mmmm.... but, imagen you were given the restriction of using Weld+Tomcat6(Servlets/JSP)+JSTL, and no scriptlet code in you JSPs and you want to process the values of a form submit... the only way to reach the values that were submitted in the from is with direct access to HttpServletRequest...
                        I mean, I basically I need to reinvent something like the @RequestParam annotation of Seam, and there is no way I can do that without direct access to HttpServletRequest...

                        • 9. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                          Gavin King Master

                          Well, if you're coding directly to the servlet API, you have access to the HttpServletRequest in the HttpServlet.doXxxx() methods. Do you really want to propagate the dependency to that very technical interface deeper into your business logic? It's something that I would personally try to avoid.


                          Look, what I'm really trying to say is that this is a line-drawing problem between what is provided built-in to the spec, and what is provided by portable extensions. Right now, no portable extensions exist. In a couple of months I will be able to point you to an easily downloadable jar which has this and plenty more.


                          Now, perhaps we got the line sightly wrong first time around - people are already yelling at me for not supporting injection of FacesContext out-of-the-box - and if so, we can fix it by adding a couple more objects to the list in section 3.6 of the spec. But I did not want to bloat out the spec in the very first release.

                          • 10. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                            Francisco Jose Peredo Noguez Master

                            Gavin King wrote on Nov 15, 2009 18:18:


                            Well, if you're coding directly to the servlet API, you have access to the HttpServletRequest in the HttpServlet.doXxxx() methods. Do you really want to propagate the dependency to that very technical interface deeper into your business logic? It's something that I would personally try to avoid.


                            I agree, but remember, I am not writing only business logic, I creating a mini Weld-MVC... Maybe what I should do is bind HttpServletRequest to a thread local variable in filter (as you suggested) and then write a @Produces method that exposes the form values as a java.util.Map to my org.jboss.weld.examples.numberguess.Game component?



                            Look, what I'm really trying to say is that this is a line-drawing problem between what is provided built-in to the spec, and what is provided by portable extensions.


                            Guess I am writing a mini-portable extensions inside my NumberGuessJPS to to try and hide this details from Game (but in order to hide those details from Game I need to work with them somewhere else)



                            Right now, no portable extensions exist.


                            So I am the first creating one? Whoooa! :-)



                            In a couple of months I will be able to point you to an easily downloadable jar which has this and plenty more.


                            Or maybe I will be able to point you to mine ;-)



                            Now, perhaps we got the line sightly wrong first time around - people are already yelling at me for not supporting injection of FacesContext out-of-the-box - and if so, we can fix it by adding a couple more objects to the list in section 3.6 of the spec.


                            No no, I think the less Weld does, and the more is left to external plugins the better. One thing I did not like about Seam was precisely that for non experts like me it was really hard to draw the line between Core Seam and Seam-Everything-Else. But since Weld has some minor external contamination (for example the ConversationScope source has a comment in source saying it only works for JSF) I was afraid of creating an extension to reach the form values from my component only to find out later that one was already included inside Weld.




                            But I did not want to bloat out the spec in the very first release.


                            Please do not bloat it ever, remember: Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away.. The more specific and to the core is the spec, the better.


                            • 11. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                              Francisco Jose Peredo Noguez Master

                              As a first step, I tried writing a @Produces method that produces a  ServletRequest:


                              @RequestScoped
                              class ServletContexts extends Serializable{
                               
                               @Produces @Request
                               def getServletRequest()={
                                ServletContexts.getServletRequest()
                               }
                                
                               @Produces @Response
                               def getServletResponse()={
                                ServletContexts.getServletResponse()
                               }
                              }
                              
                              object ServletContexts {
                              
                               private var threadLocalRequest = new ThreadLocal[ServletRequest]();
                               private var threadLocalResponse = new ThreadLocal[ServletResponse]();
                               
                               def getServletRequest()={
                                threadLocalRequest.get()
                               }
                               
                               def setServletRequest(request:ServletRequest) {
                                if (request == null) {
                                 threadLocalRequest.remove();
                                }
                                threadLocalRequest.set(request);
                               }
                               
                               def getServletResponse()={
                                threadLocalResponse.get()
                               }
                               
                               def setServletResponse(response:ServletResponse) {
                                if (response == null) {
                                 threadLocalResponse.remove();
                                }
                                threadLocalResponse.set(response);
                               }
                              }
                              



                              and then inject that at my Game class:


                              private var request:HttpServletRequest=null;
                              
                              @Inject
                                def setRequest(@Request newRequest:ServletRequest){
                                  request=newRequest.asInstanceOf[HttpServletRequest];
                                }
                              



                              but I got this error:


                              WELD-000055 Producers cannot produce non-serializable instances for injection into parameters of initializers of beans declaring passivating scope.\\n\\nBean\:  org.jboss.weld.bean-flat-ProducerMethod-org.jboss.weld.examples.common.ServletContexts.getServletRequest()\\nInjection Point\:  parameter 0 of method public void org.jboss.weld.examples.numberguess.Game.setRequest(javax.servlet.ServletRequest)
                              



                              Apparently I can not inject ServletRequest in to Game because Game is SessionScoped and that is a passivating scope. What should I be doing then?

                              • 12. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                                Gavin King Master

                                Try:


                                class ServletContexts {
                                 
                                 @Produces @RequestScoped @Request
                                 def getServletRequest()={
                                  ServletContexts.getServletRequest()
                                 }
                                  
                                 @Produces @RequestScoped @Response
                                 def getServletResponse()={
                                  ServletContexts.getServletResponse()
                                 }
                                
                                }



                                You see why you need to do that, right?


                                • 13. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                                  Francisco Jose Peredo Noguez Master

                                  Mmm, but it is:


                                  @RequestScoped
                                  class ServletContexts {
                                   
                                  }
                                  



                                  if I already have @RequestScoped for all the ServletContexts class, why do I need to add it to the @Produces methods...

                                  • 14. Re: How to reach HttpServletRequest and HttpServletResponse from bean?
                                    Francisco Jose Peredo Noguez Master

                                    Well, it did make a difference, I guess I need @Produces @RequestScoped @Response to indicate that what is being returned by getServletResponse() will be RequestScoped... no more WELD-000055 error for me... but maybe I have hit a Weld/Scala incompatibility?:



                                    java.lang.RuntimeException: by java.lang.NoClassDefFoundError: javassist/util/proxy/ProxyObject
                                         javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:344)
                                         javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:314)
                                         javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:273)
                                         org.jboss.weld.util.Proxies.createProxyClass(Proxies.java:153)
                                         org.jboss.weld.util.Proxies.createProxy(Proxies.java:136)
                                         org.jboss.weld.bean.proxy.ClientProxyProvider.createClientProxy(ClientProxyProvider.java:81)
                                         org.jboss.weld.bean.proxy.ClientProxyProvider.access$000(ClientProxyProvider.java:45)
                                         org.jboss.weld.bean.proxy.ClientProxyProvider$1.call(ClientProxyProvider.java:114)
                                         java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
                                         java.util.concurrent.FutureTask.run(FutureTask.java:138)
                                         org.jboss.weld.util.collections.ConcurrentCache.putIfAbsent(ConcurrentCache.java:125)
                                         org.jboss.weld.bean.proxy.ClientProxyProvider.getClientProxy(ClientProxyProvider.java:104)
                                         org.jboss.weld.BeanManagerImpl.getReference(BeanManagerImpl.java:949)
                                         org.jboss.weld.BeanManagerImpl.getReference(BeanManagerImpl.java:1019)
                                         org.jboss.weld.BeanManagerImpl.getInjectableReference(BeanManagerImpl.java:1041)
                                         org.jboss.weld.injection.ParameterInjectionPoint.getValueToInject(ParameterInjectionPoint.java:93)
                                         org.jboss.weld.injection.MethodInjectionPoint.getParameterValues(MethodInjectionPoint.java:268)
                                         org.jboss.weld.injection.MethodInjectionPoint.invoke(MethodInjectionPoint.java:105)
                                         org.jboss.weld.util.Beans.callInitializers(Beans.java:753)
                                         org.jboss.weld.util.Beans.injectFieldsAndInitializers(Beans.java:740)
                                         org.jboss.weld.bean.ManagedBean$1$1.proceed(ManagedBean.java:219)
                                         org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:51)
                                         org.jboss.weld.bean.ManagedBean$1.inject(ManagedBean.java:213)
                                         org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:141)
                                         org.jboss.weld.context.AbstractMapContext.get(AbstractMapContext.java:108)
                                         org.jboss.weld.bean.proxy.ClientProxyMethodHandler.getProxiedInstance(ClientProxyMethodHandler.java:143)
                                         org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:101)
                                         org.jboss.weld.examples.numberguess.Game_$$_javassist_0.getMessage(Game_$$_javassist_0.java)
                                         sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
                                         sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
                                         sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                                         java.lang.reflect.Method.invoke(Method.java:597)
                                         javax.el.BeanELResolver.getValue(BeanELResolver.java:62)
                                         javax.el.CompositeELResolver.getValue(CompositeELResolver.java:53)
                                         org.apache.el.parser.AstValue.getValue(AstValue.java:118)
                                         org.apache.el.ValueExpressionImpl.getValue(ValueExpressionImpl.java:186)
                                         org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate(PageContextImpl.java:925)
                                         org.apache.jsp.home_jsp._jspx_meth_c_005fout_005f0(home_jsp.java:136)
                                         org.apache.jsp.home_jsp._jspService(home_jsp.java:83)
                                         org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
                                         javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
                                         org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:374)
                                         org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
                                         org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
                                         javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
                                         org.jboss.weld.examples.common.WeldFilter.doFilter(WeldFilter.scala:25)
                                    
                                    



                                    I mean, the javassist/util/proxy/ProxyObject is obviusly there, inside weld-servlet.jar...


                                    This is what I have in my WEB-INF\lib dir:


                                    15/11/2009  12:30 p.m.    <DIR>          .
                                    15/11/2009  12:30 p.m.    <DIR>          ..
                                    13/11/2009  06:58 a.m.            20,682 jstl.jar
                                    13/11/2009  11:42 p.m.           269,699 scala-dbc.jar
                                    13/11/2009  11:42 p.m.         3,789,991 scala-library.jar
                                    13/11/2009  11:42 p.m.           623,359 scala-swing.jar
                                    13/11/2009  06:58 a.m.           393,259 standard.jar
                                    11/11/2009  10:24 p.m.             4,479 weld-api.jar
                                    11/11/2009  10:24 p.m.           551,470 weld-core.jar
                                    11/11/2009  10:24 p.m.             3,915 weld-logger.jar
                                    11/11/2009  10:24 p.m.            20,700 weld-se.jar
                                    11/11/2009  10:24 p.m.            28,712 weld-servlet-int.jar
                                    11/11/2009  10:24 p.m.         2,052,123 weld-servlet.jar
                                    11/11/2009  10:24 p.m.            50,674 weld-spi.jar
                                    11/11/2009  10:24 p.m.            10,156 weld-tomcat-support.jar
                                    



                                    1 2 Previous Next