myfaces-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Vladimir Isakovich" <ivla...@gmail.com>
Subject Re: Tomahawk+DataScroller+WorkingWithLargeTables
Date Mon, 09 Jul 2007 16:51:42 GMT
Hi Paul,
I am getting to the conclusion that it will be impossible to use hibernate
generated pojos with jsf directly (I tried to change from date to timestamp
in mySql - no better). Here is my example with the date issue:

<t:inputText value*="#{customers.date}"
*valueChangeListener="#{customers.orderChanged}">
 <f:convertDateTime pattern="MM/dd/yyyy" timeZone="EDT"/>
</t:inputText>

    static Date defaultDate;
    static {
        try {
            SimpleDateFormat sdt = new SimpleDateFormat("MM/dd/yyyy");
            sdt.setTimeZone(TimeZone.getTimeZone("EDT"));
            defaultDate = sdt.parse(sdt.format(new Date()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private Date* date* = defaultDate;

It works fine with jsf. In the log at submition:
...validate: previousValue: Sun Jul 08 20:00:00 EDT 2007 convertedValue: Sun
Jul 08 20:00:00 EDT 2007

Probably in this particular case I may not blame JSF. After all it gets this
j.u.Date from any source and is not responsible for formatting deficiencies
which are made by DB/hibernate (in my case). Once I supplied a Date
fromatted exactly to the same standard that I use in my custom tag, I have
no more problem (even there was no problem with *sligt* format difference).

Generally speaking, this is not anything new (additional data conversion
between 'model' and 'view'), in my last struts project we were using as a
standard approach a whole layer of POJOs on the top of hibernate pojos (not
to mention struts has it's own layer of ActionForm pojos). Well I don't like
the idea of multiplying dummy (mostly) pojos, but using this case with the
date and thinking of some more possible issues, I'm getting to the point of
creating an additional layer with some conversion logic between my hibernate
pojos and jsf 'view'.
I'll try to make some reusable map based pojo, those constants for
datePattern and timeZone may be stored in some interface and will be
accessable from my backing bean (so they may be and should be referred by
jsp custom tag). Later in development I may add some more smarts to this
class or if it gets too ugly, delegate some logic to additional util
classes.
I thought to avoid of doing this conversion, but that was idealistic
approach. Well, whatever works.

vlad

On 7/9/07, Paul Iov <paul@voller-ernst.de> wrote:
>
> Hi Vladimir,
>
> I was also tired with this converter stuff in my day. Yes, surely, there
> is converter facility in JSF! But to make such statement is IMO the only
> useful way, how one can utilize it :(  Take a look at topic
> "Converter.getAsString not called?" started by Toppac. I've studied
> source code of API and implementation for lot of hours and found, that
> it's just impossible to get it work properly without to change too many
> things in code. In fact this lack (indirectly in spec itself) is covered
> sometimes at component level, or else nowhere. That's why some (but not
> all!) components works with conversion correctly, and that's why
> "convert" brings hundreds of hit in this list. The date conversion is
> not only tender spot... just try to implement trivial tristate boolean
> (i.e. true-false-doesn't matter) with a standard checkbox or even to
> bind the checkbox not to boolean, but to String property wit simple
> conversion rules (YES - > true, NO or "" or null ->FALSE), and you will
> see, what I'm talking about :) Few months ago I've opened JIRA issue and
> had a long discussion about this, but it has end up with nothing. The
> workaround stay to maintain conversion yourself, in backing bean.
>
> My Date fields are more often the regular Oracle Date mapped to
> java.util.Date, but the values must be 'transported' in Strings. So, I'm
> using in this case just an inputText with extra JS calendar from
> http://www.dynarch.com/projects/calendar/ (because no one from Tomahawk
> works really correct with String ) I've written an extra class, which
> has getter and setter for each data type (String, Date, boolean) and
> makes conversion internally (when applicable). However you can try
> following to get your Date displayed properly:
>
> <f:convertDateTime *pattern*="dd.MM.yyyy"/> //'regular' Java format
> pattern as you would use with String.format()
>
> As input for Date I'm using:
> <t:inputDate value="#{myBean.dateValue}"
> popupCalendar="true"
> renderAsPopup="true"
> />
> I've no joy with getting t:inputCalendar to work correctly. There is
> also calendar component from Jenia project and some other "AJAX
> compatible", which are often suggested, but only difference is look and
> feel. The bugs are the same, although this time not with conversion: all
> of this components (except JS) are buggy with positioning of DIV, if you
> just get an idea to use some advanced CSS in your project. However -
> rehashing your idea - "one could not use CSS somehow" :) or use it with
> a lot of handicraft, i.e. with JS calendar from
> http://www.dynarch.com/projects/calendar/:
>
> <h:inputText
>                 id="cal-field-1"
>                 value="#{myBean.myDateValue}"/>
> <img id="cal-button-1" src="tools/calendar/calendar_icon_1.gif"
> style="cursor: pointer; border: none;margin-top:2px;margin-left:2px;" />
> <script  id="scriptInitCa-l">
>                Calendar.setup({
>                  inputField    : "searchform:cal-field-1", //we need
> here "formID:inputTextID" !
>                  button        : "cal-button-1",
>                  ifFormat      : "%d.%m.%Y",  //another one format
> pattern to maintain in config :(!
>                  align         : "Tr"
>                });
> </script>
>
> Looks terrible, but if you are using Facelet, you can declare custom
> namespace and pack this code in separate file, i.e.:
> <facelet-taglib>
>    <namespace>http://my.url</namespace>
>
>    <!-- my:inputDate  -->
>    <tag>
>        <tag-name>inputDate</tag-name>
>        <source>../includes/inputDate.xhtml</source>
>    </tag>
> </facelet-taglib>
>
>
> regards,
> paul
>
>
> Vladimir Isakovich schrieb:
> > I was trying not to massage the incoming data in any way, but using
> > the attributes in convertDateTime only. What I found so far, this
> > approach works with the following setting:
> >
> > <t:inputText value="#{customers.date }"
> > valueChangeListener="#{customers.orderChanged}">
> >             <f:convertDateTime type="both" dateStyle="default"
> > timeStyle="default" timeZone="EST"/>
> > </t:inputText>
> >
> > The most important I think is type=both, then I can see exact match
> > and no event is fired:
> > ...validate: previousValue: Sun Jul 08 19:45:23 EDT 2007
> > convertedValue: Sun Jul 08 19:45:23 EDT 2007
> >
> > However this for me is not acceptable for the date entry, I'd like to
> > see something simple like Jul 08 2007 - no time or timezone at all.
> > Well I'll play with this isssue some more.
> >
> > vlad
> >
> >
> > On 7/8/07, *daniel ccss* <danielccss2@gmail.com
> > <mailto:danielccss2@gmail.com>> wrote:
> >
> >     Vladimir you can´t use a Calendar to pick the date in the format
> >     you want?
> >
> >
> >     On 7/8/07, *Vladimir Isakovich* <ivlad10@gmail.com
> >     <mailto:ivlad10@gmail.com>> wrote:
> >
> >         Paul,
> >         may be you know how to deal with this problem. On a date field
> >         I'm using valueChangeListener (I have java.util.Date in the
> >         backing bean). This listener is firing on submit no matter if
> >         the value is changed or not . In UIInput I see:
> >
> >             public void validate(FacesContext context)
> >             {
> >                 if (context == null) throw new
> >         NullPointerException("context");
> >                 Object submittedValue = getSubmittedValue();
> >                 System.out.println("...validate: submittedValue:
> >         "+submittedValue);
> >                 if (submittedValue == null) return;
> >
> >                 Object convertedValue = getConvertedValue(context,
> >         submittedValue);
> >
> >                 if (!isValid()) return;
> >
> >                 validateValue(context, convertedValue);
> >
> >                 if (!isValid()) return;
> >
> >                 Object previousValue = getValue();
> >                 System.out.println("...validate: previousValue:
> >         "+previousValue+ " convertedValue: "+convertedValue);
> >                 try{    //-I added this
> >                     Converter converter =
> >         _SharedRendererUtils.findUIOutputConverter(context, this);
> >                     if (converter != null)
> >                     {
> >                         System.out.println("...validate: previousValue
> >         converted: "+converter.getAsString(context,this,
> previousValue));
> >                     }
> >                 }catch(Exception e){
> >                     e.printStackTrace ();
> >                 }
> >                 setValue(convertedValue);
> >                 setSubmittedValue(null);
> >                 if (compareValues(previousValue, convertedValue))
> >                 {
> >                     queueEvent(new ValueChangeEvent(this,
> >         previousValue, convertedValue));
> >                 }
> >             }
> >
> >         In my log:
> >         ...validate: submittedValue:
> >         org.apache.myfaces.custom.date.HtmlInputDate$UserData@14feea
> >         ...validate: previousValue: 2007-01-02 00:00:00.0
> >         convertedValue: Tue Jan 02 00:00:00 EST 2007
> >         ...validate: previousValue converted: Jan 2, 2007
> >
> >         As you can see, the values are not the same, so here I'm
> >         getting the event.
> >         In my page:
> >                               <t:inputDate value="#{order.orderDate }"
> >         type="date" dateStyle="default" timeZone="EST"
> >
> >         valueChangeListener="#{customers.orderChanged}" id="orderDate">
> >                                     <!--f:convertDateTime type="date"
> >         dateStyle="default" timeZone="EST"/-->
> >                               </t:inputDate>
> >
> >         I tried t:inputText with the converter first, and that time
> >         the first log was showing exact same value as the 3rd one.
> >
> >         But I think, that I'm making some basic mistake with the use
> >         of date field, my init value from the DB has no timezone, and
> >         may be something else is missed. See the 'prevoiusValue'.
> >         Even so I get through this issue with the valueChangeEvent,
> >         I'm facing the loading the new value into the DB, and this one
> >         has obviously a different format.
> >
> >         I guess the solution should be in adjusting the date format in
> >         the DB somehow. (I'm using mySql now). When retrieved from DB,
> >         my date should read: Tue Jan 02 00:00:00 EST 2007 - not
> >         2007-01-02 00:00:00.0
> >
> >         Your thoughts???
> >
> >         thanks
> >         vlad
> >
> >
> >         On 7/8/07, *Paul Iov* < paul@voller-ernst.de
> >         <mailto:paul@voller-ernst.de>> wrote:
> >
> >             Daniel, I think your approach is ok. But... why do you
> >             need some properties-file? You can just extend my class
> >             with something like
> >
> >             private boolean _invalidated = true;
> >
> >             public void Invalidate(){
> >               this._invalidated = true;
> >             }
> >             and then in
> >
> >             private DataPage<T> doFetchPage(int startRow, int pageSize){
> >                     if ((_lastPage == null) || (_lastStartRow !=
> >             startRow) || (_lastPageSize != pageSize) || *_invalidated*){
> >                         _log.debug("**Fetch: required -> fetching...");
> >                         _lastPage = fetchPage(startRow, pageSize);
> >                         _lastStartRow = startRow;
> >                         _lastPageSize = pageSize;
> >                        _invalidated = false;//don't vorget to set it
> >             to FALSE
> >                     }else{
> >                         _log.debug("**Fetch: not required (already
> >             fetched)!");
> >                     }
> >                     return _lastPage;
> >                 }
> >
> >
> >             Just call this Invalidate() method from your bean after
> >             making changes, and the current page becomes refetched
> >             during next access at rendering phase. (It's exactly what
> >             you are doing now with the property file :)) The
> >             _invalidated flag 'overrides' any other condition and
> >             forces the page to be refetched just once.
> >
> >             Unfortunately I have not enough time right now to explain
> >             the approach in my implementation in detail (because I
> >             have to switch to another nonJSF-project), but I plan to
> >             build small example application next week, you have asked
> >             for. It would be nice, if someone be able then to correct
> >             my terrible English and publish it at Wiki...
> >
> >             Just few tips about delete/edit situation:
> >             - If you delete some record, you have to 'reload' at least
> >             the total count value (since the stored in instance of
> >             paged list value becomes incorrect). (The worst case: you
> >             land at incorrect page number, if you delete the only one
> >             item being at the LAST page.)
> >             - If you edit something, what (due to your sorting order)
> >             can affect the subset of items being displayed at current
> >             page, you have to reload the page as well. (This can lead
> >             into situation, when your just edited item 'disappears'
> >             from the current page.)
> >
> >             regards,
> >             paul
> >
> >             daniel ccss schrieb:
> >>             Ok Paul, this is the thing,
> >>
> >>             Since I´m new in this and in my work they are asking for
> >>             results from the Tomahawk investigation that i'm doing
> >>             implementing a simple maintain module, I think that I
> >>             can´t impplement all that you have done, at least in this
> >>             moment.
> >>
> >>             This is what i have done until now, I changed the
> >>             PagedList class from the wiki for yours, that was the
> >>             only class that Ichanged, the other change was to put the
> >>             bean in session (Vladimir idea) (by the way nice tip, you
> >>             gave for put it in session from code). Until now all
> >>             works fine.
> >>
> >>             Then i made my delete, add and edit methods, they simple
> >>             recived the Patient id and call an EJB that calls to the
> >>             DAOs methods to do that. They are called from an
> >>             actionlistener on the JSP. They all works fine, but I
> >>             don`t saw the changes on the DataTable, in the moment,
> >>             but when I click on the pages numbers I saw the changes.
> >>
> >>             What I need, is from code, and after call a
> >>             delte/add/edit method, fetch the data(as happen when i
> >>             click on a page number) from my backing bean, and of
> >>             course always pass for the filter to do the fetch after
> >>             this methods are called, something like:
> >>
> >>             backing_bean:
> >>             public void delete()
> >>             ...
> >>             EJB.deletePatient(...)
> >>             fetch data
> >>
> >>             I made a hardcore test ( I need to do it for test my idea
> >>             :( ) I made a properties file, and put a key call
> >>             forceToFetch = false, and in the dofetch method I get
> >>             this property then in your filter (If) I add this:
> >>             if(.... || forceToFetch). Inside the if I ask if the
> >>             forceToFetch is true and put it again in false in the
> >>             properties file.Then in the backing_bean after call the
> >>             add/delete/edit methods I put the value in the properties
> >>             in true, and as I thought it wors fine, I can saw all the
> >>             changes on the DataTable. Can you give a way to do this
> >>             witout use the properties file?  Can you give me an step
> >>             by step solution since I`m new in this and I still
> >>             understanding all your code.
> >>
> >>             Other thing I see a problem with this solution when I
> >>             delete the last row of a DataPage (example the last row
> >>             of the second DataPage) or when I delete the last row of
> >>             the first DataPage, I recived a row index exception. How
> >>             can I fix this issue, can you explain me. If I delete the
> >>             last row of dataPage 3 how can I show, from code, the
> >>             dataPage2 and in the case of the last row of the first
> >>             DataPage how can I delete that last row and show the
> >>             First DataPage without data? Can you also explain me this
> >>             step by step?
> >>
> >>             Paul really really sorry for all this, but I think that
> >>             your are the person that more knows of this, you are a
> >>             Guru on this, and I really need help, also thanks to you
> >>             Vladimir!!
> >>
> >>
> >>
> >>             On 7/6/07, *Paul Iov* <paul@voller-ernst.de
> >>             <mailto:paul@voller-ernst.de>> wrote:
> >>
> >>                 Vladimir Isakovich schrieb:
> >>                 > Yes, I have just one call getting through to my DB,
> >>                 the session scoped
> >>                 > bean with Paul's blocking method worked. The
> >>                 drawback with this
> >>                 > approach, we may start thinking on cleaning session
> >>                 off of the unused
> >>                 > objects, otherwise our app may consume too much
> >>                 cache on the server.
> >>                 >
> >>                 > vlad
> >>                 That's why I don't utilize the JSF backing bean
> >>                 facility. It's not
> >>                 flexibly enough to maintain high dynamically
> >>                 applications.
> >>                 I've implement own session controller and it's the
> >>                 only backing bean I
> >>                 have to declare in my faces-config.xml ;) The other
> >>                 part of magic is
> >>                 application wide controller (started with
> >>                 ServletContextListener) to
> >>                 maintain some global issues and, first of all the
> >>                 sessions, which I
> >>                 catch with HTTPSessionListener.
> >>
> >>                 Just a little hint: you can 'inject' your beans into
> >>                 session without
> >>                 declaring it in config.
> >>
> >>                 <managed-bean>
> >>                       <managed-bean-name>MyBean</managed-bean-name>
> >>                       <managed-bean-class>my.MyClass
> </managed-bean-class>
> >>                       <managed-bean-scope>session</managed-bean-scope>
> >>                 </managed-bean>
> >>
> >>                 is equal to:
> >>
> >>                 FacesContext fCtx    = FacesContext.getCurrentInstance
> ();
> >>                 ExternalContext eCtx    = _fCtx.getExternalContext();
> >>                 ServletContext srvCtx  =
> >>                 (ServletContext)_eCtx.getContext();
> >>                 HttpSession session =
> >>                 (HttpSession)_eCtx.getSession(false);
> >>                 ...
> >>                 MyClass myInstance = new MyClass();
> >>                 session.setAttribute("MyBean", myInstance);//put
> >>                 MBean to session
> >>
> >>
> >>
> >
> >
> >
> >
>
>

Mime
View raw message