TemporalType injection with Calendar using JPA

#1

I have ObjectDB  JPA  comsummed by a RESTful web service deployed on Tomcat.

I am using an embedded object as a primary key, which has time fields which I have annotated with TemporalType.TIMESTAMP

When I use a java.util.Date as a field on this object there is no problem. However, if I use a java.util.Calendar it encounters an exception.  

Calendar is what I need.  Is there something obvious here that I am failing to see?

 

@Embeddable
@Access(AccessType.PROPERTY)
public class TimePeriod implements Serializable {
   
    private Calendar beginTime;
    private Calendar endTime;
    private String periodType;

    @Temporal(TemporalType.TIMESTAMP)
    public Calendar getBeginTime() {
        return beginTime;
    }

    public void setBeginTime(Calendar beginTime) {
        this.beginTime = beginTime;
    }

    @Temporal(TemporalType.TIMESTAMP)
    public Calendar getEndTime() {
        return endTime;
    }

    public void setEndTime(Calendar endTime) {
        this.endTime = endTime;
    }

@Override
    public String toString() {
        return "com.foo.bar.jpa.entity.TimePeriod[ " + periodType + ", " + beginTime + ", " + endTime + " ]";
    }

 

And this is embedded in this Entity class

@Entity
@Access(AccessType.PROPERTY)
public class Chart implements Serializable {
    private TimePeriod id;

    private List<Point> points;

    public Chart() {
        this.points = new ArrayList<Point>();
    }

 

    @EmbeddedId
    public TimePeriod getId() {
        return id;
    }

 

    public void setId(TimePeriod id) {
        this.id = id;
    }

 

    @OneToMany(cascade=javax.persistence.CascadeType.ALL,fetch=javax.persistence.FetchType.EAGER)
    public List<Point> getPoints() {
        return points;
    }

 

    public void setPoints(List<Point> points) {
        this.points = points;
    }

 

 

And the exception is as follows:

mapMappableContainerException
SEVERE: The RuntimeException could not be mapped to a response, re-throwing to the HTTP container
[ObjectDB 2.2.5_02] javax.persistence.PersistenceException
Unexpected argument (com.foo.bar.jpa.enity.TimePeriod[ day, java.util.GregorianCalendar[time=1306779283031,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/London",offset=0,dstSavings=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2011,MONTH=4,WEEK_OF_YEAR=22,WEEK_OF_MONTH=5,DAY_OF_MONTH=30,DAY_OF_YEAR=150,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=7,HOUR_OF_DAY=19,MINUTE=14,SECOND=43,MILLISECOND=31,ZONE_OFFSET=0,DST_OFFSET=3600000], java.util.GregorianCalendar[time=1306779283031,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/London",offset=0,dstSavings=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2011,MONTH=4,WEEK_OF_YEAR=22,WEEK_OF_MONTH=5,DAY_OF_MONTH=30,DAY_OF_YEAR=150,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=7,HOUR_OF_DAY=19,MINUTE=14,SECOND=43,MILLISECOND=31,ZONE_OFFSET=0,DST_OFFSET=3600000] ]) as a primary key (error 691)
at com.objectdb.jpa.EMImpl.find(EMImpl.java:554)
at com.objectdb.jpa.EMImpl.find(EMImpl.java:472)
...  my JPA findEntity call
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.jersey.server.impl.model.method.dispatch.AbstractResourceMethodDispatchProvider$ResponseOutInvoker._dispatch(AbstractResourceMethodDispatchProvider.java:187)
at com.sun.jersey.server.impl.model.method.dispatch.ResourceJavaMethodDispatcher.dispatch(ResourceJavaMethodDispatcher.java:71)
at com.sun.jersey.server.impl.uri.rules.HttpMethodRule.accept(HttpMethodRule.java:280)
at com.sun.jersey.server.impl.uri.rules.ResourceClassRule.accept(ResourceClassRule.java:108)
at com.sun.jersey.server.impl.uri.rules.RightHandPathRule.accept(RightHandPathRule.java:147)
at com.sun.jersey.server.impl.uri.rules.RootResourceClassesRule.accept(RootResourceClassesRule.java:84)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1341)
at com.sun.jersey.server.impl.application.WebApplicationImpl._handleRequest(WebApplicationImpl.java:1273)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1223)
at com.sun.jersey.server.impl.application.WebApplicationImpl.handleRequest(WebApplicationImpl.java:1213)
at com.sun.jersey.spi.container.servlet.WebComponent.service(WebComponent.java:414)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:537)
at com.sun.jersey.spi.container.servlet.ServletContainer.service(ServletContainer.java:699)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:820)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:454)
at java.lang.Thread.run(Thread.java:619)
Caused by: com.objectdb.o.UserException: Unexpected argument (com.foo.bar.jpa.entity.TimePeriod[ day, java.util.GregorianCalendar[time=1306779283031,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/London",offset=0,dstSavings=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2011,MONTH=4,WEEK_OF_YEAR=22,WEEK_OF_MONTH=5,DAY_OF_MONTH=30,DAY_OF_YEAR=150,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=7,HOUR_OF_DAY=19,MINUTE=14,SECOND=43,MILLISECOND=31,ZONE_OFFSET=0,DST_OFFSET=3600000], java.util.GregorianCalendar[time=1306779283031,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/London",offset=0,dstSavings=3600000,useDaylight=true,transitions=242,lastRule=java.util.SimpleTimeZone[id=Europe/London,offset=0,dstSavings=3600000,useDaylight=true,startYear=0,startMode=2,startMonth=2,startDay=-1,startDayOfWeek=1,startTime=3600000,startTimeMode=2,endMode=2,endMonth=9,endDay=-1,endDayOfWeek=1,endTime=3600000,endTimeMode=2]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2011,MONTH=4,WEEK_OF_YEAR=22,WEEK_OF_MONTH=5,DAY_OF_MONTH=30,DAY_OF_YEAR=150,DAY_OF_WEEK=2,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=7,HOUR_OF_DAY=19,MINUTE=14,SECOND=43,MILLISECOND=31,ZONE_OFFSET=0,DST_OFFSET=3600000] ]) as a primary key
at com.objectdb.o.MSG.d(MSG.java:74)
at com.objectdb.o.OBC.aF(OBC.java:745)
at com.objectdb.jpa.EMImpl.find(EMImpl.java:536)
... 43 more
Caused by: com.objectdb.o.InternalException
at com.objectdb.o.VUT.e(VUT.java:220)
at com.objectdb.o.VUT.e(VUT.java:147)
at com.objectdb.o.UMR.s(UMR.java:418)
at com.objectdb.o.UMR.r(UMR.java:395)
at com.objectdb.o.MMM.Y(MMM.java:828)
at com.objectdb.o.OBC.aF(OBC.java:742)

 

 

 

