Interval Timer in XPages losing Date value on refresh - xpages

Hi I have a 'mail in' application and display the emails waiting in the queue (line) on a 'wallboard'. I wish to refresh the display every x seconds using a partial refresh of the repeat containing the mail data. This works fine other than the I have a problem with a date field, which displays correctly until the first refresh, when it converts to the default 1 Jan 1970. I use the created date to calculate the no. of minutes the mail has been waiting - not shown here.
Any help would be appreciated.
Many thanks
On the XPage I have:
<xp:scriptBlock
id="scriptBlockRefresh">
<xp:this.value>
<![CDATA[
setInterval(function() {
XSP.partialRefreshGet("#{id:mailInPanel}", {})
}, 5 * 1000)
]]>
</xp:this.value>
</xp:scriptBlock>
<xp:this.beforePageLoad><![CDATA[#{javascript:miniWallboardBean.loadOutstandingMailin();}]]></xp:this.beforePageLoad>
<xp:panel id="mailInPanel">
<xp:repeat id="repeat1" rows="30" value="#{miniWallboardBean.outstandingMailin}" var="rowData">
<xp:text escape="true" id="computedField1" value="#{rowData.from}"></xp:text>
<xp:text escape="true" id="computedField2" value="#{rowData.subject}"></xp:text>
<xp:text escape="true" id="computedField5" value="#{javascript:rowData.getCreatedDate().toJavaDate()}"></xp:text>
</xp:repeat>
</xp:panel>
In my Mailin Class
import lotus.domino.DateTime;
public class Mailin {
private String from;
private String subject;
private DateTime createdDate;
private String owner;
public String getFrom() {return from;}
public void setFrom(String from) {this.from = from;}
public String getSubject() {return subject;}
public void setSubject(String subject) {this.subject = subject;}
public DateTime getCreatedDate() {return createdDate;}
public void setCreatedDate(DateTime createdDate) {this.createdDate = createdDate;}
public String getOwner() {return owner;}
public void setOwner(String owner) {this.owner = owner;}
}
I get the data from view columns in my business logic:
public List <Mailin> getOutstandingMailin(){
ArrayList<Mailin> outstandingMailin = new ArrayList<Mailin>();
try {
ViewEntryCollection entries = NCLWallboardUtil.getAllEntries("Server","DB","View"); //Method to get a collection
if (entries !=null) {
ViewEntry entry = entries.getFirstEntry();
while (entry !=null){
Mailin mailin = loadMailInFromEntry(entry);
outstandingMailin.add(mailin);
ViewEntry oldEntry = entry;
entry = entries.getNextEntry(entry);
oldEntry.recycle();
}
entries.recycle();
}
} catch (NotesException e) {
e.printStackTrace();
}
return outstandingMailin;
}
private Mailin loadMailInFromEntry(ViewEntry entry) throws NotesException{
Mailin mailin = new Mailin();
mailin.setFrom((String) entry.getColumnValues().get(0));
mailin.setSubject((String) entry.getColumnValues().get(3));
mailin.setOwner((String) entry.getColumnValues().get(5));
mailin.setCreatedDate((DateTime) entry.getColumnValues().get(4));
return mailin;
}
In my session scope bean I have:
public class MiniWallboardBean implements Serializable{
private static final long serialVersionUID = 1L;
private List <Mailin> outstandingMailin;
private MiniWallboard miniWB;
public MiniWallboardBean(){
miniWB = new MiniWallboard();}
public void loadOutstandingMailin(){
try{
setOutstandingMailin(miniWB.getOutstandingMailin());
}catch (Exception e){
e.printStackTrace();
}
}
public void setOutstandingMailin(List <Mailin> outstandingMailil{
this.outstandingMailin = outstandingMailin;}
public List <Mailin> getOutstandingMailin() {
return outstandingMailin;}

DateTimes, like other Domino objects, are not serializable. So once the initially page load is completed and the Session recycled, your DateTime will also be recycled.
Store the values as Java Dates instead and you will be fine.

Related

radiogroup with tooltip not working properly

I have the same situation as one of previous questions :
checkboxgroup returning only last selected value
But this time only 1 value can be selected from the same data ,so I thought using a radio instead of a checkbox.
Values are comming from the repeat from the viewScope choices
<xp:repeat id="repeat4" rows="100" value="#{viewScope.choices}"
indexVar="rownumber" var="row" first="0">
<xp:radio id="radio1" groupName="selection">
<xp:this.text><![CDATA[#{javascript:row[3]}]]></xp:this.text>
<xp:this.value><![CDATA[#{viewScope.selected[rownumber]}]]></xp:this.value>
</xp:radio>
<xe:tooltip id="tooltip3" for="radio1">
<xe:this.label><![CDATA[#{javascript:return viewScope.choices[rownumber].get(3)}]]></xe:this.label>
</xe:tooltip>
</xp:repeat>
The tooltip seems correct but :
1) I can select all the radio boxes if I want instead of only one
2) data doesn't seem to update (so I don't know which box has been selected)
Add this onClientLoad CSJS code to your XPage:
<xp:eventHandler
event="onClientLoad"
submit="false">
<xp:this.script><![CDATA[
dojo.query("input").forEach(function(node){
var attr = node.getAttributeNode("name");
if (attr.value.indexOf(':selection') >= 0) {
attr.value = 'selection';
}
});
]]></xp:this.script>
</xp:eventHandler>
It "repairs" the name attribute of input elements so they get all the same name "selection" without the "repeat"-part:
from
to
Are you able to use a radio group?
<xp:radioGroup id="radioGroup1"></xp:radioGroup>
Question 1:
UPDATE:
You have to calculate a unique groupName for each row of your repeat control.
You have to calculate a common groupName for all of your radio buttons.
And there is the problem, each xp:radio control will be rendered with his own groupname, lets take a look at the rendered html code:
One possible workaround could be to work with native html:
<input id="radio1" type="radio" name="selection" value="#{viewScope.selected[rownumber]}">
</input>
If you need the full functionality of the xp:radio button core control then another option could be to rename the name property of your xp:radio buttons after rendering (e.g. with client side javascript).
Question 2:
I use a valueChangeListener for this purpose.
Example (from my own project):
XPage:
<xp:repeat var="entry" rows="30" value="#{accessBean.entries}" removeRepeat="true" repeatControls="false">
<xp:radio id="rbReadAccess" rendered="#{javascript:docData.isEditable()}"
title="Set read access" value="#{entry.accessLevelAsString}" selectedValue="READACCESS"
groupName="#{entry.name}" valueChangeListener="#{accessBean.accessLevelChanged}">
<xp:eventHandler event="onchange" submit="true" refreshMode="partial"
refreshId="pnlAccessControl">
</xp:eventHandler>
</xp:radio>
<xp:radio id="rbEditAccess" rendered="#{javascript:docData.isEditable()}"
title="Set edit access" value="#{entry.accessLevelAsString}" selectedValue="EDITACCESS"
groupName="#{entry.name}" valueChangeListener="#{accessBean.accessLevelChanged}">
<xp:eventHandler event="onchange" submit="true" refreshMode="partial"
refreshId="pnlAccessControl">
</xp:eventHandler>
</xp:radio>
<xp:radio id="rbFullAccess" rendered="#{javascript:docData.isEditable()}"
title="Set full access" value="#{entry.accessLevelAsString}" selectedValue="FULLACCESS"
groupName="#{entry.name}" valueChangeListener="#{accessBean.accessLevelChanged}">
<xp:eventHandler event="onchange" submit="true" refreshMode="partial"
refreshId="pnlAccessControl">
</xp:eventHandler>
</xp:radio>
</xp:repeat>
AccessControlBean:
public class AccessControlBean implements Serializable {
public Set<AccessControlEntry> getEntries() {
Set<AccessControlEntry> entries = new TreeSet<AccessControlEntry>(accessControlUserService.getEntries());
entries.addAll(accessControlGroupService.getEntries());
return entries;
}
public void accessLevelChanged(ValueChangeEvent valueChangeEvent) {
XspInputRadio component = (XspInputRadio) valueChangeEvent.getComponent();
System.out.println("phaseId: " + valueChangeEvent.getPhaseId());
System.out.println("accessLevelChanged");
System.out.println(component.getGroupName());
System.out.println("oldValue: " + valueChangeEvent.getOldValue());
System.out.println("newValue: " + valueChangeEvent.getNewValue());
}
}
AccessControlEntry:
public class AccessControlEntry implements Comparable<AccessControlEntry> {
// Enumerations
public static enum AccessLevel {
READACCESS,
EDITACCESS,
FULLACCESS;
}
// Fields
private String name;
private AccessLevel accessLevel;
private boolean accessLevelRestricted = false;
// Constructors
public AccessControlEntry(String name, AccessLevel accessLevel) {
this.name = name;
this.accessLevel = accessLevel;
}
// Getter & Setter
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public AccessLevel getAccessLevel() {
return accessLevel;
}
public void setAccessLevel(AccessLevel accessLevel) {
this.accessLevel = accessLevel;
}
// nessecary for EL (managed bean)
public String getAccessLevelAsString() {
return accessLevel.toString();
}
// nessecary for EL (managed bean)
public void setAccessLevelAsString(String accessLevel) {
this.accessLevel = AccessLevel.valueOf(accessLevel.toUpperCase());
}
// Operations
public boolean isReadAccess() {
return accessLevel == AccessLevel.READACCESS;
}
public void setEditAccess(boolean editAccessRestricted) {
accessLevel = AccessLevel.EDITACCESS;
accessLevelRestricted = editAccessRestricted;
}
public boolean isEditAccess() {
return accessLevel == AccessLevel.EDITACCESS;
}
public boolean isEditAccessRestricted() {
return isEditAccess() && accessLevelRestricted;
}
public void setFullAccess(boolean fullAccessRestricted) {
accessLevel = AccessLevel.FULLACCESS;
accessLevelRestricted = fullAccessRestricted;
}
public boolean isFullAccess() {
return accessLevel == AccessLevel.FULLACCESS;
}
public boolean isFullAccessRestricted() {
return isFullAccess() && accessLevelRestricted;
}
public int compareTo(AccessControlEntry aControlEntry) {
return getName().compareTo(aControlEntry.getName());
}
#Override
public String toString() {
return getClass().getSimpleName() + ": name=\"" + name +
"\", accessLevel=\"" + accessLevel +
"\", isEditAccessRestricted=\"" + isEditAccessRestricted() +
"\", isFullAccessRestricted=\"" + isFullAccessRestricted() + "\"";
}
}

Xpages: 'RichText' field on web and saving with java bean

I have a requirement to allow users to enter 'RichText' in a field in an Xpages form on the web. It is just rich text (bold, size, color) no attachments/links/pictures. And no need to edit it on the client.
I have googled this and put together something that kind of is close, but doesn't work. I am only trying to get a minimal working example right now.
Used some info in this link and in another one I cannot find right now.
Any help would be greatly appreciated.
Xpage:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:messages id="messages1"></xp:messages>
<xp:panel id="pnlAll">
<xp:this.data>
<xe:objectData saveObject="#{javascript:docModel.save()}"
var="docModel">
<xe:this.createObject><![CDATA[#{javascript:var docModel = new com.scoular.model.Doc();
var unid = sessionScope.get("key");
if (unid != null) {
docModel.loadByUnid(unid);
sessionScope.put("key","");
viewScope.put("readOnly","Yes");
} else {
docModel.create();
viewScope.put("readOnly","No");
}
return docModel;}]]></xe:this.createObject>
</xe:objectData>
</xp:this.data>
<xp:inputRichText id="inputRichText1"
value="#{docModel.body}">
</xp:inputRichText>
<xp:button value="Save"
id="button1"
type="button"
styleClass="btn-primary">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete" save="true">
<xp:this.action><![CDATA[#{javascript:if (docModel.save() == true) {
}}]]></xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:view>
Java:
package com.scoular.model;
import java.io.Serializable;
import java.util.Date;
import org.openntf.domino.Database;
import lotus.domino.MIMEEntity;
import lotus.domino.Stream;
import org.openntf.domino.DateTime;
import org.openntf.domino.Document;
import org.openntf.domino.Session;
import org.openntf.domino.utils.Factory;
import org.openntf.domino.xsp.XspOpenLogUtil;
public class Doc implements Serializable {
private static final long serialVersionUID = -5867831497684227875L;
private com.ibm.xsp.http.MimeMultipart body;
// Common Fields
private String unid;
private Boolean newNote;
private DateTime crtDte;
private String crtUsr;
public Doc() {
}
public void create() {
try {
newNote = true;
Session session = Factory.getSession();
Date date = new Date();
crtDte = session.createDateTime(date);
crtUsr = session.getEffectiveUserName();
} catch (Exception e) {
XspOpenLogUtil.logError(e);
}
}
public void loadByUnid(String unid) {
try {
Session session = Factory.getSession();
String DataDBpath = session.getCurrentDatabase().getServer() + "!!" + "scoApps\\Spectrum\\cashmarkData.nsf";
Database DataDB = session.getDatabase(DataDBpath);
Document doc = DataDB.getDocumentByUNID(unid);
if (null == doc) {
System.out.println("Document not found");
} else {
loadValues(doc);
}
} catch (Exception e) {
XspOpenLogUtil.logError(e);
}
}
public void loadValues(Document doc) {
try {
// common fields
newNote = false;
unid = doc.getUniversalID();
crtDte = doc.getItemValue("checkInDate", DateTime.class);
crtUsr = doc.getItemValueString("crtUsr");
// custom fields
} catch (Exception e) {
XspOpenLogUtil.logError(e);
}
}
public boolean save() {
boolean tmpSave = true;
try {
Document doc = null;
Session session = Factory.getSession();
String DataDBpath = session.getCurrentDatabase().getServer() + "!!" + "scoApps\\Spectrum\\cashmarkData.nsf";
Database DataDB = session.getDatabase(DataDBpath);
if (newNote) {
doc = DataDB.createDocument();
doc.put("form", "doc");
} else {
doc = DataDB.getDocumentByUNID(unid);
}
//Create the body as a MIME entity
session.setConvertMIME(false); // Do not convert MIME to RT MIMEEntity body = doc.createMIMEEntity("body");
Stream stream = session.createStream();
stream.writeText("<ul><li>hello</li><li>world</li></ul>Google");
//body.setContentFromText(stream, "text/html;charset=UTF-8", MIMEEntity.ENC_IDENTITY_7BIT);
stream.close();
doc.save();
} catch (Exception e) {
XspOpenLogUtil.logError(e);
}
return tmpSave;
}
// Getters and Setters for common fields
public String getUnid() {
return unid;
}
public void setUnid(String unid) {
this.unid = unid;
}
public Boolean getNewNote() {
return newNote;
}
public void setNewNote(Boolean newNote) {
this.newNote = newNote;
}
public DateTime getCrtDte() {
return crtDte;
}
public void setCrtDte(DateTime crtDte) {
this.crtDte = crtDte;
}
public String getCrtUsr() {
return crtUsr;
}
public void setCrtUsr(String crtUsr) {
this.crtUsr = crtUsr;
}
public com.ibm.xsp.http.MimeMultipart getBody() {
return body;
}
public void setbody(com.ibm.xsp.http.MimeMultipart body) {
this.body = body;
}
}
To save your MimeMultipart to a MimeEntity field give this a try:
String fieldName = "yourFieldName";
if (doc.hasItem(fieldName))
doc.removeItem(fieldName);
Stream stream = session.createStream();
stream.writeText(body.getHTML());
MIMEEntity mimeEnt = doc.createMIMEEntity(fieldName);
mimeEnt.setContentFromText(stream,
"text/html;charset=UTF-8", MIMEntity.ENC_NONE);
stream.close();
stream.recycle();
Also you may want to remove some CKEditor plugins by adding a dojoAttribute called 'removePlugins'
<xp:inputRichText id="inputRichText1">
<xp:this.dojoAttributes>
<xp:dojoAttribute name="removePlugins"
value="ibmxspimage,smiley,ibmsametimeemoticons"></xp:dojoAttribute>
</xp:this.dojoAttributes>
</xp:inputRichText>
This will remove the toolbar buttons that allow the user to choose emoticons / upload images (which will cause an error)
Note however this will not prevent users from trying to paste Images into the CKEditor, to prevent that you need to make/obtain a custom CKEditor plugin that prevents pasting images both via a 'Data URL' (clipboard paste) or via 'Href' e.g. web address based images.

Populating selectItems of the combobox (label, value) using a managed bean

I have a combo in my page which I want to have populated with some keywords from configuration. I want to use a managed bean to accomplish it.
Let's say that I have a bean called Config, where there is a List categories field. ..
public class Configuration implements Serializable {
private static final long serialVersionUID = 1L;
private List<String> categories;
public List<String> getCategories() {
if (categories == null)
categories = getCats();
return categories;
}
//... etc.
}
When I use this field for my combo, it works well...
<xp:comboBox>
<xp:selectItems>
<xp:this.value><![CDATA[#{config.categories}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
But, it's only a list of labels. I need values, too. How do I populate selectItems of my combo with TWO strings - a label and a value?
EDIT:
I tried to create an object Combo with label and value fields and use a repeat inside my comboBox.
<xp:comboBox>
<xp:repeat id="repeat1" value="#{config.combo}" var="c" rows="30">
<xp:selectItem itemLabel="#{c.label}" itemValue="#{c.value}" />
</xp:repeat>
</xp:comboBox>
Still not working... :-(
Instead of returning a List<String> your function should return a List<javax.faces.model.SelectItem>. Here's a sample:
public static List<SelectItem> getComboboxOptions() {
List<SelectItem> options = new ArrayList<SelectItem>();
SelectItem option = new SelectItem();
option.setLabel("Here's a label");
option.setValue("Here's a value");
options.add(option);
return options;
}
Advantage of using this method (besides not having to use that nonconceptual stuff :-) is that you can also the SelectItemGroup class to group the options:
public static List<SelectItem> getGroupedComboboxOptions() {
List<SelectItem> groupedOptions = new ArrayList<SelectItem>();
SelectItemGroup group = new SelectItemGroup("A group of options");
SelectItem[] options = new SelectItem[2];
options[0] = new SelectItem("here's a value", "here's a label");
options[1] = new SelectItem("here's a value", "here's a label");
group.setSelectItems(options);
groupedOptions.add(group);
return groupedOptions;
}
You can use SelectItems. (see http://docs.oracle.com/javaee/6/api/javax/faces/model/SelectItem.html)
You can specify both value and label, or value only.
import javax.faces.model.SelectItem;
public List<SelectItem> getCategories() {
try {
ArrayList<SelectItem> ret = new ArrayList<SelectItem>();
ret.add(new SelectItem("my value", "my label"));
return ret;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}

Netbeans CRUD generator: customization and is it efficient for real applications?

I use netbeans 7.2.1. Is JSF CRUD Generated code efficient for real applications?
I have created a test database and used netbeans CRUD generator. It uses DataModel and PaginationHelper instead of Lists for CRUD operations. There is an Entity Test.java, a TestFacade.java and TestController.java. and jsf files list.xhtml, edit.xhtml, view.xhtml, create.xhtml. I added a NemdQuery to entity file:
#Entity
#NamedQuery(name = "Test.findByTestCriteria", query = "SELECT t FROM Test t WHERE t.testCriteria = true")
public class Test implements Serializable {
private static final long serialVersionUID = 1L;
#Id
#GeneratedValue
#Column(name = "id")
private Integer id;
#Column(name = "title")
private String title;
#Column(name = "testCrieteria")
private boolean testCrieteria;
public Test() {
}
//Getters and Setters
And created the query in TestFacade.java:
#Stateless
public class TestFacade extends AbstractFacade<Test> {
#PersistenceContext(unitName = "testPU")
private EntityManager em;
#Override
protected EntityManager getEntityManager() {
return em;
}
public TestFacade() {
super(Test.class);
}
public List<Test> testCriteria(){
Query q = em.createNamedQuery("Test.findByTestCriteria",Test.class);
return q.getResultList();
}
}
And I have added a method in TestController.java to retrieve testCriteria Query:
#ManagedBean(name = "testController")
#SessionScoped
public class TestController implements Serializable {
private Test current;
private DataModel items = null;
private DataModel testCriteria = null;
#EJB
private com.test.TestFacade ejbFacade;
private PaginationHelper pagination;
private int selectedItemIndex;
public Test getSelected() {
if (current == null) {
current = new Test();
selectedItemIndex = -1;
}
return current;
}
public PaginationHelper getPagination() {
if (pagination == null) {
pagination = new PaginationHelper(10) {
#Override
public int getItemsCount() {
return getFacade().count();
}
#Override
public DataModel createPageDataModel() {
return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}));
}
};
}
return pagination;
}
public DataModel getItems() {
if (items == null) {
items = getPagination().createPageDataModel();
}
return items;
}
public String prepareList() {
recreateModel();
return "List";
}
public String prepareView() {
current = (Test) getItems().getRowData();
selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
return "View";
}
//getting testCriteria items
public DataModel getTestCriteria(){
if(items == null){
items = getPagination().createPageDataModel();
}
testCriteria = new ListDataModel(ejbFacade.testCriteria());
return testCriteria;
}
//custom view page
public String viewTest(){
current = (Test) getItems().getRowData();
selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
return "ViewTest?faces-redirect=true";
}
//custom viewTestCriteria
public String viewTestCriteria(){
current = (Test) getTestCriteria ().getRowData();
selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
return "ViewTest?faces-redirect=true";
}
And Retrieving testCriteria in a p:dataGrid in index.xhtml:
<h:form>
<p:dataGrid value="#{testController.testCriteria()}" var="item" columns="4">
<p:column>
<h:panelGrid columns="1">
<h:commandLink id="viewTestCriteria" value="#{item.title}" action="#{testController.viewTestCriteria()}"/>
</h:panelGrid>
</p:column>
</p:dataGrid>
</h:form>
With this code all testCriteria data are there in index.xhtml but when I click the commadnButton to view them they all show the first Item. It seems that in the DataGrid it doesn't get the selected item. And if I refresh the List.xhtml which contains all test data, and then coming back to index.xhtml and pressing commandLink it throws a NoRowAvailable exception.
I hope I have stated my question clearly and I would appreciate any guide because I am new to this technology.
Update:
After googling and research for two days and thinking I thought of using <f:setPropertyActionListener value="#{item.id}" target="#{testController.selected.id}"> and <f:param name="#{testController.selected.id}" value="#{item.id}"> but it didn't work.
Update:
So far I'm almost confident that no row is getting selected so the data grid returns first row. But I'm still not sure how to modify viewTestCriteria() to set the current item and selectedItemIndex correctly.

How do I iterate through the properties of a bean to populate cells of spreadsheet

I'm using POI to generate the Excel spreadsheet from my managed bean. Here's my Student Bean:
package edu.phc.students.model;
public class Student {
private String m_firstName;
private String m_lastName;
private String m_id;
public Student() {}
public Student(
String firstName,
String lastName,
String id,
)
{
m_firstName=firstName;
m_lastName=lastName;
m_id=id;
}
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;
}
}
This is a small segment of the final code (SSJS).
var students:java.util.List = studentlist.getStudents();
var iterator:java.util.Iterator = students.iterator();
var count = 0;
while (iterator.hasNext()) {
var student:edu.phc.students.model.Student = iterator.next();
count++;
var row:HSSFRow = sheet1.createRow(count);
for( f = 0 ; f <= fieldList.length-1 ; f++){//column List
// output student's data into Excel row
row.createCell((java.lang.Integer)(f)).setCellValue(student.getid());
}
}
This works perfectly. It generates the spreadsheet with the column names and inserts the student ID into each cell (for each row returned by the iterator).
However, I want to iterate through the properties available for the student bean - ID, Lastname, Firstname etc. and populate the cells of the spreadsheet. How do I do that? Can I reference the properties of the student bean by index?
Thanks,
Dan
You could use java.lang.reflection. Here is an example for all fields in your student class:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:repeat id="repeat1" rows="30" var="field">
<xp:this.value><![CDATA[#{javascript:
var student = new edu.phc.students.model.Student();
student.getClass().getDeclaredFields()}]]>
</xp:this.value>
<xp:label value="#{field.name}" id="labelFieldName" /><xp:br />
</xp:repeat>
</xp:view>
The output looks like this:
m_firstName
m_lastName
m_id
Please check the documentation for other options.
EDIT:
This example iterates the methods and returns the current values of all methods which return a String:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:repeat id="repeat1" rows="30" var="method">
<xp:this.value><![CDATA[#{javascript:
var student = new edu.phc.students.model.Student();
student.setid("A");
student.setLastname("Meiser");
student.setFirstname("Hans");
student.getClass().getDeclaredMethods()}]]>
</xp:this.value>
<xp:label id="label1">
<xp:this.value>
<![CDATA[#{javascript:
if( method.getReturnType().getSimpleName() == 'String' )
return method.invoke(student, null );}]]>
</xp:this.value>
</xp:label>
<xp:br />
</xp:repeat>
</xp:view>
This will create the following output:
A
Hans
Meiser

Resources