Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    #16
    Hi Isomorphic,

    Thanks for your detailed response. My problem is not the data and not the fetch and add operations (these are solved already), it is the criteria in update operations that is making trouble whenever it contains the id.
    What happens:
    The id criteria (e.g. id=”1234567890123456) is of type text, so in order for this to work, I need to either
    Option 1: convert the criteria to long (DMI). This is not possible (as reported) because it is back converted to text due to the type of the id field (which is text). See
    Originally posted by Isomorphic View Post
    As far as Option 1, the field is declared as type "text" so validation forces it to a String.
    Option 2: do the update operation using an alias field of type text (stringId). Two suboptions
    Option 2.1: remove the id field form the DS. Then I get
    Code:
    com.isomorphic.base.UpdateWithoutPKException: Criteria received from the client for update operation is missing the following required unique and/or primary fields: [id]
    Option 2.2: let the id field in place
    What happens: I get both, id and stringID in the criteria. Because id is not accurate (crippled long version), I need to remove it from the critiera (DMI), which then leads to the same error as above.
    I don’t know whether both “issues” are by design, but they clearly derail my text field approach.

    Originally posted by Isomorphic View Post
    In theory, the same thing should also work by declaring a field "stringId" with a valueXPath to the field "id" - here you would be hoping JXPath is smart enough to handle String<-> Long conversion. It may not be, however, it doesn't look like you've tried this properly yet: in your previous attempts, you either did a no-op valueXPath (field name "id" valueXPath "id") or reversed the suggestion (field name "id" valueXPath "stringId").
    I tried this as well i.e.
    Code:
    <field name="stringId" type="text" title="IdString" valueXPath="id" primaryKey="true"/>
    But this id is crippled too.
    Originally posted by Isomorphic View Post
    And again the feature we referred to in the new version is for *SQL*DataSource, not Hibernate, so you won't get anything out of new versions, you'd have to switch to SQLDataSource first.
    Yeah, I missed that.
    Originally posted by Isomorphic View Post
    Also, what database product and version is this that is using full-range Longs as IDs?
    Postgres on the server, but the ids are by design. They are generated using a hash of the content of a second binary field. 64-bit hashes are just considered ok, less would become more and more problematic (collisions). These records are generated and used on mobile Android devices whose SQL-APIs (CursorAdapter) need an id field of type long.

    Hope things are clear now,
    Thanks,
    fatzopilot

    Comment


      #17
      Beating a dead horse here..

      The DMI solution does **not** involve declaring the field as type "text". It involves your own code converting from Long to String as described above. So there is no possible way the ID could end up "crippled".

      Likewise the alias field solution does not involve declaring the "id" field *at all*. So you can't possibly get a warning about a missing PK. And again with this solution, your own code does the Long<->String conversion, so there's no way for the framework to be truncating the value.

      Comment


        #18
        Originally posted by Isomorphic View Post
        Beating a dead horse here..
        The DMI solution does **not** involve declaring the field as type "text". It involves your own code converting from Long to String as described above. So there is no possible way the ID could end up "crippled".
        Again, the problem now is not the data, it is the criteria.
        When I do like advised, i.e.
        Code:
        <field name="id" type="sequence" title="Id" valueXPath="stringId" primaryKey="true"/>
        I still get
        Code:
        org.hibernate.TypeMismatchException: Provided id of the wrong type for class com.aCompany.Attachment. Expected: class java.lang.Long, got class java.lang.String
        	at org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:135)
        	at org.hibernate.impl.SessionImpl.fireLoad(SessionImpl.java:1090)
        	at org.hibernate.impl.SessionImpl.get(SessionImpl.java:1005)
        	at com.isomorphic.hibernate.HibernateDataSource.processRequest(HibernateDataSource.java:1458)
        	at com.isomorphic.hibernate.HibernateDataSource.executeUpdate(HibernateDataSource.java:821)
        	at com.isomorphic.datasource.DataSource.execute(DataSource.java:1383)
        	at com.isomorphic.application.AppBase.executeDefaultDSOperation(AppBase.java:723)
        	at com.isomorphic.application.AppBase.executeAppOperation(AppBase.java:658)
        	at com.isomorphic.application.AppBase.execute(AppBase.java:491)
        	at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:2044)
        	at com.aCompany.MyDMI$$EOHuass3.convertStringIDCriteriaToLong(MyDMI.java)
        	at com.aCompany.MyDMI$$EOHuass3.markDeleted(MyDMI.java:256)
        	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        	at java.lang.reflect.Method.invoke(Method.java:606)
        	at org.springsource.loaded.ri.ReloadedTypeInvoker$2.invoke(ReloadedTypeInvoker.java:122)
        	at org.springsource.loaded.ri.ReflectiveInterceptor.jlrMethodInvoke(ReflectiveInterceptor.java:1288)
        	at com.isomorphic.base.Reflection.adaptArgsAndInvoke(Reflection.java:973)
        	at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:416)
        	at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:64)
        	at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:2041)
        	at com.isomorphic.servlet.IDACall.handleDSRequest(IDACall.java:216)
        	at com.isomorphic.servlet.IDACall.processRPCTransaction(IDACall.java:173)
        	at com.isomorphic.servlet.IDACall.processRequest(IDACall.java:138)
        	at com.isomorphic.servlet.IDACall.doPost(IDACall.java:74)
        	at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
        on an update/delete operation, even if I manually convert the id Criteria into a Long in an updateDMI.
        This is what I don’t understand and cannot figure out by myself. The field is defined to be of type sequence (so this should not apply here:)
        Originally posted by Isomorphic View Post
        As far as Option 1, the field is declared as type "text" so validation forces it to a String.
        the id criteria is converted to Long and still the org.hibernate.impl.SessionImpl.get() method is invoked by com.isomorphic.hibernate.HibernateDataSource.processRequest () with an id of type String. Why? Is the type=”sequence” attribute meaningful at all in this case?
        This is the code where above exception is raised:
        org.hibernate.event.def.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:135)
        Code:
        final Class idClass = persister.getIdentifierType().getReturnedClass();
        		if ( persister.getIdentifierType().isComponentType() && EntityMode.DOM4J == event.getSession().getEntityMode() ) {
        			// skip this check for composite-ids relating to dom4j entity-mode;
        			// alternatively, we could add a check to make sure the incoming id value is
        			// an instance of Element...
        		}
        		else {
        			if ( idClass != null && ! idClass.isInstance( event.getEntityId() ) ) {
        				// we may have the kooky jpa requirement of allowing find-by-id where
        				// "id" is the "simple pk value" of a dependent objects parent.  This
        				// is part of its generally goofy "derived identity" "feature"
        				if ( persister.getEntityMetamodel().getIdentifierProperty().isEmbedded() ) {
        					final EmbeddedComponentType dependentIdType =
        							(EmbeddedComponentType) persister.getEntityMetamodel().getIdentifierProperty().getType();
        					if ( dependentIdType.getSubtypes().length == 1 ) {
        						final Type singleSubType = dependentIdType.getSubtypes()[0];
        						if ( singleSubType.isEntityType() ) {
        							final EntityType dependentParentType = (EntityType) singleSubType;
        							final Type dependentParentIdType = dependentParentType.getIdentifierOrUniqueKeyType( source.getFactory() );
        							if ( dependentParentIdType.getReturnedClass().isInstance( event.getEntityId() ) ) {
        								// yep that's what we have...
        								loadByDerivedIdentitySimplePkValue(
        										event,
        										loadType,
        										persister,
        										dependentIdType,
        										source.getFactory().getEntityPersister( dependentParentType.getAssociatedEntityName() )
        								);
        								return;
        							}
        						}
        					}
        				}
        				throw new TypeMismatchException(
        						"Provided id of the wrong type for class " + persister.getEntityName() + ". Expected: " + idClass + ", got " + event.getEntityId().getClass()
        				);
        			}
        because (as mentioned above) org.hibernate.impl.SessionImpl.get() is invoked with a String argument.

        Conclusion:
        Unless it is not possible to convert String id criteria to Long, the whole approach (stringIds on the client) is doomed to failure for update/delete operations using the hibernate datasource.
        Originally posted by Isomorphic View Post
        Likewise the alias field solution does not involve declaring the "id" field *at all*. So you can't possibly get a warning about a missing PK.
        Apologies, I missed an inheritsFrom statement which inherits a hidden id field. That’s why it appeared as if removing the id field does not work (because the update operations still requested it).

        Cheers,
        fatzopilot

        Comment


          #19
          You are mixing working approaches together in ways that break them.

          For the DMI approach, get rid of the valueXPath on your sequence field, and do not declare any additional setters. Add the described DMI logic to convert outbound dsResponse values to String and inbound dsRequest criteria and values to Long.

          That's it and nothing else.

          If you're still having trouble with this approach, you need to post your code for converting the dsRequest. It looks like it's not working.

          Comment


            #20
            Hi,

            thanks, the last suggestion/clarification finally works in all cases and is comparatively simple.
            I was wrong in the assumption that using the custom stingId s/getter and mapping it to the id field using a valueXPath is basically the same as
            Originally posted by Isomorphic View Post
            add DMI logic to your "fetch" operation where you call the server-side DSResponse.getRecord()s and convert all the Long values to Strings
            Thanks for your patience and sorry for the trouble,
            fatzopilot

            Comment


              #21
              As of the latest 5.1d builds, we now have built-in features for automatically converting Long, BigDecimal and BigInteger values to Strings when they are delivered to the browser - see dataSourceField.stringInBrowser.

              Comment

              Working...
              X