#2

Calender is currently not one of the supported types for primary keys.

JPA supports only java.sql.Date (or java.util.Date that is annotated as DATE).

ObjectDB adds support of Time and Timestamp as an extension, but not Calendar.

You will have to replace Calendar with one of the supported temporal types.

ObjectDB Support
#3

Ah!!!   I can see that in the small print now.  blush  (After I wasted too much time on it)

The following documentation is misleading Embeddable Classes (and Simple Java Data Types), as it clearly states that java.util.Calendar is a persistable type for a field in a Embeddable class.

Perhaps you should add "except when the embeddable class is a primary key!"

And why not anyway?  Why supported in one case, but not the other?

 

#4

I agree that this could be confusing.

However, that page starts with the following definition:

    The term persistable types refers to data types that can be used in storing data in the database.

The rules for primary keys are more restrictive, as explained on the primary key page.

Probably Calendar may be supported in the future - but as long as it is not portable JPA - it should be avoided anyway when possible.

ObjectDB Support
#5

Thank you for your swift reply.   Based on that, I have replaced the Calendar fields with "long" data types which represent the millisecond value of the Date, and added some converter methods.

 

@Embeddable
@Access(AccessType.PROPERTY)
public class TimePeriod implements Serializable {
   
    private long beginTime;
    private long endTime;
    private String periodType;

 

    public long getBeginTime() {
        return beginTime;
    }
    public void setBeginTime(long beginTime) {
        this.beginTime = beginTime;
    }

 

    public long getEndTime() {
        return endTime;
    }
    public void setEndTime(long endTime) {
        this.endTime = endTime;
    }

 

    public String getPeriodType() {
        return periodType;
    }
    public void setPeriodType(String periodType) {
        this.periodType = periodType;
    }

 

    public Calendar beginCalendar() {
        return asCalenderObject(beginTime);
    }
    public Calendar endCalendar() {
        return asCalenderObject(endTime);
    }

 

    public void setBeginTime(Calendar c) {
        this.beginTime = c.getTimeInMillis();
    }
    public void setEndTime(Calendar c) {
        this.endTime = c.getTimeInMillis();
    }

 

    private Calendar asCalenderObject(long timeInMilliseconds)
    {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(timeInMilliseconds);
        return c;
    }

Reply