0

I want to use the same View for different states of a bean. Therefore I need to Inject/pass/whatever get the current bean I want to modify, but I always get null.

I already tried it with , with @Inject, and the other solutions given in How can I pass selected row to commandLink inside dataTable or ui:repeat?

The View:

import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

import org.primefaces.PrimeFaces;

import de.auticon.beans.Mitarbeiter;
import de.auticon.beans.Skill;

@Named(value = "skillView")
@ViewScoped
public class SkillView implements Serializable {
    private static final long serialVersionUID = -3256509521249071048L;

    private Mitarbeiter employee;

    private Skill skill = new Skill();
    private List<String> expertises = new ArrayList<String>();

    @PostConstruct
    public void init() {
        List<Expertise_String> expertiseObjects = Queries.findAllExpertises();
        for (Expertise_String singleExpertise : expertiseObjects) {
            expertises.add(singleExpertise.getExpertise() + " - " + singleExpertise.getFullNameString());
        }
    }

//Here employee is null, but I need the new/existing employee
    public void addSkill() {
        employee.getSkills().add(skill);
        PrimeFaces.current().dialog().closeDynamic(null);
    }

    public void closeDialog() {
        PrimeFaces.current().dialog().closeDynamic(null);
    }

    public Skill getSkill() {
        return skill;
    }

    public void setSkill(Skill skill) {
        this.skill = skill;
    }

    public Mitarbeiter getEmployee() {
        return employee;
    }

    public void setEmployee(Mitarbeiter employee) {
        this.employee = employee;
    }
}

XHTML from which it is called for existing employees:

   <h:form id="form">
    <p:panelGrid columns="2" styleClass="ui-noborder">
        <p:menu toggleable="true">
            <p:submenu label="Verwaltung">
                <p:menuitem>
                    <p:commandButton value="Mitarbeiter anlegen" action="#{adminView.addNewEmployee}" icon="pi pi-users" 
                            process="@this :form:skillsDialog">
                        <p:ajax event="dialogReturn" listener="#{mitarbeiterView.update}" update=":form, :form:table"/>
                    </p:commandButton>
                </p:menuitem>
            </p:submenu>
        </p:menu>

        <p:dataTable id="table" var="row" value="#{mitarbeiterView.mitarbeiter}" liveResize="true" resizableColumns="true">
            <p:column headerText="Skillset">
                <p:commandLink update=":form:skillsDialog, :form:skillsDetails" oncomplete="PF('skillsDialog').show()" title="Detail" 
                        styleClass="ui-icon pi pi-search">
                    <f:setPropertyActionListener value="#{row}" target="#{mitarbeiterView.selectedEmployee}" />
                </p:commandLink>
                <p:commandLink action="#{adminView.openNewSkillDialog(row)}" title="add" styleClass="ui-icon pi pi-plus">
<!--                    <f:setPropertyActionListener value="#{row}" target="#{skillView.employee}" /> -->
                </p:commandLink>
            </p:column>
        </p:dataTable>
    </p:panelGrid>

    <p:dialog id="skillsDialog" header="Skillsheet von #{mitarbeiterView.selectedEmployee.vorname} #{mitarbeiterView.selectedEmployee.name}" 
            showEffect="fade" widgetVar="skillsDialog" modal="true" resizable="true">
        <p:outputPanel id="skillsDetails">
            <p:dataTable var="skillRow" value="#{mitarbeiterView.selectedEmployee.skills}">
                <p:column headerText="Skill">
                    <h:outputText value="#{skillRow.name}" />
                </p:column>
                <p:column headerText="Ausprägung">
                    <h:outputText value="#{skillRow.expertise} - #{skillRow.expertiseString.fullName}" />
                </p:column>
                <p:column headerText="Beschreibung">
                    <h:outputText value="#{skillRow.description}" />
                </p:column>
            </p:dataTable>
        </p:outputPanel>
    </p:dialog>
</h:form>

Second XHTML, for new employees:

<h:form id="newForm">
    <h3>Skillsheet</h3>
    <p:panelGrid id="skillPanel" columns="2" cellpadding="5" styleClass="ui-noborder">
        <p:column style="width:50px">
            <p:commandButton id="openAddSkill" process="@this" action="#{adminView.openNewSkillDialog}"
                    title="Neuer Skill" icon="pi pi-plus">
                <!-- <f:setPropertyActionListener target="#{skillView.employee}" value="#{newEmployeeView.newEmployee}"/> -->
                <p:ajax event="dialogReturn" update=":newForm :newForm:skillPanel"/>
            </p:commandButton>      
        </p:column>
    </p:panelGrid>

  <p:commandButton value="Hinzufügen" id="addSkill" icon="pi pi-plus" action="#{skillView.addSkill()}"/>
</h:form>

AdminView.java:

@Named(value = "adminView")
@ViewScoped
public class AdminView implements Serializable {

    private static final long serialVersionUID = 5252224062484767900L;

    @Inject
    private SkillView skillView;

    public void addNewEmployee() {
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("id", "newEmployeeDialogID");
        options.put("widgetVar", "newEmployeeDialogVar");
        options.put("resizable", false);
        options.put("modal", false);
        PrimeFaces.current().dialog().openDynamic("/dialogs/newEmployee", options, null);
    }

    public void openNewSkillDialog(Mitarbeiter employee) {
        Map<String, Object> options = new HashMap<String, Object>();
        options.put("resizable", true);
        options.put("modal", false);
        options.put("contentWidth", 420);
        PrimeFaces.current().dialog().openDynamic("/dialogs/skill", options, null);

        skillView.setEmployee(employee);
    }
}

Skill.java:

public class Skill {

    @NotNull(message = "Skill fehlt")
    private String name;
    @NotNull(message = "Bitte Ausprägung angeben")
    private short expertise;
    private String description;
    private String expertiseFullname;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public short getExpertise() {
        return expertise;
    }

    public void setExpertise(short expertise) {
        this.expertise = expertise;
    }

    public String getExpertiseFullname() {
        return expertiseFullname;
    }

    public void setExpertiseFullname(String expertiseFullname) {
        this.expertiseFullname = expertiseFullname;
    }

    public void setExpertise(String fullName) {
        try {
            this.expertise = Short.valueOf(fullName.substring(0, fullName.indexOf(" - ")));
        } catch (Exception e) {
            this.expertise = 0;
        }
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }
}

Mitarbeiter.java:

public class Mitarbeiter {

    private int id;
    @NotNull(message = "Nachname fehlt")
    private String name;
    @NotNull(message = "Vorname fehlt")
    private String vorname;
    private Date entryDate;
    private List<Skill> skills = new ArrayList<Skill>();
    private int expertise;
    public Mitarbeiter() {

    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getVorname() {
        return vorname;
    }

    public void setVorname(String vorname) {
        this.vorname = vorname;
    }
    public List<Skill> getSkills() {
        return skills;
    }

    public void setSkills(List<Skill> skills) {
        this.skills = skills;
    }

    public int getExpertise() {
        return expertise;
    }

    public void setExpertise(int expertise) {
        this.expertise = expertise;
    }

MitarbeiterView.java:

@Named(value = "mitarbeiterView")
@ViewScoped
public class MitarbeiterView implements Serializable {

    private static final long serialVersionUID = 7924178697538784022L;

    @Inject
    MitarbeiterService mitarbeiterService;

    private List<Mitarbeiter> mitarbeiter;
    private Mitarbeiter selectedEmployee;

@PostConstruct
    public void init() {
        SessionConfig.initSession();
        new Commons();
        updateMitarbeiter();
    }

    private void updateMitarbeiter() {
        mitarbeiter = new ArrayList<Mitarbeiter>();
        List<EmployeeDTO> dtos = Queries.findAllEmployees();

        for (EmployeeDTO employeeDTO : dtos) {
            mitarbeiter.add(mitarbeiterService.convertToMitarbeiter(employeeDTO));
        }
    }

    public void update() {
        updateMitarbeiter();
        PrimeFaces.current().ajax().update("form:table");
    }
    public List<Mitarbeiter> getMitarbeiter() {
        return mitarbeiter;
    }

    public void setMitarbeiter(List<Mitarbeiter> mitarbeiter) {
        this.mitarbeiter = mitarbeiter;
    }

    public void setSelectedEmployee(Mitarbeiter selectedEmployee) {
        this.selectedEmployee = selectedEmployee;
    }

    public Mitarbeiter getSelectedEmployee() {
        return selectedEmployee;
    }

NewEmployeeView.java:

@Named(value = "newEmployeeView")
@ViewScoped
public class NewEmployeeView implements Serializable {

    private static final long serialVersionUID = 789108010781037452L;

    @ManagedProperty(value = "#{mitarbeiter}")
    private Mitarbeiter newEmployee = new Mitarbeiter();

    @PostConstruct
    public void init() {

    }

    public Mitarbeiter getNewEmployee() {
        return newEmployee;
    }

    public void setNewEmployee(Mitarbeiter mitarbeiter) {
        this.newEmployee = mitarbeiter;
    }

Calling adSkill() from the first XHTML should have the selected employee from the Datatable. In the second case, it should have a freshly created, "empty" employee, which I already provide.

Thomas
  • 13
  • 7
  • How is your `h:form` defined in these two cases? – Adam Waldenberg Jul 17 '19 at 12:26
  • Simple . I have added it to the Question. – Thomas Jul 17 '19 at 12:52
  • Yeah, you can use `f:param`, `f:attribute` or `f:setPropertyActionListener` to send in the selected row - but the easiest way it to just use a method expression similar to `action="{adminView.addSkill(row)}"`. Many topics here on stackoverflow covering the same thing. – Adam Waldenberg Jul 17 '19 at 23:29
  • Also, I see you are already doing that with `openNewSkillDialog()`. But there is no `addSkill` call anywhere, so I'm not following exactly what you are trying to do. If a row is an employee, then just set the employee in the callback. – Adam Waldenberg Jul 17 '19 at 23:36
  • As mentioned above, I already tried `f:param`, `f:attribute`, the remains of `f:setPropertyActionlistener` even are still there. All gave the same result: employee is null when I call addSkill() in a submit Button in `skillDiagId`. I am adding it to the shown code now. – Thomas Jul 18 '19 at 08:18
  • I briefly tested your code and its working perfectly fine. However, I had to patch some of it because your example is still incomplete - so the error is probably caused by something you are not showing us. Please provide a [mcve]. – Adam Waldenberg Jul 18 '19 at 12:25
  • I did notice `update=":form:skillsDialog`. Please be aware that dialogs should have their own form - never wrap them in another form or put them inside a form. They essentialy use an `iframe`, so doing that will not work. – Adam Waldenberg Jul 18 '19 at 12:27
  • I did not want to cluster the Question with code that is needed to run, but not for the Question itself, eg. the entities. But ok, am adding... – Thomas Jul 18 '19 at 12:31

1 Answers1

0

I think that major cause of your problems is that skillView bean is @RequestScoped meaning that it is being constructed and destroyed on each request and thus your employee is being reinitialized/reset to null every time. Check out this accepted answer for details.

Hints that might lead you to solution:

  • put debug lines in at least init() and setEmployee(..) methods of skillView and observe behaviour,
  • change scope of skillView to @ViewScoped which will preserve employee object across multiple Ajax requests
Dusan Kovacevic
  • 1,377
  • 1
  • 13
  • 19
  • Setting it to `@Requestscope` was only one thing I tried. `@Viewscope` was the original state. So, yeah tried it already. Sorry that I forgot to mention this. – Thomas Jul 17 '19 at 09:25