Creating a ToolTip Managed bean

蹲街弑〆低调 提交于 2019-12-24 08:29:12

问题


This is a followup to my previous post at ToolTip Performance in XPages I have got the code to do it written (not tested) so I can't seem to get my Managed Bean to get called properly. My config contians the following:

<managed-bean id="ToolTip">
<managed-bean-name>WFSToolTip</managed-bean-name>
<managed-bean-class>ca.workflo.wfsToolTip.ToolTipText</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>

and I have stripped my code down to the bare minimum:

package ca.workflo.wfsToolTip;

public class ToolTipText   {

    public String getToolTipText(String key){
        return key;
    }
}

My class is in the build path. I have a simple XPage with one filed on it and a tool tip for that field. The code for the tooltip is:

<xe:tooltip id="tooltip1" for="inputText1">
<xe:this.label>
<![CDATA[#{javascript:WFSToolTip.getToolTipText("More Stuff");}]]>
</xe:this.label>
</xe:tooltip>

When I load the test XPage in the browser I get an error that:

Error while executing JavaScript computed expression Script interpreter error, line=1, col=12: Error calling method 'getToolTipText(string)' on java class 'ca.workflo.wfsToolTip.ToolTipText'

JavaScript code

1: WFSToolTip.getToolTipText("More Stuff");

I can't figure out why the call to getToolTipText would fail.

Can anyone see where I'm going wrong. This is my first Managed Bean and at the moment it is managing me rather than the other way around.

Thanks.


回答1:


You need to: - implement Serializable which boils down to state it and provide a version - implement Map ... a little more work

Then you use Expression Language instead of SSJS. It would look like #{WFSToolTip["More Stuff"]}

This is how such a class would look like. You need to:

  • adjust the view name to reflect the name you want
  • the view needs to be flat, column 1 = tooltip name, column 2 = tooltip text
  • somewhere (on an admin/config page) you need to call WFSToolTip.clear(); (in SSJS) after you update the values in the configuration.

The example doesn't lazyload since running though a view navigator once is really fast. No point to do all these lookups.

Here you go:

package com.notessensei.xpages;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import lotus.domino.Base;
import lotus.domino.Database;
import lotus.domino.NotesException;
import lotus.domino.View;
import lotus.domino.ViewEntry;
import lotus.domino.ViewEntryCollection;

import com.ibm.xsp.extlib.util.ExtLibUtil;

public class Parameters implements Serializable, Map<String, String> {

    private final static String       CONFIG_VIEW      = "keywords";

    private static final long         serialVersionUID  = 1L;
    private final Map<String, String>   internalMap    = new HashMap<String, String>();

    public Parameters() {
        this.populateParameters(internalMap);
    }

    private void populateParameters(Map<String, String> theMap) {

        Database d = ExtLibUtil.getCurrentDatabase();
        try {
            View v = d.getView(CONFIG_VIEW);
            ViewEntryCollection vec = v.getAllEntries();
            ViewEntry ve = vec.getFirstEntry();
            ViewEntry nextVe = null;

            while (ve != null) {
                nextVe = vec.getNextEntry(ve);
                // Load the parameters, column 0 is the key, column 0 the value
                Vector colVal = ve.getColumnValues();
                theMap.put(colVal.get(0).toString(), colVal.get(1).toString());
                // Cleanup
                this.shred(ve);
                ve = nextVe;
            }
            // recycle, but not the current database!!!
            this.shred(ve, nextVe, vec, v); 
        } catch (NotesException e) {
            e.printStackTrace();
        }
    }

    public void clear() {
        this.internalMap.clear();
        this.populateParameters(this.internalMap);
    }

    public boolean containsKey(Object key) {
        return this.internalMap.containsKey(key);
    }

    public boolean containsValue(Object value) {
        return this.internalMap.containsValue(value);
    }

    public Set<java.util.Map.Entry<String, String>> entrySet() {
        return this.internalMap.entrySet();
    }

    public String get(Object key) {
        return this.internalMap.get(key);
    }

    public boolean isEmpty() {
        return this.internalMap.isEmpty();
    }

    public Set<String> keySet() {
        return this.internalMap.keySet();
    }

    public String put(String key, String value) {
        return this.internalMap.put(key, value);
    }

    public void putAll(Map<? extends String, ? extends String> m) {
        this.internalMap.putAll(m);
    }

    public String remove(Object key) {
        return this.internalMap.remove(key);
    }

    public int size() {
        return this.internalMap.size();
    }

    public Collection<String> values() {
        return this.internalMap.values();
    }

    private void shred(Base... morituri) {

        for (Base obsoleteObject : morituri) {
            if (obsoleteObject != null) {
                try {
                    obsoleteObject.recycle();
                } catch (NotesException e) {
                    // We don't care we want go get
                    // rid of it anyway
                } finally {
                    obsoleteObject = null;
                }
            }
        }

    }
}

The difference to a regular HashMap is only the constructor that populates it. Hope that clarifies it.




回答2:


I've never seen that id property.. My beans in faces-config look like this:

<managed-bean>
    <managed-bean-name>CurrentJob</managed-bean-name>
    <managed-bean-class>com.domain.inventory.Job</managed-bean-class>
    <managed-bean-scope>session</managed-bean-scope>
</managed-bean>

Technically managed beans should implement Serializable and have a blank constructor. So you should have something like this inside :

public ToolTipText() {

}

I THINK you can get away without the Serializable for somethings... I always implement though but I'm sure you need the no argument constructor.




回答3:


Thanks to all that have responded and helped out here especially Stephan Wissel. I thought I would post my version of Stephan's code, pretty much the same. There are issues with making the class an ApplicationScope because you need to shut down the HTTP task to refresh and reload the Class. What I did was added a button to the custom control where I to the view of the tooltips where I do the CRUD stuff and in the button do WFSToolTip().clear() and it rebuilds the map. Pretty neat. My next task for this is try to do the CRUD using JAVA and update the map directly. At the moment though I need to move on to my next task. My next task revolves around a very similar Class. I have a master database that contains all the basic design and code. Then I have one or more applications that use that code and store the documents in their own database that contains the forms and views for that specific application. In the master I have created one or more application documents. Each of these documents contains the AppName (the key value) then the Map value is an array (Vector) containing the ReplicaID of the Application Database and a few other pieces of information. My class the loads a Map entry for each Application and collects a bunch of other information about the application from several places and stores that in the Map Value. At this point then I can set Database db = thisClass.getDatabase("App Name"). so a single custom control can be used for any/all of the applications. Pretty cool. I think I could get to like this. Anyway here is the code I'm using for the ToolTips - BTW It has taken an XPage with about 175 fields and 100+ tooltips from being painfully slow to being acceptable. The good thing about it is that the XPage is creating a process profile document and once created it is not frequently modified as an admin action - not an everyday user action. Please feel free point out error, omitions or suggestions to the code:

package ca.workflo.wfsToolTip;

import lotus.domino.Base;
import lotus.domino.Session;
import lotus.domino.Database;
import lotus.domino.View;
import lotus.domino.NotesException;
import lotus.domino.ViewEntry;
import lotus.domino.ViewEntryCollection;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import com.ibm.xsp.extlib.util.ExtLibUtil;

public class ToolTipText implements Serializable, Map<String, String> {

    private static final long serialVersionUID = 1L;
    private Session s;
    private String repID;
    private Database db;
    private Database helpDB;
    private View helpView;
    private ViewEntry ve;
    private ViewEntry tVE;
    private ViewEntryCollection veCol;
    private final Map<String, String> internalMap = new HashMap<String, String>();

    public ToolTipText() {
        this.populateMap(internalMap);
    }

    private void populateMap(Map<String, String> theMap) {

        try {
            s = ExtLibUtil.getCurrentSession();
            db = s.getCurrentDatabase();
            repID = db.getProfileDocument("frmConfigProfile", "").getItemValue(
                    "WFSHelpRepID").firstElement().toString();
            helpDB = s.getDbDirectory(null).openDatabaseByReplicaID(repID);
            helpView = helpDB.getView("vwWFSToolTipHelp");
            veCol = helpView.getAllEntries();
            ve = veCol.getFirstEntry();
            ViewEntry tVE = null;
            while (ve != null) {
                tVE = veCol.getNextEntry(ve);
                Vector colVal = ve.getColumnValues();
                theMap.put(colVal.get(0).toString(), colVal.get(1).toString());
                recycleObjects(ve);
                ve = tVE;
            }
        } catch (NotesException e) {
            System.out.println(e.toString());
        }finally{
            recycleObjects(ve, tVE, veCol, helpView, helpDB);
        }
    }

    public void clear() {
        this.internalMap.clear();
        this.populateMap(this.internalMap);
    }

    public boolean containsKey(Object key) {
        return this.internalMap.containsKey(key);
    }

    public boolean containsValue(Object value) {
        return this.internalMap.containsValue(value);
    }

    public Set<java.util.Map.Entry<String, String>> entrySet() {
        return this.internalMap.entrySet();
    }

    public String get(Object key) {
        try {
            if (this.internalMap.containsKey(key)) {
                return this.internalMap.get(key);
            } else {
                return "There is no Tooltip Help for " + key;
            }

        } catch (Exception e) {
            return "error in tooltip get Object ";
        }
    }

    public boolean isEmpty() {
        return this.internalMap.isEmpty();
    }

    public Set<String> keySet() {
        return this.internalMap.keySet();
    }

    public String put(String key, String value) {
        return this.internalMap.put(key, value);
    }

    public void putAll(Map<? extends String, ? extends String> m) {
        this.internalMap.putAll(m);
    }

    public String remove(Object key) {
        return this.internalMap.remove(key);
    }

    public int size() {
        return this.internalMap.size();
    }

    public Collection<String> values() {
        return this.internalMap.values();
    }

    public static void recycleObjects(Object... args) {
        for (Object o : args) {
            if (o != null) {
                if (o instanceof Base) {
                    try {
                        ((Base) o).recycle();
                    } catch (Throwable t) {
                        // who cares?
                    }
                }
            }
        }
    }
}


来源:https://stackoverflow.com/questions/24542449/creating-a-tooltip-managed-bean

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!