Search code examples
jsfjakarta-eeweb-applicationsjsf-2primefaces

Why does my Object become null when going from bean to .xhtml page in jsf


I am building a JSF 2.0 Application using primfaces. I have a managed bean that has several objects for different scenarios. In this particular portion of the application I move from a data table/form to a managed bean with an identification number. I pull the information from the database and even have it in the log. However when I make it to the JSF xhtml page the object values are null and I can't seem to figure out why, any help would be great as I am getting no errors, exceptions, or warnings in the logs and all information seems to point to the loading of the data including the log.

JSF Page that I am coming from... jobs.xhtml (I am using jsf 2.2 and primefaces to build this application) From this page the link specifies a job number to be retrieved and the next bean will retrieve that job based on the job number I have it down to just a button that will take you to the primary method and get the information to the next page...

<?xml version="1.0" encoding="ISO-8859-1" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<body>
    <div style="margin-bottom:350px;">
        <p:column>
            <h:form>
                <h:commandButton id="editProject" action="#{editProjects.getProjectForm()}" value="Edit" />
            </h:form>
        </p:column>
    </div>
</body>
</html>

EditProjects.java the backing bean for the editMailerJob.xhtml which will take in the medium id and the job number the medium id will be used to direct the application to the next page and the job number will be used to retrieve a specific job

::::UPDATED::::

package beans;

import java.io.Serializable;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.RossProjectManagement.rpm.objects.MailerProject;

@ManagedBean
@RequestScoped
public class EditProjects implements Serializable {
/**
 * 
 */
private static final long serialVersionUID = -6680733133634363295L;

private final Log LOG = LogFactory.getLog(this.getClass().getName());

// Editable projects
private MailerProject edit_mailer = new MailerProject();
//Changed this to be a static set value
private String mailerProject = "THIS IS THE MAILER STRING";

public int getProjectForm() {

    loadEditMailer();

    return 1;
}

public void loadEditMailer() {
    this.edit_mailer = new MailerProject("REDJ15061005",
            convertDate("2015-06-29"), false, "RickD",
            "RickD and the Gang", "new", true, true, "SPEC", 1, 1, 1,
            "REDJ15061005", "11X17", "SPOT_COLOR", "20,000",
            convertDate("2015-06-30"), convertDate("2015-07-13"),
            convertDate("2015-07-06"), convertDate("2015-07-06"),
            convertDate("2015-07-15"), true, "BDC",
            "someone@example.com", "STANDARD", 7500.00, "CONQUEST",
            "NONE", "JS DIRECT", "NONE");
    //Commented this out to keep the value static
    //setMailerProject(edit_mailer.toString());
    LOG.debug(":::MAILER PROJECT TO STRING::: " + this.mailerProject);
}

public Date convertDate(String date) {
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
    Date date1 = null;
    try {
        date1 = df.parse(date);
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return date1;
}

}

JSF page that I am redirecting to editMailerJob.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<body>
    <div style="margin-bottom: 350px;">
                <h:outputLabel>#{editProjects.edit_mailer}</h:outputLabel>
                <h:outputLabel>Mailer String::: #{editProjects.mailerProject}        </h:outputLabel>

    </div>
</body>
</html>

The log shows that all of the information has been received and loaded but shows no where that the information has been cleaned or the object made anew. I have tried instantiating the object in different places at different times but that didn't work.

Before I leave the bean the object has value, when I get to the page the object has no value, I don't understand why

I then tried loading the information from different places. I have tried changing the scope of the bean from request to view back to request but no luck, (I thought about doing session but I didn't see the benefit as well as I just couldn't see reasoning to put all of that information into the session).

The problem seems to be revolving directly around the bean itself and the getProjectForm Method because at one point the object is loaded and then it just loses all of its information.

All of my values seem to be correct as far as I can tell but none of the information is loading.

I can't seem to wrap my head around the issue so any help would be greatly appreciated. if any more information is needed just let me know.

I hope all of this helps Let me know if I have forgotten anything.

EDITS:::

I have created just a string to see if at any point it would be delivered either, and so far I am still getting nothing, the .xhtml page is reading that it exists but not that it has value. Still working with this if anyone else has a solution it would be awesome, or if you know the solution and could at the least point me in the right direction that would be great also.

UPDATE #2 So I found that if I set the value outside a method it will properly be displayed so it seems to me like the methods are keeping the value from the xhtml page. What is the deal with that, I have getters and setters for the variables I have them declared and defined properly, but for what ever reason the values when loaded by the method are not kept outside the method, the values are not able to be accessed by the xhtml page.

10:00 pm update Found out that if I instantiate the MailerProject object the same way I don't get the same results I still produce an object full of null attribute values.

Any ideas guys?


Solution

  • Start Here - It'll make the rest of this very trivial.

    The Problem

    You're using a @RequestScoped bean, and what you're experiencing is the expected behaviour for beans of that scope. Between the first and the second page, you should understand by now, that you're dealing with two different instances of the editProjects bean : a field you set on the first page, backed by one instance of editProjects will not be available on the destination page, backed by a new instance of editBean.

    To Solve

    While it wasn't mentioned in the answer I linked to, what you need here is the FlashScope, that serves the express purpose of being transitory in nature: use it just to transport "stuff" between two pages/beans/scopes etc. Sorta. To use:

    1. Declare your undying love for the flash scope around the point of origination of the data. In so doing, you're storing your data in the flash scope object, as implicitly provided by JSF, after which you can then navigate away:

      Flash fScope = FacesContext.getCurrentInstance().getExternalContext().getFlash();
      fScope.put("editMailer",edit_mailer);
      
    2. You can then refer to the variable you stored in the flash scope, on the destination page:

      <h:outputLabel>#{flash.edit_mailer}</h:outputLabel>
      

      Like I mentioned earlier, the flash scope is a transitory scope: once the destination page has been rendered and the content of the scope displayed, you can consider the data as good as gone. If you would like to hang on to it for just one page redirect longer, you can specify the keep directive:

      <h:outputLabel>#{flash.keep.edit_mailer}</h:outputLabel>
      

    Unrelated to the problem

    1. Avoid doing any heavy lifting in a getter/accessor method (like you're doing in getProjectForm). It's bad for business

    2. What's the significance of returning "1" from that navigation method? Why not "destination_page", or "edit_page.xhtml", y'know, something easier to read? That's just a style thing anyway, no evil can come of that.