JSF
After getting over the initial brain load of JSF, there are some pretty cool things about the technology. For instance, the following code handles the rendering of a menu bar and its state.
then the faces code for just the menu.
The first hurdle is the configuration - especially the navigation configuration. It seems like this could be quite a bit easier since you will have a navigation entry for each action/submit. There is something with the
The next part of this is that the C# equivalent code would simpiler to create simply because Visual Studio has been designed to help build these types of projects. Eclipse and its Web Tools project has definitely moved forward, but has yet to seemlessly integrate the faces configuration with the faces jsp files (not sure this is a goal either).
MyFaces.org (in the process of moving to apache) provides a great tool for moving jsf technology to the next level.
/*
* Created on Jan 21, 2005 for Project maridspace
* Filename: MessageFolderHandler.java
*
*/
package org.marid.application.faces.ui;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.ResourceBundle;
import javax.faces.application.Application;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import org.marid.fwk.application.MaridException;
import org.marid.services.personalmessenger.PersonalMessenger;
import org.marid.services.personalmessenger.folders.MessageFolder;
import org.marid.services.personalmessenger.folders.MessageFolderStatus;
import org.marid.services.personalmessenger.folders.MySQLMessageFolder;
/**
* @author pgirard
*/
public class MessageFolderHandler {
private static final Comparator ASC_NAME_COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2) {
String s1 = null;
String s2 = null;
try {
s1 = ((MessageFolder) o1).getName();
s2 = ((MessageFolder) o2).getName();
} catch (MaridException e) {
}
return s1.compareTo(s2);
}
};
private static final Comparator DESC_NAME_COMPARATOR = new Comparator() {
public int compare(Object o1, Object o2) {
String s1 = null;
String s2 = null;
try {
s1 = ((MessageFolder) o1).getName();
s2 = ((MessageFolder) o2).getName();
} catch (MaridException e) {
}
return s2.compareTo(s1);
}
};
private static final int SORT_BY_NAME = 0;
private boolean ascending = false;
private MessageFolder currentFolder;
private int firstRowIndex = 0;
private DataModel foldersModel;
private int noOfRows = 5;
private int sortBy = SORT_BY_NAME;
private boolean inEditor = false;
/**
*
*/
public MessageFolderHandler() {
super();
currentFolder = getCurrentFolder();
}
/**
* Returns the current folder instance, or a new instance
* if there's no current instance.
* @return MessageFolder
*/
public MessageFolder getCurrentFolder() {
if (currentFolder == null) {
currentFolder = createNewMessageFolder();
System.out.println("created new when getting current");
} else {
try {
System.out.println("getting current name = " + currentFolder.getName());
} catch (MaridException e) {
System.out.println("error getting name");
}
}
return currentFolder;
}
/**
* Creates a new MessageFolder and makes it the current folder.
* @return String
*/
public String create() {
currentFolder = createNewMessageFolder();
return "success";
}
/**
* Deletes the current folder, or queues an error message if
* the current user isn't allowed to do that
* @return String
*/
public String delete() {
try {
refreshCache();
}
catch (MaridException e) {
addMessage("registry_error", e.getMessage());
return "error";
}
if (isDeleteDisabled()) {
addMessage("report_no_delete_access", null);
return "error";
}
String outcome = "success";
try {
PersonalMessenger pm = PersonalMessenger.getInstance();
pm.getFolderChief().removeMessageFolder(currentFolder.getName());
currentFolder = pm.getFolderChief().getFolder("inbox");
}
catch (MaridException e) {
addMessage("registry_error", e.getMessage());
outcome = "error";
}
return outcome;
}
/**
*
* @return int
*/
public int getFirstRowIndex( ) {
return firstRowIndex;
}
/**
*
* @return List
*/
public List getFolders() {
PersonalMessenger pm = null;
List folders = new ArrayList();
try {
pm = PersonalMessenger.getInstance();
} catch (MaridException e) {
// whup couldn't get list - return nothing
System.out.println("Could not get pm instance!");
return folders;
}
for (MessageFolder folder : pm.getFolderChief().getFolders().values()) {
folders.add(folder);
}
return folders;
}
/**
*
* @return DataModel
*/
public DataModel getFoldersModel() {
if (foldersModel == null) {
foldersModel = new ListDataModel();
}
foldersModel.setWrappedData(getFolders());
return foldersModel;
}
/**
*
* @return int
*/
public int getNoOfRows( ) {
return noOfRows;
}
/**
*
* @return DataModel
*/
public DataModel getSortedFoldersModel( ) {
if (foldersModel == null) {
foldersModel = new ListDataModel( );
}
List folders = getFolders( );
sortFolders(folders);
foldersModel.setWrappedData(folders);
return foldersModel;
}
/**
* Returns "true" if the current folder is new or
* the current user isn't allowed to delete the folder.
* @return boolean
*/
public boolean isDeleteDisabled() {
boolean retval = true;
try {
retval = !inEditor || currentFolder.getName().equalsIgnoreCase("inbox") || currentFolder.getName().equalsIgnoreCase("trashbin");
} catch (MaridException e) {
// ignore
}
return retval;
}
/**
* Returns "true" if the current folder is new.
* @return boolean
*/
public boolean isNewDisabled() {
//return isFolderNew();
// you are always allowed to add a new folder unless you are editing one already
return inEditor;
}
/**
*
* @return boolean
*/
public boolean isScrollFirstDisabled( ) {
return firstRowIndex == 0;
}
/**
*
* @return boolean
*/
public boolean isScrollLastDisabled( ) {
return firstRowIndex >= foldersModel.getRowCount( ) - noOfRows;
}
/**
*
* @return boolean
*/
public boolean isScrollNextDisabled( ) {
return firstRowIndex >= foldersModel.getRowCount( ) - noOfRows;
}
/**
*
* @return boolean
*/
public boolean isScrollPreviousDisabled( ) {
return firstRowIndex == 0;
}
/**
* Returns "true" if the current folder is new.
* @return boolean
*/
public boolean isSubmitDisabled() {
boolean retval = true;
try {
retval = !inEditor || currentFolder.getName().equalsIgnoreCase("inbox") || currentFolder.getName().equalsIgnoreCase("trashbin");
} catch (MaridException e) {
// ignore
}
return retval;
}
/**
*
* @return String
*/
public String scrollFirst( ) {
firstRowIndex = 0;
return "success";
}
/**
*
* @return String
*/
public String scrollLast( ) {
firstRowIndex = foldersModel.getRowCount( ) - noOfRows;
if (firstRowIndex < 0) {
firstRowIndex = 0;
}
return "success";
}
/**
*
* @return String
*/
public String scrollNext( ) {
firstRowIndex += noOfRows;
if (firstRowIndex >= foldersModel.getRowCount( )) {
firstRowIndex = foldersModel.getRowCount( ) - noOfRows;
if (firstRowIndex < 0) {
firstRowIndex = 0;
}
}
return "success";
}
/**
*
* @return String
*/
public String scrollPrevious( ) {
firstRowIndex -= noOfRows;
if (firstRowIndex < 0) {
firstRowIndex = 0;
}
return "success";
}
/**
*
* @return String
*/
public String select() {
MessageFolder selectedFolder = (MessageFolder) foldersModel.getRowData();
currentFolder = selectedFolder;
try {
System.out.println("Selected folder " + selectedFolder.getName());
} catch (MaridException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
inEditor = true;
return "success";
}
/**
*
* @param noOfRows
*/
public void setNoOfRows(int noOfRows) {
this.noOfRows = noOfRows;
}
/**
*
* @return String
*/
public String sortByName( ) {
if (sortBy == SORT_BY_NAME) {
ascending = !ascending;
}
else {
sortBy = SORT_BY_NAME;
ascending = true;
}
return "success";
}
/**
* Submits the current folder, or queues an error message if
* the current user isn't allowed to do that or the registry
* throws an exception.
* @return String
*/
public String submit() {
try {
refreshCache();
}
catch (MaridException e) {
addMessage("registry_error", e.getMessage());
return "error";
}
if (this.isSubmitDisabled()) {
addMessage("report_no_submit_access", null);
return "error";
}
String outcome = "success";
MessageFolderStatus currentStatus = currentFolder.getStatus();
currentFolder.setStatus(MessageFolderStatus.STORED);
try {
//saveReport();
PersonalMessenger pm = PersonalMessenger.getInstance();
pm.getFolderChief().updateMessageFolder(currentFolder.getID(), currentFolder.getName());
}
catch (MaridException e) {
addMessage("registry_error", e.getMessage());
currentFolder.setStatus(MessageFolderStatus.STORED);
outcome = "error";
}
return outcome;
}
/**
* Adds the message matching the key in the application's
* resource bundle, formatted with the parameters (if any),
* the the JSF message queue as a global message.
* @param messageKey
* @param param
*/
private void addMessage(String messageKey, Object param) {
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
String messageBundleName = application.getMessageBundle();
Locale locale = context.getViewRoot().getLocale();
ResourceBundle rb =
ResourceBundle.getBundle(messageBundleName, locale);
String msgPattern = rb.getString(messageKey);
String msg = msgPattern;
if (param != null) {
Object[] params = {param};
msg = MessageFormat.format(msgPattern, params);
}
FacesMessage facesMsg =
new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, msg);
context.addMessage(null, facesMsg);
}
/**
* Creates a new MessageFolder instance initialized with the current
* user as the owner, and resets the cached entries DataModel.
* @return MessageFolder
*/
private MessageFolder createNewMessageFolder() {
MessageFolder folder = null;
try {
folder = new MySQLMessageFolder();
folder.setStatus(MessageFolderStatus.NEW);
} catch (MaridException e) {
System.out.println("Could not create folder");
}
return folder;
}
/**
* Returns "true" if the current report has status "new".
* @return boolean
*/
private boolean isFolderNew() {
return currentFolder.getStatus() == MessageFolderStatus.NEW;
}
/**
* If the current folder isn't new (i.e., not yet stored),
* refreshes the current folder with a copy from FolderChief
* @throws MaridException
*/
private void refreshCache() throws MaridException {
if (!isFolderNew()) {
PersonalMessenger pm = PersonalMessenger.getInstance();
setCurrentFolder(pm.getFolderChief().getFolder(currentFolder.getName()));
}
}
/**
* Makes the provided Folder the current folder
* @param folder
*/
private void setCurrentFolder(MessageFolder folder) {
currentFolder = folder;
}
private void sortFolders(List folders) {
switch (sortBy) {
case SORT_BY_NAME:
Collections.sort(folders,
ascending ? ASC_NAME_COMPARATOR : DESC_NAME_COMPARATOR);
break;
}
}
/**
*
* @return boolean
*/
public boolean isCancelRendered() {
return inEditor;
}
/**
*
* @return String
*/
public String cancel() {
inEditor = false;
return "success";
}
}
then the faces code for just the menu.
<table cellpadding="0" cellspacing="0" width="100%">
<tr>
<td>
<h:commandButton value="#{labels.newButtonLabel}"
disabled="#{reportHandler.newDisabled}"
action="#{reportHandler.create}" />
<h:commandButton value="#{labels.deleteButtonLabel}"
disabled="#{reportHandler.deleteDisabled}"
action="#{reportHandler.delete}" />
<h:commandButton value="#{labels.submitButtonLabel}"
disabled="#{reportHandler.submitDisabled}"
action="#{reportHandler.submit}" />
<h:commandButton value="#{labels.acceptButtonLabel}"
rendered="#{reportHandler.acceptRendered}"
disabled="#{reportHandler.acceptDisabled}"
action="#{reportHandler.accept}" />
<h:commandButton value="#{labels.rejectButtonLabel}"
rendered="#{reportHandler.rejectRendered}"
disabled="#{reportHandler.rejectDisabled}"
action="#{reportHandler.reject}" />
</td>
<td align="right">
<span class="small">
<h:outputText value="#{labels.loggedInAs}" />
"${pageContext.request.remoteUser}"
[<h:outputLink value="../../logout.jsp">
<h:outputText value="#{labels.logoutLinkLabel}" />
</h:outputLink>]
[<h:outputLink value="prefs.faces">
<h:outputText value="#{labels.prefLinkLabel}" />
</h:outputLink>]
</span>
</td>
</tr>
</table>
The first hurdle is the configuration - especially the navigation configuration. It seems like this could be quite a bit easier since you will have a navigation entry for each action/submit. There is something with the
/*
part of the configuration that I havent grokked yet.
The next part of this is that the C# equivalent code would simpiler to create simply because Visual Studio has been designed to help build these types of projects. Eclipse and its Web Tools project has definitely moved forward, but has yet to seemlessly integrate the faces configuration with the faces jsp files (not sure this is a goal either).
MyFaces.org (in the process of moving to apache) provides a great tool for moving jsf technology to the next level.
Comments