p:media NullPointerException at MediaRenderer.encodeEnd

UI Components for JSF
ActionAdi
Posts: 26
Joined: 14 Nov 2019, 11:31

30 Jun 2020, 10:58

Hello everyone,

I am trying to display a dynamic media file on a dialog opened from a files datatable. I am using primefaces 7. I get the famous nullpointer, I am lost, I overrided the MediaRenderer.java. I have the following:

cFileController.java

Code: Select all

@Named("cFileController")
@ApplicationScoped
public class CFileController implements Serializable {
   public StreamedContent getAsdf() {
        FacesContext context = FacesContext.getCurrentInstance();
        if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
            // So, we're rendering the HTML. Return a stub StreamedContent so that it will generate right URL.
            return new DefaultStreamedContent();
        } else {
            String location = "C:/Utils/apache-tomee-7.0.5/apache-tomee/webapps/[redacted]/resources/sounds/files/";
            InputStream stream = this.getClass().getResourceAsStream(location + videoFileName);
            return new DefaultStreamedContent(stream, "video/quicktime");
        }
    }
}
cFile/List.xhtml

Code: Select all

<h:form id="CFileListForm">
<p:dataTable id="datalist" value="#{cFileController.lazyDataModel}" var="item"
                                         selectionMode="single" selection="#{cFileController.selected}"
                                         paginator="true" rowIndexVar="rowIndex"
                                         paginatorTemplate=" {PreviousPageLink} {CurrentPageReport} {NextPageLink}  {RowsPerPageDropdown}"
                                         paginatorPosition="bottom"
                                         rowKey="#{item.id}"
                                         rows="25"
                                         rowsPerPageTemplate="10,20,25, 30,40,50, 100"
                                         resizableColumns="true"
                                         draggableColumns="true"
                                         scrollable="true" scrollHeight="73%"
                                         filteredValue="#{cFileController.filteredItems}"
                                         lazy="true"
                                         multiViewState="true"
                                         widgetVar="cTable"
                                         editable="true" >
                              <p:column width="10%">
                                    <f:facet name="header">
                                        <h:outputText value="Actions"/>
                                    </f:facet>
                                    <p:commandButton id="tButton" icon="fa fa-comments" process="@this"
                                                      update=":TForm"
                                                     oncomplete="PF('tDlg').show()" action="#{cFileController.setVideoFileName(item.name)}"
                                                     actionListener="#{cFileController.setSelected(item)}"/>
                                    <p:tooltip id="toolTipFade5" for="tButton" value="Transcript" position="top"/>
                              </p:column>
</h:form>
 <ui:include src="T.xhtml"/>
T.xhtml (the file with the dialog that displays p:media)

Code: Select all

<ui:composition>
    <h:form id="TForm">
    <p:dialog id="TDlg" widgetVar="tDlg"  modal="true" resizable="false" appendTo="@(body)" header="Transcript">
        <p:media value="#{cFileController.asdf}" width="190" height="250"  player="quicktime">
            <f:param name="autoPlay" value="false" />
        </p:media>
     </p:dialog>
    </h:form>
</ui:composition>
faces-config.xml

Code: Select all

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
              xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
    <application>
...
<render-kit>
        <renderer>
            <component-family>org.primefaces.component.media</component-family>
            <renderer-type>org.primefaces.component.media.MediaRenderer</renderer-type>
            <renderer-class>[redacted].MediaRendererOverride</renderer-class>
        </renderer>
    </render-kit>
</faces-config>
MediaRendererOverride.java

Code: Select all

public class MediaRendererOverride extends MediaRenderer {
    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
        Media media = (Media) component;
        MediaPlayer player = resolvePlayer(context, media);
        ResponseWriter writer = context.getResponseWriter();
        String src;
        try {
            src = getMediaSrc(context, media);
        }
        catch (Exception ex) {
            throw new IOException(ex);
        }
        boolean isIE = AgentUtils.isIE(context);
        String sourceParam = player.getSourceParam();

