Announcement

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

    [bug] Dynamic DS lookup returns incorrect DataSource object

    I found a patter matcher bug that seems to be an edge case, but is causing an NPE when I try to use <isc:loadDS="DynamicDS_10" /> on a JSP when a DynamicDS_1 already exists.

    It appears that the
    Code:
    getDynamicDataSource("DynamicDS_10", new DSRequest())
    actually returns the pointer to "DynamicDS_1" instead (I don't have the source code to be exactly sure).

    SmartClient Version: v9.1p_2014-08-06/Pro Deployment (built 2014-08-06)
    Browsers: all (server-side issue)

    To reproduce, you need over 10 datasources, including 1 and 10. Here are two classes that will replicate the issue:

    This dynamic generator in production would be pulling fields from the database, but this is hardcoded for test case purposes.
    Code:
    public class DynamicDSGeneratorTestCase implements DynamicDSGenerator {
    
    	private static Logger log = new Logger(DynamicDSGeneratorTestCase.class.getName());
    
    	private String dynamicDSName;
    
    	public void setDynamicDSName(final String dynamicDSName) {
    
    		this.dynamicDSName = dynamicDSName;
    	}
    
    	@Override
    	public DataSource getDataSource(final String paramString, final DSRequest paramDSRequest) {
    
    		if (dynamicDSName.equals(paramString)) {
    			try {
    
    				final StringWriter stringWriter = new StringWriter();
    
    				stringWriter.write("<DataSource ID=\"" + dynamicDSName + "\" titleField=\"name\" "
    						+ "serverConstructor=\"spring:rankingSummaryColumnsDataSource\">\n");
    
    				stringWriter.write("<fields> \n");
    
    				stringWriter.write("<field name=\"date\" title=\"Date\" type=\"text\" />");
    
    				stringWriter.write("<field name=\"transcription\" " + "title=\"Transcription\" type=\"text\" />");
    
    				stringWriter.write("</fields>\n</DataSource>");
    
    				return DataSource.fromXML(stringWriter.toString());
    
    			} catch (final Exception e) {
    
    				log.error("Problems when creating dynamic server side datasource.", e);
    
    			}
    
    		}
    
    		return null;
    	}
    }
    This class will create 12 of the above classes and register them. After doing so, it will create an NPE.

    Code:
    public class DynamicDSGeneratorTestCaseRegistrar {
    
    	public void registerMultipleDataSources() {
    
    		final DynamicDSGeneratorTestCase dynamicDSGeneratorTestCase = new DynamicDSGeneratorTestCase();
    
    		final String dynamicDSName = "DynamicDS";
    
    		for (int i = 1; i < 13; i++) {
    
    			final String dynamicDSId = dynamicDSName + "_" + i;
    			dynamicDSGeneratorTestCase.setDynamicDSName(dynamicDSId);
    			DataSource.addDynamicDSGenerator(dynamicDSGeneratorTestCase, dynamicDSId);
    		}
    
    		//returns dynamicDS_1, causing getDataSource() to fail the first if statement and return null
    		final DataSource ds = DataSource.getDynamicDataSource("DynamicDS_10", new DSRequest());
    
    		//NPE
    		System.out.println(ds.toString());
    	}
    }

    #2
    If someone has registered a DynamicDSGenerator with prefix "DynamicDS_1" and that generator is used when requesting "DynamicDS_10", then this behavior is correct per docs. "DynamicDS_1" is indeed a substring of "DynamicDS_10".

    It looks like your code is making an assumption that the most specific registered DynamicDSGenerator will be used, that is, the one whose prefix most closely matches the requested DS ID. But we don't document that this will be the behavior, and we don't want to switch to a more complicated lookup strategy here - it's an inner loop.

    Comment


      #3
      This was not my understanding from a previous post I made in July. Here was your response at that point:

      http://forums.smartclient.com/showthread.php?t=30740
      7th Jul 2014, 16:39
      "Regardless of pooling settings, the system will never return a Datsource that has an ID that does not match the requested ID."
      In my opinion, "DynamicDS_1" does not match "DynamicDS_10".

      Comment


        #4
        We're not returning a DataSource in this instance. We're returning the DSGenerator you registered, because you registered it under a prefix, not a specific ID.

        If your DSGenerator then malfunctions and returns the wrong DataSource, that's an issue with your generator, not the framework - though the framework does warn about the error.

        Comment


          #5
          In that case, how do I register my dynamic data sources with a specific ID instead of a prefix?

          Comment


            #6
            By design there is no such API, as that would be an inefficient way of doing things - just provide a single DynamicDSGenerator that can call the appropriate logic when handed a range of possible IDs.

            Comment

            Working...
            X