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* <[EMAIL PROTECTED]
<mailto:[EMAIL PROTECTED]>> wrote:
Vladimir you can´t use a Calendar to pick the date in the format
you want?
On 7/8/07, *Vladimir Isakovich* <[EMAIL PROTECTED]
<mailto:[EMAIL PROTECTED]>> 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:
[EMAIL PROTECTED]
...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* < [EMAIL PROTECTED]
<mailto:[EMAIL PROTECTED]>> 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* <[EMAIL PROTECTED]
<mailto:[EMAIL PROTECTED]>> 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