        Object value = media.getValue();
        if (value instanceof StreamedContent && "application/pdf".equals(player.getType())) {
            StreamedContent streamedContent = (StreamedContent) value;
            if (streamedContent.getName() != null) {
                int index = src.indexOf("?");
                src = src.substring(0, index) + ";/" + streamedContent.getName() + "" + src.substring(index, src.length());
            }
        }

        String type = player.getType();
        if (type != null && type.equals("application/pdf")) {
            String view = media.getView();
            String zoom = media.getZoom();

            if (view != null) {
                src = src + "#view=" + view;
            }

            if (zoom != null) {
                src += (view != null) ? "&zoom=" + zoom : "#zoom=" + zoom;
            }
        }

        writer.startElement("object", media);
        writer.writeAttribute("type", player.getType(), null);
        writer.writeAttribute("data", src, null);

        if (isIE) {
            encodeIEConfig(writer, player);
        }

        if (media.getStyleClass() != null) {
            writer.writeAttribute("class", media.getStyleClass(), null);
        }

        renderPassThruAttributes(context, media, HTML.MEDIA_ATTRS);

        if (sourceParam != null) {
            encodeParam(writer, player.getSourceParam(), src, false);
        }

        for (UIComponent child : media.getChildren()) {
            if (child instanceof UIParameter) {
                UIParameter param = (UIParameter) child;

                encodeParam(writer, param.getName(), param.getValue(), false);
            }
        }

        renderChildren(context, media);

        writer.endElement("object");
    }
}
And the error:
30-Jun-2020 11:37:45.298 1100 [http-nio-8680-exec-8] com.sun.faces.context.ExceptionHandlerImpl.log JSF1073: java.lang.NullPointerException caught during processing of RENDER_RESPONSE 6 : UIComponent-ClientId=, Message=null
30-Jun-2020 11:37:45.298 1100 [http-nio-8680-exec-8] com.sun.faces.context.ExceptionHandlerImpl.log No associated message
java.lang.NullPointerException
at org.primefaces.component.media.MediaRenderer.encodeEnd(MediaRenderer.java:61)
at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:619)
at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:87)
at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:69)
Primefaces 7
JSF 2.2.12
TomEE 7.0.5

Melloware
Posts: 3717
Joined: 22 Apr 2013, 15:48

30 Jun 2020, 13:47

Yep those NPE's have been fixed in Media if you update to PF 7.0.13 Elite or to PF 8.0.

See all the tickets closed on Media: https://github.com/primefaces/primeface ... s%3Aclosed
PrimeFaces Developer | PrimeFaces Extensions Developer
GitHub Profile: https://github.com/melloware
PrimeFaces Elite 13.0.0 / PF Extensions 13.0.0
PrimeReact 9.6.1

ActionAdi
Posts: 26
Joined: 14 Nov 2019, 11:31

30 Jun 2020, 13:55

Hi Melloware,

Thank you for your answer. Unfortunately all hell breaks loose when I update primefaces. I prefer to keep it at 7.0 for now :D .
I was hoping for that quick fix with overriding the Renderer.
Primefaces 7
JSF 2.2.12
TomEE 7.0.5

Melloware
Posts: 3717
Joined: 22 Apr 2013, 15:48

30 Jun 2020, 14:17

Yep just look at the current Source for MediaRenderer and copy it in your project and override in Faces-config. the latest MediaRenderer has all the fixes.

See: https://github.com/primefaces/primeface ... derer.java
PrimeFaces Developer | PrimeFaces Extensions Developer
GitHub Profile: https://github.com/melloware
PrimeFaces Elite 13.0.0 / PF Extensions 13.0.0
PrimeReact 9.6.1

kukeltje
Expert Member
Posts: 9605
Joined: 17 Jun 2010, 13:34
Location: Netherlands

30 Jun 2020, 14:46

ActionAdi wrote:
30 Jun 2020, 13:55
Unfortunately all hell breaks loose when I update primefaces.
Out of curiosity... where does it break loose?

ActionAdi
Posts: 26
Joined: 14 Nov 2019, 11:31

30 Jun 2020, 14:55

