Announcement

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

    Parametrize schema name that datasources point to

    Is there a (good) way in SmartGWT to parametrize the schema that the datasource's sql statement will use? Specifically, I am using a MySQL database that has multiple databases, eg "db_client1", "db_client2", "db_client3", each of which is identical in structure. In my datasources, 90% of my queries are partially custom queries. I'd like the table names in the final sql statements to be prefixed with the schema name. So, instead of

    select bar from foo1, foo2
    where foo1.pk=foo2.fk

    it should read

    select bar from db_client1.foo1, db_client1.foo2
    where db_client1.foo1.pk=db_client1.foo2.fk

    All this said, I'm very open to other, cleaner suggestions of getting the datasource to point to a different schema. Currently, the server.properties file's parameter "sql.Infini.driver.name" is set to use an Apache Tomcat JDBC pool, so my best idea was to parameterize the datasource's tables names. But, if there was a way that just prior to every sql statement, SmartGWT would execute some sort of "use db_client1" statement, that might be best (since it would involve the least change to all my code.)

    Additional details:
    ======================
    SmartGWT (not smartclient) Version: SmartClient Version: v8.3p_2012-11-26/PowerEdition Deployment (built 2012-11-26)
    ...
    Browser: Mozilla Firefox ESR 10.0.7
    GWT SDK: 2.5.0rc2
    Sun JDK 1.6.0_13
    OS: Centos 6.x
    IDE: MyEclipse 10.6 with Google Plugin for Eclipse (3.1.0)

    #2
    A couple of approaches:

    1. create a new set of connection settings for each schema - this post shows how this was done for using different credentials to log into the DB

    2. use the ability to get direct access to the SQLConnection to execute your own statement to change the default schema

    Comment


      #3
      Ok option 1 is helpful for me. But, is there any reason then that I simply cannot set each datasource's dbname after I retrieve it? I'm thinking of something along these lines:

      ds = DataSource.get("myDS");
      ds.setDbname("db_client2");

      But, I couldn't find any setDbname, so my guess is that it should instead read:

      ds.setAttribute("dbName", "db_client2");

      Is there anything wrong with this approach? I'm assuming that this "overriden" dbName only applies to the user's sessions, ie the user's browser's session and would not therefore impact any other user (that is, this is not some sort of static server based setting).

      Comment


        #4
        Connection pooling and caching is the reason you cannot do that.

        Comment


          #5
          So I was following the solution outlined in this similar post by Isomorphic (http://forums.smartclient.com/showthread.php?t=15937&highlight=DataSource.addDynamicDSGenerator) in which one modifies the datasource id with the appropriate prefix. With some testing, I've discovered that this does not work, as it seems that SmartGWT immediately discards this "faked/prefixed" id and does not call therefore the custom added DynamicDSGenerator. (I verified that for datasource ids which are normal, it is calling my custom DynamicDSGenerator).It's as if it has "cached" all the real datasources, and so immediately assumes that if a DataSource.get() command is executed on an id that it's not awre of, it should return null right away -- it doesn't bother,threfore, to proceed to my custom DynamicDSGenerator which would have parsed the data out properly....So, how can I get SmartGWT to NOT ignore what it thinks is a "bad" ds id and to let it continue on to my custom DynamicDSGenerator? In particular, this should work since SmartGWT has this method called

          public static void addDynamicDSGenerator(DynamicDSGenerator ddsg, java.lang.String prefix)

          in which a prefix is expected, so I'm assuming that we can prefix datasources accordingly (even if these prefixed named datasources don't actually exist on disk.)

          If, for some reason, I must follow the stratedgy in this post instead (http://forums.smartclient.com/showthread.php?t=24504&highlight=username+sql), then how does one "smuggle" the DB_USER field into the http session attribute? (The code in that post seems to be able to access an attribute called DB_USER, but it's not clear how that field is set in the client side of the code.)

          Comment


            #6
            Your comments don't really make sense - note that the thread we linked you to involved another user who had no trouble using this API (among many others), so it's obviously not broken.

            If you need help correcting your approach, you'll need to post your code.

            Comment


              #7
              I have created a test case. Please see below the code for

              1) the client code snippet
              2) the custom DynamicDSGeneator
              3) The output results of running the client code snippet
              4) the relevant portion of the web.xml file
              5) the relevant potion of the builinds.html file.

              Code:
              	DataSource workingDS = DataSource.get("dsProtXMLFileName");
              		workingDS.fetchData(null, new DSCallback() {
              
              			@Override
              			public void execute(DSResponse response, Object rawData, DSRequest request) {
              				// TODO Auto-generated method stub
              				System.out.println("Response is " + response);
              			}
              		});
              		
              		DataSource notWorkingDS = DataSource.get("dbDefined_Infini876_dsProtXMLFileName");
              		
              		notWorkingDS.fetchData(null, new DSCallback() {
              			@Override
              			public void execute(DSResponse response, Object rawData, DSRequest request) {
              				// TODO Auto-generated method stub
              				System.out.println("Response is " + response);
              			}
              		});

              And, now here's the custom dynamicDSGeneratorServlet code

              Code:
              public class DynamicDSGeneratorServlet extends HttpServlet {
              
              	/**
              	 * 
              	 */
              	private static final long serialVersionUID = 1L;
              
              	public DynamicDSGeneratorServlet() {
              		super();
              	
              		System.out.println("Starting dynamic ds generator servlet");
              	DynamicDSGenerator ddsg;
              	ddsg = new DynamicDSGenerator() {
              		
              		@Override
              		public DataSource getDataSource(String id, DSRequest dsRequest) {
              			System.out.println("The getDataSource method of the DynamicDSGeneratorServlet was called for datasource ID:" + id);
              
              			return null;
              		}
              And now, here's the output of running the client code. Please note that the "workingDS" correctly calls the custom DynamicDSGeneratorServlet's getDataSource method and therefore prints out the statement "The getDataSource method was called for datasource ID ....". But, when it comes to the "notWorkingDS", we get a null pointer exception. The notWorkingDS is null. I'm confused as to why this is and would greatly appreciate any help.

              Code:
              The getDataSource method of the DynamicDSGeneratorServlet was called for datasource ID:transaction
              The getDataSource method of the DynamicDSGeneratorServlet was called for datasource ID:Object
              The getDataSource method of the DynamicDSGeneratorServlet was called for datasource ID:List
              The getDataSource method of the DynamicDSGeneratorServlet was called for datasource ID:DataSource
              The getDataSource method of the DynamicDSGeneratorServlet was called for datasource ID:elem
              The getDataSource method of the DynamicDSGeneratorServlet was called for datasource ID:dsProtXMLFileName
              === 2013-08-01 20:15:13,883 [l0-6] INFO  IDACall ---- Performing 1 operation(s)
              === 2013-08-01 20:15:13,920 [l0-6] INFO  SQLDataSource ---- [builtinApplication.dsProtXMLFileName_fetch] Performing fetch operation with
              	criteria: {}	values: {}
              === 2013-08-01 20:15:14,438 [l0-6] INFO  SQLWhereClause ---- [builtinApplication.dsProtXMLFileName_fetch] empty condition
              === 2013-08-01 20:15:14,441 [l0-6] INFO  SQLDataSource ---- [builtinApplication.dsProtXMLFileName_fetch] derived query: SELECT $defaultSelectClause FROM $defaultTableClause WHERE $defaultWhereClause
              === 2013-08-01 20:15:14,451 [l0-6] INFO  SQLDataSource ---- [builtinApplication.dsProtXMLFileName_fetch] Executing SQL query on 'Infini': SELECT td_prot_xml_filename.filename_no_path, td_prot_xml_filename.prot_xml_filename, td_prot_xml_filename.td_prot_xml_filename_key, SUBSTRING(td_prot_xml_filename.filename_no_path,6,LOCATE('-',td_prot_xml_filename.filename_no_path,6)-6) AS workflowID, td_prot_xml_filename.workflowName FROM td_prot_xml_filename WHERE ('1'='1')
              === 2013-08-01 20:15:14,557 [l0-6] INFO  PoolManager ---- [builtinApplication.dsProtXMLFileName_fetch] SmartClient pooling started for 'Infini' objects
              === 2013-08-01 20:15:14,636 [l0-6] INFO  SQLDriver ---- [builtinApplication.dsProtXMLFileName_fetch] Executing SQL query on 'Infini': SELECT td_prot_xml_filename.filename_no_path, td_prot_xml_filename.prot_xml_filename, td_prot_xml_filename.td_prot_xml_filename_key, SUBSTRING(td_prot_xml_filename.filename_no_path,6,LOCATE('-',td_prot_xml_filename.filename_no_path,6)-6) AS workflowID, td_prot_xml_filename.workflowName FROM td_prot_xml_filename WHERE ('1'='1')
              === 2013-08-01 20:15:15,747 [l0-6] INFO  DSResponse ---- [builtinApplication.dsProtXMLFileName_fetch] DSResponse: List with 18 items
              The getDataSource method of the DynamicDSGeneratorServlet was called for datasource ID:dsProtXMLFileName
              === 2013-08-01 20:15:15,776 [l0-6] INFO  Compression ---- /builtinds/sc/IDACall: 4353 -> 744 bytes
              Cause is: Exception caught: null
              My theory is that SmartGWT will only allow the DataSource.get method for datasources that are "known". One cannot put some random id in there and then have it intercepted by the custom "DynamicDSGeneator's getDataSource" method. But it seems like this should be supported based on the documentation and even other posts (e.g., http://forums.smartclient.com/showth...aSource.addDyn amicDSGenerator)

              Any/all help would be appreciated.

              Quick edit: Here's the web.xml and builtinds.html files respectively:

              key part of web.xml -->
              Code:
              	<!-- This is Gautam's custom servlet that will start up on startup
                       to add the dynamic datasource piece -->
                  <servlet>
                      <servlet-name>DynamicDSGeneratorServlet</servlet-name>
                      <servlet-class>com.smartgwt.sample.server.DynamicDSGeneratorServlet</servlet-class>
                      <load-on-startup>0</load-on-startup>
                  </servlet>
              key part of builtinds.html -->

              (You will note that the datasource dbDefined_Infini876_dsProtXMLFileName doesn't actually exist.)

              Code:
              <body>
              
                  <!--load the datasources-->
                  <script src="builtinds/sc/DataSourceLoader?dataSource=dsIAFileOrFolderBase,to_workflow,dsGenericWorkflow,dsXTandemProcess,dsProcessMSConvert,dsProcessProteinProphet,dsProcessIProphet,dsProcessPeptideProphet,dsProcessFTP,dsIAFileOrFolder,dsIAFolderONLY,dsSQLSelectedFiles,dsProcessXTandemToPepXML,dsProcessLoadPASS,dstf_prot_xml_peptides,dsProcessOMSSA,dsProteinPerspective,dsProtXMLFileName,dstm_percentages,dstd_prot_xml_proteins,dsModsObserved,dsMzObserved,dsStaticMods,dsMsFilename,dsProcessLibra,dsProcessConvertFASTAtoXTandem,dsProcessCreateDecoy,dsProcessMakeBlastDB,dsProcessConcatenatedFiles,dsNewFolder,dstm_yesno,dsShareFileOrFolder,dsIAFolderONLYClientOnly,dsUsers,dsAuthorities,dsGroups,dsMessage,VO_workflowProcessStatus,dsProteinPerspectiveiTRAQ,dstf_prot_xml_peptidesiTRAQ,dsMetabolites,dsProcessXCMS"></script>
              
                  <!-- OPTIONAL: include this if you want history support -->
                  <iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
              
                </body>
              Last edited by iainc.dev; 1 Aug 2013, 16:34.

              Comment


                #8
                What you've shown here is a DynamicDSGenerator that always returns null, so it never provides a dynamic DataSource.

                That would be expected to have no effect on the behavior of the system - if a DataSource was not defined in a .ds.xml file and you tried to load it, this should fail, exactly as it should if you did not define a DynamicDSGenerator at all.

                It seems like you expected something different - what were you expecting?

                You're also showing client-side code using DataSource.get() - this won't initiate a call to the server to load a DataSource at all so it's not clear why you're showing this code...

                Overall you're not showing any code that would try to load your dynamically defined DataSource ("dbDefined_Infini876_dsProtXMLFileName") - it's not included in your <script src=> to call the DataSourceLoader, so is there some code you're not showing that you were expecting would make an attempt to load this DataSource?

                As far as a log file showing some kind of Exception, this doesn't indicate a malfunction since again DataSource loading would be expected to fail for a DataSource that does not exist if you define a generator that always returns null. But you seem to have cut off the rest of the log with details of the exception? Please don't do this - these logs are critical for understanding what went wrong.

                Comment

                Working...
                X