You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tapestry.apache.org by Greg Pagendam-Turner <gr...@liftyourgame.com> on 2010/03/12 01:25:55 UTC

AjaxFormLoop example in JumpStart and JIRA 733

Guys,

I'm trying to work out how to fix the AjaxFormLoop example in Jump Start.

http://jumpstart.doublenegative.com.au:8080/jumpstart/examples/tables/ajaxformloop1

The code recommends that it should use conversations instead of session 
persistence. I've changed the code to use conversations but still get 
the hidden from field element error when clicking the "Add Row" link as 
mentioned in the JIRA https://issues.apache.org/jira/browse/TAP5-733.

This is because there is nothing in the rendered partial xml that 
contains a tag that the hidden field can be placed after (such as input, 
select, textarea, label, p, div, td or li).

Stepping through the code shows that the markup retruned when clicking 
Add Row is just:
<ajax-partial></ajax-partial>

I'd appreciate any clues on where to look next please.

Regards,

Greg.

PS: Modified AjaxFormLoop1.java is

package jumpstart.web.pages.examples.tables;

import java.text.DateFormat;
import java.text.Format;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import jumpstart.business.domain.examples.Person;
import jumpstart.business.domain.examples.iface.IPersonServiceLocal;
import jumpstart.client.IBusinessServicesLocator;
import jumpstart.web.commons.Conversation;
import jumpstart.web.commons.Conversations;
import jumpstart.web.commons.ExceptionUtil;
import jumpstart.web.pages.Index;
import jumpstart.web.pages.examples.wizard.WizardUsingComponents.Step;
import jumpstart.web.state.examples.wizard.CreditRequest;

import org.apache.tapestry5.BindingConstants;
import org.apache.tapestry5.ComponentResources;
import org.apache.tapestry5.EventContext;
import org.apache.tapestry5.ValueEncoder;
import org.apache.tapestry5.annotations.Component;
import org.apache.tapestry5.annotations.InjectPage;
import org.apache.tapestry5.annotations.Parameter;
import org.apache.tapestry5.annotations.Persist;
import org.apache.tapestry5.annotations.Property;
import org.apache.tapestry5.annotations.SessionState;
import org.apache.tapestry5.corelib.components.Form;
import org.apache.tapestry5.ioc.annotations.Inject;

public class AjaxFormLoop1 {
     private String _conversationId = null;

     @SessionState
     private Conversations _conversations;

     // We've used "session" persistence but it is risky. Better 
techniques include wrapping this field in a
     // Conversation (see the Wizard examples) or persisting it in the 
database.
     @Parameter(defaultPrefix = BindingConstants.PROP)
     @Property
     //@Persist
     private List<PersonHolder> _personHolders;

     @SuppressWarnings("unused")
     @Property
     private PersonHolder _personHolder;

     private List<Person> _persons;

     @Component(id = "personsedit")
     private Form _form;

     @Inject
     private IBusinessServicesLocator _businessServicesLocator;

     @InjectPage
     private AjaxFormLoop2 _page2;

     @Inject
     private Locale _currentLocale;

     @Inject
     private ComponentResources _resources;

     Object[] onPassivate() {
         return new Object[] { _conversationId };
     }

     Object onActivate(EventContext context) throws Exception {
         if (context.getCount() == 0) {
             setupPersonHolders();
             _conversationId = startConversation(_personHolders);
         }
         else
         {
             _conversationId = context.get(String.class, 0);
         }

         _personHolders = getPersonHoldersFromConversation(_conversationId);

         return null;
     }

     void setupPersonHolders()
     {
         // Get all persons - ask business service to find them (from 
the database)
         _persons = getPersonService().findPersons();

         _personHolders = new ArrayList<PersonHolder>();
         for (Person person : _persons) {
             _personHolders.add(new PersonHolder(person, false, 
person.getId()));
         }
     }

     // Form triggers the PREPARE event during form render and form 
