Announcement
Collapse
No announcement yet.
X
-
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.
-
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 Postadd DMI logic to your "fetch" operation where you call the server-side DSResponse.getRecord()s and convert all the Long values to Strings
fatzopilot
Leave a comment:
-
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.
Leave a comment:
-
Originally posted by Isomorphic View PostBeating 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".
When I do like advised, i.e.
Code:<field name="id" type="sequence" title="Id" valueXPath="stringId" primaryKey="true"/>
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)
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 PostAs far as Option 1, the field is declared as type "text" so validation forces it to a String.
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() ); }
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 PostLikewise 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.
Cheers,
fatzopilot
Leave a comment:
-
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.
Leave a comment:
-
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). SeeOriginally posted by Isomorphic View PostAs far as Option 1, the field is declared as type "text" so validation forces it to a String.
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]
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 PostIn 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").
Code:<field name="stringId" type="text" title="IdString" valueXPath="id" primaryKey="true"/>
Originally posted by Isomorphic View PostAnd 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.
Originally posted by Isomorphic View PostAlso, what database product and version is this that is using full-range Longs as IDs?
Hope things are clear now,
Thanks,
fatzopilot
Leave a comment:
-
To hopefully clarify things again:
The DMI approach means you simply declare fields normally, then add DMI logic to your "fetch" operation where you call the server-side DSResponse.getRecord()s and convert all the Long values to Strings, then call DSResponse.setData() with the updated data. Likewise, take any inbound values in a DSRequest that are in String format and change them to Long.
The alternative approach of creating an "alias field" on your Hibernate bean works as follows: say your bean has getter/setter methods getId()/setId() that work with Long.
1. Create getStringId()/setStringId() which return and take String, which actually convert between String and Long and call getId()/setId() with Long values
2. Declare a field "stringId" of type "text" in your DataSource and make that the primaryKey.
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").
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.
Also, what database product and version is this that is using full-range Longs as IDs?
Leave a comment:
-
Originally posted by Isomorphic View PostNo, a field declared as "text" is expected to be "text" and not something else.
Changing that field to "integer" and yet still having an error message about a missing primary key doesn't make sense and we can't reproduce that.
There are basically two approaches here:
1) use the original id field to submit a text version of the long id
2) use an alias data source field stringId with type text (and do some tricks to interact with hibernate.
1:
In order to work with very long ids, I tried to circumvent the crippled ids by converting them to text. This can be done if an additional getter/setter/formula field is provided in the bean which is named e.g. stringId. This can then be used in a valueXPath of the id field to obtain a String. Of course, the type of the id field in these cases is text.
Problem here: A text id from the client (e.g. in update operations) cannot be converted back (as described in a previous post) and hibernate does not accept string ids
2:
The field id has a type of "long" in the DB and in usual cases a type of "sequence" in the DS description.
As advised, I changed the type of the id data source field from sequence to integer and removed the primary key attribute, because I wanted to use a different data source field (e.g. stringId with corresponding getter/setter/formula fields in the bean) for that purpose.
Problem here:
Still, the id field is identified as a primary key field for some reason (probably, because it is a primary key field in hibernate), and so, all update operations require it (and it cannot be removed in a DMI, which is a showstopper here).
Originally posted by Isomorphic View PostSorry, we need to move on to bugs. Upgrading or using a DMI are two ways to solve this.
And I tried the latest Evaluation build
SmartClient Version: SNAPSHOT_v9.1d_2013-09-17/EVAL Deployment
which exhibits the exact same behavior in these regards.
Leave a comment:
-
No, a field declared as "text" is expected to be "text" and not something else.
Changing that field to "integer" and yet still having an error message about a missing primary key doesn't make sense and we can't reproduce that.
Sorry, we need to move on to bugs. Upgrading or using a DMI are two ways to solve this.
Leave a comment:
-
Originally posted by Isomorphic View PostAs far as Option 1, the field is declared as type "text" so validation forces it to a String.
Originally posted by Isomorphic View PostOn the PK error message, you've declared the type as "sequence" so that implies primaryKey=true.
Thanks,
fatzopilot
Leave a comment:
-
As far as Option 1, the field is declared as type "text" so validation forces it to a String.
On the PK error message, you've declared the type as "sequence" so that implies primaryKey=true.
Leave a comment:
-
Hm, seems like I was a bit to optimistic. Updating is still an issue as hibernate needs a long valued id to access the object via id (it's a long in the db).
Option 1): The obvious option:
Code:<field name="id" type="text" title="Id" valueXPath="stringId" primaryKey="true" detail="false"/> <!-- stringId delivers the id as string -->
I tried to replace both, the id criteria and the id value that are contained in a dsRequest. This works but if the request reaches Hibernate through DsRequest, AppBase, and HibernateDataSource, it is "magically" back converted to a String and consequently, Hibernate throws an exception:
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
Code:<field name="id" type="sequence" title="Id" detail="false"/> <field name="stringId" type="text" title="Id" primaryKey="true" valueXPath="stringId" canView="true" hidden="false" detail="false"/>
However, 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]. Either provide all primary key fields or set allowMultiUpdate on the OperationBinding
In addition, I feel that option 2 is clearly a bit too hacky.
Can you please check why the long id gets back-converted as described in 1 or propose another solution?
Thanks,
fatzopilot
Leave a comment:
-
OK, I was able to solve this using getStringId/setStringId on the bean, a valueXPath="stringId" in the DS field definition for id, and a formula for stringId on the bean (to make queries work).
Cheers,
fatzopilot
Leave a comment:
-
Yes that's what we meant, but clearly it doesn't work.
On the old version, you'll need to either transform the data once the dsResponse has been retrieved, or create a parallel getter/setter on your bean that returns a String and can take a String.
Leave a comment:
-
Originally posted by Isomorphic View PostIn older versions, setting a trivial valueXPath (same name as the bean getter method) would be one way to force conversion.
Code:<field name="id" type="text" valueXPath="id" title="Id" primaryKey="true" detail="false">
Thanks,
fatzopilot
Leave a comment:
Leave a comment: