I'm trying to use a JPA datasource to populate a TreeGrid. I'm obviously not getting something even after reading the various JavaDocs for TreeGrid, Tree, DataSource, and TreeDataBinding.
So my first questions was how best to add nodes to the tree using my JPA DataSource. I presumed that I should use the addData() method on the data source to do this. If not, then I need to go back and start over.
My next problem came when trying to deal with my JPA and its ManyToOne relationship between the node and its parent node. All of my attempts to use the actual node objects (i.e. datasource records) failed and searching through the forums led me to believe that I need to use a parentId instead. So I reworked things to do that, including adding a hack to my JPA bean to include a parentId and not just a reference to a parent object along with some annotations so that it would share the same database Id column between the parent field/object and the parentId field.
My next problem then came with how to create the initial node if there is no parentId. I chose a variety of values to no avail. I've used null and avoided some errors but not others (like null pointer exceptions in the server). I've used 0 with a different set of exceptions (null pointer and number format exceptions).
So I know someone must have succeeded here, but I'm just failing. No matter what I seem to do, I end up with a record in the database with a correct id, a correct name, and a null parentId.
BTW, this is all on the latest GWT 2.3 and SmartGWT EE eval.
Here's my JPA (removed the setters/getters):
And here's the data source xml:
And now most of the Java code:
So my first questions was how best to add nodes to the tree using my JPA DataSource. I presumed that I should use the addData() method on the data source to do this. If not, then I need to go back and start over.
My next problem came when trying to deal with my JPA and its ManyToOne relationship between the node and its parent node. All of my attempts to use the actual node objects (i.e. datasource records) failed and searching through the forums led me to believe that I need to use a parentId instead. So I reworked things to do that, including adding a hack to my JPA bean to include a parentId and not just a reference to a parent object along with some annotations so that it would share the same database Id column between the parent field/object and the parentId field.
My next problem then came with how to create the initial node if there is no parentId. I chose a variety of values to no avail. I've used null and avoided some errors but not others (like null pointer exceptions in the server). I've used 0 with a different set of exceptions (null pointer and number format exceptions).
So I know someone must have succeeded here, but I'm just failing. No matter what I seem to do, I end up with a record in the database with a correct id, a correct name, and a null parentId.
BTW, this is all on the latest GWT 2.3 and SmartGWT EE eval.
Here's my JPA (removed the setters/getters):
Code:
@Entity @Table(name = "T_DOMAIN") public class Domain { @Id @GeneratedValue(strategy = IDENTITY) @Column(nullable = false) private long id; @Basic private String name; @OneToMany(mappedBy = "domain") private Collection<DomainManaged> domainManaged; @ManyToOne(fetch = LAZY, optional = true) @JoinColumn(name = "parentDomainId", referencedColumnName = "parentDomainId", nullable=false, insertable=false, updatable=false) private Domain parentDomain; @OneToMany(mappedBy = "parentDomain") private Collection<Domain> subDomains; private Long parentDomainId;
Code:
<DataSource ID="domain_DataSource" serverConstructor="com.isomorphic.jpa.JPADataSource" beanClassName="mobi.droidcloud.mgmt.model.Domain" dropExtraFields="true" > <fields> <field name="id" type="sequence" hidden="true" primaryKey="true" /> <field name="name" type="text" title="Name" required="true" /> <field name="parentDomainId" type="int" title="Parent Domain Id" canEdit="false" foreignKey="id" rootValue="0" /> </fields> </DataSource>
Code:
public void onModuleLoad() { KeyIdentifier debugKey = new KeyIdentifier(); debugKey.setCtrlKey(true); debugKey.setKeyName("D"); Page.registerKey(debugKey, new KeyCallback() { public void execute(String keyName) { SC.showConsole(); } }); VStack vStack = new VStack(); vStack.setTop(50); vStack.setWidth("100%"); vStack.setMembersMargin(20); final TreeGrid treeGrid = new TreeGrid(); treeGrid.setWidth(500); treeGrid.setHeight(250); final DataSource domainDS = DataSource.get("domain_DataSource"); treeGrid.setTreeRootValue(0); domainDS.fetchData(new Criteria("name", "Global"), new DSCallback() { @Override public void execute(DSResponse response, Object rawData, DSRequest request) { if (response.getTotalRows() == 0) { Record r = new Record(); r.setAttribute("name", "Global"); r.setAttribute("parentDomainId", new Long(0)); // (Long)null); domainDS.addData(r, new DSCallback() { @Override public void execute(DSResponse resp, Object data, DSRequest req) { if (resp.getTotalRows() != 1) { System.out.println("Unexpected response after adding the global node"); } } }); } } }); TreeGridField nameField = new TreeGridField("name"); nameField.setTreeField(true); treeGrid.setFields(nameField); treeGrid.setDataSource(domainDS); treeGrid.setAutoFetchData(true); treeGrid.setCanEdit(true); treeGrid.setCanAcceptDroppedRecords(true); IButton newDomainButton = new IButton("New Domain"); newDomainButton.addClickHandler(new ClickHandler() { public void onClick (ClickEvent event) { final ListGridRecord r = treeGrid.getSelectedRecord(); if (r != null) { Record newDomain = new Record(); newDomain.setAttribute("name", "new-domain"); newDomain.setAttribute("parentDomainId", r.getAttributeAsInt("id")); // newDomain.setAttribute("parentDomainId", r); domainDS.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); } } }); } else { // new top-level domain Record record = new Record(); record.setAttribute("name", "new-domain"); System.out.println("Assigning a global with a parentId of 1 (cheating)"); record.setAttribute("parentDomainId", new Long(0)); //(Long)null); domainDS.addData(record, new DSCallback() { @Override public void execute(DSResponse response, Object rawData, DSRequest request) { } }); } } }); IButton rmDomainButton = new IButton("Delete Domain"); rmDomainButton.addClickHandler(new ClickHandler() { public void onClick (ClickEvent event) { ListGridRecord r = treeGrid.getSelectedRecord(); if (r != null) { domainDS.removeData(r); } } }); IButton adminButton = new IButton("Admin Console"); adminButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { com.smartgwtee.tools.client.SCEE.openDataSourceConsole(); } }); IButton dsGeneratorButton = new IButton("DS Generator"); dsGeneratorButton.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { com.smartgwtee.tools.client.SCEE.openDataSourceGenerator(); } }); vStack.addMember(treeGrid); vStack.addMember(newDomainButton); vStack.addMember(rmDomainButton); vStack.addMember(adminButton); vStack.addMember(dsGeneratorButton); vStack.draw(); }
Comment