Uploaded image for project: 'ZK'
  1. ZK
  2. ZK-3966

saving a conditional binding throws IllegalStateException: can only add one element

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: Normal Normal
    • None
    • 8.5.1, 8.5.1.2
    • None
    • Security Level: Jimmy
    • None
    • ZK 8.5.2 S2

      Problem description

      original case is a date returned by Hibernate, so its type is java.sql.Timestamp

      Steps to Reproduce

      1. run the attached zul
      2. click the button

      Current Result

      java.lang.IllegalStateException: can only add one element
      	at org.zkoss.zkmax.bind.impl.SingleObjectSet.add(SingleObjectSet.java:43)
      	at org.zkoss.zkmax.bind.impl.AllocUtilEx.addLinkedHashSet(AnnotateBinderEx.java:131)
      	at org.zkoss.zkmax.bind.impl.TrackerImplEx.addBeanMap(TrackerImplEx.java:126)
      	at org.zkoss.bind.tracker.impl.TrackerImpl.tieValue(TrackerImpl.java:343)
      	at org.zkoss.bind.xel.zel.BindELResolver.tieValue(BindELResolver.java:285)
      	at org.zkoss.zkmax.bind.impl.BindELResolverEx.tieValue(BindELResolverEx.java:143)
      	at org.zkoss.bind.xel.zel.BindELResolver.getValue(BindELResolver.java:154)
      	at org.zkoss.zel.impl.parser.AstValue.getValue(AstValue.java:188)
      	at org.zkoss.zel.impl.ValueExpressionImpl.getValue(ValueExpressionImpl.java:184)
      	at org.zkoss.zkmax.bind.impl.ValueExpressionImplEx.getValue(ValueExpressionImplEx.java:52)
      	at org.zkoss.xel.zel.ELXelExpression.evaluate(ELXelExpression.java:41)
      	at org.zkoss.zkmax.bind.impl.BindEvaluatorXImplEx$LazyBindXelExpression.evaluate(BindEvaluatorXImplEx.java:124)
      	at org.zkoss.bind.impl.BindEvaluatorXImpl.getValue(BindEvaluatorXImpl.java:46)
      	at org.zkoss.bind.impl.LoadPropertyBindingImpl.load(LoadPropertyBindingImpl.java:58)
      	at org.zkoss.bind.impl.BinderImpl.doPropertyChange0(BinderImpl.java:460)
      	at org.zkoss.bind.impl.BinderImpl.doPropertyChange(BinderImpl.java:435)
      	at org.zkoss.bind.impl.BinderImpl.access$300(BinderImpl.java:132)
      	at org.zkoss.bind.impl.BinderImpl$QueueListener.onEvent(BinderImpl.java:394)
      	at org.zkoss.zk.ui.event.impl.DesktopEventQueue$QueueListener.onEvent(DesktopEventQueue.java:168)
      	at org.zkoss.zk.ui.AbstractComponent.onEvent(AbstractComponent.java:3168)
      	at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3138)
      	at org.zkoss.zk.ui.AbstractComponent.service(AbstractComponent.java:3080)
      	at org.zkoss.zk.ui.impl.EventProcessor.process(EventProcessor.java:138)
      	at org.zkoss.zk.ui.impl.UiEngineImpl.processEvent(UiEngineImpl.java:1846)
      	at org.zkoss.zk.ui.impl.UiEngineImpl.process(UiEngineImpl.java:1618)
      	at org.zkoss.zk.ui.impl.UiEngineImpl.execUpdate(UiEngineImpl.java:1321)
      	at org.zkoss.zk.au.http.DHtmlUpdateServlet.process(DHtmlUpdateServlet.java:611)
      	at org.zkoss.zk.au.http.DHtmlUpdateServlet.doGet(DHtmlUpdateServlet.java:487)
      	at org.zkoss.zk.au.http.DHtmlUpdateServlet.doPost(DHtmlUpdateServlet.java:495)
      

      Expected Result

      no error

      Debug Information

      • not sure if this is a bug, please verify
      • no exception with
        1. 8.5.0 before
        2. 8.5.1 CE
      • caused by the fix of ZK-3808
      • Notice that we can't compare a java.sql.Timestamp and java.util.Date with equal(). It might return false even when both represent the same time according to javadoc: https://docs.oracle.com/javase/8/docs/api/java/sql/Timestamp.html
        Assume you have:
        Date d = new Date(100000000);
        Date t = new Timestamp(100000000); //same instant
        

      you get the following inconsistent results based on the execution order:
      d.equals(t) -> true
      t.equals(d) -> false
      We can only compare a Timestamp with another Timestamp.
      Other persons observe similar issues (https://gist.github.com/ccare/3917104)
      Oracle clearly mentions this to work as designed/documented https://bugs.openjdk.java.net/browse/JDK-7060309

      Workaround

      1. https://www.thoughts-on-java.org/hibernate-tips-map-java-util-date-database-column/
      2. declare java.time.LocalDateTime (recommended in Java 8) for that member field with hibernate 5
      Please refer to https://www.thoughts-on-java.org/hibernate-5-date-and-time/
      3. declare java.sql.Timestamp for that member field in an entity class
      4. implement a UserType that converts java.sql.Timestamp to java.util.Date
      Please refer to https://www.sourceallies.com/2012/02/hibernate-date-vs-timestamp/

        1. 3966.zul
          0.2 kB
          hawk
        2. T5674VM.java
          0.5 kB
          hawk

            Unassigned Unassigned
            hawk hawk
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved: