0

UPDATE:

Any @ViewScoped and @SessionScoped beans' lifecycles are not what would be expected. That is, they are ending sooner than they should. For instance, when an ajax postback is done where the method returns void neither @ViewScoped or @SessionScoped beans should end, but they do.

After deploying it to our development environment and others testing it, it seems like it only occurs on my machine and when locally ran. No idea why. tc Server 3.1 is what is being used.

I'm leaving the original in case someone comes upon the issue similarly.

Original:

I have a tree that is populated by a ViewScoped that reads data from an XML file and creates TreeNode objects for it. Performance isn't super quick so it being created in the view once is ideal. (Some of the code has been omitted below, the functionality does work though)

@ManagedBean
@ViewScoped
public class FundsXmlTreeBuilder implements Serializable {

    private TreeNode root;

    public FundsXmlTreeBuilder() throws SAXException, IOException, ParserConfigurationException {
        root = new DefaultTreeNode("Root", null);
        buildTree();
    }

    public void buildTree() throws SAXException, IOException, ParserConfigurationException {
        //reads xml file and adds TreeNodes
    }
}

There is another RequestScoped bean that has a method that handles the ajax event of a tree node being selected in the onNodeSelect method. It basically determines how another part of the page will be shown.

@ManagedBean
@RequestScoped
public class FundsXmlDisplay implements Serializable{

    private Fund fund;
    private FundFamily fundFamily;
    private FocusedPortfolioModel model;

    public TreeNode selectedRoot;

    public FundsXmlDisplay() {
        fund = null;
        fundFamily = null;
        model = null;

        selectedRoot = null;
    }

    public void onNodeSelect(NodeSelectEvent event) {
        Object data = event.getTreeNode().getData();

        fund = null;
        fundFamily = null;
        model = null;
        if (data instanceof Fund) {
            fund = (Fund) data;
        } else if (data instanceof FundFamily) {
            fundFamily = (FundFamily) data;
        } else if (data instanceof FocusedPortfolioModel) {
            model = (FocusedPortfolioModel) data;
            model.createPieModel();
        }
    }
}

Here are the main portions of the markup.

<h:body>

    <h:form styleClass="form" id="form1">
        *** For Home Office Use Only
        <br />

        <p:layout id="xmlArea"
            style="min-width:400px;min-height:600px;width:95%;">
            <p:layoutUnit id="xmlTree" position="west" resizable="false"
                closable="false" scrollable="true" size="25%" minSize="40"
                maxSize="400" style="padding:.25em;" header="Funds XML Elements">
                    <p:tree value="#{fundsXmlTreeBuilder.root}" var="node"
                        dynamic="false" selectionMode="single">
                        <p:ajax event="select" update=":form1:xmlDisplay"
                            listener="#{fundsXmlDisplay.onNodeSelect}" />
                        <p:treeNode>
                            <h:outputText value="#{node}" style="font-size:small" />
                        </p:treeNode>
                    </p:tree>
            </p:layoutUnit>

            <p:layoutUnit position="center" header="Element Detail" size="75%">
                <p:scrollPanel id="xmlDisplay" mode="native"
                    style="height:100%;">
                    ...
                </p:scrollPanel>
            </p:layoutUnit>
        </p:layout>
    </h:form>

</h:body>

The issue I am having is that FundsXmlTreeBuilder is recreated after the ajax event is fired, but before the listener. I would expect it to not be recreated at all since, from what I understand, the view is not changing.

There are quite a few rendered attributes in the xmlDisplay area. Not sure if that is relevant. I understand that a view lives when an action method returns null or void, but I don't think the rendered methods being used count as "action methods".

What is also interesting, if I change FundsXmlTreebuilder to be SessionScoped it gets recreated after selecting a node too, which is really what has stumped me.

Hope everything is clear and enough information is given. Thanks!

cfreih
  • 100
  • 4
  • 9
  • the bean in question that is being recreated is FundsXmlDisplay, right? – Mahendran Ayyarsamy Kandiar Jan 05 '16 at 17:05
  • Should've specified. FundsXmlTreeBuilder is the one that is being recreated when I don't expect it to (after ajax event, but before the listener is performed). I will edit the question to make it more clear. – cfreih Jan 05 '16 at 17:11
  • can you replace layout and layoutUnits with plain old divs and css and see what happens? – Mahendran Ayyarsamy Kandiar Jan 06 '16 at 15:00
  • A form around a layout is not the best design. And **don't do any work in a constructor, use an `@PostConstruct` annotated method. Search for a duplicate in SO, it exists – Kukeltje Jan 20 '16 at 08:52
  • Possible duplicate of [Constructor of CDI managed bean is invoked twice while opening the page](http://stackoverflow.com/questions/18911646/constructor-of-cdi-managed-bean-is-invoked-twice-while-opening-the-page) – Kukeltje Jan 20 '16 at 09:00
  • Hmmm the duplicate is not fully correct… need to find another one – Kukeltje Jan 20 '16 at 09:02
  • The requirements have changed a little so I have since removed the layoutUnits. Could you explain why that is such a bad design though? I have tried using `@PostConstruct`, but that method would never call. I feel like it could be related to the beans recreating unexpectedly locally. – cfreih Jan 20 '16 at 18:27
  • Big chance of getting nested forms by accident. Read about the 'god form' here (2nd bullet): http://stackoverflow.com/questions/2118656/commandlink-commandbutton-ajax-backing-bean-action-listener-method-not-invoked – Kukeltje Jan 21 '16 at 13:56

1 Answers1

0

In the web.xml, the <secure> tag needed to be commented out. So it the corresponding section looks like:

<session-config>
    <session-timeout>60</session-timeout>
    <cookie-config>
        <http-only>true</http-only>
<!--        <secure>true</secure> --> <-- Not be set locally -->
    </cookie-config>
    <tracking-mode>COOKIE</tracking-mode>
</session-config>

This tag tells the browser to only send the cookie on HTTPS transmission, which I do not believe to be the case when ran locally.

This is where I found the explanation. A teammate discovered the fix.

cfreih
  • 100
  • 4
  • 9