5

I "inherited" a JSF 2 (JSF 2.2.7) application in my company and facing a java.lang.IllegalStateException because two component seem to have the same ID.

The structure of the view is as follows (I extracted the relevant code for illustration purpose, it may contain some typos/invalid syntax as I changed some names):

<p:commandButton id="editButton"
   action="#{controller.prepareItem()}"
   update=":itemEditDlg" oncomplete="PF('itemtEditDlg').show()" />


<comp:editItemDlg id="itemEditDlg"  />

<p:dialog id="anotherDlg" >
   <h:form id="anotherForm">
      <c:forEach items="#{controller.allArgs}" var="arg" >
         <!-- next line is the problem -->
         <comp:mycomponent arg="#{arg}"  />
      </c:forEach>
   </h:form>
</p:dialog>

mycomponent.xhtml looks as follows:

<cc:interface>
    <cc:attribute name="arg" required="true" />
</cc:interface>
<cc:implementation>
    <p:inputText id="argValue" value="#{cc.attrs.arg}" />
    <p:message id="argValueMessage" for="argValue" />
</cc:implementation>

Important: The mycomponent component is also used inside editItemDlg (in the same manner as in "anotherDlg"), i.e. within an dialog and forEach-loop)

If I click the editButton, I get:

java.lang.IllegalArgumentException: Component ID anotherForm:j_idt192:argValue  
has already been found in the view.

Its rather strange because the "anotherDlg" is not openend in this case, but apparently already rendered.

I get the following info in the StackTrace (only relevant parts shown):

         +id: j_idt192
             type: javax.faces.component.UINamingContainer@399bd0dc
              +id: j_id2
               type: javax.faces.component.UIPanel@24ad3910
                +id: argValue  <===============
                 type: org.primefaces.component.inputtext.InputText@687d5c3f
                +id: argValueMessage
                 type: org.primefaces.component.message.Message@7e3361b0
                +id: argValue  <===============
                 type: org.primefaces.component.inputtext.InputText@5f52aa8a
                +id: argValueMessage
                 type: org.primefaces.component.message.Message@2c3a7aea

So somehow these component get rendered twice, but I cannot figure out why.

I've gone trough SO answer but I cant really determine which of the listed causes is the issue in my case. I don't use any bindings.

What I tried so far: played around with setting id excplicitly, i.e. surrounding mycomonent with , passing loop-counters as ID to the component etc.. with no success. I think the problem cannot be solved within mycomponent . The only workaround I found was to make a physical copy of mycomponent and refer to that copy in my anotherForm (such that editItemDlg and anotherDlg do not use the same components).

Any help is appreciated

Raphael Roth
  • 26,751
  • 15
  • 88
  • 145
  • Upon closer inspection, the tree in the stack trace is indeed fishy. The composite component's implementation is duplicated back into the very same composite instance. This is not right. The cause of that problem is not visible in the information provided so far. Please post the problematic code in MCVE format (http://stackoverflow.com/tags/jsf/info) and also try upgrading Mojarra to latest (currently 2.2.12) to exclude an already fixed bug from being the cause. – BalusC Oct 22 '15 at 06:55
  • @BalusC with 2.2.12 same problem. I think I need some time to create a minimal project that actually runs. – Raphael Roth Oct 22 '15 at 08:30
  • I am facing the same problem with Mojarra 2.2.7. Any progress with the issue? – David Goshadze Dec 08 '15 at 15:58
  • What seems starange to me is that sequence of generated ids is broken. Comment is too restrictive to paste component tree dump here, but in a nutshell - a see generated compontnt ids are in perfect order from j_idt1 to j_idt65 then they suddenly break to j_idt311 then continue with j_idt66. And at this very place duplicate id found marker is shown. – David Goshadze Dec 08 '15 at 16:16
  • @BalusC I attemped to reproduce the error in a simple MCVE project, but I failed to do so... – Raphael Roth Dec 09 '15 at 07:13
  • @RaphaelRoth I have the same issue. Did you solved it? – Peter Šály Dec 28 '16 at 18:26
  • @RaphaelRoth in my case it happens after ajax request (p:remoteCommand), when nesting components inside other component, which is used multiple times on same page. – Peter Šály Dec 29 '16 at 09:19

2 Answers2

0

You should not assign an id for your input text on your component.

If you are looping through an array on your form, it's certain that your input text element will be created more than once.

The specified identifier must be unique among all the components (including facets) that are descendents of the nearest ancestor UIComponent that is a NamingContainer, or within the scope of the entire component tree if there is no such ancestor that is a NamingContainer.

As stated on UINamingContainer.

Let's consider that your controller.allArgs has two items on list.

Your generated output:

<form id="anotherForm">
   <input type="text" id="**argValue**">
   <p:message>
   <input type="text" id="**argValue**">
   <p:message>
</form>

And this'll cause a duplicated id exception.

You could create a new naming container to keep your input id unique or append an index information on your add.

Bruno
  • 709
  • 4
  • 11
  • "You should not assign an id for your input text on your component" : I thought I needed that ID because p:message must refer to a component by the for-attribute? – Raphael Roth Oct 21 '15 at 12:52
  • yout generated pseude html-code is not correct. The id of the input-field consists of several componets, ":argValue" is just the last one. Therefore I don't see a Problem in specifying these IDs in my component. – Raphael Roth Oct 21 '15 at 13:07
  • Looking at your stack trace, you have the following JSF component tree: +id: j_idt192 (Naming Container) +id: j_id2 (Panel) +id: argValue (input text) +id: argValueMessage (message) +id: argValue (input text) +id: argValueMessage (message) You have duplicated ids below the same parent. There is nothing wrong with the pseudocode. Balusc answer gives a better overall solution to your problem. Please disregard the suggestion to take the id of your input text but have a closer look on how your structure had been created. – Bruno Oct 21 '15 at 13:11
  • ok, makes sense. But how can I use p:message for a specific inputText field without giving it an ID to which I can refer to? – Raphael Roth Oct 21 '15 at 13:15
  • Hmm I read your comment on Balusc answer and I think that is easier to handle layout issues than create a logic to generate your client ID manually. I would not recommend that approach but this answer could help you in that way: http://stackoverflow.com/questions/16043218/refer-to-jsf-dynamically-generated-ids-based-on-iteration-index – Bruno Oct 21 '15 at 13:34
0

What you have right now is multiple JSF components with the same ID, which is not going to work..

When dynamically generating components you have to append some kind of an iteration index to the respective ids.

<p:inputText id="argValue_#{bean.counter}" value="#{cc.attrs.arg}" />
    <p:message id="argValueMessage_#{bean.counter}" for="argValue" />

The best thing you can do though is remove the id tag completely and let JSF auto-generate them.

If, of course you do not refence those ids from somewhere else.

cristianhh
  • 128
  • 12