[JBoss Seam] - DataTable invokes bean one time too much
by QPool.Char
Hello, i have a small strange problem...
I have a datatable inside my JSF code.
<h:dataTable rendered="#{not empty pooledTaskInstanceList}"
| value="#{showWorkflows.tableContent}"
| var="task" >
|
| <h:column>
| <f:facet name="header"> Id </f:facet>
| <h:outputText value="#{task.taskID}"/>
| </h:column>
| ...
|
|
The JSF gets the data for the table as a Collection (ArrayList) from a stateless SessionBean.
| public ArrayList<ExeWorkflow> getTableContent() {
|
| log.info("INVOKE getTableContent");
|
| ArrayList<ExeWorkflow> result = new ArrayList<ExeWorkflow>();
|
| ... (some jBPM code)
|
| return result;
|
The Collection-objects are simple EntityClasses and the view is rendered correctly. But when i watch the JBOSS-console, i see that the getTableContent()-method is invoked always one time too often. Lets say we have one Object in the collection, then the method is invoked twice and so on...
Doesnt JSF just invoke this method one time and then create the datatable? Why should it invoke it so often? How can i assign a local var in JSF just for example like this: Collection c = value="#{showWorkflows.tableContent}" , so that it is just called one time?
Any more ideas?
Thx in advance
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4123653#4123653
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4123653
18 years, 5 months
[JBoss Seam] - Stateless bean holding data?
by Oberiko
Hello,
I have two pages, edit and search. From the edit screen, the user can go to the search screen (which also contains a list). From the search/list screen, they can select an entity to edit.
The problem is that my list, which is part of a stateless session bean, is being retained throughout trips to the search/list page. I.e., the previous search results are being shown after leaving and coming back.
Is this the expected behaviour? My edit page is backed by a stateful session bean using the default conversation scope, so could that be throwing things off? Should I just add a "clearList()" call to my links from the search page to empty it as I leave?
The code for the list page and its stateless session bean are below:
| package org.domain.myProject.session;
|
| import java.util.ArrayList;
| import java.util.List;
|
| import javax.ejb.Stateless;
| import javax.persistence.EntityManager;
| import javax.persistence.PersistenceContext;
|
| import org.domain.myProject.entity.Person;
| import org.domain.myProject.session.local.SearchPeopleLocal;
| import org.jboss.seam.annotations.In;
| import org.jboss.seam.annotations.Logger;
| import org.jboss.seam.annotations.Name;
| import org.jboss.seam.faces.FacesMessages;
| import org.jboss.seam.framework.EntityQuery;
| import org.jboss.seam.log.Log;
|
| @Stateless
| @Name("searchPeople")
| public class SearchPeopleAction implements SearchPeopleLocal {
| @Logger
| private Log log;
|
| @In
| FacesMessages facesMessages;
|
| @PersistenceContext
| private EntityManager em;
|
| private List<Person> peopleList;
|
| @SuppressWarnings("unchecked")
| public void search() {
| /*
| * We are using an EntityQuery since it seems to be the quickest solution to
| * dynamic searches.
| */
| EntityQuery eq = new EntityQuery();
| eq.setEntityManager(em);
| eq.setEjbql("from Person p");
|
| /*
| * The EntityQuery can have restrictions (basically the "WHERE" part of the SQL)
| * placed on the returned results. Since they are (I believe) called remotely
| * from this class, we have to pass the 'seamComponent.parameter' (which is
| * the value that we'll be restricting on) in expression language
| */
| List<String> restrictions = new ArrayList<String>();
| restrictions.add("lower(p.name) like lower(concat('%',#{searchPeople.name},'%'))");
| eq.setRestrictions(restrictions);
|
| peopleList = eq.getResultList();
|
| if (peopleList.size() == 0)
| facesMessages.add("Search returned no results");
|
| log.info("Result list size is #0", log.info("Result list size is #0", peopleList.size());
| }
|
| // ************ The below variables (and their getters / setters) are used to make
| // ************ the dynamic query
| private String name;
|
| public String getName() {
| return name;
| }
|
| public void setName(String name) {
| this.name = name;
| }
|
| public List<Person> getPeopleList() {
| return peopleList;
| }
|
| public void setPeopleList(List<Person> peopleList) {
| this.peopleList = peopleList;
| }
| }
|
| <!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
| "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
| <html xmlns="http://www.w3.org/1999/xhtml"
| xmlns:s="http://jboss.com/products/seam/taglib"
| xmlns:f="http://java.sun.com/jsf/core"
| xmlns:h="http://java.sun.com/jsf/html">
|
| <f:view>
| <h:form>
| <h:inputText value="#{searchPeople.name}" />
| <h:commandButton action="#{searchPeople.search()}" value="Search" />
|
| <h:dataTable value="#{searchPeople.peopleList}" var="person"
| rendered="#{not empty searchPeople.peopleList}">
| <h:column>
| <f:facet name="header">
| <h:outputText value="Id" />
| </f:facet>
| <s:link value="#{person.id}" view ="/editPerson.xhtml">
| <f:param name ="personId" value="#{person.id}" />
| </s:link>
| </h:column>
| <h:column>
| <f:facet name="header">
| <h:outputText value="Name" />
| </f:facet>
| <h:outputText value="#{person.name}" />
| </h:column>
| <h:column>
| <f:facet name="header">
| <h:outputText value="Number of emails" />
| </f:facet>
| <h:outputText value="#{person.emailAddresses.size}" />
| </h:column>
| <h:column>
| <f:facet name="header">
| <h:outputText value="Actions" />
| </f:facet>
| </h:column>
| </h:dataTable>
| </h:form>
| <h:messages />
| </f:view>
|
| </html>
|
If it's of any use, I can also post the code for the edit page and it's stateful session bean.
Thanks!
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4123652#4123652
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4123652
18 years, 5 months
[Tomcat, HTTPD, Servlets & JSP] - default servlet handling welcome page prior to filter runnin
by dr3342
I'm running JBoss 4.2.2 and have a filter in the ROOT.war WEB-INF/web.xml of the jboss-web.deployer. For some reason though when I request a page like http://host.domain.name/, the default servlet tacks on the index.html (which is a valid file and is one of the entries in the welcome file list of the web.xml) prior to my filter running. My filter is basically like the following:
| <filter>
| <filter-name>RewriteFilter</filter-name>
| <filter-class>my.class.RewriteFilter</filter-class>
| </filter>
|
| <filter-mapping>
| <filter-name>RewriteFilter</filter-name>
| <url-pattern>/*</url-pattern>
| </filter-mapping>
|
The default servlet portion of the jboss-web.deployer/conf/web.xml is like the following:
| <servlet>
| <servlet-name>default</servlet-name>
| <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
| <init-param>
| <param-name>debug</param-name>
| <param-value>0</param-value>
| </init-param>
| <init-param>
| <param-name>listings</param-name>
| <param-value>false</param-value>
| </init-param>
| <load-on-startup>1</load-on-startup>
| </servlet>
|
Is there something I'm missing? Or will the default servlet always process before my filter?
Thanks,
Dave
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4123650#4123650
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4123650
18 years, 5 months
[JBoss Seam] - Re: SFSB vs. JavaBean
by EricJava
"pete.muir(a)jboss.org" wrote : anonymous wrote : If I put just @Name, it's a POJO, and you're saying it's request scoped?
|
| Yes.
Ok, that clarifies things. I was using EntityHome, which is conversation scoped (in Home.java superclass). Then I was using other POJOs and wondering, why are these things not starting conversations? Now I see. I need to put @Scope(CONVERSATION) on them.
"pete.muir(a)jboss.org" wrote : anonymous wrote : This still doesn't fully answer the question. Most things can be done with POJOs. For example most beans aren't message-driven. For many simple things there is no performance benefit to clustering beans. So, should we be using EJBs or POJOs? POJOs have a benefit of simplicity: no need to write an interface.
|
| You've summed up the arguements well, and so can now make an informed decision for which to use ;)
Ok, now I'm getting it. I'll use POJOs. Are there any other limitations on POJOs that are significant for routine use? For example, I assume I can do all the same Seam security stuff on POJOs that I can on SFSBs? And I assume that POJOs can be members of long-running conversations, and can use @Begin and @End on them? This last factor (being in long-running conversations) is the most important.
Thanks
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4123644#4123644
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4123644
18 years, 5 months
[JBoss Seam] - Re: Using rich:datascroller With Seam and Hibernate Paginati
by neilac333
So I have done some research, and I have found that it actually isn't the rich:datascroller I should be focusing on but rather the rich:dataTable to which it is bound. It appears to me I need to do two things.
First, I need to write my own DataModel. It seems I am supposed to use the RichFaces class ExtendedDataModel to help manage paging. Here is an implementation of a SerializableDataModel, which subclasses ExtendedDataModel, from the RichFaces site:
| package org.richfaces.demo.extendeddatamodel;
|
|
|
| import java.io.IOException;
|
| import java.util.ArrayList;
|
| import java.util.HashMap;
|
| import java.util.List;
|
| import java.util.Map;
|
|
|
| import javax.faces.context.FacesContext;
|
|
|
| import org.ajax4jsf.model.DataVisitor;
|
| import org.ajax4jsf.model.Range;
|
| import org.ajax4jsf.model.SequenceRange;
|
| import org.ajax4jsf.model.SerializableDataModel;
|
| /**
|
| *
|
| * @author ias
|
| * This is example class that intended to demonstrate use of ExtendedDataModel and SerializableDataModel.
|
| * This implementation intended to be used as a request scope bean. However, it actually provides serialized
|
| * state, so on a post-back we do not load data from the data provider. Instead we use data that was used
|
| * during rendering.
|
| * This data model must be used together with Data Provider, which is responsible for actual data load
|
| * from the database using specific filtering and sorting. Normally Data Provider must be in either session, or conversation
|
| * scope.
|
| */
|
| public class AuctionDataModel extends SerializableDataModel {
|
|
|
| private AuctionDataProvider dataProvider;
|
| private Integer currentPk;
|
| private Map<Integer,AuctionItem> wrappedData = new HashMap<Integer,AuctionItem>();
|
| private List<Integer> wrappedKeys = null;
|
| private boolean detached = false;
|
|
|
| /**
|
| *
|
| */
|
| private static final long serialVersionUID = -1956179896877538628L;
|
|
|
| /**
|
| * This method never called from framework.
|
| * (non-Javadoc)
|
| * @see org.ajax4jsf.model.ExtendedDataModel#getRowKey()
|
| */
|
| @Override
|
| public Object getRowKey() {
|
| return currentPk;
|
| }
|
| /**
|
| * This method normally called by Visitor before request Data Row.
|
| */
|
| @Override
|
| public void setRowKey(Object key) {
|
| this.currentPk = (Integer) key;
|
|
|
| }
|
| /**
|
| * This is main part of Visitor pattern. Method called by framework many times during request processing.
|
| */
|
| @Override
|
| public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException {
|
| int firstRow = ((SequenceRange)range).getFirstRow();
|
| int numberOfRows = ((SequenceRange)range).getRows();
|
| if (detached) { // Is this serialized model
|
| // Here we just ignore current Rage and use whatever data was saved in serialized model.
|
| // Such approach uses much more getByPk() operations, instead of just one request by range.
|
| // Concrete case may be different from that, so you can just load data from data provider by range.
|
| // We are using wrappedKeys list only to preserve actual order of items.
|
| for (Integer key:wrappedKeys) {
|
| setRowKey(key);
|
| visitor.process(context, key, argument);
|
| }
|
| } else { // if not serialized, than we request data from data provider
|
| wrappedKeys = new ArrayList<Integer>();
|
| for (AuctionItem item:dataProvider.getItemsByrange(new Integer(firstRow), numberOfRows, null, true)) {
|
| wrappedKeys.add(item.getPk());
|
| wrappedData.put(item.getPk(), item);
|
| visitor.process(context, item.getPk(), argument);
|
| }
|
| }
|
| }
|
| /**
|
| * This method must return actual data rows count from the Data Provider. It is used by pagination control
|
| * to determine total number of data items.
|
| */
|
| private Integer rowCount; // better to buffer row count locally
|
| @Override
|
| public int getRowCount() {
|
| if (rowCount==null) {
|
| rowCount = new Integer(getDataProvider().getRowCount());
|
| return rowCount.intValue();
|
| } else {
|
| return rowCount.intValue();
|
| }
|
| }
|
| /**
|
| * This is main way to obtain data row. It is intensively used by framework.
|
| * We strongly recommend use of local cache in that method.
|
| */
|
| @Override
|
| public Object getRowData() {
|
| if (currentPk==null) {
|
| return null;
|
| } else {
|
| AuctionItem ret = wrappedData.get(currentPk);
|
| if (ret==null) {
|
| ret = getDataProvider().getAuctionItemByPk(currentPk);
|
| wrappedData.put(currentPk, ret);
|
| return ret;
|
| } else {
|
| return ret;
|
| }
|
| }
|
| }
|
|
|
| /**
|
| * Unused rudiment from old JSF staff.
|
| */
|
| @Override
|
| public int getRowIndex() {
|
| throw new UnsupportedOperationException();
|
| }
|
|
|
| /**
|
| * Unused rudiment from old JSF staff.
|
| */
|
| @Override
|
| public Object getWrappedData() {
|
| throw new UnsupportedOperationException();
|
| }
|
|
|
| /**
|
| * Never called by framework.
|
| */
|
| @Override
|
| public boolean isRowAvailable() {
|
| if (currentPk==null) {
|
| return false;
|
| } else {
|
| return getDataProvider().hasAuctionItemByPk(currentPk);
|
| }
|
| }
|
|
|
| /**
|
| * Unused rudiment from old JSF staff.
|
| */
|
| @Override
|
| public void setRowIndex(int rowIndex) {
|
| throw new UnsupportedOperationException();
|
| }
|
|
|
| /**
|
| * Unused rudiment from old JSF staff.
|
| */
|
| @Override
|
| public void setWrappedData(Object data) {
|
| throw new UnsupportedOperationException();
|
| }
|
|
|
| /**
|
| * This method suppose to produce SerializableDataModel that will be serialized into View State and used on a post-back.
|
| * In current implementation we just mark current model as serialized. In more complicated cases we may need to
|
| * transform data to actually serialized form.
|
| */
|
| public SerializableDataModel getSerializableModel(Range range) {
|
| if (wrappedKeys!=null) {
|
| detached = true;
|
| // Some activity to detach persistent data from wrappedData map may be taken here.
|
| // In that specific case we are doing nothing.
|
| return this;
|
| } else {
|
| return null;
|
| }
|
| }
|
| /**
|
| * This is helper method that is called by framework after model update. In must delegate actual database update to
|
| * Data Provider.
|
| */
|
| @Override
|
| public void update() {
|
| getDataProvider().update();
|
| }
|
|
|
| public AuctionDataProvider getDataProvider() {
|
| return dataProvider;
|
| }
|
|
|
| public void setDataProvider(AuctionDataProvider dataProvider) {
|
| this.dataProvider = dataProvider;
|
| }
|
|
|
| }
|
Second, I need Seam to install my custom DataModel so that it is the one applied to the collection when I use @DataModel in a Seam component. It seems to me the way to do that is similar to what you find here (from Pete's seamdiscs example):
| package org.jboss.seam.trinidad;
|
| import static org.jboss.seam.ScopeType.STATELESS;
| import static org.jboss.seam.annotations.Install.FRAMEWORK;
|
| import javax.faces.model.DataModel;
|
| import org.jboss.seam.annotations.Install;
| import org.jboss.seam.annotations.Name;
| import org.jboss.seam.annotations.Scope;
| import org.jboss.seam.annotations.intercept.BypassInterceptors;
| import org.jboss.seam.faces.DataModels;
| import org.jboss.seam.framework.EntityQuery;
| import org.jboss.seam.framework.HibernateEntityQuery;
| import org.jboss.seam.framework.Query;
|
| /**
| * Provide enhanced features when Trinidad is used as a JSF component set
| * @author pmuir
| *
| */
|
| @Name("org.jboss.seam.faces.dataModels")
| @Install(precedence=FRAMEWORK, classDependencies="org.apache.myfaces.trinidad.component.UIXComponent")
| @Scope(STATELESS)
| @BypassInterceptors
| public class TrinidadDataModels extends DataModels
| {
|
| @Override
| public DataModel getDataModel(Query query)
| {
| // If an EntityQuery is in use we can return a CollectionModel
| // backed by the database
| if (query instanceof EntityQuery)
| {
| return new EntityCollectionModel((EntityQuery) query);
| }
| else if (query instanceof HibernateEntityQuery)
| {
| return new HibernateEntityCollectionModel((HibernateEntityQuery) query);
| }
| else
| {
| return super.getDataModel(query);
| }
| }
|
|
| }
|
|
Now I am not using the Seam CRUD stuff. However, I think if I create my ExtendedDataModel implementation and annotate it with @Install(precedence=FRAMEWORK) and give it the right name, then that should work.
I suppose I am wondering now if the steps I describe are correct and if they are sufficient.
Thanks.
View the original post : http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4123641#4123641
Reply to the post : http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4123641
18 years, 5 months