Announcement

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

    optionDataSource (and alternatives) and JPA/GAE

    I'm using SC_SNAPSHOT-2011-01-14/EVAL Deployment 2011-01-14

    I modified the 'gae-ds' sample datasource to include an optionDataSource. In this case a single reference in each Country to any City. What I really want to be able to do is map the stored cityId to a cityName - I don't want to be able to choose from any city (which is what is implied by this definition) - I simply want a lookup.

    Code:
    <DataSource ID="country_DataSource" serverConstructor="com.isomorphic.jpa.GAEJPADataSource"
    	beanClassName="com.smartgwt.sample.server.Country">
    	<fields>
    		<field name="countryId" type="text" hidden="true" primaryKey="true" />
    		<field name="countryCode" type="text" title="Code" required="true" />
    		<field name="countryName" type="text" title="Country" required="true" />
    		[b]<field name="cityInOtherCountry" type="text" optionDataSource="city_DataSource"
    			displayField="cityName" valueField="cityId" />[/b]
    		<field name="cities" type="city_DataSource" title="Cities"
    			multiple="true" javaClass="com.smartgwt.sample.server.City" />
    	</fields>
    </DataSource>
    I am a bit concerned about this exception.


    Code:
    Time to load datastore: 61 ms
    === 2011-01-17 14:43:10,400 [27-6] DEBUG GAEJPADataSource - [builtinApplication.country_DataSource_fetch] Query string: select _Country from Country _Country
    === 2011-01-17 14:43:10,874 [27-6] INFO  DSResponse - [builtinApplication.country_DataSource_fetch] DSResponse: List with 4 items
    === 2011-01-17 14:43:10,875 [27-6] DEBUG AppBase - [builtinApplication.city_DataSource_fetch] No userTypes defined, allowing anyone access to all operations for this application
    === 2011-01-17 14:43:10,875 [27-6] DEBUG AppBase - [builtinApplication.city_DataSource_fetch] No public zero-argument method named '_city_DataSource_fetch' found, performing generic datasource operation
    === 2011-01-17 14:43:10,875 [27-6] DEBUG JPADataSource - [builtinApplication.city_DataSource_fetch] Creating EntityManager and starting transaction.
    === 2011-01-17 14:43:10,876 [27-6] DEBUG GAEJPADataSource - [builtinApplication.city_DataSource_fetch] Query string: select _City from City _City
    === 2011-01-17 14:43:10,900 [27-6] INFO  DSResponse - [builtinApplication.city_DataSource_fetch] DSResponse: List with 7 items
    === 2011-01-17 14:43:10,901 [27-6] DEBUG AppBase - [builtinApplication.city_DataSource_fetch] No userTypes defined, allowing anyone access to all operations for this application
    === 2011-01-17 14:43:10,901 [27-6] DEBUG AppBase - [builtinApplication.city_DataSource_fetch] No public zero-argument method named '_city_DataSource_fetch' found, performing generic datasource operation
    === 2011-01-17 14:43:10,901 [27-6] DEBUG JPADataSource - [builtinApplication.city_DataSource_fetch] Creating EntityManager and starting transaction.
    === 2011-01-17 14:43:10,902 [27-6] DEBUG GAEJPADataSource - [builtinApplication.city_DataSource_fetch] Query string: select _City from City _City
    === 2011-01-17 14:43:10,924 [27-6] INFO  DSResponse - [builtinApplication.city_DataSource_fetch] DSResponse: List with 7 items
    === 2011-01-17 14:43:10,925 [27-6] DEBUG RPCManager - Content type for RPC transaction: text/plain; charset=UTF-8
    === 2011-01-17 14:43:10,927 [27-6] DEBUG RPCManager - non-DMI response, dropExtraFields: false
    === 2011-01-17 14:43:10,930 [27-6] DEBUG RPCManager - non-DMI response, dropExtraFields: false
    === 2011-01-17 14:43:10,931 [27-6] DEBUG RPCManager - non-DMI response, dropExtraFields: false
    === 2011-01-17 14:43:10,948 [27-6] DEBUG JPADataSource - Committing transaction.
    === 2011-01-17 14:43:10,971 [27-6] DEBUG JPADataSource - Committing transaction.
    === 2011-01-17 14:43:10,973 [27-6] DEBUG JPADataSource - Committing transaction.
    === 2011-01-17 14:43:10,978 [27-6] ERROR JPADataSource - Failed to commit transaction. Rolling back.
    javax.persistence.RollbackException: Transaction failed to commit
    	at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:118)
    	at org.datanucleus.store.appengine.jpa.DatastoreEntityTransactionImpl.commit(DatastoreEntityTransactionImpl.java:55)
    	at com.isomorphic.jpa.EMFProviderLMT.commitTransaction(EMFProviderLMT.java:153)
    	at com.isomorphic.jpa.EMF.commitTransaction(EMF.java:131)
    	at com.isomorphic.jpa.JPADataSource.freeResources(JPADataSource.java:578)
    	at com.isomorphic.datasource.DSRequest.freeResources(DSRequest.java:2771)
    	at com.isomorphic.rpc.RPCManager.completeResponse(RPCManager.java:1174)
    	at com.isomorphic.rpc.RPCManager.send(RPCManager.java:582)
    	at com.isomorphic.servlet.IDACall.processRPCTransaction(IDACall.java:130)
    	at com.isomorphic.servlet.IDACall.processRequest(IDACall.java:95)
    	at com.isomorphic.servlet.IDACall.doPost(IDACall.java:54)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:637)
    	at com.isomorphic.servlet.BaseServlet.service(BaseServlet.java:152)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    	at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:511)
    	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1166)
    	at com.google.appengine.api.blobstore.dev.ServeBlobFilter.doFilter(ServeBlobFilter.java:58)
    	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    	at com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:43)
    	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    	at com.google.appengine.tools.development.StaticFileFilter.doFilter(StaticFileFilter.java:122)
    	at org.mortbay.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1157)
    	at org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:388)
    	at org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:216)
    	at org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:182)
    	at org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:765)
    	at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:418)
    	at com.google.apphosting.utils.jetty.DevAppEngineWebAppContext.handle(DevAppEngineWebAppContext.java:70)
    	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    	at com.google.appengine.tools.development.JettyContainerService$ApiProxyHandler.handle(JettyContainerService.java:349)
    	at org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:152)
    	at org.mortbay.jetty.Server.handle(Server.java:326)
    	at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:542)
    	at org.mortbay.jetty.HttpConnection$RequestHandler.content(HttpConnection.java:938)
    	at org.mortbay.jetty.HttpParser.parseNext(HttpParser.java:755)
    	at org.mortbay.jetty.HttpParser.parseAvailable(HttpParser.java:218)
    	at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
    	at org.mortbay.io.nio.SelectChannelEndPoint.run(SelectChannelEndPoint.java:409)
    	at org.mortbay.thread.QueuedThreadPool$PoolThread.run(QueuedThreadPool.java:582)
    Caused by: javax.persistence.PersistenceException: Transaction rolled back due to failure during commit
    	at org.datanucleus.jpa.NucleusJPAHelper.getJPAExceptionForNucleusException(NucleusJPAHelper.java:283)
    	at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:116)
    	... 38 more
    Caused by: java.lang.IllegalStateException: Transaction is in state COMMITTED.  There is no legal transition out of this state.
    	at com.google.appengine.api.datastore.TransactionImpl.ensureTxnStarted(TransactionImpl.java:204)
    	at com.google.appengine.api.datastore.TransactionImpl.commitAsync(TransactionImpl.java:80)
    	at com.google.appengine.api.datastore.TransactionImpl.commit(TransactionImpl.java:76)
    	at org.datanucleus.store.appengine.DatastoreTransaction.commit(DatastoreTransaction.java:61)
    	at org.datanucleus.store.appengine.DatastoreXAResource.commit(DatastoreXAResource.java:88)
    	at org.datanucleus.transaction.Transaction.commit(Transaction.java:149)
    	at org.datanucleus.transaction.TransactionManager.commit(TransactionManager.java:95)
    	at org.datanucleus.TransactionImpl.internalCommit(TransactionImpl.java:390)
    	at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:258)
    	at org.datanucleus.jpa.EntityTransactionImpl.commit(EntityTransactionImpl.java:104)
    	... 38 more
    I have many such optionDataSource fields in my application and the number of these exceptions is growing quite large. The application appears to work, but it's getting very hard to spot any errors in the log.

    Is there

    1) a bug fix

    2) a better way to do this

    My data model has many entities with ID fields that refer to other entity types. I already asked this question here and I'm going to have a go at trying to get XPath working again.

    In general, it seems like optionDataSource is the wrong choice here. Aside from embedding the entity (ala the XPath way), are there any other ways to do this?

    Thanks in advance.

    #2
    optionDataSource is not the right way to do this (in fact it's not valid to set it in the DataSource - it's on ListGridField and FormItem only).

    JXPath is the typical approach, but since you're having trouble with that, you can replicate the functionality by adding a DMI that takes the result of dsResponse.getRecords() and adds the additional property you need by ordinary Java code.

    If it's a recurring pattern, create a custom DataSource that does this via a custom property you add to the DataSourceField - essentially your own, simplified version of the JXPath feature that isn't working for you with GAE.

    Comment


      #3
      Thanks for the quick reply.

      I had been seriously considering the approach you suggest with extra properties. The thing I'm not sure about is;

      1) Do I just add new fields to a record to represent the property (seems ugly, and difficult to handle)

      2) Do I create a new type 'type="pair_DataSource"' which I can use to pass back a displayValue/fieldValue pair, and then add custom CellFormatter to display it.

      I got a bit lost on the correct way to encode 2). On the server side, I presume I can go something like DataTools.setProperties(pair,map);

      This is all sounds far too convoluted. I think I should try and get XPath working...

      Comment


        #4
        This is what it looks like for SQL. You declare an additional field for the display value which is found in a related table, and you use a join to retrieve it.

        Very simple to the equivalent thing in Java, just replace the join with ordinary Java code to get the display value from the related bean.

        Definitely would not recommend your #2 approach, which does sound complicated.

        Comment


          #5
          Hmm, interesting. I presume all the table tags are only used by the SQL datasource and don't mean anything to the client components?

          I think I understand the SQL example. I'm a little unclear of the parts that are missing to do it as a Java DMI. I presume pretty much that I just return the same results that the join would. But do I need to do any other special handling to deal with the 'tableName' or other tags?

          Comment


            #6
            Ignore all the SQL artifacts (and note, the client doesn't even receive this information). The key take-away is that you just add another field to carry the display value, and add Java code to place it into the returned data.

            Comment


              #7
              Thanks so much. The simple approach of adding new fields makes this so much easier. I was getting seriously stuck abusing existing functionality to do something it was not meant to do.

              Comment

              Working...
              X