Howard, Thiago,
Would adding <ajax-partial> to the list of Hidden Field Location Rules
fix TAP5-733?
Regards,
Greg.
On 15/03/2010 6:25 AM, Greg Pagendam-Turner wrote:
> Geoff,
>
> I tried your onActivate method. The conversation id is now in the url
> but I'm still getting thehidden form field error.
>
> Regards,
>
> Greg
>
> On 14/03/2010 9:39 PM, Geoff Callender wrote:
>> I don't think this is the TAP5-733 bug. Running the code I've
>> recreated the exception and yes, Blackbird reported it as a
>> communication error, but the log shows Its root cause was an NPE
>> caused by _personHolders being null.
>>
>> Caused by:
java.lang.NullPointerException>> at
>> jumpstart.web.pages.examples.tables.AjaxFormLoop1New.onAddRow(AjaxFormLoop1New.java:106)
>>
>> at
>> jumpstart.web.pages.examples.tables.AjaxFormLoop1New.dispatchComponentEvent(AjaxFormLoop1New.java)
>>
>> at
>> org.apache.tapestry5.internal.structure.ComponentPageElementImpl.dispatchEvent(ComponentPageElementImpl.java:902)
>>
>> at
>> org.apache.tapestry5.internal.structure.ComponentPageElementImpl.triggerContextEvent(ComponentPageElementImpl.java:1081)
>>
>> ... 68 more
>>
>> I think it's due to the conversation id never appearing in the page
>> context. Try this change to onActivate() - when you start a
>> conversation redirect to the same page so that onPassivate() gets
>> called and therefore the conversation id goes into the URL.
>>
>> Object onActivate(EventContext context) throws Exception {
>> if (context.getCount() == 0) {
>> setupPersonHolders();
>> _conversationId = startConversation(_personHolders);
>> return this;
>> }
>> else {
>> _conversationId = context.get(String.class, 0);
>> _personHolders =
>> getPersonHoldersFromConversation(_conversationId);
>> if (_personHolders == null) {
>> setupPersonHolders();
>> _conversationId = startConversation(_personHolders);
>> return this;
>> }
>> }
>>
>> return null;
>> }
>>
>> Also, don't get in the habit of initialising fields in the
>> declaration, eg.
>>
>>> private String _conversationId = null;
>>
>> The reason is that you'll rarely get a freshly instantiated page -
>> more likely is you'll get one that Tapestry has pulled out of its
>> pool of page instances.
>>
>> Cheers,
>>
>> Geoff
>>
>>
>> On 14/03/2010, at 2:11 PM, Greg Pagendam-Turner wrote:
>>
>>> 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
>>> //@(protected)
>>> 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@(protected)
>>> For additional commands, e-mail: users-help@(protected)
>>>
>>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@(protected)
For additional commands, e-mail: users-help@(protected)