[Logo] Enterprise Client Community
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 
Form/field validation issues  XML
Forum Index -> Development
Author Message
cvieira

Power User

Joined: 08/07/2010 21:46:40
Messages: 59
Offline

Hi, i have some doubts regarding the best way to do form field validations, with CaptainCasa... i was trying to make some tests, some of them based on the CaptainCasa examples.

So, i have a class CustomerBeanUI (extends PageBean) and a detail.jsp file... in the example, the idea is to have just two fields (id, email) and a button.

The idea is to update information for the Customer entity... after some tests, i realize that if i change email of selected customer, and hit the button (without any ActionListener defined), the Customer is in fact changed (is this logical? Customer setEmail(...) was called, even if i did not force it...)... even if i define some ActionListener function that does nothing, the Customer is still change... so, how can i intercept this so that i can make a field Validation prior to the change? What kind of validation mechanism CaptainCasa offers? Is the implementation of the interface IPropertyResolverAware, one of ways to do this?

Thanks in advance!

Note: My example code is this:

detail.jsp
Code:
 <%@page contentType="text/html"%>
 <%@page pageEncoding="UTF-8"%>
 
 <%@taglib prefix="f" uri="http://java.sun.com/jsf/core"%>
 <%@taglib prefix="h" uri="http://java.sun.com/jsf/html"%>
 
 <%@taglib prefix="t" uri="/WEB-INF/eclnt"%>
 
 
 <!-- ========== CONTENT BEGIN ========== -->
 <f:view>
 <h:form>
 <f:subview id="detailg_sv">
 <t:rowbodypane id="g_1" padding="5" >
 <t:row id="g_2" >
 <t:label id="g_3" text="Customer Id" width="100" />
 <t:field id="g_4" enabled="false" text="#{d.CustomerBeanUI.customer.customerId}" width="100" />
 </t:row>
 <t:row id="g_5" >
 <t:label id="g_6" text="Customer Email" width="100" />
 <t:field id="g_7" adapterbinding="#{d.CustomerBeanUI.fields.email}" text="#{d.CustomerBeanUI.customer.email}" width="100" />
 </t:row>
 <t:row id="g_8" >
 <t:coldistance id="g_9" width="100" />
 <t:button id="g_10" text="Update" />
 </t:row>
 </t:rowbodypane>
 <t:pageaddons id="g_pa"/>
 </f:subview>
 </h:form>
 </f:view>
 <!-- ========== CONTENT END ========== -->
 
 



CustomerBeanUI.java
Code:
 /*
  * To change this template, choose Tools | Templates
  * and open the template in the editor.
  */
 
 package managedbeans;
 
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.Map;
 import org.eclnt.jsfserver.defaultscreens.Statusbar;
 import org.eclnt.jsfserver.pagebean.PageBean;
 import pojo.Customer;
 
 /**
  *
  * @author telbit
  */
 public class CustomerBeanUI
     extends PageBean
     implements Serializable
 {
 
     public CustomerBeanUI() {
         registerField("email", true);
     }
 
     // ------------------------------------------------------------------------
     // members
     // ------------------------------------------------------------------------
     Customer customer;
 
     public Customer getCustomer() {
         return customer;
     }
 
     public void setCustomer(Customer customer) {
         this.customer = customer;
     }
 
     Map<String,FIELDAdapterBinding> fields = new HashMap<String,FIELDAdapterBinding>();
 
     public Map<String, FIELDAdapterBinding> getFields() {
         return fields;
     }
 
     public void setFields(Map<String, FIELDAdapterBinding> fields) {
         this.fields = fields;
     }
 
     // ------------------------------------------------------------------------
     // public usage
     // ------------------------------------------------------------------------
     @Override
     public String getPageName() { return "/detail.jsp"; }
     @Override
     public String getRootExpressionUsedInPage() { return "#{d.CustomerBeanUI}"; }
 
     void prepare(Customer cust) {
         customer = cust;
     }
 
     public void updateCustomer(){
         Statusbar.outputWarning("just testing");
         FIELDAdapterBinding emailField = fields.get("email");
 
         if ("email".equals(customer.getEmail())){
             Statusbar.outputWarning("Wrong email address");
         }
 
         //emailField.setAttributeValue("text", customer.getEmail() + "_mytest_1");
     }
 
     // --
     // private usage
     // --
 
     private void registerField(String propertyName, boolean isMandatory){
         fields.put(propertyName,new FIELDAdapterBinding(isMandatory,propertyName));
     }
 
 }
 

--
Carlos Vieira
CaptainCasa

Power User
[Avatar]

Joined: 21/11/2007 12:23:06
Messages: 5521
Offline

Hi,

the principle of operations is:

The user changes data on the screen (e.g. fiel) + tirggers events (e.g. button). When triggering events always the whole data that is queued in the client is sent to the server side. This is a "MUST" (what else should happen?).

ON server side there are 3 main phases:
(1.) Data transfer phase => this is when the changed data is passed into the managed beans, i.e. if you changed the eMail address - then here it is transferred
(2.) Invoke phase => this is when the actionListener is called
(3.) Render phase => this is when the response to the client is given ("rendered"). All the relevant properties of the page are checked if there was a change, if so then this change is part of the repsonse.

This means for validation: the managed bean (+ its contained objects) mirror the page's data. In case the eMail address is wrong then your managed bean keeps the wrong information, too, together with some information that this is a wrong email address.

It's now "your" job to connect the managed bean layer to some business logic processing and do execute some validations.

It's important to note that validations should not directly done in the data transfer phase (1.): imagine the user changed several fields on client side. In this case all the data is passed in the request roundtrip - in a sequence that not necessarily is the same as the user input sequence. So when doing multi-property validations directly in set-phase then it could happen that the one property is "just set" and the other is to be set "just after". - At then end of the data transfer phase, or the begin of the invoke phase you can be 100% sure that all data changes from client side are passed into the managed bean.

...hope this helps... (?)

Björn

Björn Müller, CaptainCasa GmbH
cvieira

Power User

Joined: 08/07/2010 21:46:40
Messages: 59
Offline

Hi Bjorn,

I understand that when an event is triggered, all data is sent to server... ok, i agree that this is a must feature, no doubt... but, imagine that user inserts an invalid email and pushes a button for submit... a validation error is given to the user (validation logic done on server side, in this case example), and the changes are not persisted on database, or whatever... after this all components that shows email information (for example on a grid, or any other component) will have invalid email information like in the form. So, if i hit, let's say, a cancel button, i want to return to old value, but without having to read from persisted data... how can this be handled?

Thanks for the nice explanation of server side main phases

--
Carlos Vieira
CaptainCasa

Power User
[Avatar]

Joined: 21/11/2007 12:23:06
Messages: 5521
Offline

Hi,

I see what you mean: grid item and detail view in your case are referencing exactly the same data object (POJO).

So, exactly what you mention happens. When detail view changes the data then the data is also updated in the grid. (the scenarios "referencing the same data object" is nice for display scenarios, but exactly for the reason you mention not 100% nice for edit scenarios).

As consequence, you need to upate you server side management of data objects. There are many ways to do it (this is pure Java), one would be to create a clone of an object when selecting it for edit purpose. Then the grid item and the detail view work on decoupled data-beans - and only in case of the user saving/"propagating" the the cloned bean, then changes will take effect. - Of course then you require a mechanism to update/reload the grid item and pass the updated bean. E.g. you may establish some "MVC-Notification" if you want to do it the most abstracted way.

The user interface data concept is very "clear&simple" (maybe some would call it "strict"...): the data of the user interface is managed by your server side program and directly reflected into the screens. If you want/need to separate data (for the reason you're talking about) then you "just have to do it" on server side - in the Java-way that makes sense to you.

Regards, Björn


Björn Müller, CaptainCasa GmbH
cvieira

Power User

Joined: 08/07/2010 21:46:40
Messages: 59
Offline

Hi Bjorn,

I see what you mean and know understand why this is not taken care by the framework... thanks for the explanation

--
Carlos Vieira
 
Forum Index -> Development
Go to:   
Powered by JForum 2.1.6 © JForum Team