Performance like a line of schoolkids awaiting first Jab.
tony.herstell1 Aug 12, 2008 1:38 AMI have a page that is running appallingly slow.
I have provided code below.
Question 1: Can anyone spot the problem?
Question 2: What tools are recommended for analysing the problem.
This is running on Prod just as slow (if not slower) than Dev.
There are a lot of set/gets as @Out with boolean doesn't work so you have to add routines (not that I even found why in the manual). Another little quirk of Seam I guess. Have code with @Out for most private values and then put/get for booleans...
Given this:
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"
xmlns:s="http://jboss.com/products/seam/taglib" xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="/WEB-INF/pages/templateCleanWithConversations.xhtml">
<!-- content -->
<ui:define name="template_title">
<h:outputText value="#{messages.user_list_page}" />
</ui:define>
<ui:define name="template_content">
<div id="reg_form">
<h:form class="general_form">
<fieldset class="general_form_fieldset">
<legend class="general_form_legend">
<h:outputText value="#{messages.user_list_fieldset}" />
</legend>
<s:validateAll>
<!-- CONTROLS -->
<div class="left">
<span class="padded_right_left">
<h:outputLabel for="show_avatar" value="Show Avatar"/>
<h:selectBooleanCheckbox id="show_avatar" value="#{userListController.showingAvatar}">
<a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" />
</h:selectBooleanCheckbox>
</span>
<span class="padded_right_left">
<h:outputLabel for="show_email" value="Show Email"/>
<h:selectBooleanCheckbox id="show_email" value="#{userListController.showingEmail}">
<a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" />
</h:selectBooleanCheckbox>
</span>
<span class="padded_right_left">
<h:outputLabel for="show_phone" value="Show Phone"/>
<h:selectBooleanCheckbox id="show_phone" value="#{userListController.showingPhone}">
<a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" />
</h:selectBooleanCheckbox>
</span>
<span class="padded_right_left">
<h:outputLabel for="show_dressage" value="Show Dressage"/>
<h:selectBooleanCheckbox id="show_dressage" value="#{userListController.showingDressage}">
<a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" />
</h:selectBooleanCheckbox>
</span>
<span class="padded_right_left">
<h:outputLabel for="show_sj" value="Show SJ"/>
<h:selectBooleanCheckbox id="show_sj" value="#{userListController.showingSJ}">
<a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" />
</h:selectBooleanCheckbox>
</span>
<span class="padded_right_left">
<h:outputLabel for="show_showing" value="Show Showing"/>
<h:selectBooleanCheckbox id="show_showing" value="#{userListController.showingShowing}">
<a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" />
</h:selectBooleanCheckbox>
</span>
<span class="padded_right_left">
<h:outputLabel for="show_events" value="Show Events"/>
<h:selectBooleanCheckbox id="show_events" value="#{userListController.showingEvents}">
<a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" />
</h:selectBooleanCheckbox>
</span>
<span class="padded_right_left">
<h:outputLabel for="show_dates" value="Show Dates"/>
<h:selectBooleanCheckbox id="show_dates" value="#{userListController.showingDates}">
<a4j:support event="onclick" eventsQueue="eventsQueue" LimitToList="true" reRender="users_list" />
</h:selectBooleanCheckbox>
</span>
</div>
<div>
<br/>
<br/>
</div>
<!-- TABLE -->
<rich:dataTable id="users_list" value="#{userList}" var="eachUser"
columnClasses="center" rows="20" width="100%">
<f:facet name="header">
<h:outputText value="Users" />
</f:facet>
<rich:column rendered="#{userListController.isShowingAvatar() eq true}">
<f:facet name="header">
<h:outputText value="Avatar" />
</f:facet>
<s:graphicImage width="75px" rendered="#{eachUser.avatar ne null}" value="#{eachUser.avatar.image}" />
</rich:column>
<rich:column sortBy="#{eachUser.surname}">
<f:facet name="header">
<h:outputText value="Surname" />
</f:facet>
<h:outputText value="#{eachUser.surname}" />
</rich:column>
<rich:column sortBy="#{eachUser.firstname}">
<f:facet name="header">
<h:outputText value="Firstname" />
</f:facet>
<h:outputText value="#{eachUser.firstname}" />
</rich:column>
<rich:column rendered="#{userListController.isShowingEmail() eq true}">
<f:facet name="header">
<h:outputText value="Email" />
</f:facet>
<h:outputText value="#{eachUser.email}" />
</rich:column>
<rich:column sortBy="#{eachUser.homePhone}" rendered="#{userListController.isShowingPhone() eq true}">
<f:facet name="header">
<h:outputText value="Home Phone" />
</f:facet>
<h:outputText value="#{eachUser.homePhone}" />
</rich:column>
<rich:column sortBy="#{eachUser.mobilePhone}" rendered="#{userListController.isShowingPhone() eq true}">
<f:facet name="header">
<h:outputText value="Mobile Phone" />
</f:facet>
<h:outputText value="#{eachUser.mobilePhone}" />
</rich:column>
<rich:column sortBy="#{eachUser.phoneContactOk}" rendered="#{userListController.isShowingPhone() eq true}">
<f:facet name="header">
<h:outputText value="Phone Contact Ok" />
</f:facet>
<s:graphicImage rendered="#{eachUser.phoneContactOk}" url="/images/tick.gif" />
<s:graphicImage rendered="#{not eachUser.phoneContactOk}" url="/images/cross.gif" />
</rich:column>
<rich:column sortBy="#{eachUser.dressageJudge}" rendered="#{userListController.isShowingDressage() eq true}">
<f:facet name="header">
<h:outputText value="Dressage Judge" />
</f:facet>
<s:graphicImage rendered="#{eachUser.dressageJudge}" url="/images/tick.gif" />
<s:graphicImage rendered="#{not eachUser.dressageJudge}" url="/images/cross.gif" />
</rich:column>
<rich:column sortBy="#{eachUser.dressageWriter}" rendered="#{userListController.isShowingDressage() eq true}">
<f:facet name="header">
<h:outputText value="Dressage Writer" />
</f:facet>
<s:graphicImage rendered="#{eachUser.dressageWriter}" url="/images/tick.gif" />
<s:graphicImage rendered="#{not eachUser.dressageWriter}" url="/images/cross.gif" />
</rich:column>
<rich:column sortBy="#{eachUser.dressageHelper}" rendered="#{userListController.isShowingDressage() eq true}">
<f:facet name="header">
<h:outputText value="Dressage Helper" />
</f:facet>
<s:graphicImage rendered="#{eachUser.dressageHelper}" url="/images/tick.gif" />
<s:graphicImage rendered="#{not eachUser.dressageHelper}" url="/images/cross.gif" />
</rich:column>
<rich:column sortBy="#{eachUser.sjJudge}" rendered="#{userListController.isShowingSJ() eq true}">
<f:facet name="header">
<h:outputText value="SJ Judge" />
</f:facet>
<s:graphicImage rendered="#{eachUser.sjJudge}" url="/images/tick.gif" />
<s:graphicImage rendered="#{not eachUser.sjJudge}" url="/images/cross.gif" />
</rich:column>
<rich:column sortBy="#{eachUser.sjHelper}" rendered="#{userListController.isShowingSJ() eq true}">
<f:facet name="header">
<h:outputText value="SJ Helper" />
</f:facet>
<s:graphicImage rendered="#{eachUser.sjHelper}" url="/images/tick.gif" />
<s:graphicImage rendered="#{not eachUser.sjHelper}" url="/images/cross.gif" />
</rich:column>
<rich:column sortBy="#{eachUser.showingJudge}" rendered="#{userListController.isShowingShowing() eq true}">
<f:facet name="header">
<h:outputText value="Showing Judge" />
</f:facet>
<s:graphicImage rendered="#{eachUser.showingJudge}" url="/images/tick.gif" />
<s:graphicImage rendered="#{not eachUser.showingJudge}" url="/images/cross.gif" />
</rich:column>
<rich:column sortBy="#{eachUser.showingHelper}" rendered="#{userListController.isShowingShowing() eq true}">
<f:facet name="header">
<h:outputText value="Showing Helper" />
</f:facet>
<s:graphicImage rendered="#{eachUser.showingHelper}" url="/images/tick.gif" />
<s:graphicImage rendered="#{not eachUser.showingHelper}" url="/images/cross.gif" />
</rich:column>
<rich:column sortBy="#{eachUser.eventsHelper}" rendered="#{userListController.isShowingEvents() eq true}">
<f:facet name="header">
<h:outputText value="Events Helper" />
</f:facet>
<s:graphicImage rendered="#{eachUser.eventsHelper}" url="/images/tick.gif" />
<s:graphicImage rendered="#{not eachUser.eventsHelper}" url="/images/cross.gif" />
</rich:column>
<rich:column sortBy="#{eachUser.dates.creationDate}" rendered="#{userListController.isShowingDates() eq true}">
<f:facet name="header">
<h:outputText value="Creation Date" />
</f:facet>
<h:outputText value="#{eachUser.dates.creationDate}">
<s:convertDateTime pattern="dd/MMM/yyyy"/>
</h:outputText>
</rich:column>
</rich:dataTable>
<rich:datascroller for="users_list" maxPages="30"/>
</s:validateAll>
<div class="general_form_buttons">
<h:commandButton class="general_form_button" action="#{userListController.cancel}"
value="#{messages.general_button_cancel}" immediate="true" type="submit">
<s:conversationPropagation type="end" />
</h:commandButton>
</div>
</fieldset>
</h:form>
</div>
<a4j:status>
<f:facet name="start">
<h:graphicImage styleClass="page_foot_image" value="/images/ajax/animated_horse.gif" height="50" />
</f:facet>
</a4j:status>
</ui:define>
<!-- content -->
</ui:composition>
Running over this code:
package nz.co.selwynequestriancentre.action.user;
import java.io.Serializable;
import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import nz.co.selwynequestriancentre.model.entity.User;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Begin;
import org.jboss.seam.annotations.Conversational;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.End;
import org.jboss.seam.annotations.Factory;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.log.Log;
import java.util.List;
/**
* @author Tony Herstell
* @version $Revision: 1.2 $ $Date: 2008-08-11 07:09:14 $
*/
@SuppressWarnings("serial")
@Stateful
@Name("userListController")
@Conversational
@Scope(value=ScopeType.CONVERSATION)
public class UserListControllerImpl implements UserListController, Serializable {
/**
* Inject and leverage the Seam Logger.
*/
@Logger
private Log log;
/**
* Inject the EJB3 Persistence context in EXTENDED mode so will remain
* "current" over multiple client/server round trips.
*/
@PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;
@DataModel
private List<User> userList;
private boolean showingAvatar = false;
private boolean showingEmail = false;
private boolean showingPhone = true;
private boolean showingDressage = true;
private boolean showingSJ = false;
private boolean showingShowing = false;
private boolean showingEvents = false;
private boolean showingDates = false;
@Factory("userList")
@TransactionAttribute(TransactionAttributeType.REQUIRED)
public void findUsers()
{
userList = em.createQuery("from User user order by user.surname asc").getResultList();
}
@TransactionAttribute(TransactionAttributeType.REQUIRED)
@Begin
public String enter() {
return "userListController";
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public boolean isShowingAvatar() {
return showingAvatar;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void setShowingAvatar(boolean showingAvatar) {
this.showingAvatar = showingAvatar;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public boolean isShowingEmail() {
return showingEmail;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void setShowingEmail(boolean showingEmail) {
this.showingEmail = showingEmail;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public boolean isShowingPhone() {
return showingPhone;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void setShowingPhone(boolean showingPhone) {
this.showingPhone = showingPhone;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public boolean isShowingDressage() {
return showingDressage;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void setShowingDressage(boolean showingDressage) {
this.showingDressage = showingDressage;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public boolean isShowingSJ() {
return showingSJ;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void setShowingSJ(boolean showingSJ) {
this.showingSJ = showingSJ;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public boolean isShowingShowing() {
return showingShowing;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void setShowingShowing(boolean showingShowing) {
this.showingShowing = showingShowing;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public boolean isShowingEvents() {
return showingEvents;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void setShowingEvents(boolean showingEvents) {
this.showingEvents = showingEvents;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public boolean isShowingDates() {
return showingDates;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void setShowingDates(boolean showingDates) {
this.showingDates = showingDates;
}
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
@End
public String cancel() {
log.info(">cancel");
log.info("<cancel");
return "home";
}
@Remove
@Destroy
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
public void destroy() {
log.info("> destory");
log.info("< destory");
}
}