1

Well, i'm using a ConversationScoped and i hope the PostConstruct is called just one time in begin of conversation, see:

@Named("disciplinaDetalheMB")
@ConversationScoped
public class DisciplinaDetalheMBImpl {

    private static final long serialVersionUID = 1L;

    @Inject
        private Conversation conversation;

    @Inject
    @AnBasicBO
    private BasicBO boPadrao;

@PostConstruct
    public void postConstruct() {
    logger.debug("Iniciando PostConstruct...");
    init();
    beginConversation();
    }

public String salvarAndRedirecionar() {
    salvar();
    if (!FacesContext.getCurrentInstance().isValidationFailed()) {
        return goToLastPage() + "?faces-redirect=true";
    } else {
        return "";
    }
    }


private void beginConversation() {
    if (!conversation.isTransient()) {
        endConversation();
    }
    conversation.begin();
    if (conversation.isTransient()) {
        throw new RuntimeException("A conversão não foi iniciada corretamente");
    }
    SessionContext.getInstance().setAttribute("cid", conversation.getId());

    }

    public BasicBO getBoPadrao() {
        return boPadrao;
    }

    public void setBoPadrao(BasicBO boPadrao) {
        this.boPadrao = boPadrao;
    }

}

So, when my backing bean is created, the conversation is initialized and CID is stored in session to be used after. I have a commandButton "save" in my XHTML and when this button is called the PostConstruct is called again i don't know why:

<h:commandLink
            action="#{managedBeanName.salvarAndRedirecionar()}"
            styleClass="btn btn-info pull-right" value="Salvar">
            <f:ajax execute="@form" />
        </h:commandLink>

I noted the generated HTML is:

<a id="formManterDisciplina:j_idt44:j_idt46" href="#" onclick="mojarra.ab(this,event,'action','@form',0);return false" class="btn btn-info pull-right" name="formManterDisciplina:j_idt44:j_idt46">Salvar</a>

So, I understand the "href=#" avoid the onlick to be executed. I think this is the problem but i dont't know how to fix. Remenber: The salvarAndRedirecionar() method is never called because postConstruct is always called before.

2) I have another question: If i start a conversation and don't end, there is some problem ? Sometimes i don't want to end conversation manually because i just have ONE PAGE, i just start.

Javier Haro
  • 1,255
  • 9
  • 14
Ronaldo Lanhellas
  • 2,975
  • 5
  • 46
  • 92
  • What scope is this class? why not show us more of the class's definition? – John Ament Oct 19 '15 at 01:49
  • This is the *n*th time that one had to remove [java] tag from your [jsf] question. Can you please take that as a hint to not add the [java] tag anymore in a future [jsf] question? Use [java] tag only when you've a problem which is reproducible in a Java application class with `main()` method. If you have such problem, then you should instead reconsider the relevance of [jsf] and other Java EE related tags. – BalusC Oct 19 '15 at 08:29

1 Answers1

4

The reason why you are having this issue is because you are invoking the conversation begin method in the postconstruct method of the conversation scoped bean. So, the conversation will be set to long-running state during the Render Response phase and not before it. The problem is that the CID parameter is rendered on the HTML form element, but at this point the conversation is still in transient state, because the postconstruct method has not still been invoked after the request. The postconstruct method is invoked when redenring the commandLink element, and then is too late, and the HTML form element won't carry the CID parameter:

<form id="yourForm" name="yourForm" method="post" action="/path/to/yourPage.xhtml" enctype="application/x-www-form-urlencoded">

So, the solution consists of moving the conversation begin to a point before the Render Response phase. You can do it with the f:viewAction tag if you are using JSF 2.2 or with the f:event tag if you are using an older version.

And then you will see the CID parameter rendered inside your HTML form element, like so:

<form id="yourForm" name="yourForm" method="post" action="/path/to/yourPage.xhtml?cid=1" enctype="application/x-www-form-urlencoded">

  • If you use f:event tag:

In your page:

<f:metadata>
    <f:event listener="#{disciplinaDetalheMB.initConversation}" type="preRenderView" /> 
</f:metadata>

In your backing bean:

public void initConversation(){
    if (!FacesContext.getCurrentInstance().isPostback() && conversation.isTransient()) {
          conversation.begin();
    }
}
  • If you use f:viewAction tag:

In your page:

<f:metadata>
    <f:viewAction action="#{disciplinaDetalheMB.initConversation}" />
</f:metadata>

In your backing bean:

public void initConversation(){
    if (conversation.isTransient()) {
          conversation.begin();
    }
}

Regarding your second question there is not big problem in not ending a conversation, because it has a timeout like a HTTP session. You can set the timeout value depending on your server resource management strategy and the desired lifetime for an idle conversation. Anyway, when you only have one page you better use a view scoped backing bean.

Javier Haro
  • 1,255
  • 9
  • 14
  • worked very well, thanks. But i can't mix @ ViewScoped (jsf annotation) with @ Named (CDI annotation) , bugs occurs. Can you help me ? – Ronaldo Lanhellas Oct 19 '15 at 22:36
  • If you use JSF 2.2 then use `javax.faces.view.ViewScoped`, but not `javax.faces.bean.ViewScoped`. – Javier Haro Oct 19 '15 at 22:44
  • Now work, thank you again. But i read in some article that is not a good practice mix JSF annotations and CDI Annotations, this is true ? If yes, why ? Work normally without any problems. – Ronaldo Lanhellas Oct 19 '15 at 22:46
  • The best practice is to use only CDI managed beans in your Model. This is why JSF 2.2 has introduced a new "view scoped" scope (javax.faces.view.ViewScoped) using CDI Portable Extension. – Javier Haro Oct 19 '15 at 23:00