Reputation: 477
How can I use a model property with type of java.sql.Timestamp
in a JSF date component like PrimeFaces <p:calendar>
? This component needs an instance of java.util.Date
for its input and it will also return the same type of java.util.Date
.
Is it possible to create a converter for this case? How do I implement a converter to convert java.sql.Timestamp
to java.util.Date
? I think I need a JSF converter with getAsObject()
and getAsString()
, but I don't know where should I do the conversion?
Actually in this case I have a List<Model>
to be displayed in <p:dataTable>
. In each rows, I can set the startDate and endDate directly from the table. So I need to use the model property directly to get the latest / updated data from the table during save()
process.
This is sample for my model:
public class Model {
private Timestamp startDate;
private Timestamp endDate;
public Timestamp getStartDate() {
return startDate;
}
public void setStartDate(Timestamp startDate) {
this.startDate = startDate;
}
public Timestamp getEndDate() {
return endDate;
}
public void setEndDate(Timestamp endDate) {
this.endDate = endDate;
}
}
This is sample for my bean:
public class PageBean {
private List<Model> listModel;
public String save() {
// Process insert / update listModel to database here
return "next-page"
}
public List<Model> getListModel() {
return listModel;
}
public void setListModel(List<Model> listModel) {
this.listModel = listModel;
}
}
And this is sample for my xhtml:
<p:dataTable value="#{pageBean.listModel}" var="model" >
<p:column headerText="Start Date">
<p:calendar value="#{model.startDate}" pattern="dd-MMM-yyyy" ></p:calendar>
</p:column>
<p:column headerText="End Date">
<p:calendar value="#{model.endDate}" pattern="dd-MMM-yyyy" ></p:calendar>
</p:column>
</p:dataTable>
<p:commandButton value="Save" action="#{pageBean.save()}" ajax="false" />
I think it is OK to use the model directly if the model property type is java.util.Date
, but I got type of java.sql.Timestamp
here.
Upvotes: 1
Views: 4550
Reputation: 477
The best practice is by creating a model that is separated with persistence layer types as mentioned by @BaulusC. But I found a solution (actually a trick) that fit my case, that is by using java.util.Map
or creating another model for binding with view, but it requires a little more work. You need to put the values from the map or the model mapper to your actual model.
java.util.Map
This is the sample bean:
public class PageBean {
private List<Model> listModel;
private List<Map> listMap;
public String save() {
// Move the values from listMap to listModel
listModel = new ArrayList<Model>();
for (Map map : listMap) {
Model model = new Model();
model.setStartDate(new Timestamp(((Date) map.get("startDate")).getTime());
model.setEndDate(new Timestamp(((Date) map.get("endDate")).getTime());
listModel.add(model);
}
// Process listModel to database ...
return "next-page"
}
public List<Map> getListMap() {
return listMap;
}
public void setListMap(List<Map> listMap) {
this.listMap = listMap;
}
}
in xhtml page we use listMap
for <p:dataTable>
value:
<p:dataTable value="#{pageBean.listMap}" var="map" >
<p:column headerText="Start Date">
<p:calendar value="#{map.startDate}" pattern="dd-MMM-yyyy" ></p:calendar>
</p:column>
<p:column headerText="End Date">
<p:calendar value="#{map.endDate}" pattern="dd-MMM-yyyy" ></p:calendar>
</p:column>
</p:dataTable>
<p:commandButton value="Save" action="#{pageBean.save()}" ajax="false" />
The sample of new model for binding with the view:
public class ModelMapper {
private Date startDate;
private Date endDate;
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public Date getEndDate() {
return endDate;
}
public void setEndDate(Date endDate) {
this.endDate = endDate;
}
}
in bean:
public class PageBean {
private List<Model> listModel;
private List<ModelMapper> listModelMapper;
public String save() {
// Move the values from listModelMapper to listModel
listModel = new ArrayList<Model>();
for (ModelMapper modelMapper : listModelBinder) {
Model model = new Model();
model.setStartDate(new Timestamp(modelMapper.getStartdate().getTime());
model.setEndDate(new Timestamp(modelMapper.getEndDate().getTime());
listModel.add(model);
}
// Process listModel to database ...
return "next-page"
}
public List<ModelMapper> getListModelMapper() {
return listModelMapper;
}
public void setListModelMapper(List<ModelMapper> listModelMapper) {
this.listModelMapper = listModelMapper;
}
}
in xhtml page we use listModelMapper
for <p:dataTable>
value:
<p:dataTable value="#{pageBean.listModelMapper}" var="mapper" >
<p:column headerText="Start Date">
<p:calendar value="#{mapper.startDate}" pattern="dd-MMM-yyyy" ></p:calendar>
</p:column>
<p:column headerText="End Date">
<p:calendar value="#{mapper.endDate}" pattern="dd-MMM-yyyy" ></p:calendar>
</p:column>
</p:dataTable>
<p:commandButton value="Save" action="#{pageBean.save()}" ajax="false" />
This workaround needs no modification to the actual model, although we need to do other things for moving the values to the actual model. It works well for me. Hope it will be useful.
Upvotes: 0
Reputation: 1108722
You are in first place not supposed to have a persistence layer specific typed property in your model. Your model should have a java.util.Date
property. Instead, your persistence layer should be altered to be able to deal with java.util.Date
model properties.
Do the conversion in the persistence layer instead.
preparedStatement.setTimestamp(i, new Timestamp(model.getDate().getTime()));
The other way round is not necessary as java.sql.Timestamp
is already a subclass of java.util.Date
.
Upvotes: 4
Reputation: 535
You can delegate timestamp to date and vise versa.
import java.sql.Timestamp;
import java.util.Date;
...
private Timestamp timestamp;
...
public Timestamp getTimestamp() {
return timestamp;
}
public void setTimestamp(Timestamp timestamp) {
this.timestamp = timestamp;
}
public Date getDate() {
return timestamp == null ? null : new Date(timestamp.getTime());
}
public void setDate(Date date) {
timestamp = date == null ? null : new Timestamp(date.getTime())
}
JSF:
<p:calendar id="button" value="#{bean.date}" showOn="button" />
Upvotes: 1