1

I have got this site:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.prime.com.tr/ui">

<h:head></h:head>
<h:body>


    <h:form id="form-some">
        <h:inputText id="copingFilePhaseFocus">
            <p:ajax event="focus" actionListener="#{installationController.startCopyingWarFile}" />
        </h:inputText>
    </h:form>


</h:body>
</html>

And backing bean:

@ManagedBean(name = "installationController")
@SessionScoped
public class InstallationController implements IPluginInstallationListener {

    // Some methods here (...)

    public void startCopyingWarFile(ActionEvent event) {
        System.out.println("\n\n\n\nStarted\n\n\n\n");
    }
}

This code was working under MyFaces 2.0.0. But under MyFaces 2.0.2 or Mojarra 2.0.2 does not. By telling "does not work" I mean that clicking (focusing) input text does not triggering actionListener (Text "Started" does not appear on standard output). Has anybody similar problem ?

EDIT 1 (After changing p:ajax to f:ajax):

    <p:outputPanel id="copingFilePhase">
        <p:accordionPanel speed="0.2"
            rendered="#{pluginInstallerWebBean.copingFilePhase}">
            <p:tab
                title="#{msg['installPlugin.copyingWar']} ... #{pluginInstallerWebBean.copingFilePhaseState}">
                <h:form prependId="false">
                    <p:focus for="copingFilePhaseFocus" />
                    <h:inputText id="copingFilePhaseFocus"
                        rendered="#{pluginInstallerWebBean.copingFilePhaseFocus}"
                        style="display:none;">
                        <f:ajax event="focus"
                            render="copingFilePhase obtainingPluginInformationPhase"
                            listener="#{installationController.startCopyingWarFile}" />
                    </h:inputText>
                </h:form>
                #{msg['installPlugin.copyingWarDescription']}
            </p:tab>
        </p:accordionPanel>
    </p:outputPanel>

    <p:outputPanel id="obtainingPluginInformationPhase">(...)</p:outputPanel>

And the error is:

javax.faces.FacesException: contains an unknown id 'copingFilePhase' - cannot locate it in the context of the component copingFilePhaseFocus

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
Kamil Sobon
  • 45
  • 2
  • 7

1 Answers1

4

This can have two causes:

  1. The Primefaces resource servlet is not properly configured which will cause that the necessary JavaScripts won't be loaded. You should be able to see it by checking the JS error console in your webbrowser for any JS errors when focusing the input. In Firefox, the console is available by pressing Ctrl+Shift+J.

    The resource servlet will be loaded automatically in Servlet 3.0 environments (Glassfish v3, Tomcat 7, JBoss 6, etc), however in older environments, you need to configure it manually in web.xml:

    <servlet>
        <servlet-name>PrimeFaces Resource Servlet</servlet-name>
        <servlet-class>org.primefaces.resource.ResourceServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>PrimeFaces Resource Servlet</servlet-name>
        <url-pattern>/primefaces_resource/*</url-pattern>
    </servlet-mapping>
    
  2. The method signature is wrong. You should be able to see it by reading the server logs and seeing a javax.el.MethodNotFoundException in the logs. The code example in your question is correct, but there's ambiguity in ActionEvent. There's a class with the same name in java.awt.event package. You might have accidently (auto-)imported it. Verify if it is indeed javax.faces.event.ActionEvent and not something else.

If none helps, you may want to consider to replace the PrimeFaces p:ajax by the standard JSF 2.0 f:ajax:

<f:ajax event="focus" listener="#{installationController.startCopyingWarFile}" />

with

public void startCopyingWarFile(AjaxBehaviorEvent event) {
    // ...
}

where AjaxBehaviorEvent is javax.faces.event.AjaxBehaviorEvent.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Ad. 1: I've got appropriate entries in my web.xml file. Ad. 2: It is also not an issue. I'm importing javax.faces.event.ActionEvent for sure and there is no entry about error in my log files. f:ajax seem to be working right. But in f:ajax instead of "update" attribute there is "render". Can "render" renders component outside its h:form component ? I have got an error that cannot find component "copingFilePhase". I will attach code in my original question (EDIT: code attached). – Kamil Sobon Dec 04 '10 at 17:21
  • Could you write an example ? I not really understand your tip ;) – Kamil Sobon Dec 04 '10 at 18:34
  • The `render` is relative to the current `UINamingContainer` parent (which is `` in your case, see also generated HTML output). If you prefix with `:`, it'll be absolute to the root. So, in your specific case: `render=":copingFilePhase :obtainingPluginInformationPhase"` – BalusC Dec 04 '10 at 18:38
  • I understood you in complete opposite way and I typed render="copingFilePhase: obtainingPluginInformationPhase:". Your solution actually helped ;) Thanks a lot again. But I have one more question. Do you know a way to invoke some asynchronous method (via ajax) when one ajax call will return ? I mean chain of invocation. I have quite funny hack in my code. I invoke some method, and when it return it change some render flag and update some component. In that component sets focus for some hidden input form (style="display:none") that invokes another method via ajax. – Kamil Sobon Dec 04 '10 at 19:06
  • As it turns out p:ajax works fine with JSF > 2.0.0 but we need to specify components to update properly. The best way is to specyfy while path to component parentForm:parentUI:toUpdateUI – Kamil Sobon Dec 14 '10 at 16:07