0

i am trying to develop and understand communication in between classes and jsf tags. I figured out that jsf tags use classes directly without making any instance while when communication in between beans is required, an instance of the class is must to be built. In a dare need of dynamic listing and then copying selected values to different beans, i tried to build a custom tag for dynamic list but stuck at the point when selected value is required to be copied to the bean needing to hold the value other the bean used for building the list.

Following is the minimal reproducible example

pinnacleTags.taglib.xml

<?xml version="1.0" encoding="UTF-8"?>
<facelet-taglib>
    <namespace>pinnacleTags/facelets</namespace>
    <tag>
        <tag-name>PinnacleCombo</tag-name>
        <source>pinnacleCombo.xhtml</source>
        <attribute>
            <name>actionListenerBeanMethod</name>
        </attribute>
    </tag>
</facelet-taglib>

the List Tag

<?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://xmlns.jcp.org/jsf/html"
      xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
      xmlns:p="http://primefaces.org/ui"
      xmlns:o="http://omnifaces.org/ui"
      xmlns:f="http://xmlns.jcp.org/jsf/core">
    <h:head>
    </h:head>
    <h:body>
        <ui:composition> 
            <o:methodParam name="method" value="#{actionListenerBeanMethod}" />
            <p:dialog id="dlgTBL" modal="true" showEffect="bounce" widgetVar="dlg" resizable="false">
                <p:dataTable var="result" id="tbl" widgetVar="dtlTBL"
                                    value="#{liveRangeService.tableData}" 
                                    filteredValue="#{liveRangeService.filteredData}"
                                    paginator="false"
                                    scrollable="true"  rowIndexVar="rowindex"  scrollHeight="500" 
                                    scrollRows="50" liveScroll="true"
                                    filterDelay="1100"
                    >
                    <p:ajax event="rowSelect" listener="#{method}"  />
                    <f:facet name="header">
                        <p:outputPanel layout="inline" styleClass="tabSpacer">
                            <h:outputText value="Global Filter:" />
                            <p:inputText id="globalFilter" onkeyup="PF('dtlTBL').filter()" style="width:150px;margin-left:10px;"/>
                        </p:outputPanel>
                    </f:facet>

                    <p:column width="50">
                        <f:facet name="header">
                            <h:outputText value="Sr." />
                        </f:facet>
                        <p:commandButton value="#{rowindex}" style="width: 49px" action="#{method}"/>
                    </p:column>

                    <p:columns value="#{liveRangeService.tableHeaderNames}"
                               var="mycolHeader" 
                               width="#{colIndex==0?'10%':colIndex==1?'70%':colIndex==2?'10%':colIndex==3?'10%':'0'}" 
                               columnIndexVar="colIndex" 
                               sortBy="#{result[mycolHeader]}"
                               filterBy="#{result[mycolHeader]}"
                               filterMatchMode="contains"                        
                               >
                        <f:facet name="header">
                            <h:outputText value="#{mycolHeader}" />
                        </f:facet>
                        <h:outputText value="#{result[mycolHeader]}" />
                        <br />
                    </p:columns>
                </p:dataTable>
            </p:dialog>
        </ui:composition>
    </h:body>
</html>

Dynamic List Bean

package classes;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.ViewScoped;
import org.primefaces.PrimeFaces;

@ManagedBean(name="liveRangeService", eager = true)
@RequestScoped

public class LiveRangeService implements Serializable {
    private static List< Map<String, String> > tableData;
    public static List< Map<String, String> > filteredData;
    private static List<String> tableHeaderNames;
    private String tableColWidths;

    public List<Map<String, String>> getTableData() {
        return tableData;
    }
    public List<String> getTableHeaderNames() {
        return tableHeaderNames;
    }

    public LiveRangeService() {

    }

    public static void LiveRangeServicesss(int noOfRows) {
        tableData = new ArrayList< Map<String, String> >();
        filteredData = new ArrayList< Map<String, String> >();
        tableHeaderNames = new ArrayList<String>();
        try {
            tableData.clear();
            tableHeaderNames.clear();
            filteredData.clear();
        } catch (Exception e) {
            System.out.println("error:!"  + e.getMessage());
        }
        tableHeaderNames.add("ID");
        tableHeaderNames.add("Title");
        tableHeaderNames.add("Opn_Amt");
        tableHeaderNames.add("Smr_Amt");

        for (int i = 0; i < noOfRows; i++) {
            Map<String, String> playlist = new HashMap<String, String>();
            playlist.put("ID", "101000" + i);
            playlist.put("Title", "Share Capital - Mr. " + i);
            playlist.put("Opn_Amt", "0");
            playlist.put("Smr_Amt", "0");
            tableData.add(playlist);
        }
        filteredData=tableData;
        System.out.println("Filled " + filteredData.size() + ", " + noOfRows);
        String dlgTBL="form:dlgTBL";
        String dlg="PF('dlg').show();";
        PrimeFaces.current().ajax().update(dlgTBL);
        PrimeFaces.current().executeScript(dlg);
    }

    public String getTableColWidths() {
        return tableColWidths;
    }

    public void setTableColWidths(String tableColWidths) {
        this.tableColWidths = tableColWidths;
    }

    public List<Map<String, String>> getFilteredData() {
        return filteredData;
    }

    public void setFilteredData(List<Map<String, String>> filteredData) {
        this.filteredData = filteredData;
    }
}

test Bean

package classes;


import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.PrimeFaces;
import org.apache.commons.beanutils.PropertyUtils;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author Administrator
 */

@ManagedBean(name="test")
@SessionScoped

public class Test implements Serializable {
    public String id;
    public String title;

    public Test() {
        id="1";
        title="Testing";
    }

    public String getId() {
        return id;
    }

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

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public void onRowSelect(int row) {
        try {
            System.out.println("Start:");
            String i="ID";
            String t="Title";
            String ci="id";
            String ct="title";
            this.getClass().getDeclaredField(ci).set(this, LiveRangeService.filteredData.get(row).get(i));
            this.getClass().getDeclaredField(ct).set(this, LiveRangeService.filteredData.get(row).get(t));
            PrimeFaces.current().ajax().update("form:inp");
            PrimeFaces.current().ajax().update("form:inp1");
            PrimeFaces.current().executeScript("PF('dlg').hide();");            
            System.out.println("End:");
        } catch (Exception e) {
            System.out.println("Error! " + e.getMessage() );
        }
    }
}
  • 1
    What is PropertyUtils? Does getProperty() possibly require an **instance** of the given class as first argument, instead of the class? This does not seeme to be JSF related. – Selaron Nov 24 '19 at 15:58
  • @Seleron the main aim is to build. one list to be called from hundreds of jsf tags passing class names and properties as string so that the selected value could be passed to the respective properties – Nasir Abbas Nov 25 '19 at 02:02
  • @Seleron, although it worked as u said but again from jsf page class is referenced not a new instance and i have tried to explain the purpose, may u pls suggest a way to dynamically set properties of classes??? – Nasir Abbas Nov 25 '19 at 04:13
  • Class properties are typically `static` ones, but `var01` and `var02` are instance properties and cannot be accessed on class level. – Selaron Nov 25 '19 at 07:24
  • @Selaron you mean to say that the possibility of being dynamic in regard to passing class name through JSF Tags and passing parameters to those classes is impossible?? or is there any work around?? – Nasir Abbas Nov 25 '19 at 08:00
  • So far it's not clear to my how you attempt to `pass class name through JSF Tags and pass parameters to those classes`. You can increase your chances of getting answers by editing your question to provide a real [mcve] and explain expected/actual results. – Selaron Nov 25 '19 at 08:04
  • @Selaron i have updated the code as per instructions, i am confused @ liveRangeService.onRowSelect event on how to pass the selected values to the bean's property the copy is required. – Nasir Abbas Nov 25 '19 at 13:56
  • So you accepted my answer - did it solve your question? After your edit I'm somewhat not sure if accepted answer and question still fit together. Make sure to not get into this area: [Change to question invalidates my answer, what to do?](https://meta.stackexchange.com/questions/286803/change-to-question-invalidates-my-answer-what-to-do) - Future visitors with similar problems should be able to understand the relation between question and answer. – Selaron Dec 04 '19 at 07:22
  • @Selaron actually the portion of your answer regarding scopes of beans gave me the hint and 1. i changed the scope of one bean 2. i transferred the function onRowSelect() from ViewScope Bean to SessionScope bean which resolves my problem. Futhermore, it took 2-3 days while i tried my best to transfer to CDI, but i failed, so i resolved my problem in old code and update the solution and will later on work on transferring to CDI. Also i have changed the habbits of naming conventions according to your suggestions. – Nasir Abbas Dec 04 '19 at 08:51

1 Answers1

0

Assuming your problem is how to access the sessionScoped test bean from within the applicationScoped LiveRangeService: you cannot simply instantiate a ManagedBean this way:

test t = new test();

Instances are Managed by JSF and instantiated on demand with a lifespan defined by their scope.

Please read How to access property of one managed bean in another managed bean and the blog article Communication in JSF 2.0 - Injecting managed beans in each other linked by BalusC.

There are several additional issues with your example:

  1. The scopes of your beans do not seeme to be chosen correctly, please read How to choose the right bean scope?
  2. You do not follow java naming conventions. Class names should start with upper case character while fields and variables should start with lower case character. E.g. rename class test to class Test and private String CopyValuesToClass; to private String copyValuesToClass;
  3. The example is by far not minimal. You should remove all the code not relevant to understand the problem.
  4. You should think about migrating to a recent version of JSF and CDI as @ManagedBean is deprecated: Migrate JSF managed beans to CDI managed beans
Selaron
  • 6,105
  • 4
  • 31
  • 39