Announcement

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

    #31
    Originally posted by Isomorphic View Post
    Regarding this NPE/NumberFormatException issue, this is the interesting one to isolate - can we see the DataSource definition and client code?

    Note that the log has two different threads (10-2 and 10-3) with interleaved logs. It looks like you are simultaneously adding new nodes and fetching existing nodes. Unless you wait for the callback from DataSource.addData() before fetching, this is going to have unpredictable results from run to run. Also, your own logs aren't going through log4j so aren't getting thread markers, so we can't tell what thread you're in.
    I've attached the source code to the data source, the client app, and the JPA user in the server. This is the code specifically that results in a numberformatexception when a subdomain is added to the root domain.

    While you may have other suggests, here is how the client code works. When it starts, it sends a query looking for a node named Global in the tree. If the results is empty, it will then use addData to create a rootNode with the name "Global". It does this only after the results of the initial query is returned.

    I suspect that there is an implicit fetch issued by the treeGrid to get the contents of the tree (which on the initial run of the app, should be empty). Perhaps to make things cleaner, I should spawn the initial query/addData for the Global node after the treeGrid renders and has loaded its empty tree from the server.

    After the global node was created and shows up in the tree, there is a contextMenu added to the nodes that lets me (a) create a subdomain/node under the selected domain/node (b) remove the selected node, (c) create another root domain/node. It is when I select "add subdomain" from the global node that I see the numberformatexception. When the add subdomain menu is selected, I grab the Id of the selected node, add that to the record with a name of "parentDomainId" along with a default name "new-domain" and send that to the server using addData.

    In both cases (adding root node or a sub node), I get a NPE when the server attempts to create the results to send back to the client.

    I never, ever specify an id for the record (only the parentId). That is assigned by JPA/Hibernate and is returned in the results via your RPC mechanism.

    If you have a different/better way of adding a node to the tree other than addData() with a record holding the name and parentId property I'm all ears.

    As to adding new Root domain nodes, I use the same strategy but I set the parentDomainId property in the record to "null" since that is the "treerootvalue".

    As to the server logs, I'm guilty. Rather than crank up log4j, I just used System.out.println(). You lose the timestamp, but the order in the log file is likely correct since log4j uses the System printer to write to the same log file.

    And I can assure you, I don't get any NPE in my getters/setters. The first and the last thing they do before returning is to write their values to System.out - those output lines are always there.

    I've included the source files to this message.
    Attached Files

    Comment


      #32
      Setting autoFetchData and then also manually calling fetchData() is what results in the duplicate fetch, which is also making it impossible to figure out what's going because you've got an "add" and a "fetch" executing concurrently with unmarked logs in the midst. Can you correct the code and send an updated log?

      Comment


        #33
        Note also, your server code is blending two strategies that were intended to be distinct. The mix of the two strategies breaks both.

        The two approaches are:

        1. use the default rootValue of null, or insert a specific row to serve as the rootValue.

        In this case, don't declare a parentDomainId field at all, just declare the relation and use the implicit support for relations documented under the JpaIntegration doc.

        You said you had some kind of NPE / NumberFormatException with this approach, but there's code mixed in here from a totally unrelated strategy, and it would definitely interfere with the default behavior here.

        2. declare a non-null rootValue such as "root" and, since JPA won't store that, map a null parent reference to "root" *entirely outside of JPA*.

        You added some getters and setters to do this but then made it into a persistent JPA field. To end all possible confusion, you could write this as a DMI instead completely outside your JPA bean - modify inbound criteria containing parentId:"root" to null, and modify outbound data (dsResponse.getRecords()) so that parentId:null is replaced with "root".

        Comment


          #34
          Originally posted by Isomorphic View Post
          Setting autoFetchData and then also manually calling fetchData() is what results in the duplicate fetch, which is also making it impossible to figure out what's going because you've got an "add" and a "fetch" executing concurrently with unmarked logs in the midst. Can you correct the code and send an updated log?
          The fetchData() call is made with criteria name="Global". The second fetch is called by the autoFetchData presumably by the TreeGrid code to get what it needs to render.

          I changed it to use a different strategy. Instead of doing a search for my "Global" tree node, I hang a DataArrivedHandler on the TreeGrid and then inspect the tree to see if there are any nodes. If not, I then call addData to create the "Global" node. With this, you won't see multiple fetches.

          I've attached another log file that includes the log contents for the initial load/fetch, the addData for the root node ("Global"), followed by a subDomain addData(), which resulted in a fetch being sent by the client. Looking at the RPCs info, they are all serial.
          Attached Files

          Comment


            #35
            Originally posted by Isomorphic View Post
            Note also, your server code is blending two strategies that were intended to be distinct. The mix of the two strategies breaks both.
            Hmmm. I didn't think I was doing these both at the same time. I believe I have tried both of them to no avail

            Originally posted by Isomorphic View Post
            The two approaches are:

            1. use the default rootValue of null, or insert a specific row to serve as the rootValue.

            In this case, don't declare a parentDomainId field at all, just declare the relation and use the implicit support for relations documented under the JpaIntegration doc.

            You said you had some kind of NPE / NumberFormatException with this approach, but there's code mixed in here from a totally unrelated strategy, and it would definitely interfere with the default behavior here.
            Funny thing, this is where I started. I only added the parentDomainId field when I got stuck trying to figure out how to add a root node (heck, any node) using just my plan JPA annotations.

            I had a manytoone relationship for a parentDomain object of type Domain. e.g.
            Code:
            @ManyToOne(fetch=LAZY, optional=true)
            Domain parentDomain;
            I had no parentDomainId field at all. I could't find anything that showed how I could get a Domain object reference (whether it be null or something else) to be added to the database. If I remember correctly, I was getting a variety of "can't cast X to Domain" errors. I didn't see any examples of adding nodes via JPA in either the samples or the JpaIntegration doc. Perhaps I missed them.

            In any case, while searching your forums, I ran across a collection of articles that suggested I needed to add a parentId field to my JPA. I would be more than happy to find that I don't and that there is something that would work for me using my original JPA beans.
            Originally posted by Isomorphic View Post
            2. declare a non-null rootValue such as "root" and, since JPA won't store that, map a null parent reference to "root" *entirely outside of JPA*.

            You added some getters and setters to do this but then made it into a persistent JPA field. To end all possible confusion, you could write this as a DMI instead completely outside your JPA bean - modify inbound criteria containing parentId:"root" to null, and modify outbound data (dsResponse.getRecords()) so that parentId:null is replaced with "root".
            I guess I could do that, but that seemed to be counter to all I read - I was encouraged to "just use the built-in datasource support in smartgwt-ee". I've been trying real hard to do that since then.

            Comment


              #36
              On duplicate fetches - you didn't need to switch strategy, you just needed to choose between a manual call to fetchData or setting autoFetchData. Don't do both or you're telling the system to fetch twice.

              On the new logs - what we're seeing is that everything is going exactly as it shown, except that every time we call getParentDomainId() a NullPointerException is thrown, and every time we call setParentDomainId() setter a NumberFormatException is thrown. These are seemingly coming from JPA, and seem to be spurious. We've added some logging so that, in tomorrow's build of 3.1d, it will show the full stack trace if the com.isomorphic.datasource.DataSource log category is set to DEBUG.

              On inserting with no explicitly declared field - you can do this and the main JPA examples showing one-to-many and many-to-one both do this. We couldn't tell you what the problem was there because the only code we've seen from you mixes other strategies in.

              On the last point - all strategies discussed in fact leverage the built-in connectors in SmartGWT-EE. If you use a DMI to modify inbound and outbound data for a single field you are still using the connector to do all the heavy lifting.

              Comment


                #37
                Originally posted by Isomorphic View Post
                On duplicate fetches - you didn't On the new logs - what we're seeing is that everything is going exactly as it shown, except that every time we call getParentDomainId() a NullPointerException is thrown, and every time we call setParentDomainId() setter a NumberFormatException is thrown. These are seemingly coming from JPA, and seem to be spurious. We've added some logging so that, in tomorrow's build of 3.1d, it will show the full stack trace if the com.isomorphic.datasource.DataSource log category is set to DEBUG.
                Ok. I'm pretty sure that my getter/setters aren't throwing exceptions, but the getter does return a null and the setter is getting called with a null.
                Originally posted by Isomorphic View Post
                On inserting with no explicitly declared field - you can do this and the main JPA examples showing one-to-many and many-to-one both do this. We couldn't tell you what the problem was there because the only code we've seen from you mixes other strategies in.
                I'm reworking to go back to that approach. Right now it is properly creating database entries but tossing NPEs and getting cast exceptions (probably related). I'll look over the JPA samples again to see if I notice anything I'm doing wrong.

                Comment


                  #38
                  Originally posted by bjvetter View Post
                  I'm reworking to go back to that approach. Right now it is properly creating database entries but tossing NPEs and getting cast exceptions (probably related). I'll look over the JPA samples again to see if I notice anything I'm doing wrong.
                  I think I have things setup correctly, but the one thing I am stymied on is what to stick into the Record provided to addData() for the parentDomain object.

                  The UI for the app is design to let the user select a node on the tree and then using a context menu, add a new sub-node. I have the selected "parent node" and to create the new object, I want to call addData passing that "node" or a reference to it inside the Record object. Passing the id doesn't work completely. The DB gets updated properly but I see NPEs and cast errors and then the tree can't be rendered.

                  When I look over the manytoone sample, I see calls in the listGrid to startEditingNew() which seems to handle all of the update magic. I didn't see a startEditingTreeNode() or anything like it in the TreeGrid/Tree classes. I think I must have missed something in the docs and can't find the obvious object/method in the haystack since there is so much there.

                  Comment


                    #39
                    On your last comment about startEditingNew, TreeGrid is a subclass of ListGrid.

                    Comment


                      #40
                      Originally posted by Isomorphic View Post
                      On your last comment about startEditingNew, TreeGrid is a subclass of ListGrid.
                      Yep it sure is. And when I use it I get some exceptions:
                      Code:
                      11:56:50.067 [ERROR] [JPADS_js] Uncaught exception escaped
                      
                      com.google.gwt.core.client.JavaScriptException: (String): Invoking an instance method on a null instance
                          at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                          at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
                          at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
                          at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
                          at com.google.gwt.dev.shell.ModuleSpace.createJavaScriptException(ModuleSpace.java:70)
                          at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:60)
                          at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
                          at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)
                          at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)
                          at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
                          at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
                          at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
                          at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
                          at com.smartgwt.client.widgets.tree.TreeGrid.getExtraIcon(TreeGrid.java)
                          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.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
                          at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
                          at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
                          at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)
                          at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)
                          at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
                          at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
                          at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
                          at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
                          at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
                          at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:213)
                          at sun.reflect.GeneratedMethodAccessor86.invoke(Unknown Source)
                          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                          at java.lang.reflect.Method.invoke(Method.java:597)
                          at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
                          at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
                          at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
                          at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)
                          at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)
                          at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
                          at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
                          at com.google.gwt.dev.shell.ModuleSpace.invokeNativeVoid(ModuleSpace.java:289)
                          at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeVoid(JavaScriptHost.java:107)
                          at com.smartgwt.client.widgets.grid.ListGrid.startEditingNew(ListGrid.java)
                          at mobi.droidcloud.mgmt.client.JPADS$3.onClick(JPADS.java:159)
                          at com.smartgwt.client.widgets.menu.events.MenuItemClickEvent.dispatch(MenuItemClickEvent.java:96)
                          at com.smartgwt.client.widgets.menu.events.MenuItemClickEvent.dispatch(MenuItemClickEvent.java:1)
                          at com.google.gwt.event.shared.GwtEvent.dispatch(GwtEvent.java:1)
                          at com.google.web.bindery.event.shared.EventBus.dispatchEvent(EventBus.java:40)
                          at com.google.web.bindery.event.shared.SimpleEventBus.doFire(SimpleEventBus.java:193)
                          at com.google.web.bindery.event.shared.SimpleEventBus.fireEvent(SimpleEventBus.java:88)
                          at com.google.gwt.event.shared.HandlerManager.fireEvent(HandlerManager.java:127)
                          at com.smartgwt.client.core.DataClass.fireEvent(DataClass.java:248)
                          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.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
                          at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
                          at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
                          at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessagesWhileWaitingForReturn(BrowserChannelServer.java:337)
                          at com.google.gwt.dev.shell.BrowserChannelServer.invokeJavascript(BrowserChannelServer.java:218)
                          at com.google.gwt.dev.shell.ModuleSpaceOOPHM.doInvoke(ModuleSpaceOOPHM.java:136)
                          at com.google.gwt.dev.shell.ModuleSpace.invokeNative(ModuleSpace.java:561)
                          at com.google.gwt.dev.shell.ModuleSpace.invokeNativeObject(ModuleSpace.java:269)
                          at com.google.gwt.dev.shell.JavaScriptHost.invokeNativeObject(JavaScriptHost.java:91)
                          at com.google.gwt.core.client.impl.Impl.apply(Impl.java)
                          at com.google.gwt.core.client.impl.Impl.entry0(Impl.java:213)
                          at sun.reflect.GeneratedMethodAccessor86.invoke(Unknown Source)
                          at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
                          at java.lang.reflect.Method.invoke(Method.java:597)
                          at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:103)
                          at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
                          at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
                          at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:292)
                          at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:546)
                          at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)
                          at java.lang.Thread.run(Thread.java:680)
                      Once I dismiss these exceptions, the inplace editor lets me create a root node. It wasn't obvious how I could pass the parent node to startEditingNew() that would result in a new node added under another in the tree.

                      But I did find out something important this morning. The adding/inserting of the data into the tree is working with using just JPA relationships if what I provide in the addData for the parentDomain is the id value of the parentNode.

                      As it turns out, my problems are not adding/persisting the new node, the problem is with a call to openFolder() that I call after I get the results back from the addData() call. Commenting out openFolder() and not trying to open the tree shows a clean insert. The code that triggers the issues follows, but it is also triggered simply by opening the node in the UI:
                      Code:
                                 	treeGrid.addData(newDomain, new DSCallback() {
                      					@Override
                      			public void execute(DSResponse response,
                      							Object rawData, DSRequest request) {
                      	                	Tree t = treeGrid.getData();
                      	                	if (!t.isOpen((TreeNode)r)) {
                      	                		// open parent node to show the new node
                      	                		t.openFolder((TreeNode)r);
                      	                	}
                      			}
                                  	});
                      The log in the server follows:
                      Code:
                      === 2012-07-25 12:30:44,981 [0-36] INFO  RequestContext - URL: '/JPADS_js/sc/IDACall', User-Agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:5.0.1) Gecko/20100101 Firefox/5.0.1': Moz (Gecko) with Accept-Encoding header
                      === 2012-07-25 12:30:44,983 [0-36] DEBUG XML - Parsed XML from (in memory stream): 2ms
                      === 2012-07-25 12:30:44,985 [0-36] DEBUG RPCManager - Processing 1 requests.
                      === 2012-07-25 12:30:44,986 [0-36] DEBUG RPCManager - Request #1 (DSRequest) payload: {
                          criteria:{
                              parentDomain:4
                          },
                          operationConfig:{
                              dataSource:"domain_DataSource",
                              operationType:"fetch",
                              textMatchStyle:"exact"
                          },
                          componentId:"isc_TreeGrid_0",
                          appID:"builtinApplication",
                          operation:"domain_DataSource_fetch",
                          oldValues:{
                              parentDomain:4
                          }
                      }
                      === 2012-07-25 12:30:44,986 [0-36] INFO  IDACall - Performing 1 operation(s)
                      === 2012-07-25 12:30:44,987 [0-36] DEBUG AppBase - [builtinApplication.domain_DataSource_fetch] No userTypes defined, allowing anyone access to all operations for this application
                      === 2012-07-25 12:30:44,987 [0-36] DEBUG AppBase - [builtinApplication.domain_DataSource_fetch] No public zero-argument method named '_domain_DataSource_fetch' found, performing generic datasource operation
                      === 2012-07-25 12:30:44,987 [0-36] DEBUG JPADataSource - [builtinApplication.domain_DataSource_fetch] Creating EntityManager and starting transaction.
                      === 2012-07-25 12:30:44,988 [0-36] DEBUG DSRequest - [builtinApplication.domain_DataSource_fetch] Clobbering existing FreeResourcesHandler of type 'com.isomorphic.jpa.JPADataSource' with a 'com.isomorphic.jpa.JPADataSource'
                      === 2012-07-25 12:30:44,988 [0-36] DEBUG JPADataSource - [builtinApplication.domain_DataSource_fetch] Executing fetch.
                      === 2012-07-25 12:30:44,988 [0-36] WARN  JPADataSource - [builtinApplication.domain_DataSource_fetch] Failed to cast value for field 'parentDomain'.
                      Value '4' of type 'class java.lang.Long' can not be casted to type 'class mobi.droidcloud.mgmt.model.Domain'.
                      Skipping.
                      === 2012-07-25 12:30:44,988 [0-36] DEBUG JPADataSource - [builtinApplication.domain_DataSource_fetch] Query string: select _Domain from Domain _Domain
                      Hibernate: 
                          select
                              domain0_.id as id5_,
                              domain0_.name as name5_,
                              domain0_.parentDomainId as parentDo3_5_ 
                          from
                              T_DOMAIN domain0_
                      === 2012-07-25 12:30:44,991 [0-36] INFO  DSResponse - [builtinApplication.domain_DataSource_fetch] DSResponse: List with 11 items
                      === 2012-07-25 12:30:44,991 [0-36] DEBUG RPCManager - Content type for RPC transaction: text/plain; charset=UTF-8
                      === 2012-07-25 12:30:44,991 [0-36] DEBUG JPADataSource - Committing current transaction.
                      === 2012-07-25 12:30:44,993 [0-36] DEBUG RPCManager - non-DMI response, dropExtraFields: true
                      === 2012-07-25 12:30:44,994 [0-36] WARN  DataSource - Couldn't get value for property 'parentDomain' for datasource 'domain_DataSource' - ignoring. Actual error: java.lang.NullPointerException
                      === 2012-07-25 12:30:44,996 [0-36] WARN  DataSource - Couldn't get value for property 'parentDomain' for datasource 'domain_DataSource' - ignoring. Actual error: java.lang.NullPointerException
                      === 2012-07-25 12:30:44,996 [0-36] WARN  DataSource - Couldn't get value for property 'parentDomain' for datasource 'domain_DataSource' - ignoring. Actual error: java.lang.NullPointerException
                      === 2012-07-25 12:30:44,997 [0-36] WARN  DataSource - Couldn't get value for property 'parentDomain' for datasource 'domain_DataSource' - ignoring. Actual error: java.lang.NullPointerException
                      === 2012-07-25 12:30:44,997 [0-36] WARN  DataSource - Couldn't get value for property 'parentDomain' for datasource 'domain_DataSource' - ignoring. Actual error: java.lang.NullPointerException
                      === 2012-07-25 12:30:45,000 [0-36] DEBUG JPADataSource - Releasing entity manager.
                      [WARN] 404 - GET /JPADS_js/sc/system/reference/skin/images/server_client_exchange.png (127.0.0.1) 1453 bytes
                         Request headers
                            Host: 127.0.0.1:8888
                            User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.7; rv:5.0.1) Gecko/20100101 Firefox/5.0.1
                            Accept: image/png,image/*;q=0.8,*/*;q=0.5
                            Accept-Language: en-us,en;q=0.5
                            Accept-Encoding: gzip, deflate
                            Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
                            Connection: keep-alive
                            Referer: http://127.0.0.1:8888/JPADS_js/sc/system/helpers/Log.html
                            Cookie: isc_cState=ready; JSESSIONID=10u699kv33svs; GLog=%7B%0D%20%20%20%20left%3A17%2C%20%0D%20%20%20%20top%3A25%2C%20%0D%20%20%20%20width%3A640%2C%20%0D%20%20%20%20height%3A480%2C%20%0D%20%20%20%20priorityDefaults%3A%7B%0D%20%20%20%20%20%20%20%20Log%3A4%0D%20%20%20%20%7D%2C%20%0D%20%20%20%20defaultPriority%3A3%2C%20%0D%20%20%20%20trackRPC%3Atrue%0D%7D
                         Response headers
                            Content-Type: text/html; charset=iso-8859-1
                            Content-Length: 1453
                      As you can see, there is a cast exception as well as an NPE for each of the parentDomainId's that are null. There are some other exceptions reported as well which might be the cause of these, just not sure. Again, one per root node. The message Adding node to tree with id property set to:1 changes in each exception to one of 1,4,5,6 & 7 which are exactly the ids that have null as a parentDomain (root nodes).
                      Code:
                      12:30:49.167 ERROR JPADS_js 12:30:45.055:XRP9:WARN:ResultTree:isc_ResultTree_0 (created by: isc_TreeGrid_0):Adding node to tree with id property set to:1. A node with this ID is already present in this Tree - that node will be replaced. Note that this warning may be disabled by setting the reportCollisions attribute to false.
                      
                      com.smartgwt.client.core.JsObject$SGWT_WARN: 12:30:45.055:XRP9:WARN:ResultTree:isc_ResultTree_0 (created by: isc_TreeGrid_0):Adding node to tree with id property set to:6. A node with this ID is already present in this Tree - that node will be replaced. Note that this warning may be disabled by setting the reportCollisions attribute to false.
                          at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
                          at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
                          at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
                          at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
                          at com.google.gwt.dev.shell.MethodAdaptor.invoke(MethodAdaptor.java:105)
                          at com.google.gwt.dev.shell.MethodDispatch.invoke(MethodDispatch.java:71)
                          at com.google.gwt.dev.shell.OophmSessionHandler.invoke(OophmSessionHandler.java:172)
                          at com.google.gwt.dev.shell.BrowserChannelServer.reactToMessages(BrowserChannelServer.java:292)
                          at com.google.gwt.dev.shell.BrowserChannelServer.processConnection(BrowserChannelServer.java:546)
                          at com.google.gwt.dev.shell.BrowserChannelServer.run(BrowserChannelServer.java:363)
                          at java.lang.Thread.run(Thread.java:680)
                      The RPC request/response from the fetch sent due to the openFolder() looks like the following:
                      Code:
                      The DSRequest:
                      
                      {
                          "dataSource":"domain_DataSource", 
                          "operationType":"fetch", 
                          "operationId":"domain_DataSource_fetch", 
                          "componentId":"isc_TreeGrid_0", 
                          "data":{
                              "parentDomain":4
                          }, 
                          "textMatchStyle":"exact", 
                          "resultTree":[ResultTree ID:isc_ResultTree_0 (created by: isc_TreeGrid_0)], 
                          "parentNode":{
                              "id":4, 
                              "name":"Global-2", 
                              "parentDomain":null, 
                              "isFolder":true, 
                              "children":[
                                  {
                                      "id":1, 
                                      "name":"Global", 
                                      "parentDomain":4, 
                                      "isFolder":true, 
                                      "children":[
                                          {
                                              "parentDomain":1, 
                                              "id":2, 
                                              "name":"new-domain", 
                                              "isFolder":true
                                          }, 
                                          {
                                              "parentDomain":1, 
                                              "id":3, 
                                              "name":"new-domain", 
                                              "isFolder":true
                                          }
                                      ]
                                  }, 
                                  {
                                      "id":4, 
                                      "name":"Global-2", 
                                      "parentDomain":4, 
                                      "isFolder":true, 
                                      "children":[
                                          {
                                              "parentDomain":4, 
                                              "id":8, 
                                              "name":"this-sub-domain", 
                                              "isFolder":true
                                          }, 
                                          {
                                              "parentDomain":4, 
                                              "id":9, 
                                              "name":"another-sub-domain", 
                                              "isFolder":true
                                          }, 
                                          {
                                              "parentDomain":4, 
                                              "id":10, 
                                              "name":"goobers", 
                                              "isFolder":true
                                          }, 
                                          {
                                              "parentDomain":4, 
                                              "id":11, 
                                              "name":"new-domain", 
                                              "isFolder":true
                                          }
                                      ]
                                  }, 
                                  {
                                      "id":5, 
                                      "name":"whoa", 
                                      "parentDomain":4, 
                                      "isFolder":true
                                  }, 
                                  {
                                      "id":6, 
                                      "name":"jeez", 
                                      "parentDomain":4, 
                                      "isFolder":true
                                  }, 
                                  {
                                      "id":7, 
                                      "name":"new-domain", 
                                      "parentDomain":4, 
                                      "isFolder":true
                                  }
                              ]
                          }, 
                          "callback":{
                              "caller":[ResultTree ID:isc_ResultTree_0 (created by: isc_TreeGrid_0)], 
                              "methodName":"loadChildrenReply"
                          }, 
                          "willHandleError":true, 
                          "showPrompt":true, 
                          "prompt":"Finding Records that match your criteria...", 
                          "oldValues":{
                              "parentDomain":4
                          }, 
                          "clientContext":{
                              "parentNode":'$$BACKREF$$:.dataSource.operationType.operationId.componentId.data.textMatchStyle.resultTree.parentNode', 
                              "relationship":{
                                  "childDS":[DataSource ID:domain_DataSource], 
                                  "parentDS":[DataSource ID:domain_DataSource], 
                                  "isFolderProperty":null, 
                                  "parentIdField":"parentDomain", 
                                  "idField":"id", 
                                  "rootValue":null
                              }, 
                              "childrenReplyCallback":null
                          }, 
                          "requestId":"domain_DataSource$6271"
                      }
                      
                      And the Response:
                      [
                          {
                              data:[
                                  {
                                      id:1, 
                                      name:"Global"
                                  }, 
                                  {
                                      parentDomain:1, 
                                      id:2, 
                                      name:"new-domain"
                                  }, 
                                  {
                                      parentDomain:1, 
                                      id:3, 
                                      name:"new-domain"
                                  }, 
                                  {
                                      id:4, 
                                      name:"Global-2"
                                  }, 
                                  {
                                      id:5, 
                                      name:"whoa"
                                  }, 
                                  {
                                      id:6, 
                                      name:"jeez"
                                  }, 
                                  {
                                      id:7, 
                                      name:"new-domain"
                                  }, 
                                  {
                                      parentDomain:4, 
                                      id:8, 
                                      name:"this-sub-domain"
                                  }, 
                                  {
                                      parentDomain:4, 
                                      id:9, 
                                      name:"another-sub-domain"
                                  }, 
                                  {
                                      parentDomain:4, 
                                      id:10, 
                                      name:"goobers"
                                  }, 
                                  {
                                      parentDomain:4, 
                                      id:11, 
                                      name:"new-domain"
                                  }
                              ], 
                              endRow:11, 
                              invalidateCache:false, 
                              isDSResponse:true, 
                              operationType:"fetch", 
                              queueStatus:0, 
                              startRow:0, 
                              status:0, 
                              totalRows:11
                          }
                      ]
                      As you can see, the response does not include parentDomain for any of the nodes where the parentDomain is null. The result is that the treeGrid is redrawn empty.

                      It would seem that using the treeGrid.setTreeRootValue to null doesn't work for all cases - due to a bug, design issue, whatever. But when I tried to use non-null values, I ran into the case where JPA refused to insert objects when the parent object doesn't exist. All efforts to use JPA to insert one have resulted in failure (adding ids, overriding getters/setters).

                      One suggestion was to insert a node 0 outside of JPA and use a rootvalue of 0 and make all of my top-level root nodes refer to it. I'd then need code in place to hide that node yet have all of the other nodes.

                      Another option I believe that was suggested, but I didn't grasp at the time, was to use a serverObject to filter the root values/nodes in the request/response. I can see how it would be possible to edit the responses and add the null parentDomain values to the response fields for those root level nodes. There would still be all of these NPEs/exceptions in the server, but the results would be "patched".

                      Or perhaps there is a code patch to the isc server that makes it more resilient when dealing with null parent nodes.
                      Attached Files
                      Last edited by bjvetter; 25 Jul 2012, 10:10. Reason: added source code

                      Comment


                        #41
                        Have you read the JavaDoc for startEditingNew() *on TreeGrid*? It explains special usage concerns for trees in particular.

                        Comment


                          #42
                          Originally posted by Isomorphic View Post
                          Have you read the JavaDoc for startEditingNew() *on TreeGrid*? It explains special usage concerns for trees in particular.
                          Nope. Looked in TreeGrid jdoc. Looked in ListGrid jdoc. Looked in TreeDataBinding jdoc. Looked in Editing jdoc. Didn't see it in any of those.

                          In any case, it is the least of my worries. I mostly interested in how I can get past the cast errors and the NPE in the server returning the datasource fetch of my domain objects to the client.

                          After experimenting with the serverObject, it would appear that the NPE's are coming from the DataSource code that is pulling properties out of my Domain objects well after even an inserted ServerObject can convene.

                          The cast exception only appears when I open a node (and its subsequent fetch of the tree) and appear to happen just before the fetch is delivered to JPA/hibernate. The fetch appears work (I see the select) and the datasource returns a list of 12 Domain objects. I inserted a class using serverObject and I see all of the objects. So not sure what the issue is with the cast warning, but it didn't seem to cause the query any grief.

                          The NPEs occur at the end of every fetch of the tree (whether the initial or as a result of opening a folder). It would appear that it is occurring when the DMI code is preparing the response using the list of Domain objects it has received.

                          I'm out of ideas on how to proceed. I don't have the source code to those class libraries to narrow it down any farther - my instrumented serverObject class could only go so far.

                          I've attached a log file with more of the details.
                          Attached Files

                          Comment


                            #43
                            Here's the stack trace for one of the NPEs
                            Code:
                            RPCManager._requestQueueIncludesPriorUpdate(DSRequest) line: 2538	
                            RPCManager.requestQueueIncludesUpdates() line: 2533	
                            JPADataSource(BasicDataSource).autoJoinAtGlobalLevel(DSRequest) line: 2261	
                            JPADataSource(BasicDataSource).shouldAutoJoinTransaction(DSRequest) line: 2176	
                            JPADataSource.execute(DSRequest) line: 381	
                            AppBase.executeDefaultDSOperation() line: 725	
                            AppBase.executeAppOperation() line: 658	
                            AppBase.execute(DSRequest, RequestContext) line: 491	
                            DSRequest.execute() line: 1954	
                            TreeDMI.fixRootNodes(DSRequest, HttpServletRequest) line: 16	
                            NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
                            NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
                            DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
                            Method.invoke(Object, Object...) line: 597	
                            Reflection.adaptArgsAndInvoke(Object, Method, ReflectionArgument[], ReflectionArgument[], DataSource, DSRequest) line: 950	
                            DataSourceDMI.execute() line: 386	
                            DataSourceDMI.execute(DSRequest, RPCManager, RequestContext) line: 64	
                            DSRequest.execute() line: 1951	
                            IDACall.handleDSRequest(DSRequest, RPCManager, RequestContext) line: 199	
                            IDACall.processRPCTransaction(RPCManager, RequestContext) line: 156	
                            IDACall.processRequest(HttpServletRequest, HttpServletResponse) line: 121	
                            IDACall.doPost(HttpServletRequest, HttpServletResponse) line: 73	
                            IDACall(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 637	
                            IDACall(BaseServlet).service(HttpServletRequest, HttpServletResponse) line: 152	
                            IDACall(HttpServlet).service(ServletRequest, ServletResponse) line: 717	
                            ServletHolder.handle(ServletRequest, ServletResponse) line: 487	
                            ServletHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 362	
                            SecurityHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 216	
                            SessionHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 181	
                            JettyLauncher$WebAppContextWithReload(ContextHandler).handle(String, HttpServletRequest, HttpServletResponse, int) line: 729
                            Here is the cast exception stack trace:
                            Code:
                            DataTools.castValue(Object, Class) line: 4175	
                            JPADataSource.executeFetch(DSRequest) line: 702	
                            JPADataSource(DataSource).execute(DSRequest) line: 1289	
                            JPADataSource.execute(DSRequest) line: 440	
                            AppBase.executeDefaultDSOperation() line: 725	
                            AppBase.executeAppOperation() line: 658	
                            AppBase.execute(DSRequest, RequestContext) line: 491	
                            DSRequest.execute() line: 1954	
                            TreeDMI.fixRootNodes(DSRequest, HttpServletRequest) line: 16	
                            NativeMethodAccessorImpl.invoke0(Method, Object, Object[]) line: not available [native method]	
                            NativeMethodAccessorImpl.invoke(Object, Object[]) line: 39	
                            DelegatingMethodAccessorImpl.invoke(Object, Object[]) line: 25	
                            Method.invoke(Object, Object...) line: 597	
                            Reflection.adaptArgsAndInvoke(Object, Method, ReflectionArgument[], ReflectionArgument[], DataSource, DSRequest) line: 950	
                            DataSourceDMI.execute() line: 386	
                            DataSourceDMI.execute(DSRequest, RPCManager, RequestContext) line: 64	
                            DSRequest.execute() line: 1951	
                            IDACall.handleDSRequest(DSRequest, RPCManager, RequestContext) line: 199	
                            IDACall.processRPCTransaction(RPCManager, RequestContext) line: 156	
                            IDACall.processRequest(HttpServletRequest, HttpServletResponse) line: 121	
                            IDACall.doPost(HttpServletRequest, HttpServletResponse) line: 73	
                            IDACall(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 637	
                            IDACall(BaseServlet).service(HttpServletRequest, HttpServletResponse) line: 152	
                            IDACall(HttpServlet).service(ServletRequest, ServletResponse) line: 717	
                            ServletHolder.handle(ServletRequest, ServletResponse) line: 487	
                            ServletHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 362	
                            SecurityHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 216	
                            SessionHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 181	
                            JettyLauncher$WebAppContextWithReload(ContextHandler).handle(String, HttpServletRequest, HttpServletResponse, int) line: 729	
                            JettyLauncher$WebAppContextWithReload(WebAppContext).handle(String, HttpServletRequest, HttpServletResponse, int) line: 405	
                            RequestLogHandler(HandlerWrapper).handle(String, HttpServletRequest, HttpServletResponse, int) line: 152	
                            RequestLogHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 49	
                            Server(HandlerWrapper).handle(String, HttpServletRequest, HttpServletResponse, int) line: 152	
                            Server.handle(HttpConnection) line: 324	
                            HttpConnection.handleRequest() line: 505
                            Here is another NPE that occurs when opening a folder
                            Code:
                            JPADataSource.getRelationFieldValue(RelationFieldInfo, Object, List, ValidationContext) line: 3357	
                            JPADataSource(DataSource).getProperties(Object, Collection, boolean, boolean, ValidationContext, List, Collection) line: 1731	
                            DataSourceBeanFilter.filter(Object, ValidationContext) line: 204	
                            JSTranslater.convert(Object, Writer, IBeanFilter) line: 659	
                            JSTranslater.convertIterator(Iterator, Writer, IBeanFilter, boolean) line: 1163	
                            JSTranslater.convertCollection(Collection, Writer, IBeanFilter) line: 1114	
                            JSTranslater.convert(Object, Writer, IBeanFilter) line: 621	
                            JSTranslater.convert(Object, Writer) line: 557	
                            JSTranslater.convert(Object) line: 548	
                            JSTranslater.convertMap(Map, Writer, IBeanFilter) line: 1001	
                            JSTranslater.convert(Object, Writer, IBeanFilter) line: 619	
                            JSTranslater.convertIterator(Iterator, Writer, IBeanFilter, boolean) line: 1163	
                            JSTranslater.convertCollection(Collection, Writer, IBeanFilter) line: 1114	
                            JSTranslater.convert(Object, Writer, IBeanFilter) line: 621	
                            JSTranslater.convert(Object, Writer) line: 557	
                            JSTranslater.toJS(Object, Writer) line: 519	
                            RPCManager.completeResponse() line: 1278	
                            RPCManager.send(DSRequest, DSResponse) line: 592	
                            IDACall.processRPCTransaction(RPCManager, RequestContext) line: 156	
                            IDACall.processRequest(HttpServletRequest, HttpServletResponse) line: 121	
                            IDACall.doPost(HttpServletRequest, HttpServletResponse) line: 73	
                            IDACall(HttpServlet).service(HttpServletRequest, HttpServletResponse) line: 637	
                            IDACall(BaseServlet).service(HttpServletRequest, HttpServletResponse) line: 152	
                            IDACall(HttpServlet).service(ServletRequest, ServletResponse) line: 717	
                            ServletHolder.handle(ServletRequest, ServletResponse) line: 487	
                            ServletHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 362	
                            SecurityHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 216	
                            SessionHandler.handle(String, HttpServletRequest, HttpServletResponse, int) line: 181	
                            JettyLauncher$WebAppContextWithReload(ContextHandler).handle(String, HttpServletRequest, HttpServletResponse, int) line: 729	
                            JettyLauncher$WebAppContextWithReload(WebAppContext).handle(String, HttpServletRequest, HttpServletResponse, int) line: 405	
                            RequestLogHandler(HandlerWrapper).handle(String, HttpServletRequest, HttpServletResponse, int) line: 152

                            Comment


                              #44
                              On TreeGrid.startEditingNew() - we've just discovered that the special docs for this API on TreeGrid are appearing for SmartClient but not SmartGWT. Here are those docs in raw form for now:

                              // This inherited +link{listGrid.startEditingNew,ListGrid API} is not supported by the TreeGrid
                              // since adding a new tree node arbitrarily at the end of the tree is usually not useful.
                              // Instead, to add a new tree node and begin editing it, use either of these strategies:
                              // <ol>
                              // <li> add a new node to the client-side Tree model via +link{Tree.add()}, then use
                              // +link{startEditing()} to begin editing this node. Note that if using a DataSource, when the
                              // node is saved, an "update" operation will be used since adding a node directly to the
                              // client-side +link{ResultTree} effectively means a new node has been added server side.
                              // <li> use +link{DataSource.addData()} to immediately save a new node. Automatic cache sync
                              // by the +link{ResultTree} will cause the node to be integrated into the tree. When the
                              // callback to addData() fires, locate the new node by matching primary key and call
                              // +link{startEditing()} to begin editing it.
                              // </ol>
                              //
                              // @param [newValues] (object) Optional initial set of properties for the new record
                              // @param [suppressFocus] (boolean) Whether to suppress the default behavior of moving focus
                              // to the newly shown editor.

                              Comment

                              Working...
                              X