kukeltje wrote:
30 Jun 2020, 14:46
ActionAdi wrote:
30 Jun 2020, 13:55
Unfortunately all hell breaks loose when I update primefaces.
Out of curiosity... where does it break loose?
On lazyModel, I updated the load() method to 8.0 version, I was hoping for a quick fix.
Primefaces 7
JSF 2.2.12
TomEE 7.0.5

ActionAdi
Posts: 26
Joined: 14 Nov 2019, 11:31

30 Jun 2020, 14:58

Melloware wrote:
30 Jun 2020, 14:17
Yep just look at the current Source for MediaRenderer and copy it in your project and override in Faces-config. the latest MediaRenderer has all the fixes.

See: https://github.com/primefaces/primeface ... derer.java
I used that version, had to create the PDFPlayer too, I still get the same error, I think my code is wrong or something. :cry:
Primefaces 7
JSF 2.2.12
TomEE 7.0.5

Melloware
Posts: 3717
Joined: 22 Apr 2013, 15:48

30 Jun 2020, 15:02

Yeah you should be able to debug the NPE and where it is and what is NULL.
PrimeFaces Developer | PrimeFaces Extensions Developer
GitHub Profile: https://github.com/melloware
PrimeFaces Elite 13.0.0 / PF Extensions 13.0.0
PrimeReact 9.6.1

ActionAdi
Posts: 26
Joined: 14 Nov 2019, 11:31

01 Jul 2020, 09:13

Hey,

I've tried a new setup, found something digging the forums, added the following code in the @PostConstruct, also made the class @RequestScoped. I've checked with debugger and it gets values, but still uses the old MediaRenderer.encodeEnd, I was wondering, maybe I didnt override the renderer correctly. Posted the faces-config.xml too. What do you guys think?
Edit: used the debugger, it breaks at the expected row:

Code: Select all

