8 Replies Latest reply on Mar 23, 2009 10:30 PM by vinitadhopia

    Renderer adding "project" directory at the front of h:graphicImage url

    bradleydouglas

      In our app we use an injected Renderer to generate xhml content for mail etc.  Since uprading to 2.1 our all the URLs generated by h:graphicImage tags are being gerated with a bogus project directory in them.  For examlpe the following tag:



      <h:graphicImage id="orgLogoImage" url="/servlet/fileServlet?id=1" 
          rendered="#{!empty generatingOrg.logo and documentGenerationDocument.includeLogo and documentGenerationDocument.logoAlignment.string == 'LEFT'}"/>



      is generating this IMG HTML:


      <img id="orgLogoImage" src="../../../../project/servlet/fileServlet?id=1" alt="" />



      Does anyone know why project would start appearing in the src URLs in 2.1?


      Thanks,
      Brad

        • 1. Re: Renderer adding "project" directory at the front of h:graphicImage url
          bradleydouglas

          Here I go again replying to my own post......


          I've did a grep across all the seam code base and found the following gem in the MockHttpServletRequest class:


          public String getContextPath()
             {
                return "/project";
             }



          I just set a break point in there, then rendered our page, and it's definately being invoked.  Here is the invocation stack:


          MockHttpServletRequest.getContextPath() line: 135     
          ExternalContextImpl.getRequestContextPath() line: 312     
          GeneratedMethodAccessor247.invoke(Object, Object[]) line: not available     
          DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: not available     
          Method.invoke(Object, Object...) line: not available     
          BeanELResolver.getValue(ELContext, Object, Object) line: 62     
          FacesCompositeELResolver(CompositeELResolver).getValue(ELContext, Object, Object) line: 53     
          FacesCompositeELResolver.getValue(ELContext, Object, Object) line: 72     
          AstPropertySuffix.getValue(Object, EvaluationContext) line: 53     
          AstValue.getValue(EvaluationContext) line: 67     
          ValueExpressionImpl.getValue(ELContext) line: 186     
          ELText$ELTextVariable.toString(ELContext) line: 174     
          ELText$ELTextComposite.toString(ELContext) line: 115     
          AttributeInstruction.write(FacesContext) line: 49     
          UIInstructions.encodeBegin(FacesContext) line: 39     
          JSF.renderChild(FacesContext, UIComponent) line: 172     
          JSF.renderChildren(FacesContext, UIComponent) line: 163     
          RendererRequest.renderFacelet(FacesContext, Facelet) line: 103     
          RendererRequest.run() line: 73     
          FaceletsRenderer.render(String) line: 43     
          DocumentGenerationActionBean.generateDocument(Document, ReservationCustomer, boolean) line: 920



          Is this a bug? Is there anyway to get around it?

          • 2. Re: Renderer adding "project" directory at the front of h:graphicImage url
            bradleydouglas

            Ok, more info.


            It looks to me like this is caused by the new RendererRequest class.  It has a MockHttpServletRequest member variable, and in it's init() routine it looks like the origial context is set aside and a new one created with this mock request:


            private void init()
               {
                  request = new MockHttpServletRequest(HttpSessionManager.instance());
                  response = new MockHttpServletResponse();
                  
                  // Generate the FacesContext from the JSF FacesContextFactory
                  originalFacesContext = FacesContext.getCurrentInstance();
                  facesContext = RendererFacesContextFactory.instance().getFacesContext(request, response);
                  DelegatingFacesContext.setCurrentInstance(facesContext);
            
                  ...



            As I've shown above the MockHttpServletRequest always returns /project.


            So that explains it, but is this a known things?  Is it something I can work around in 2.1?

            • 3. Re: Renderer adding "project" directory at the front of h:graphicImage url
              alxs.alxs.gmx.de

              Hi,


              I've faced similar problems with RendererRequest. When sending the email fails it leavs the MockHttpServletRequest in place and the next page is also rendered with /project in all generated links (JIRA 3698). I too do not understand why the Mock... classes are used inside the RendererRequest.


              Maybe you can workaround this for now by generating the URL before your bean calls the renderer and put it in a context by the Contexts.getXXContext().set() method. To turn rendering on/off you can use <s:fragment> around a plain <img> tag.


              Alex

              • 4. Re: Renderer adding "project" directory at the front of h:graphicImage url
                bradleydouglas

                Thanks for the info and hint.  I've got a workaround now.....


                I've added the following code in my action bean which calculates the full URL and sets it in the context:


                final HttpServletRequest request =
                    (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
                final String logoUrl = request.getContextPath() + "/servlet/fileServlet?id="
                                + generatingOrg.getLogo().getIdLazyFix();
                Contexts.getEventContext().set("orgLogoUrl", logoUrl);



                Then in the page I use at straight IMG tag like you said:


                <img id="orgLogoId" src="#{orgLogoUrl}"/>



                I'm amazed this wasn't picked up in test 2.1 before it went production ready.

                • 5. Re: Renderer adding "project" directory at the front of h:graphicImage url
                  joblini

                  Hi Brad,


                  It is great that you found a workaround for this.  The preferred way to get the context path is


                  FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath()



                  Apart from being more concise, this will avoid the cast to HttpServletRequest, which can cause problems, for example, when running in a portal server environment.

                  • 6. Re: Renderer adding "project" directory at the front of h:graphicImage url
                    bradleydouglas

                    Hi Ingo,


                    Yep - I did tried it - but it ended up even worse.  The call to


                    FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath()



                    also eventually hit the MockHttpServletRequest to get the path which resulted in /project, and then the renderers appeared to hit it again to get work out the relative aspects of the URL/value attributes of the h:graphicImage tag.


                    Long story short, I ended up with /project/project in the src when I used it.  Crazy stuff.

                    • 7. Re: Renderer adding "project" directory at the front of h:graphicImage url
                      bradleydouglas

                      Ignore this last post - replied too fast for my own good.  I'm sure that would have worked before we got into the crazy MockXXX classes in the render context.  Will change our code in accord with your suggestion.


                      Thanks,
                      Brad

                      • 8. Re: Renderer adding "project" directory at the front of h:graphicImage url
                        vinitadhopia

                        We are having the same problem, in a simpler approach (using a static /img directory instead of a
                        file servlet). The ContextURL is coming out as /project, even though we've tried both



                        String contextURL = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath()
                        



                        and



                        final HttpServletRequest request =
                                      (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
                        final String contextURL = request.getContextPath();




                        Either followed by



                        Contexts.getEventContext().set("ourActualContextPath", contextURL);
                        



                        And in the rendered email, using



                        <h:graphicImage value="#{ourActualContextPath}/img/IMS_home_pic.jpg" alt="TCP" />
                        



                        But the email is still coming through with <img src=".../project/img/IMS_home_pic.jpg"/>


                        where the ... is the urlBase (just the server name and port number).


                        In short, the workaround given earlier in this thread does not appear to work.


                        Is there some way to get rid of the /project/ part?