Announcement

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

    DataSource includeFrom DSRequest Instead of Join

    I have a couple database tables that have a many-to-many relationship. I've included the foreign key with multiple="true" in my ds.xml and the fetch works just fine. However, when I add another field with includeFrom from the related data source, I get duplicate rows. I'm using the hibernate data source and I've looked at the query and it's doing a left outer join to get the related records.

    I've looked at the documentation: https://www.smartclient.com/smartgwt...ml#includeFrom

    Is there a way to specify that this included data should be from another DSRequest instead of a join?

    #2
    It's difficult to comment without seeing the DataSources and the desired output, but, the Server Summaries feature allows you to do aggregation across multiple related records.

    There's no way to have the includeFrom feature do a query for every row - that would be extremely slow for all but tiny datasets - but you can simply add DMI logic that does that, or does something like a single query to get relevant related records after the first query completes, and then alters the default DSResponse with data from the second query or queries.

    Comment


      #3
      Ok, so doing an includeFrom a field where multiple="true" is the issue. But this is doing a subsequent query for each related record.

      Here's my schema, 3 tables: opening, door, and opening_door. An opening can have multiple openings. My Opening.ds.xml:

      Code:
      <DataSource ID="Opening">
          <fields>
              <field name="openingId" type="integer" primaryKey="true" hidden="true"/>
              <field name="openingDoors" type="OpeningDoor" multiple="true" foreignKey="OpeningDoor.openingDoorId"/>
          </fields>
      </DataSource>
      With the above, I get the initial query to opening (returns 100 rows), then 1 query to opening_door per returned opening record (100 more queries). Can these be combined into a single query instead of 1 per row? Or I'm assuming I would have to add DMI logic?

      Comment


        #4
        You don't have an includeFrom here, you just have foreignKey + multiple=true. Please revisit the JPA/Hibernate Relations overview - the software is doing exactly what you've configured it to do, which is to return the main records and nested records.

        We definitely wouldn't recommend doing this, however, since you still haven't explained what you actually want instead of this, we're not in a position to help yet.

        Comment


          #5
          Ok, let me explain what I'm doing. We have a ListGrid that is displaying data from our opening table. Some of the columns that we would like to display come from another table where there are multiple results (many-to-many relationship). I'm using cell formatters to aggregate the data and display it how we want it. My issue is how to properly query the data with this relationship in mind. I would be fine if there was a field that was just an array of the related records, then I can handle the display client side.

          When I just add the field directly to the ds.xml it creates a left outer join, which then returns duplicate rows from our opening table, so that won't work. To make this work I'm trying to add a single fetch after the main fetch via DMI. I have the 2 fetches working, but I'm not sure how to join the data together so it's returned to the client. I'd like the related data as an array field in the original DSResponse. Here's my method:

          Code:
              public DSResponse fetch(final DSRequest dsRequest) throws Exception {
                  // Execute standard fetch
                  final DSResponse dsResponse = dsRequest.execute();
          
                  // Get IDs of records to search for in sub query
                  final long[] ids = ((List<Opening>) dsResponse.getDataList()).stream().mapToLong(Opening::getOpeningId).toArray();
          
                  // Execute second fetch
                  final DSRequest openingDoorRequest = new DSRequest("TitanOpeningDoor", "fetch", dsRequest.getRPCManager());
                  openingDoorRequest.setFieldValue("opening", ids);
                  final DSResponse openingDoorResponse = openingDoorRequest.execute();
          
                  // Add the data to the original response
                  dsResponse.getRecords().forEach(o -> {
                      // Get the ID of the record
                      final long openingId = (long) ((Map) o).get("openingId");
          
                      // Search for an array of related recods
                      final Object[] openingDoors = openingDoorResponse.getRecords().stream().filter(o1 -> ((long) ((Map) o1).get("opening")) == openingId).toArray();
          
                      // Add the records to the response
                      // TODO this doesn't work
                      ((Map) o).put("blah", openingDoors);
                  });
                  return dsResponse;
              }
          And the data source:

          Code:
          <DataSource ID="OpeningTest"
                      serverType="hibernate"
                      beanClassName="com.assaabloy.protech.domain.Opening"
                      configBean="protechSessionFactory"
                      autoDeriveSchema="false"
                      dropExtraFields="true"
                      xmlns:fmt="WEB-INF/">
              <fields>
                  <!-- Keys -->
                  <field name="openingId" type="integer" primaryKey="true" hidden="true"/>
                  <field name="project" type="integer" foreignKey="Project.projectId" hidden="true"/>
                  <field name="library" type="integer" foreignKey="Library.libraryId" hidden="true"/>
          
                  <!-- Hidden Data Fields -->
                  <field name="bank" type="boolean" hidden="true"/>
                  <field name="hardwareSetAssignedAtOpening" type="boolean" hidden="true"/>
                  <field name="openingGroup" type="integer" foreignKey="OpeningGroup.openingGroupId" hidden="true"/>
                  <field name="sortAlpha" type="text" length="25" hidden="true"/>
                  <field name="sortNumeric" type="integer" hidden="true"/>
                  <field name="sortOrder" type="integer" hidden="true"/>
                  <field name="deleted" type="boolean" hidden="true"/>
                  <field name="allItemsOrdered" type="boolean" hidden="true"/>
                  <field name="updatedInChange" type="boolean" hidden="true"/>
                  <field name="installed" type="boolean" hidden="true"/>
                  <field name="codeByHingeStrikeLocation" type="integer" foreignKey="Code.codeId" hidden="true"/>
                  <field name="codeByHardwareStatus" type="integer" foreignKey="Code.codeId" hidden="true"/>
                  <field name="codeByDoorsStatus" type="integer" foreignKey="Code.codeId" hidden="true"/>
                  <field name="codeByFrameStatus" type="integer" foreignKey="Code.codeId" hidden="true"/>
                  <!--        <field name="openingDoorCosts" type="localeCurrency" includeFrom="TitanOpeningDoor.cost" multiple="true"/>-->
                  <!--        <field name="openingDoorListCosts" type="localeCurrency" includeFrom="TitanOpeningDoor.listCost" multiple="true"/>-->
                  <!--        <field name="openingDoorMarkups" type="float" decimalPrecisoin="12" includeFrom="TitanOpeningDoor.markup" multiple="true"/>-->
                  <!--        <field name="openingDoorSellPrices" type="localeCurrency" includeFrom="TitanOpeningDoor.sellPrice" multiple="true"/>-->
          
                  <!-- Hidden Display Fields -->
                  <field name="hand" type="text" includeFrom="Code.code" includeVia="codeByHand" hidden="true"/>
                  <field name="style" type="text" includeFrom="Code.code" includeVia="codeByUom" hidden="true"/>
                  <field name="frameType" type="text" includeFrom="Frame.name" hidden="true"/>
                  <field name="label" type="text" includeFrom="Code.code" includeVia="codeByLabelId" hidden="true"/>
                  <!--        <field name="doorType" type="text" includeFrom="TitanOpeningDoor.doorName" hidden="true" multiple="true"/>-->
                  <field name="hardwareSetName" type="text" includeFrom="TitanHardwareSet.name" hidden="true"/>
          
                  <!-- Display Fields -->
                  <field name="needsAttention" type="boolean" title="Flag"/>
                  <field name="mark" type="text" required="true" title="Opening ID"/>
                  <field name="qty" type="integer"/>
                  <field name="exterior" type="boolean"/>
                  <field name="group" type="text" includeFrom="OpeningGroup.group"/>
                  <field name="codeByHand" type="integer" foreignKey="Code.codeId" displayField="hand" title="Hand"/>
                  <field name="codeByUom" type="integer" foreignKey="Code.codeId" displayField="style" title="Style"/>
                  <field name="width" type="integer"/>
                  <field name="height" type="integer"/>
                  <field name="frameCost" type="localeCurrency" canEdit="false"/>
                  <field name="frameListCost" type="localeCurrency" canEdit="false"/>
                  <field name="frameMarkup" type="float"/>
                  <field name="frameSellPrice" type="localeCurrency" canEdit="false"/>
                  <field name="frame" type="integer" foreignKey="Frame.frameId" displayField="frameType" title="Frame Type"/>
                  <field name="frameMaterial" type="text" includeFrom="Frame.material"/>
                  <field name="hardwareSet" type="integer" foreignKey="TitanHardwareSet.hardwareSetId" displayField="hardwareSetName"/>
                  <field name="hardwareSetCost" type="localeCurrency" includeFrom="TitanHardwareSet.cost" canEdit="false"/>
                  <field name="hardwareSetListCost" type="localeCurrency" includeFrom="TitanHardwareSet.listCost" canEdit="false"/>
                  <field name="hardwareSetSellPrice" type="localeCurrency" includeFrom="TitanHardwareSet.sellPrice" canEdit="false"/>
                  <field name="blah"/>
                  <!--        <field name="openingDoors" type="TitanOpeningDoor" multiple="true" foreignKey="TitanOpeningDoor.openingDoorId" title="Door Type(s)"/>-->
                  <!--        <field name="doorMaterial" type="text" multiple="true" includeFrom="TitanOpeningDoor.doorMaterial" includeSummaryFunction="concat"-->
                  <!--               title="Door Material"/>-->
                  <field name="location1" type="text"/>
                  <field name="fromTo" type="text" title="To/From"/>
                  <field name="location2" type="text"/>
                  <field name="architectsMark" type="text" title="Arch Mark"/>
                  <field name="codeByLabelId" type="integer" foreignKey="Code.codeId" displayField="label" title="Label"/>
                  <field name="degrees" type="integer"/>
                  <field name="wallType" type="text"/>
                  <field name="wallThickness" type="integer"/>
                  <field name="description" type="text"/>
                  <field name="notes" type="text"/>
              </fields>
          
              <operationBindings>
                  <operationBinding operationType="fetch">
                      <serverObject lookupStyle="spring" bean="openingService" className="com.assaabloy.protech.server.services.impl.OpeningServiceImpl"/>
                      <criteria fieldName="deleted" value="false"/>
                  </operationBinding>
                  <operationBinding operationType="update" operationId="applyToAll" allowMultiUpdate="true"/>
              </operationBindings>
          </DataSource>
          How do I join the results of the 2 fetches and return them both to the client?

          Comment


            #6
            You mention using cell formatters to display aggregated data - did you look at the Server Summaries feature we linked earlier? Because it sounds like what you want is very close to the CONCAT summaries operator.

            As far as your current approach of returning nested records, your approach is OK, so can you elaborate on "doesn't work"? Are you able to see the data arriving at the client (via the RPC tab)? If so then are you having trouble accessing it from a formatter?

            Or if you are not receiving the data client-side, are you sure that you save your DataSource with the new "blah" field and restarted the server before retesting? Because you have dropExtraFields=true, so without that field declaration, the data would be dropped server side.

            Finally, although it wouldn't create a problem for returning data, right now your field is declared without a type at all, and this could affect serialization and display further down the line.

            Comment


              #7
              I've looked at Server Summaries, but as soon as I add the foreign key entry, I get subsequent queries for each returned row:

              Code:
              <field name="openingDoors" type="TitanOpeningDoor" multiple="true" foreignKey="TitanOpeningDoor.openingDoorId" title="Door Type(s)"/>
              When I say it doesn't work, I'm not getting anything returned to the client. The "blah" field is null. I've stepped through the debugger, the correct data is being added to the map, but is null when reaching the client. Here's both the data sources and the function as I have it now:

              Code:
              <DataSource ID="OpeningTest"
                          serverType="hibernate"
                          beanClassName="com.assaabloy.protech.domain.Opening"
                          configBean="protechSessionFactory"
                          autoDeriveSchema="false"
                          dropExtraFields="true"
                          xmlns:fmt="WEB-INF/">
                  <fields>
                      <!-- Keys -->
                      <field name="openingId" type="integer" primaryKey="true" hidden="true"/>
                      <field name="project" type="integer" foreignKey="Project.projectId" hidden="true"/>
                      <field name="library" type="integer" foreignKey="Library.libraryId" hidden="true"/>
              
                      <!-- Hidden Data Fields -->
                      <field name="bank" type="boolean" hidden="true"/>
                      <field name="hardwareSetAssignedAtOpening" type="boolean" hidden="true"/>
                      <field name="openingGroup" type="integer" foreignKey="OpeningGroup.openingGroupId" hidden="true"/>
                      <field name="sortAlpha" type="text" length="25" hidden="true"/>
                      <field name="sortNumeric" type="integer" hidden="true"/>
                      <field name="sortOrder" type="integer" hidden="true"/>
                      <field name="deleted" type="boolean" hidden="true"/>
                      <field name="allItemsOrdered" type="boolean" hidden="true"/>
                      <field name="updatedInChange" type="boolean" hidden="true"/>
                      <field name="installed" type="boolean" hidden="true"/>
                      <field name="codeByHingeStrikeLocation" type="integer" foreignKey="Code.codeId" hidden="true"/>
                      <field name="codeByHardwareStatus" type="integer" foreignKey="Code.codeId" hidden="true"/>
                      <field name="codeByDoorsStatus" type="integer" foreignKey="Code.codeId" hidden="true"/>
                      <field name="codeByFrameStatus" type="integer" foreignKey="Code.codeId" hidden="true"/>
                      <!--        <field name="openingDoorCosts" type="localeCurrency" includeFrom="TitanOpeningDoor.cost" multiple="true"/>-->
                      <!--        <field name="openingDoorListCosts" type="localeCurrency" includeFrom="TitanOpeningDoor.listCost" multiple="true"/>-->
                      <!--        <field name="openingDoorMarkups" type="float" decimalPrecisoin="12" includeFrom="TitanOpeningDoor.markup" multiple="true"/>-->
                      <!--        <field name="openingDoorSellPrices" type="localeCurrency" includeFrom="TitanOpeningDoor.sellPrice" multiple="true"/>-->
              
                      <!-- Hidden Display Fields -->
                      <field name="hand" type="text" includeFrom="Code.code" includeVia="codeByHand" hidden="true"/>
                      <field name="style" type="text" includeFrom="Code.code" includeVia="codeByUom" hidden="true"/>
                      <field name="frameType" type="text" includeFrom="Frame.name" hidden="true"/>
                      <field name="label" type="text" includeFrom="Code.code" includeVia="codeByLabelId" hidden="true"/>
                      <!--        <field name="doorType" type="text" includeFrom="TitanOpeningDoor.doorName" hidden="true" multiple="true"/>-->
                      <field name="hardwareSetName" type="text" includeFrom="TitanHardwareSet.name" hidden="true"/>
              
                      <!-- Display Fields -->
                      <field name="needsAttention" type="boolean" title="Flag"/>
                      <field name="mark" type="text" required="true" title="Opening ID"/>
                      <field name="qty" type="integer"/>
                      <field name="exterior" type="boolean"/>
                      <field name="group" type="text" includeFrom="OpeningGroup.group"/>
                      <field name="codeByHand" type="integer" foreignKey="Code.codeId" displayField="hand" title="Hand"/>
                      <field name="codeByUom" type="integer" foreignKey="Code.codeId" displayField="style" title="Style"/>
                      <field name="width" type="integer"/>
                      <field name="height" type="integer"/>
                      <field name="frameCost" type="localeCurrency" canEdit="false"/>
                      <field name="frameListCost" type="localeCurrency" canEdit="false"/>
                      <field name="frameMarkup" type="float"/>
                      <field name="frameSellPrice" type="localeCurrency" canEdit="false"/>
                      <field name="frame" type="integer" foreignKey="Frame.frameId" displayField="frameType" title="Frame Type"/>
                      <field name="frameMaterial" type="text" includeFrom="Frame.material"/>
                      <field name="hardwareSet" type="integer" foreignKey="TitanHardwareSet.hardwareSetId" displayField="hardwareSetName"/>
                      <field name="hardwareSetCost" type="localeCurrency" includeFrom="TitanHardwareSet.cost" canEdit="false"/>
                      <field name="hardwareSetListCost" type="localeCurrency" includeFrom="TitanHardwareSet.listCost" canEdit="false"/>
                      <field name="hardwareSetSellPrice" type="localeCurrency" includeFrom="TitanHardwareSet.sellPrice" canEdit="false"/>
                      <field name="blah" type="TitanOpeningDoor" multiple="true"/>
                      <!--        <field name="openingDoors" type="integer" multiple="true" foreignKey="TitanOpeningDoor.openingDoorId" title="Door Type(s)"/>-->
                      <!--        <field name="doorMaterial" type="text" multiple="true" includeFrom="TitanOpeningDoor.doorMaterial" includeSummaryFunction="concat"-->
                      <!--               title="Door Material"/>-->
                      <field name="location1" type="text"/>
                      <field name="fromTo" type="text" title="To/From"/>
                      <field name="location2" type="text"/>
                      <field name="architectsMark" type="text" title="Arch Mark"/>
                      <field name="codeByLabelId" type="integer" foreignKey="Code.codeId" displayField="label" title="Label"/>
                      <field name="degrees" type="integer"/>
                      <field name="wallType" type="text"/>
                      <field name="wallThickness" type="integer"/>
                      <field name="description" type="text"/>
                      <field name="notes" type="text"/>
                  </fields>
              
                  <operationBindings>
                      <operationBinding operationType="fetch">
                          <!--                          outputs="openingId,hand,style,frameType,label,hardwareSetName,needsAttention,mark,qty,exterior,group,codeByHand,codeByUom,width,height,frameCost,frameListCost,frameMarkup,frameSellPrice,frame,frameMaterial,hardwareSet,hardwareSetCost,hardwareSetListCost,hardwareSetSellPrice,blah,location1,fromTo,location2,architectsMark,codeByLabelId,degrees,wallType,wallThickness,description,notes">-->
                          <serverObject lookupStyle="spring" bean="openingService" className="com.assaabloy.protech.server.services.impl.OpeningServiceImpl"/>
                          <criteria fieldName="deleted" value="false"/>
                      </operationBinding>
                      <operationBinding operationType="update" operationId="applyToAll" allowMultiUpdate="true"/>
                  </operationBindings>
              </DataSource>
              Code:
              <DataSource ID="TitanOpeningDoor"
                          serverType="hibernate"
                          beanClassName="com.assaabloy.protech.domain.OpeningDoor"
                          configBean="protechSessionFactory"
                          autoDeriveSchema="false"
                          dropExtraFields="true"
                          xmlns:fmt="WEB-INF/">
                  <fields>
                      <field name="openingDoorId" hidden="true" type="text" primaryKey="true"/>
                      <field name="opening" type="integer" foreignKey="OpeningTest.openingId"/>
                      <field name="openingId" type="integer" includeFrom="OpeningTest.openingId"/>
                      <field name="door" type="integer" title="Door Type" foreignKey="TitanDoor.doorId" displayField="doorName"/>
                      <field name="doorName" type="text" length="100" includeFrom="TitanDoor.name"/>
                      <field name="doorMaterial" type="text" includeFrom="TitanDoor.material"/>
                      <field name="doorVendor" type="text" length="100" title="Vendor" includeFrom="TitanDoor.vendorName"/>
                      <field name="hardwareSet" canEdit="false" foreignKey="TitanHardwareSet.hardwareSetId" displayField="hardwareSetName"/>
                      <field name="hardwareSetName" type="text" length="100" hidden="true" includeFrom="TitanHardwareSet.name"/>
                      <field name="width" type="integer" align="left"/>
                      <field name="height" type="integer" align="left"/>
                      <field name="doorThickness" type="integer" align="left"/>
                      <field name="leaf" type="integer" foreignKey="Code.codeId" displayField="leafCode"/>
                      <field name="leafCode" type="text" length="100" hidden="true" includeFrom="Code.code" includeVia="leaf"/>
                      <field name="hand" type="integer" foreignKey="Code.codeId" displayField="handCode"/>
                      <field name="handCode" type="text" length="100" hidden="true" includeFrom="Code.code" includeVia="hand"/>
                      <field name="degrees" type="integer" align="left"/>
                      <field name="listCost" type="localeCurrency"/>
                      <field name="cost" type="localeCurrency"/>
                      <field name="markup" type="float" decimalPrecision="12"/>
                      <field name="sellPrice" type="localeCurrency" canEdit="false"/>
                      <field name="numHinges" type="integer"/>
                      <field name="undercut" type="integer" align="left"/>
                  </fields>
              
                  <operationBinding>
                      <operationBinding operationType="fetch"
                                        outputs="openingDoorId,openingId,door,doorName,doorMaterial,doorVendor,hardwareSet,hardwareSetName,width,height,doorThickness,leaf,leafCode,hand,handCode,degrees,listCost,cost,markup,sellPrice,numHines,undercut"/>
                  </operationBinding>
              </DataSource>
              Code:
                  public DSResponse fetch(final DSRequest dsRequest) throws Exception {
                      // Execute standard fetch
                      final DSResponse dsResponse = dsRequest.execute();
              
                      // Get IDs of records to search for in sub query
                      // final long[] ids = ((List<HashMap>) dsResponse.getDataList()).stream().mapToLong(o -> (long) o.get("openingId")).toArray();
                      final long[] ids = ((List<Opening>) dsResponse.getDataList()).stream().mapToLong(Opening::getOpeningId).toArray();
              
                      // Execute second fetch
                      final DSRequest openingDoorRequest = new DSRequest("TitanOpeningDoor", "fetch", dsRequest.getRPCManager());
                      openingDoorRequest.setFieldValue("openingId", ids);
                      final DSResponse openingDoorResponse = openingDoorRequest.execute();
              
                      // Add the data to the original response
                      // ((List<Opening>) dsResponse.getDataList()).forEach(o -> {
                      ((List<Map>) dsResponse.getRecords()).forEach(o -> {
                          // Search for an array of related records
                          final Set<OpeningDoor> openingDoors = ((List<OpeningDoor>) openingDoorResponse.getDataList()).stream()
                                  .filter(openingDoor -> openingDoor.getOpening().getOpeningId().equals(o.get("openingId"))).collect(Collectors.toSet());
              
                          // Add the results the return data, but nothing is getting returned.
                          o.put("blah", openingDoors);
                      });
                      return dsResponse;
                  }
              I added a type to the "blah" field and I've restarted the server more times than I can count. I know it's being loaded because I can see the "blah" property in the field map when in the server side method in the debugger. Any ideas?

              Comment


                #8
                Hi aderosso,

                I have a similar setup, 2 tables, lets say user and role and a n:m user_role table with the respective IDs (and a column tenant_id, as the app is multi-tenant).
                Like you, I want to display in the order-ListGrid an aggregated, comma separated column of products in the order.

                Right now I solve it like this (some downsides, see below):
                VIEW:
                Code:
                CREATE OR REPLACE FORCE VIEW v_user_rolelist AS 
                  SELECT u.tenant_id,
                  u.id AS user_id,
                  ListAgg(r.name, ', ') WITHIN GROUP (
                ORDER BY r.name) AS rolelist
                FROM t_user u
                LEFT OUTER JOIN t_user_role ur
                ON u.id         = ur.user_id
                AND u.tenant_id = ur.tenant_id
                LEFT OUTER JOIN t_role r
                ON ur.role_id    = r.id
                AND ur.tenant_id = r.tenant_id
                GROUP BY u.tenant_id,
                  u.id;
                
                COMMENT ON TABLE v_user_rolelist IS 'Aggregated list of roles assigned to a user.';
                .ds.xml:
                Code:
                <DataSource dbName="Oracle" tableName="V_USER_ROLELIST" ID="V_USER_ROLELIST" serverType="sql"
                    joinOnly="true" serverOnly="false">
                    <fields>
                        <field hidden="true" name="TENANT_ID" type="integer" canEdit="false" />
                        <field name="USER_ID" type="integer" [B]foreignKey="T_USER.ID"[/B] joinType="outer" />
                        <field name="ROLELIST" type="text" length="4000" escapeHTML="true">
                            <title><fmt:message key="assignedRoles" /></title>
                        </field>
                    </fields>
                </DataSource>
                Please see that the foreignKey is on this view and not on T_USER, as one would expect. It works both ways, but if you had it the other way around AND would have a 2nd n:m table for user, you could not set foreignKey twice on the T_USER.ID-field.

                This does work for me but has some downsides:
                • "slow"
                • Oracle error out of nowhere in Oracle 11.2, when you have too many entries for a user and the length of the string exceeds 4000 CHAR (not an issue in Oracle 12.2)
                I'll change it like here eventually, perhaps this is also an option for you:
                • Removal of VIEW
                • 2 options then
                • 1)
                  • Generate VIEW-data in java, store in singleton (might be memory intensive and therefore not an option)
                  • In fetch in SQLDataSource, update the SELECT-result with the data from the singleton
                • 2)
                  • Have a field for comma separated role-ID storage in user table (multiple=true in .ds.xml)
                  • Update and maintain this field from a trigger on the n:m table as "id1, id2, id3"
                  • customSelectExpression to count comma+1 of the field and display this as role-count
                  • Hover that loads data from the n:m table (but no display in-row in the ListGrid)
                  • Filtering still working because of multiple=true in .ds.xml
                I'll most likely go for the 2nd option. Hope this helps.

                Best regards
                Blama

                Comment


                  #9
                  Thank you Blama for the response. I was able to figure this out actually. To get the data to return from my method I needed to call dsResponse.setData() instead of just adding content to the records directly.

                  Comment


                    #10
                    Sorry we missed the need to call setData(). Note that your approach would have worked for a SQLDataSource, but for Hibernate, the underlying data is Java beans, and the Maps you were working with are just read-only views on the data, created by DataSourceBeanFilter.

                    Comment

                    Working...
                    X