ICEfaces
  1. ICEfaces
  2. ICE-2714

The Description and Source tabs of Component Showcase don't work in portlets

    Details

    • Type: Improvement Improvement
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.7DR#3
    • Fix Version/s: 1.7Beta1, 1.7
    • Component/s: Sample Apps
    • Labels:
      None
    • Environment:
      Portal portlet
    • Affects:
      Sample App./Tutorial

      Description

      The original issue was that that page fragments that were included for each component that generated the IFrames for the Description and Source tabs used relative references to retrieve their content: For example:

      <iframe src="./docs/selectInputTextDoc.html"
                     class="includeIframe"
                     width="100%">
      </iframe>

      This did not work in portlets, so the original fix was to hard code the context to the path to make it absolute. Like this:

      <iframe src="/component-showcase/docs/selectInputTextDoc.html"
                     class="includeIframe"
                     width="100%">
      </iframe>

      Unfortunately, this makes things a bit fragile. If the .war file isn't named exactly right (i.e. component-showcase.war), then the context is incorrect and the IFrame content can't be found. This showed up prominently in Jetspeed 2 were the deployment process requires that the deployed war is prefixed with the term "jetspeed" (i.e jetspeedcomponent-showcase.war).

      So we need a way to dynamically include the context in the src path in a way that works for both portlets and web-apps.

        Activity

        Hide
        Deryk Sinotte added a comment -

        We looked at a number of different solutions to this problem.

        Probably the best solution would be to build an <ice:iframe> component. We may still do this at a later date but we are too late in the current release to tackle that now.

        In a typical JSP page, you'd simply add something like <%= request.getContextPath() %>. However, ICEfaces doesn't process JSP code within it's own parser so this won't work.

        With Facelets, we'd be able to add a JSF expression (much like the JSP solution above) right into the <iframe> markup and have it correctly processed but we're not currently using the Facelets version of component-showcase for portlets so that is not an option.

        What we ended up doing was using an <ice:outputText> component to generate the entire <iframe> markup like this:

        <ice:outputText id="docFrame"
        value="#

        {ctxtUtil['/docs/buttonAndLinksDoc.html']}

        "
        escape="false" />

        The ctxtUtil bean is an application-scoped bean that extends HashMap. This is a creative use of the HashMap API as the text of the resource we want to process can be passed in as a parameter. The bean looks like this:

        package com.icesoft.icefaces.samples.showcase.util;

        import javax.faces.context.ExternalContext;
        import javax.faces.context.FacesContext;
        import java.util.HashMap;

        public class ContextUtilBean extends HashMap {

        private static final String IFRAME_PREFIX = "<iframe src=\"";
        private static final String IFRAME_SUFFIX = "\"class=\"includeIframe\" width=\"100%\"></iframe>";

        public String getContextPath()

        { FacesContext fc = FacesContext.getCurrentInstance(); ExternalContext ec = fc.getExternalContext(); return ec.getRequestContextPath(); }

        public Object get(Object source)

        { return generateMarkup( getContextPath() + source); }

        private static String generateMarkup(String source)

        { StringBuffer markup = new StringBuffer(); markup.append(IFRAME_PREFIX); markup.append(source); markup.append(IFRAME_SUFFIX); return markup.toString(); }

        }

        We are not using the Map for storage, simply to all an easy EL syntax to pass in a value for processing. The returned value is the entire <iframe> markup with the src attribute constructed with the context in front.

        Show
        Deryk Sinotte added a comment - We looked at a number of different solutions to this problem. Probably the best solution would be to build an <ice:iframe> component. We may still do this at a later date but we are too late in the current release to tackle that now. In a typical JSP page, you'd simply add something like <%= request.getContextPath() %>. However, ICEfaces doesn't process JSP code within it's own parser so this won't work. With Facelets, we'd be able to add a JSF expression (much like the JSP solution above) right into the <iframe> markup and have it correctly processed but we're not currently using the Facelets version of component-showcase for portlets so that is not an option. What we ended up doing was using an <ice:outputText> component to generate the entire <iframe> markup like this: <ice:outputText id="docFrame" value="# {ctxtUtil['/docs/buttonAndLinksDoc.html']} " escape="false" /> The ctxtUtil bean is an application-scoped bean that extends HashMap. This is a creative use of the HashMap API as the text of the resource we want to process can be passed in as a parameter. The bean looks like this: package com.icesoft.icefaces.samples.showcase.util; import javax.faces.context.ExternalContext; import javax.faces.context.FacesContext; import java.util.HashMap; public class ContextUtilBean extends HashMap { private static final String IFRAME_PREFIX = "<iframe src=\""; private static final String IFRAME_SUFFIX = "\"class=\"includeIframe\" width=\"100%\"></iframe>"; public String getContextPath() { FacesContext fc = FacesContext.getCurrentInstance(); ExternalContext ec = fc.getExternalContext(); return ec.getRequestContextPath(); } public Object get(Object source) { return generateMarkup( getContextPath() + source); } private static String generateMarkup(String source) { StringBuffer markup = new StringBuffer(); markup.append(IFRAME_PREFIX); markup.append(source); markup.append(IFRAME_SUFFIX); return markup.toString(); } } We are not using the Map for storage, simply to all an easy EL syntax to pass in a value for processing. The returned value is the entire <iframe> markup with the src attribute constructed with the context in front.
        Hide
        Deryk Sinotte added a comment -

        Another suggestion was to use <ice:outputFormat> something like this:

        <ice:outputFormat id="docFrame"
        escape="false"
        value="\<iframe src='

        {0}

        ' class='

        {1}

        ' width='

        {2}

        ' />">
        <f:param value="#

        {ctxtUtil.contextPath}

        /docs/buttonAndLinksDoc.html"/>
        <f:param value="includeIframe"/>
        <f:param value="100%"/>
        </ice:outputFormat>

        However, it appears that you can't have markup in the value as it threw this exception:

        org.xml.sax.SAXParseException: The value of attribute "value" associated with an element type "ice:outputFormat" must not contain the '<' character.

        Show
        Deryk Sinotte added a comment - Another suggestion was to use <ice:outputFormat> something like this: <ice:outputFormat id="docFrame" escape="false" value="\<iframe src=' {0} ' class=' {1} ' width=' {2} ' />"> <f:param value="# {ctxtUtil.contextPath} /docs/buttonAndLinksDoc.html"/> <f:param value="includeIframe"/> <f:param value="100%"/> </ice:outputFormat> However, it appears that you can't have markup in the value as it threw this exception: org.xml.sax.SAXParseException: The value of attribute "value" associated with an element type "ice:outputFormat" must not contain the '<' character.
        Hide
        Deryk Sinotte added a comment -

        I've checked in the ContextUtilBean to the showcase as well as modified versions of all in the .jspx files that create the iframes for the Description and Source tabs so that they use the new strategy. Marking as fixed.

        Show
        Deryk Sinotte added a comment - I've checked in the ContextUtilBean to the showcase as well as modified versions of all in the .jspx files that create the iframes for the Description and Source tabs so that they use the new strategy. Marking as fixed.

          People

          • Assignee:
            Unassigned
            Reporter:
            Deryk Sinotte
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: