Mindoo Blog - Cutting edge technologies - About Java, Lotus Notes and iPhone

  • XPages series #4: Backing Bean Management with XPages

    Karsten Lehmann  July 16 2009 09:58:16
    In this part of the XPages series about an alternative application architecture, I'm going to talk about Backing Bean Management.

    At the end of this blog entry, you should get the trick how the XPages user interface can be connected to backend Java Beans. I will follow up with another article that contains code snippets you might need after you start working with this technology in a real-life project.

    And I promise to show an example at the very end of this series, to not leave you alone, totally confused with Java, Beans, Bindings, Expression Language and other things. :-)

    Warning! This article is looooong ;-).

    Separation of UI and application logic
    A Backing Bean is a Java Bean that is associated with UI components used in a page. The purpose of Backing Beans is to separate the definition of UI components from objects that perform application-specific processing and hold data. That way your XPage will contain more or less just the UI, while the application logic is stored in the bean.

    To continue with our Movie Actor database, we start with a pretty simple Java class that is a container for the data of an actor:

    package com.acme.actors.model;

    public class Actor {
            private String m_id;
            private String m_firstName;
            private String m_lastName;
            private String m_comment;
           
            public Actor() {}
           
            public Actor(String id, String firstName, String lastName, String comment) {
                    m_id=id;
                    m_firstName=firstName;
                    m_lastName=lastName;
                    m_comment=comment;
            }

            public String getId() {
                    return m_id;
            }
           
            public void setId(String newId) {
                    m_id=newId;
            }
           
            public String getFirstname() {
                    return m_firstName;
            }
           
            public void setFirstname(String newFirstName) {
                    m_firstName=newFirstName;
            }
           
            public String getLastname() {
                    return m_lastName;
            }
           
            public void setLastname(String newLastname) {
                    m_lastName=newLastname;
            }
           
            public String getComment() {
                    return m_comment;
            }
           
            public void setComment(String newComment) {
                    m_comment=newComment;
            }
    }


    Well, pretty self-explanatory. The class will be is used to store the firstname, lastname, a comment and a unique identifier of an actor. Notice, that the class is completely independent from Lotus Notes. The identifier field might be later on used for a Notes document's universal id (in case we load Notes data), but it could just as well be something completely different like a primary key of table rows in a SQL database.

    Let's take a look at our first Backing Bean. It will be used to provide the backend logic of our actor list XPage:

    package com.acme.actors.controller;

    import java.util.ArrayList;
    import java.util.List;
    import java.util.UUID;
    import com.acme.actors.model.Actor;

    public class ActorList {
            private List<Actor> m_actors;

            public ActorList() {}

            private void init() {
                    if (m_actors==null) {
                            //list is empty and needs to be filled
                            m_actors=new ArrayList<Actor>();

                            m_actors.add(new Actor(createNewId(), "Sean", "Connery", "James Bond"));
                            m_actors.add(new Actor(createNewId(), "Daniel", "Craig", "James Bond"));
                            m_actors.add(new Actor(createNewId(), "Catherine", "Zeta-Jones", "Ocean's Twelve"));
                            m_actors.add(new Actor(createNewId(), "Tobey", "Maguire", "Spiderman"));
                            m_actors.add(new Actor(createNewId(), "Kirsten", "Dunst", "Spiderman"));
                            m_actors.add(new Actor(createNewId(), "John", "Travolta", "Pulp Fiction"));
                            m_actors.add(new Actor(createNewId(), "Bruce", "Willis", "Die Hard"));
                            m_actors.add(new Actor(createNewId(), "Christopher", "Lee", "Dracula"));
                            m_actors.add(new Actor(createNewId(), "Patrick", "Stewart", "Star Trek"));
                            m_actors.add(new Actor(createNewId(), "Charlton", "Heston", "Planet of the Apes"));
                    }
            }

            private String createNewId() {
                    //create a new unique identifier for a list entry
                    return UUID.randomUUID().toString();
            }

            public List<Actor> getActors() {
                    //init() initializes the actor list the first time it is called
                    init();

                    return m_actors;
            }

            public void setActors(List<Actor> newActors) {
                    m_actors=newActors;
            }
    }


    Our class does not contain any real business logic at the moment. It contains a list of ten actors that are written into the internal variable "m_actors", which is returned by the method "getActors()".
    We will use this method in our XPage, to feed the rows of a table.

    Bean declaration in faces-config.xml
    Next we need to tell the JavaServer Faces runtime about our new bean.
    To do this, modify the faces-config.xml file and add the following <managed-bean> section:

    <?xml version="1.0" encoding="UTF-8"?>
    <faces-config>
      <managed-bean>
        <managed-bean-name>ActorList</managed-bean-name>
        <managed-bean-class>com.acme.actors.controller.ActorList</managed-bean-class>
        <managed-bean-scope>session</managed-bean-scope>
      </managed-bean>
    </faces-config>


    With this information, the JSF runtime is able to resolve an expression language construct like "#{ActorList}" to find our bean. It knows that the bean has the classname "com.acme.actors.controller.ActorList" and can create a new instance of it.
    We also tell the runtime something about the bean's life span, called "scope", in this line:

    <managed-bean-scope>session</managed-bean-scope>

    The scope "application" means that there will be only one instance of the bean in the whole application (=one bean for all users, useful for translation dictionaries). With"session", one bean is created for the whole session of a single user, e.g. to hold personal profile information. With the scope"request" you can create a bean that is only valid for a single HTTP request (to pass data from one page to the other) and the scope "none"  lets the JSF runtime dispose the bean after every HTTP request. In that case, it is stored nowhere automatically.

    And now, the end is near
    To bring all the pieces together, we now create our ActorList XPage and insert a data table control with three columns:

    Image:XPages series #4: Backing Bean Management with XPages

    For the table's binding, we click on "Advanced", select "Expression Language (EL)" from the combo box and enter the following text: ActorList.actors.
    This produces the string "#{ActorList.actors}" in the source code of the XPage. When the JavaServer Faces runtime resolves this expression to retrieve the row data for the table, it fetches/creates our ActorList Java Bean from the sessionScope and searches for a method "getActors" in it. This is our method that returns the List of actors.

    The table will now display each List entry in its own table row. By entering the string "currentActor" in the Collection name field (see #2 in the screenshot above), the row data (the current Actor objects) can be accessed in the row controls (in my case three computed fields for the firstname, lastname and comment):

    Image:XPages series #4: Backing Bean Management with XPages

    Here is the full source code of the ActorList XPage:

    <?xml version="1.0" encoding="UTF-8"?>
    <xp:view xmlns:xp="http://www.ibm.com/xsp/core">
            <xp:dataTable rows="5" id="actorTable" var="currentActor"
                    style="width:50%" value="#{ActorList.actors}">
                    <xp:this.facets>
                            <xp:pager layout="Previous Group Next" xp:key="header" id="pager1">
                            </xp:pager>
                            <xp:pager layout="Previous Group Next" xp:key="footer" id="pager2">
                            </xp:pager>
                    </xp:this.facets>
                    <xp:column id="firstnameColumn">
                            <xp:text escape="true" id="firstnameField" value="#{currentActor.firstname}">
                            </xp:text>
                    </xp:column>
                    <xp:column id="lastnameColumn">
                            <xp:text escape="true" id="lastnameField" value="#{currentActor.lastname}">
                            </xp:text>
                    </xp:column>
                    <xp:column id="commentColumn">
                            <xp:text escape="true" id="commentField" value="#{currentActor.comment}">
                            </xp:text>
                    </xp:column>
            </xp:dataTable>
    </xp:view>


    And finally:
    This is how our example looks like. It's a table with our in-memory Actor Java objects:

    Image:XPages series #4: Backing Bean Management with XPages

    Instead of a data table, you could of course also use a repeat control to have full control over the generated code. To make the table cells editable, just use an edit box instead of the computed fields. The XPages/JavaServer Faces runtime will automatically inform you about the new values by calling the set-methods of the Actor objects.

    Hint #1
    The method "getActors()" is called on every page refresh and also when the user switches from page 1 of the table to page 2. So you should make sure that you do some caching in your bean and avoid CPU intensive data lookups on every call.

    Hint #2:
    Please note that we return a Java List (java.util.List) implementation in our method "getActors()".
    Nobody said that all the data needs to be in-memory when the data table component calls "getActors()". When you develop your own List implementation, you have full control, which data really has to be loaded from your (external) data store. The table/pager only needs the currently visible rows of the active page.

    Hint #3
    You should avoid to return a Java Collection (java.util.Collection) instead of the Java List in the "getActors()" method.
    That does works, but the pager around the data table needs to know how many elements there are, to calculate the amount of pages for the navigation. Since a Java Collection does not return the total number of entries, the pager calls Collection.toArray(), which grabs the whole data list as an array into memory. That might kill the server for large amounts of data.

    Comments

    1John Mackey  07/18/2009 15:02:53  XPages series #4: Backing Bean Management with XPages

    Excellent series Karsten. Thanks for sharing this. I can't wait for the next one....

    I'm particularly interested in adding JSF listeners to fields on an XPage application. Any plans to demonstrate that?

    -John

    2Rob McDonagh  07/18/2009 17:43:06  XPages series #4: Backing Bean Management with XPages

    I'm really enjoying this as well. It's one thing to know XPages have JSF technology under the covers, but it's much more useful to see how we can take advantage of that directly.

    3Karsten Lehmann  07/19/2009 18:54:34  XPages series #4: Backing Bean Management with XPages

    Thanks guys!

    @1:

    I haven't tried so far to use JSF listeners with XPages. Don't know if they work properly like they do in JSF. I will do some testing.

    A PhaseListener or ValueChangedListener may make sense for some use cases.

    For ActionListener, an alternative is to call the backing bean methods directly in JavaScript code, e.g. in an onClick event of a button.

    You can see how to get a handle on the bean in series part #5. The getBindingValue() function demonstrated there does also work in JavaScript:

    var bean=com.acme.tools.JSFUtil.getBindingValue("#{ActorList}");

    bean.doSomething();

    4Veer  07/20/2009 20:06:56  XPages series #4: Backing Bean Management with XPages

    This is what I was waiting for. Thanks so much.

    Now, what will make this truely invaluable would be to code in Java, all the logic to get data from Notes.

    And also, Junit tests for this code.

    Waiting for more.

    5Andreas Nebel  09/29/2009 16:21:39  XPages series #4: Backing Bean Management with XPages

    Very nice and usefull. Thank you.

    Do you have an idea how works the richtext and attachment handling, with an own bean?

    -Andreas

    6Karsten Lehmann  09/29/2009 17:28:37  XPages series #4: Backing Bean Management with XPages

    I don't think that IBM is using Managed beans internally in the XPages API. Their code is based on the public Notes Java API with some native code add-ons (that you can also implement on your own by calling C API methods via JNI - the Java Native Interface).

    Managed beans is just something that is inherited from the JavaServer Faces system that XPages is built upon.

    Looks like IBM tries to emphasize the rapid application nature of XPages, e.g. by supporting server side JavaScript (SSJS) in various events and libraries.

    That's fine to quickly assemble an application, but to build large modular applications and to integrate already existing libraries, JavaScript is not enough. With Managed Java Beans, you get a completely new view of the XPages technology.

    7Laura  12/16/2009 14:39:56  XPages series #4: Backing Bean Management with XPages

    Hi Karsten,

    It's me again! I commented/sent a question to you on your JSF Helpers entry earlier this month -- Thanks again for that help btw.

    Now, I have a question regarding this entry. :) You are probably going to think "this girl works backward"! But, I do have a partial bean solution in place (ie. the XPage repeaters can see my beans)... but I am now realizing I don't have the "whole picture".

    I will admit, I am a java newbie... so if you have any good java resource books, etc. that you can recommend (esp. for Domino 8.5.x), that would be awesome!

    Here's the setup:

    I have 2 java beans, both declared in my faces-config.xml:

    <?xml version="1.0" encoding="UTF-8"?>

    <faces-config>

    <managed-bean>

    <managed-bean-name>FOHeaderList</managed-bean-name>

    <managed-bean-class>javaMethods.FOHeaderList</managed-bean-class>

    <managed-bean-scope>request</managed-bean-scope>

    </managed-bean>

    <managed-bean>

    <managed-bean-name>FOLineList</managed-bean-name>

    <managed-bean-class>javaMethods.FOLineList</managed-bean-class>

    <managed-bean-scope>request</managed-bean-scope>

    </managed-bean>

    <!--AUTOGEN-START-BUILDER: Automatically generated by IBM Lotus Domino Designer. Do not modify.-->

    <!--AUTOGEN-END-BUILDER: End of automatically generated section-->

    </faces-config>

    As you can see, I am just referencing a "packageName.BeanName"..... not a controller like you did. That's the piece I am missing! None of my other java classes have any knowledge of these beans, although the XPage does... so I didn't realize this was a problem until I went to use the beans in my actual java code. :-}

    How does one setup a controller and/or model for a java package inside a Notes db? (I don't know if this would be different than outside a Notes db... but the former is what I really want to do).

    I understand this may be a loaded question... but any help you can provide would be terrific!!

    Thanks,

    Laura

    8Karsten Lehmann  12/16/2009 15:01:19  XPages series #4: Backing Bean Management with XPages

    Hi Laura!

    I think the answer is here:

    { Link }

    When you search for the string "public static DataStoreManager getManager()" in that article, you will find a static method that can be used in a Java class to access the active Java bean instance:

    DataStoreManager ds=(DataStoreManager) JSFUtil.getBindingValue("#{DataStoreManager}");

    You can also use this method to access bean properties:

    String firstName=(String) JSFUtil.getBindingValue("#{Person.firstname}");

    Which would make the JSF framework call Person.getFirstname() and return the result.

    Best regards,

    Karsten

    9Bill Hanson  02/10/2010 19:36:57  XPages series #4: Backing Bean Management with XPages

    Hi Karsten,

    First, thank you for posting this info!

    I thought I had followed the instructions properly, but when I preview the xpage, I receive the following error:

    - com.ibm.xsp.FacesExceptionEx: Invalid context factory.

    So the JavaServer Faces runtime cannot locate my backing bean. I wonder if I created the classes in the right place.

    Here's what my project looks like in the 'Java' Perspective...

    - MovieAct.nsf

    -- Local

    -- WebContent/WEB-INF/source

    --- com.acme.actors.controller

    ---- ActorList.java

    --- com.acme.actors.model

    ---- Actor.java

    ...

    -- WebContent

    --- WEB-INF

    ---- faces-config.xml

    File contents are the same as your example code above.

    Also, the IDE shows this warning:

    "Referenced class 'plugin.Activator' in attribute 'class' is not on the plug-in classpath"

    I wonder what I did wrong?

    Any help would be greatly appreciated!

    10Fedor Belov  07/14/2010 12:31:38  XPages series #4: Backing Bean Management with XPages

    Does it mean that we are able to realize background logic using beans without any Java/LS agent? Is it faster, better? What about memory leak?

    11Karsten Lehmann  07/15/2010 2:25:14  XPages series #4: Backing Bean Management with XPages

    Fedor, yes, it's possible. Should be faster, but another advantage is that you can directly call Java from Javascript and pass variables between both languages without writing values to Notes documents, pass their note id to an agent etc.

    Regarding the memory leaks: Well, it depends on your code. Compared to executing an agent, using beans might have a higher risk of producing memory leaks, because the Notes agents are loaded with their own classloader and unloaded after their execution (which makes it slower to call the agent compared to call Java methods directly).

    You should avoid using the singleton design pattern in your bean code, because all XPages code is executed in the same JVM instance and that JVM only shuts down when you shut down the whole server. By using singletons, the garbage collector is not able to release the memory allocated by your bean code.

    A better approach is to store data and object references either in one of the scope maps (e.g. session scope). The Domino server flushes those maps after a timeout. I think the default session duration is 30 minutes.

    12Fedor Belov  07/15/2010 10:43:29  XPages series #4: Backing Bean Management with XPages

    Thanks... is is very interesting info. Pls continue your work =)

    I've got a crazy idea, pls comment it:

    1. Java application server (tomcat) is responsible for background logic. It doesn't know about LN objects because we store content in SQL DB (mySQL, for example)

    2. xPages is used to display/update content in LN Client from/to SQL DB (using beans)

    13Karsten Lehmann  07/15/2010 11:16:05  XPages series #4: Backing Bean Management with XPages

    Yes, that's possible. I think I saw some samples in the Designer wiki where they accessed web services from XPages in SSJS, but that's also possible in Java code.

    In 8.5.1, you may have to tweak with the Java security settings to make it work in the client, but IBM has worked on that issue for 8.5.2.

    See this blog posting for details on running XPages in the Notes client with code in Java beans:

    { Link }

    It should work in an XPages app on a Domino server without security issues.

    14Olle Thalén  07/31/2010 15:19:49  XPages series #4: Backing Bean Management with XPages

    Great article Karsten, I was looking for some examples for how to connect a table in the ui to a managed bean back-end. Now I know how to do it. :)

    I was thinking about one thing though, in your example the columns and their names are fixed. So it is difficult to swap between different views. I was thinking about creating a dynamic view control where you can set the view name as a parameter and then load the content of that view in a custom control. My idea was to use a backing bean to read which view the user wants to use, then using the standard domino api to access that view and populate a backing bean with data from that view.

    But in order to achieve this you must be able to render the columns in the table in a dynamic way, maybe using a repeat control? And instead of mapping the column value to a string property like you do, e.g value = "#{currentActor.firstname}", I would use value = "#{myBean.columns[indexVar]}". Where indexVar is the counter of the repeat control and columns is a java.util.List in the java bean.

    Do you think this would be possible? I know it is technically possible to access a list in a java bean with the above syntax in E.L, I'm not sure however if you can index one element in the list using the counter from the repeat control.

    I've seen example of dynamic views before, but those solutions have been based on SSJS and not the JSF technology. I think it breaks the MVC design pattern when you use too much SSJS, and I would prefer to have all my buisiness logic in beans, and use E.L to access data in the UI.

    15Karsten Lehmann  07/31/2010 16:08:14  XPages series #4: Backing Bean Management with XPages

    Thanks Olle!

    For a completely flexible data table, you could try three things:

    1. use two nested repeater controls

    The outer repeater iterates over the rows of your data (e.g. a Notes view). You could implement your own Java List interface that lazily loads data from a Notes view when someone calls List.get(index). I did this in a project. The List implementation contains a fixed cache of entries, so for example, when you call List.get(0), it not only fetches the view entry in row 0, but the entries with index 0 to 50 to improve performance.

    In your inner repeater, you can then render the code for the table columns. Each row of your outer List could return another List with the column values.

    2. use a Dojo grid component and feed it with JSON

    There are already some pretty nice components that can display data lists, so why not use one of these and let it read its data via Ajax call from your XPage as a JSON string? Stephan Wissel from IBM demonstrated in his blog how to return any kind of data in an XPage:

    { Link }

    2. use a completely dynamic approach

    For another project, I created something more flexible. By using the XPages extensibility APIs, you can develop your own controls. I created a tree control that visualizes a Swing tree model on the web. The whole XPages UI is created in backend Java code when the XPages component tree is build at page load.

    All value bindings and method bindings for expand/collapse links and partial refreshs are created programmatically as well. You can get some hints on how to do that when you take a closer look at the OpenNTF project Medusa and I think there are also some articles in the Designer wiki.

    A sample control for this technique could look like this:

    public class MyControl extends UIComponentBase implements FacesComponent {

    public MyControl() {

    super();

    }

    public String getFamily() {

    return "com.company.MyControl";

    }

    public void buildContents(FacesContext ctx, FacesComponentBuilder builder) throws FacesException {

    Application application=ctx.getApplication();

    List children=getChildren();

    XspOutputText txt=new XspOutputText();

    ValueBinding binding=application.createValueBinding("#{javascript:return \"Hello World\"}");

    txt.setValueBinding("title", binding);

    children.add(txt);

    }

    }

    You see, you can create whatever you want in your XPages component tree.

    But be aware that this approach can be very hard to debug.

    16Olle Thalén  08/03/2010 17:03:54  XPages series #4: Backing Bean Management with XPages

    Thanks for all the tips!

    I'll think try the first advice with nested repeaters as a start. I also read your article number 5 about detecting data changes in java, I think I'll try to use that approach if I want to detect changes a user has made to the UI component.

    Thanks again,

    Olle

    17Kiruxan  10/20/2010 20:26:34  XPages series #4: Backing Bean Management with XPages

    I try to use this technique with page that contains tabs. Sometimes user want open two or more browser window with this page, but if my bean is session scope its only one instance for all browser windows and its a big problem...

    18Karsten Lehmann  10/20/2010 20:48:34  XPages series #4: Backing Bean Management with XPages

    We have reported this issue in the Design Partner program last year. IBM is aware of it. I haven't investigated whether bean definitions in faces-config.xml can have view scope in 8.5.2, but they thought about adding this to the JSF standard.

    In the meantime, you could store your data in the viewScope map and just redirect the bean methods of the session scope bean to provide view specific data from the viewScope. You don't have to store data in the session scope bean. Just use it as a proxy.

    19Kiruxan  10/21/2010 9:28:43  XPages series #4: Backing Bean Management with XPages

    We just upgrade to 8.5.2, and i try view scope for my bean, at first glance all work fine! How do you think what method have best perfomance, use bean as proxy with scope session or mb request and stroe data viewScope, or use bean with view scope?

    20Karsten Lehmann  10/21/2010 11:23:43  XPages series #4: Backing Bean Management with XPages

    I would not expect that there is a difference that you can measure. Your application requires an 8.5.2 server when you use the view scope bean, it does not run on 8.5.1 anymore.

    But 8.5.2 is a good choice anyway, for example because of the server-side OSGi support for XPages apps and the XPages extensibility API that saves you a lot of development time ( { Link } ).

    21A.G.Suriyan  08/11/2011 20:40:28  XPages series #4: Backing Bean Management with XPages

    Thanks for sharing your ideas.

    22Raphael R. Costa  08/27/2011 16:39:13  XPages series #4: Backing Bean Management with XPages

    Excelent series of articles!

    But, One question, I think you might mentioned the XPages was builded in a 1.2 JSF environment, but, when I tried to add to faces-config.xml the following tab:

    <resource-bundle>

    <cod-base>com.acme.messages</code-base>

    <var>msgs</var>

    </resource-bundle>

    The XPages just ignored and didnt recognize the var "msgs" of my resource bundle.

    So, I had to include the resource bundle myself on every single XPages :(

    Did I do something wrong? Or XPages is actually a 1.1 JSF implementation?

    Any way,

    Cant wait to put in practice some ideas that you shared.

    23Dan Soares  02/25/2013 16:57:36  XPages series #4: Backing Bean Management with XPages

    Hi Karsten,

    This was an excellent article. I'm working through implementing the code, but I get the following error:

    HTTP JVM: com.ibm.xsp.webapp.FacesServlet$ExtendedServletException: javax.faces.el.PropertyNotFoundException: Error getting property 'studentID' from bean of type edu.phc.students.model.Student

    If I remove reference to studentID and and only get firstName and lastName, the method works great and the datatable is populated.

    Thanks,

    Dan

    24Karsten Lehmann  02/25/2013 17:58:57  XPages series #4: Backing Bean Management with XPages

    Dan, do you have a method "getStudentID()" in your bean? Maybe it's missing or there is a typo in the code (Id - ID?)

    25Dan  02/25/2013 19:43:55  XPages series #4: Backing Bean Management with XPages

    Karsten,

    I was able to get it working. I just renamed the property to id (lowercase). Like you said, it was probably a typo somewhere.

    I have another question that kind of goes beyond the scope of this article. I want to integrate this XPage with a student information system to pull data into the datatable.

    I have the JDBC code to query the MS SQL db and generate the result set. I just don't know how to pass the connection parameters to the bean or how to call the bean from the lookup button.

    Would appreciate some pointers.

    Thanks,

    Dan

    26Karsten Lehmann  02/25/2013 23:30:49  XPages series #4: Backing Bean Management with XPages

    I would take a look at this:

    { Link }

    That solution seems to handle connection pooling automatically and should be available as open source.

    Otherwise you would need to make sure yourself that your connection is closed after reading the data from the JDBC driver and you might get some troubles with SecurityManager restrictions.

    Haven't really played with JDBC in XPages so far.

    27Dan Soares  02/26/2013 18:42:25  XPages series #4: Backing Bean Management with XPages

    Thanks Karsten!

    28  04/12/2013 20:12:00  XPages series #4: Backing Bean Management with XPages

    Karsten,

    Forgive this very basic question but using SSJS, how would you iterate through the list of actors and their properties in the example above?

    I have understood and implemented your your datatable example. I now want to (from a button) act on each element of that Java Array.

    Thanks,

    Dan

    29Karsten Lehmann  04/13/2013 14:20:40  XPages series #4: Backing Bean Management with XPages

    Dan, I think this should work:

    var actorList=ActorList.getActors();

    for (var i=0; i<actorList.size(); i++) {

    var currActor=actorList.get(i);

    var currId=currActor.getId();

    var currFirstname=currActor.getFirstname();

    var currLastname=currActor.getLastname();

    //do something with the actor here

    }

    30Dan Soares  04/22/2013 19:21:31  XPages series #4: Backing Bean Management with XPages

    Thanks so much Karsten. I have another use case scenario.

    How would I use the Actor bean to populate the values of a keyword field?

    For example, I have a combo box. For the values, I am using the 'Add formula Item' option. And this is my SSJS:

    Actorlist.setConnDB("jdbc:sqlserver://XX.XX.X.XX:1433;DatabaseName=Test");

    Actorlist.setConnUserName("sa");

    Actorlist.setConnPassword("password");

    Actorlist.setSQLQuery("SELECT DISTINCT Name FROM TestTable");

    Actorlist.actors;

    I get the error - 'edu.phc.students.model.actor incompatible with javax.faces.model.SelectItem'

    What am I doing wrong?

    Thank you,

    Dan

    31Dan Soares  04/22/2013 22:48:02  XPages series #4: Backing Bean Management with XPages

    Karsten, I was able to resolve this by changing the implementation to get an array of Strings to be used as selectItems attributes.

    Thanks,

    Dan

    32Kim Hansen  11/01/2013 19:35:29  XPages series #4: Backing Bean Management with XPages

    Hi Karsten,

    great article!

    How would you go around implementing the paging functionality of the getActors() method?

    If I had 1 billion actors to read from and I only wanted to return say 10 items each time and only the 10 items that match that specific page number? And how to calculate the total number of pages?

    Thanks,

    Kim

    33Karsten Lehmann  11/13/2013 0:58:52  XPages series #4: Backing Bean Management with XPages

    Hi Kim,

    that's a difficult question, because I completely left classic XPages development since I wrote the XPages series in 2009. My current approach is based on REST services on the server side and client side code that reads/writes its content via these services.

    So no XPages pager involved and not a single managed bean.

    One way to implement paging for the actors sample would be a special implementation of java.util.List that we developed and that loads its data in pages, so when page size is 50 and you call myList.get(0), it loads the first page, while myList.get(50) loads the second page.

    This works quit well when no reader fields are involved. Otherwise the list would contain gaps, because the row counts that get returned for Views include docs hidden via reader fields, so your List size might be too high.

    Another thing we did was that we implemented our own virtual scroller, quite similar to the lazy loading of the Facebook activity stream. So we load more entries when the user scrolls to the bottom and provide a few buttons for quick navigation (+/- 5 pages, scroll to the beginning/end of the view etc.).

    To load more entries we are passing the ViewEntry position string (e.g. 1.2.3) of the last visibie entry and the number of entries to return to our REST service.

    The REST service then uses the ViewNavigator to locate the entry at that position and starts reading data (either flat or categorized view data, where we also send the expanded view entry positions to the server).

    Best regards,

    Karsten

    34Andrew Magerman  09/21/2014 20:39:53  XPages series #4: Backing Bean Management with XPages

    Dear Karsten,

    You made a comment in 2009 about the RAD Nature of XPages which I found really accurate.

    I'm curious as to what front-end you are using - Angular, perhaps?

    I'm an XPages newb and I'm finding it irritating, but if I can jump over it I would be grateful.

    Great articles, by the way!

    35Karsten Lehmann  09/22/2014 0:07:36  XPages series #4: Backing Bean Management with XPages

    Thanks Andrew!

    I just created a blog article about tools we use to build web apps:

    { Link }

    • Remember me