if (value instanceof StreamedContent && player.getType().equals("application/pdf")) {
java.lang.NullPointerException
at org.primefaces.component.media.MediaRenderer.encodeEnd(MediaRenderer.java:61)

src/main/webapp/WEB-INF/faces-config.xml

Code: Select all

<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="2.2"
              xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
    <application>
        <resource-bundle>
            <base-name>/Bundle</base-name>
            <var>bundle</var>
        </resource-bundle>
        <resource-bundle>
            <base-name>/Controls</base-name>
            <var>controls</var>
        </resource-bundle>
        <resource-bundle>
            <base-name>/Controls</base-name>
            <var>validations</var>
        </resource-bundle>
        <resource-bundle>
            <base-name>/Texts</base-name>
            <var>txt</var>
        </resource-bundle>
        <resource-handler>org.omnifaces.resourcehandler.CombinedResourceHandler</resource-handler>
        <resource-bundle>
            <base-name>/Bundle</base-name>
            <var>bundle</var>
        </resource-bundle>
        <resource-bundle>
            <base-name>/Bundle</base-name>
            <var>bundle</var>
        </resource-bundle>
        <resource-bundle>
            <base-name>/Bundle</base-name>
            <var>bundle</var>
        </resource-bundle>
        <resource-bundle>
            <base-name>/Bundle</base-name>
            <var>bundle</var>
        </resource-bundle>
        <resource-bundle>
            <base-name>/Bundle</base-name>
            <var>bundle</var>
        </resource-bundle>
        <resource-bundle>
            <base-name>/Bundle</base-name>
            <var>bundle</var>
        </resource-bundle>
    </application>

    <component>
        <component-type>net.bootsfaces.component.container.Container</component-type>
        <component-class>net.bootsfaces.component.container.Container</component-class>
    </component>

    <component>
        <component-type>net.bootsfaces.component.row.Row</component-type>
        <component-class>net.bootsfaces.component.row.Row</component-class>
    </component>

    <component>
        <component-type>net.bootsfaces.component.column.Column</component-type>
        <component-class>net.bootsfaces.component.column.Column</component-class>
    </component>
    <component>
        <component-type>org.omnifaces.cdi.push.Socket</component-type>
        <component-class>org.omnifaces.cdi.push.Socket</component-class>
    </component>

    <component>
        <component-type>org.omnifaces.component.output.GraphicImage</component-type>
        <component-class>org.omnifaces.component.output.GraphicImage</component-class>
    </component>
    <render-kit>
        <renderer>
            <component-family>org.primefaces.component.media</component-family>
            <renderer-type>org.primefaces.component.media.MediaRenderer</renderer-type>
            <renderer-class>[redacted].MediaRenderer</renderer-class>
        </renderer>
    </render-kit>
</faces-config>

Code: Select all

String location = "C:/Utils/apache-tomee-7.0.5/apache-tomee/webapps/[redacted]/resources/sounds/files/";
        FacesContext context = FacesContext.getCurrentInstance();
        // So, browser is requesting the media. Return a real StreamedContent with the media bytes.
        try {
            Logger.getLogger(this.getClass().getName()).log(Level.INFO,"initMetaData called");

            /**
             * Generate a streamed media content from the media in question
             */
            String id = context.getExternalContext().getRequestParameterMap().get("CFileListForm:datalist_selection");
            CFile cFile = new CFile();
            if (id!=null) {
                cFile = ejbFacade.find(Integer.valueOf(id));
            }
            String path = location+caseFile.getName();
            if (cFile == null) {
                Logger.getLogger(this.getClass().getName()).log(Level.INFO,"Something is not right, the target media is null, will not generate a streamed content");
            } else {
                String name = cFile.getName();
                Logger.getLogger(this.getClass().getName()).log(Level.INFO,"target media has got a target of [" + name + "]");
                if (StringUtils.isEmpty(name)) {
                    Logger.getLogger(this.getClass().getName()).log(Level.INFO,"mediaLink is empty, no streamed content to be generated");
                } else {
                    File targetFile = new File(path);
                    if (targetFile.exists() && !targetFile.isDirectory()) {
                        Logger.getLogger(this.getClass().getName()).log(Level.INFO,"we will now generate a streamed content for the file [" + name + "]");
                        InputStream targetFileInputStream = new BufferedInputStream(new FileInputStream(path));
                        //InputStream targetFileInputStream = this.getClass().getResourceAsStream(path);
                        Logger.getLogger(this.getClass().getName()).log(Level.INFO,"got a not null bytestream");
                        String fileExtension = FilenameUtils.getExtension(targetFile.getName());
                        String contentType = new MimetypesFileTypeMap().getContentType(new File(path));
                        Logger.getLogger(this.getClass().getName()).log(Level.INFO,"file extenstion [" + fileExtension + "] , mimeType [" + contentType + "]");
                        media = new DefaultStreamedContent(targetFileInputStream, contentType,caseFile.getName(),Integer.valueOf((cFile.getFileSize()).toString()));
                        generatePlayerType(fileExtension);
                    } else {
                        Logger.getLogger(this.getClass().getName()).log(Level.INFO,"target file [" + name + "] does not exist, will not generate a streamed content");
                    }
                }
            }

        } catch (Exception e) {
            Logger.getLogger(this.getClass().getName()).log(Level.INFO,"Internal error:", e);

        }

Code: Select all

public StreamedContent getMedia() {
        return media;
    }
MediaRenderer:

Code: Select all

public class MediaRenderer extends org.primefaces.component.media.MediaRenderer {

    @Override
    public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
    .....
    if (value instanceof StreamedContent && PDFPlayer.MIME_TYPE.equals(player.getType())) {
    .... used the new code from 8.0
   } 
}
Primefaces 7
JSF 2.2.12
TomEE 7.0.5

Melloware
Posts: 3717
Joined: 22 Apr 2013, 15:48

01 Jul 2020, 13:25

Your renderkit is wrong try this..

Code: Select all

<renderer>
            <component-family>org.primefaces.component</component-family>
            <renderer-type>org.primefaces.component.MediaRenderer</renderer-type>
            <renderer-class>YOUR CLASS</renderer-class>
</renderer>
PrimeFaces Developer | PrimeFaces Extensions Developer
GitHub Profile: https://github.com/melloware
PrimeFaces Elite 13.0.0 / PF Extensions 13.0.0
PrimeReact 9.6.1

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 25 guests