submission.

     void onPrepare() {
         if (!_form.getHasErrors()) {
             if (_personHolders == null) {
                 //setupPersonHolders();
                 _personHolders = 
getPersonHoldersFromConversation(_conversationId);
             }
         }
     }

     PersonHolder onAddRow() {
         // Create a skeleton Person and add it to the displayed list 
with a unique key
         Person newPerson = new Person();
         PersonHolder newPersonHolder = new PersonHolder(newPerson, 
true, 0 - System.nanoTime());
         _personHolders.add(newPersonHolder);

         return newPersonHolder;
     }

     void onRemoveRow(PersonHolder personPlus) {
         int index = _personHolders.indexOf(personPlus);
         PersonHolder holder = _personHolders.get(index);

         // If the person is new, remove them from the list. Else, flag 
them to be deleted from the database.
         if (holder.isNew()) {
             _personHolders.remove(personPlus);
         }
         else {
             holder.setDeleted(true);
         }
     }

     void onValidateForm() {
         List<Person> personsToCreate = new ArrayList<Person>();
         List<Person> personsToChange = new ArrayList<Person>();
         List<Person> personsToDelete = new ArrayList<Person>();

         for (PersonHolder holder : _personHolders) {
             if (holder.isNew()) {
                 personsToCreate.add(holder.getPerson());
             }
             else if (holder.isDeleted()) {
                 personsToDelete.add(holder.getPerson());
             }
             else {
                 personsToChange.add(holder.getPerson());
             }
         }

         System.out.println(">>> personsToCreate = " + personsToCreate);
         System.out.println(">>> personsToChange = " + personsToChange);
         System.out.println(">>> personsToDelete = " + personsToDelete);

         try {
             // In a real application you would persist them to the 
database instead of printing them
             // getPersonService().bulkEditPersons(personsToCreate, 
personsToChange, personsToDelete);
         }
         catch (Exception e) {
             // Display the cause. In a real system we would try harder 
to get a user-friendly message.
             _form.recordError(ExceptionUtil.getRootCause(e));
         }
     }

     Object onSuccess() {
         List<Person> persons = new ArrayList<Person>();
         for (PersonHolder holder : _personHolders) {
             if (!holder.isDeleted()) {
                 persons.add(holder.getPerson());
             }
         }
         _page2.set(persons);
         endConversation(_conversationId);
         _resources.discardPersistentFieldChanges();
         return _page2;
     }

     void onRefresh() {
         _resources.discardPersistentFieldChanges();
         onPrepare();
     }

     Object onActionFromGoHome() {
         _resources.discardPersistentFieldChanges();
         return Index.class;
     }

     @SuppressWarnings("unchecked")
     public ValueEncoder getEncoder() {
         return new ValueEncoder<PersonHolder>() {

             public String toClient(PersonHolder value) {
                 Long key = value.getKey();
                 return key.toString();
             }

             public PersonHolder toValue(String keyAsString) {
                 Long key = new Long(keyAsString);
                 for (PersonHolder holder : _personHolders) {
                     if (holder.getKey().equals(key)) {
                         return holder;
                     }
                 }
                 throw new IllegalArgumentException("Received key \"" + key
                         + "\" which has no counterpart in this 
collection: " + _personHolders);
             }
         };
     }

     public class PersonHolder {
         private Person _person;
         private Long _key;
         private boolean _new;
         private boolean _deleted;

         PersonHolder(Person person, boolean newPerson, Long key) {
             _person = person;
             _new = newPerson;
             _key = key;
         }

         public Person getPerson() {
             return _person;
         }

         public Long getKey() {
             return _key;
         }

         public boolean isNew() {
             return _new;
         }

         public boolean setDeleted(boolean deleted) {
             return _deleted = deleted;
         }

         public boolean isDeleted() {
             return _deleted;
         }
     }

     private IPersonServiceLocal getPersonService() {
         // Use our business services locator to get the EJB3 session 
bean called "PersonServiceLocal".
         return _businessServicesLocator.getPersonServiceLocal();
     }

     public Format getDateFormat() {
         return DateFormat.getDateInstance(DateFormat.SHORT, 
_currentLocale);
     }

     private String startConversation(Object target) {
         String conversationId = Long.toString(System.currentTimeMillis());
         _conversations.add(new Conversation(conversationId, target));
         return conversationId;
     }

     private void endConversation(String conversationId) {
         _conversations.remove(conversationId);

         // If conversations ASO is now empty then remove it from the 
session

         if (_conversations.isEmpty()) {
             _conversations = null;
         }
     }

     private List<PersonHolder> getPersonHoldersFromConversation(String 
conversationId) {
         Conversation conversation = _conversations.get(conversationId);
         if (conversation != null && conversation.getTarget() instanceof 
List<?>) {
             return (List<PersonHolder>) conversation.getTarget();
         }
         return null;
     }

}


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tapestry.apache.org
For additional commands, e-mail: users-help@tapestry.apache.org