Announcement

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

  • Using same sql transaction

    I need to do run a sql query before and after the
    dsResponse.execute() in the DMIInterceptor, but in the same transaction.

    I did the same like in the showcase example but isn't transactional.
    Is this possible and should it work like this?

    Code is like:


    dsRequest.setPartOfTransaction(true);
    SQLTransaction.startTransaction(dsRequest.rpc);
    Connection connection = SQLTransaction.getConnection(dsRequest.rpc);

    // FIRST ONE:
    Connection conn = connection;
    try {
    PreparedStatement stmt = conn.prepareStatement(createNewCstmSttngSQL);
    stmt.setString(3, masterId);
    ...
    stmt.execute();
    stmt.close();
    dsResponse.setStatus(DSResponse.STATUS_SUCCESS);
    \} catch( Exception e){
    dsResponse.setStatus(DSResponse.STATUS_FAILTURE);
    }

    // SECOND ONE:
    dsRequest.execute();

    // Third one like first one:

    Connection conn = connection;
    try {
    PreparedStatement stmt = conn.prepareStatement(createNewCstmSttngSQL);
    stmt.setString(3, masterId);
    ...
    stmt.execute();
    stmt.close();
    dsResponse.setStatus(DSResponse.STATUS_SUCCESS);
    \} catch( Exception e){
    dsResponse.setStatus(DSResponse.STATUS_FAILTURE);
    }

    SQLTransaction.endTransaction(dsRequest.rpc);
    connection.close();
    Last edited by damend; 4th Oct 2011, 04:15.

  • #2
    Your code differs from the sample in some obvious ways, including manual calls to SQLTransaction and an attempt to close() the connection. Just eliminate these differences.

    Also, don't use this approach if the SQL actions you need to do can be done as normal DSRequests (which is almost everything).

    Comment


    • #3
      Hello,

      thanks for response.

      I know about this difference.
      Reason I extended the example was, because I need to get the connection
      before dsRequest.execute() is called.
      getting the connection is only working, after dsRequest.execute() is called.

      What do you mean by using normal dsRequest?
      Are you talking about having a separate dsRequest for every SQL-Query to execute? In which way this will be transactional?

      I'll remove closing of connection,

      Thanks

      Comment


      • #4
        You can create and execute additional dsRequests in a DMI (covered in QuickStart Guide) and you can make them transactional by calling dsRequest.setRPCManager().

        Comment


        • #5
          Hello.

          I have been trying to play around with multiple DSRequests in a DMI, in order to share the same transaction among them.

          The solution you wrote in the last message does not produce the desired results.

          In my example the table_a used is deleted on commit.

          Version 1. (your solution)

          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <DataSource ID="test" serverType="sql" dbName="TXDEV1" tableName="table_a">
          
            <fields>
              <field name="column_name" type="text"/>
            </fields>
            
            <serverObject lookupStyle="spring"  bean="testBean"/>
          
          </DataSource>
          
          ///////////////// DMI ///////////////////////////////
          
              // insert - insert into table_a (column_name) values ('some_value')
              // verify - select * from table_a;
              // dsRequest - select * from table_a;
              @Override
              public DSResponse fetch(DSRequest dsRequest) throws Exception {
                      Object conn = dsRequest.getDataSource().getTransactionObject(dsRequest);
                      RPCManager rpc = dsRequest.getRPCManager();
                      // create a DSRequest, setting the RPCManager from original request
                      DSRequest insert = createInsertDSRequest(rpc, "some_value");
                      // create a DSRequest, setting the RPCManager from original request
                      DSRequest verify = createVerifyDSRequest(rpc);
          
                      insert.execute(); // inserted 1 row
                      verify.execute(); // returned 0 results
                      dsRequest.execute(); // returned 0 results
              }
          Version 2. setJoinTransaction(true)

          Code:
              // insert - insert into table_a (column_name) values ('some_value')
              // verify - select * from table_a;
              // dsRequest - select * from table_a;
              @Override
              public DSResponse fetch(DSRequest dsRequest) throws Exception {
                      Object conn = dsRequest.getDataSource().getTransactionObject(dsRequest);
                      RPCManager rpc = dsRequest.getRPCManager();
                      // create a DSRequest, setting the RPCManager from original request
                      DSRequest insert = createInsertDSRequest(rpc, "some_value");
                      // create a DSRequest, setting the RPCManager from original request
                      DSRequest verify = createVerifyDSRequest(rpc);
          
                      insert.setJoinTransaction(true);      
                      verify.setJoinTransaction(true);
          
                      insert.execute(); // inserted 1 row
                      verify.execute(); // returned 1 result
                      dsRequest.execute(); // returned 0 results
              }
          Version 2a.

          Then I tried to call dsRequest.setJoinTransaction(), but an exception was thrown, indicating that the dsRequest has been started already and that it was not possible to set the join transaction property.

          Version 3. - Working solution.

          Modification on datasource.xml.ds as follows:

          Code:
          <?xml version="1.0" encoding="UTF-8"?>
          <DataSource ID="test" serverType="sql" dbName="TXDEV1" tableName="table_a" 
          autoJoinTransactions="true">
          
            <fields>
              <field name="column_name" type="text"/>
            </fields>
            
            <serverObject lookupStyle="spring"  bean="testBean"/>
          
          </DataSource>
          Same code as version 2. on the DMI.

          Code:
              // insert - insert into table_a (column_name) values ('some_value')
              // verify - select * from table_a;
              // dsRequest - select * from table_a;
              @Override
              public DSResponse fetch(DSRequest dsRequest) throws Exception {
                      Object conn = dsRequest.getDataSource().getTransactionObject(dsRequest);
                      RPCManager rpc = dsRequest.getRPCManager();
                      // create a DSRequest, setting the RPCManager from original request
                      DSRequest insert = createInsertDSRequest(rpc, "some_value");
                      // create a DSRequest, setting the RPCManager from original request
                      DSRequest verify = createVerifyDSRequest(rpc);
          
                      insert.setJoinTransaction(true);      
                      verify.setJoinTransaction(true);
            
                      insert.execute(); // inserted 1 row
                      verify.execute(); // returned 1 result
                      dsRequest.execute(); // returned 1 result
              }
          Version 3. worked, despite the DataSource documentation indicating that the autoJoinTransactions property is used only on add, remove and update operations. It worked on a fetch anyway.

          The 1st question I ask at this point in time is the following:
          Is this a/the correct approach to handle transactional requests?

          The 2nd question is:
          You can see I try to get the connection from the dsRequest, but the object returned is always null. I see from your smartgwtee showcase an example with this solution apparently working. What am I doing wrong in my code?

          Version used:
          smartgwtpower-3.0p.2012-05-02
          Last edited by ssequeira; 26th Jun 2012, 07:36.

          Comment


          • #6
            We can't tell if any of these are the recommended approach because you've got helper methods where you haven't shared the code.

            Also, you mentioned an exception but didn't post any details as required.

            Just to reiterate the docs: setRPCManager() is enough to cause a given DSRequest to join the current transaction - but only if the RPCManager's setting for autoJoinTransactions indicates that that DSRequest should join the current transaction.

            Comment


            • #7
              Unless I was deliberately posting just for fun or to create problems where they do not exist, I would chose to hide my helper methods because I would have code there specifically to make the whole thing not work. Believe me, I have better things to do...

              Plus, what the helper methods are or are not doing is irrelevant for the 2nd question.

              Code:
              private DSRequest createInsertDSRequest(RPCManager rpc, String... columnValues) throws Exception {
                      DSRequest myR = new DSRequest("test", "add");
                      myR.setRPCManager(rpc);
                      
                      List<HashMap<String, String>> all = new ArrayList<HashMap<String, String>> ();
                      for (String v : columnValues) {
                          HashMap<String, String> m = new HashMap<String, String>();
                          m.put("column_value", v);
                          all.add(m);
                      }
                       
                      myR.setValues(all);
                      return myR;
                  }
              
                  private DSRequest createSelectDSRequest(RPCManager rpc) throws Exception {
                      DSRequest myR = new DSRequest("test", "fetch");
                      myR.setRPCManager(rpc);
                      return myR;
                  }
              Exception info when calling setJoinTransaction(true) on the request that is sent from the client:

              Code:
              Request instance: com.isomorphic.servlet.ISCHttpServletRequest@1b39190 / 127.0.0.1 / /myApp/sc/IDACall / Wed Jun 27 09:26:37 CEST 2012
              Exception info:
              com.isomorphic.datasource.DSRequestAlreadyStartedException: Request processing has started;  join transactions setting cannot be changed
              	at com.isomorphic.datasource.DSRequest.setJoinTransaction(DSRequest.java:3411)
              	at my.app.interceptors.BasicDMIInterceptor.fetch(BasicDMIInterceptor.java:76)
              	at my.app.interceptors.MyInterceptor.fetch(MyInterceptor.java:28)
              	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 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
              	at org.springframework.security.access.intercept.aopalliance.MethodSecurityInterceptor.invoke(MethodSecurityInterceptor.java:67)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.aop.interceptor.AbstractTraceInterceptor.invoke(AbstractTraceInterceptor.java:113)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:50)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
              	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
              	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
              	at $Proxy83.fetch(Unknown Source)
              	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.isomorphic.base.Reflection.adaptArgsAndInvoke(Reflection.java:950)
              	at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:386)
              	at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:64)
              	at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:1945)
              	at my.app.common.security.IDACall.handleDSRequest(IDACall.java:76)
              	at com.isomorphic.servlet.IDACall.processRPCTransaction(IDACall.java:156)
              	at com.isomorphic.servlet.IDACall.processRequest(IDACall.java:121)
              	at com.isomorphic.servlet.IDACall.doPost(IDACall.java:73)
              	at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
              	at com.isomorphic.servlet.BaseServlet.service(BaseServlet.java:152)
              	at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
              	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
              	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
              	at my.app.filter.Log4jFilter.doFilterInternal(Log4jFilter.java:40)
              	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
              	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
              	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:368)
              	at my.app.support.acegi.PortalVersionRedirectFilter.doFilterInternal(PortalVersionRedirectFilter.java:41)
              	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at my.app.support.acegi.ChangeExpiredPasswordFilter.doFilter(ChangeExpiredPasswordFilter.java:76)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
              	at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at my.app.support.acegi.NoFilter.doFilter(NoFilter.java:20)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at my.app.support.acegi.NoFilter.doFilter(NoFilter.java:20)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at my.app.support.acegi.CoBrandingFilter.doFilterInternal(CoBrandingFilter.java:77)
              	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at my.app.filter.RequestWrappingFilter.doFilterInternal(RequestWrappingFilter.java:29)
              	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
              	at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380)
              	at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169)
              	at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
              	at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
              	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
              	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
              	at com.isomorphic.servlet.CompressionFilter.doFilter(CompressionFilter.java:259)
              	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
              	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
              	at my.app.support.acegi.AccessFilter.doFilter(AccessFilter.java:59)
              	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
              	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
              	at my.app.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:26)
              	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
              	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
              	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
              	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
              	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
              	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
              	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
              	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
              	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:291)
              	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
              	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
              	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
              	at java.lang.Thread.run(Thread.java:662)
              An extra piece of information, maybe relevant, maybe not; even when in the datasource definition file the autoJoinTransactions="true" setting is used, the call to dsRequest.getRPCManager().getTransactionPolicy() returns 0, i.e. TransactionPolicy.NOT_SET.

              Comment


              • #8
                Please show all of the code or we will ask for it, every time.

                You are asking us for help because you are having trouble spotting the problem, it would be silly to omit bits of code that you assume are not the cause. It's very common that we find a problem in code someone is assuming is OK.

                As far as the current code, what is the purpose of the line of code that starts "Object conn ="? This forces the connection to be retrieved sooner than would otherwise happen, but you don't do anything with the connection object. Try removing this line of code, or, if you actually have code that does something with the connection object, please show that code.

                Also, what are your settings in server.properties regarding autoJoinTransactions? Some of your results suggest you've got auto-joining turned off at this level.

                Comment


                • #9
                  Hi,

                  I would like to post here the current solution to the problem stated in this thread.
                  The problem has expanded so I will state it again.
                  1. We need to execute a fetch on an SQL datasource called "searchX", but before we need to populate a temp table (that is deleted on commit/rollback) that is used by the SQL datasource.
                  2. We also need to execute this fetch on "searchX" datasource as a Quartz offline job, not only as a request form the browser.
                  We use this for an offline export of data to the file system that later can be downloaded by the user (a kind of async export).

                  Below is the current implementation that has IMO more weak point that I'd like to clarify and improve.

                  1. In SearchDMI.fetch we need to create a new dsRequest to delete from table_tmp only to be able to create a connection to be used by our DAO that is based on spring JdbcDaoSupport class.
                  - Is it possible in a different way?
                  To me the best solution would be to be able to configure the "searchX" datasource with an external transaction manager (in our case spring based).
                  I proposed this solution some time ago (see http://forums.smartclient.com/showthread.php?t=16902 ).
                  - I would like to know how much it costs and how long it takes to be implemented.

                  2. The quartz based job executor has IMO several weak points:
                  2.1 needs mock servlet request and response objects; request needs also a mock query string (RPC like)
                  2.2 needs a RequestContext and RPCManager that are based on the mock objects
                  2.3 needs dsRequest.freeResources() to end the transaction
                  - Is it possible to implement it in a different way that doesn't require those mock objects and ending manually the transction?
                  - I know that exists a certain Quartz support in SmartGWT server library, but haven't found any documentation. Is this use cases supported already by the framework?

                  Thank you in advance,
                  Mihnea


                  Code:
                  <DataSource ID="tableTmp" serverType="sql" tableName="TABLE_TMP">
                  
                  	<fields>
                  		<field name="column_value" type="text" />
                  	</fields>
                  
                  	<operationBindings>
                  		<operationBinding operationType="remove" requires="true" />
                  	</operationBindings>
                  
                  </DataSource>
                  
                  
                  
                  <DataSource ID="searchX" serverType="sql" tableName="TABLE_X" autoJoinTransactions="true" ...>
                  
                    <fields>
                  ...
                    </fields>
                    
                    <serverObject lookupStyle="spring" bean="SearchDMI"/>
                    <operationBindings>
                      <operationBinding operationType="fetch" serverMethod="fetch" skipRowCount="true" >
                  	<whereClause>
                  
                  	$defaultWhereClause
                  	AND EXISTS (SELECT 1 
                  	FROM TABLE_TMP RES 
                  	WHERE RES.COLUMN_VALUE = TABLE_X.COLUMN_Y )
                  		
                    	</whereClause>
                    	
                      </operationBinding>  	
                    </operationBindings>
                  </DataSource>    
                  
                  
                  
                  public class SearchDMI {
                   public DSResponse fetch(DSRequest dsRequest) throws Exception {
                  
                  	// delete from temp table using anotehr dsRequest to be able to get the database connection
                  	DSRequest request = new DSRequest("tableTmp", "delete");
                  	request.setRPCManager(dsRequest.getRPCManager());
                  	request.setJoinTransaction(true);
                  	request.execute();
                  	Connection conn = (Connection)((BasicDataSource)request.getDataSource()).getTransactionObject(request); 
                  
                  	// use an existing dao based on org.springframework.jdbc.core.support.JdbcDaoSupport to insert data in TABLE_TMP
                  	MyDataSource ds = new MyDataSource(conn);// a datasource that returns always the given connection and never closes it
                  	InsertDaoImp dao = new InsertDaoImp();
                          dao.setDataSource(ds); 
                          dao.insert(...);
                          
                          // execute the final fetch based on TABLE_X and TABLE_TMP
                          // TABLE_TMP is deleted automatically on commit or rollback,
                          // so the insert in TABLE_TMP has to be done in the same database transaction as the following search
                          return dsRequest.execute();
                   }
                  }
                  
                  // quartz based job execution service
                  public class JobServiceImpl {
                   public void executeJob(Map<String, Object> jobDetails, JobStatus status) {
                          DSRequest dsRequest = new DSRequest();
                          dsRequest.setStreamResults((Boolean)jobDetails.get(ExportJobKeys.streamResults.name()));
                          dsRequest.setCriteria(jobDetails.get(ExportJobKeys.criteria.name()));
                          dsRequest.setOperationType("fetch");
                          dsRequest.setExportResults(true);
                          dsRequest.setDataSourceName((String) jobDetails.get(ExportJobKeys.dataSourceName.name())); //"searchX" datasource
                          
                          MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest();
                          // set a dummy query string to look like an RCP request, otherwise cannot be created a new RPCManager for this request
                          // it contains a request without any operation
                          mockHttpServletRequest.setQueryString("is_isc_rpc=true&_transaction=%3Ctransaction%20xmlns%3Axsi%3D%22http%3A//www.w3.org/2000/10/XMLSchema-instance%22%20xsi%3Atype%3D%22xsd%3AObject%22%3E%3CtransactionNum%20xsi%3Atype%3D%22xsd%3Along%22%3E63%3C/transactionNum%3E%3Coperations%20xsi%3Atype%3D%22xsd%3AList%22%3E%3C/operations%3E%3C/transaction%3E&protocolVersion=1.0");
                  	MockHttpServletResponse mockHttpServletResponse = new MockHttpServletResponse();
                  	dsRequest.setRequestContext(RequestContext.instance(ISCFile.servletContext, mockHttpServletRequest, mockHttpServletResponse));
                                  
                          Map<?, ?> map = (Map<?,?>) jobDetails.get(ExportJobKeys.templateMap.name());
                          for(Object key : map.keySet()) {
                              dsRequest.addToTemplateContext((String) key, map.get(key));
                          }
                          
                          RPCManager rpcManager = new RPCManager(mockHttpServletRequest, mockHttpServletResponse);
                          // without the next line the export doesn't work
                          // unless the sql datasource has autoJoinTransactions="true" 
                          // or a similar global setting exists
                          rpcManager.setTransactionPolicy(TransactionPolicy.ALL);
                  	dsRequest.setRPCManager(rpcManager);
                  		
                  	dsRequest.execute();  //will call SearchDMI.fetch        
                  	
                  	dsRequest.freeResources();// Ending the transaction 	
                   }
                  }

                  Comment


                  • #10
                    The second request (be able to use transactions without any servlet APIs being involved) makes sense as a sponsorship and we'll send an estimate.

                    On the first request, can you clarify why you're interested in this - are you integrating with some other library that requires that it creates the SQLConnection (rather than simply using the one SmartGWT creates automatically)?

                    The Quartz functionality you've discovered is currently not documented or supported.

                    Comment


                    • #11
                      We integrate on the server side existing implementations of Services/DAOs that use JDBC (or Hibernate) with SQL Datasources.

                      Comment


                      • #12
                        So to restate: you have your own custom and pre-existing Services/DAOs, and the way they are implemented, they require that they create the JDBC Connection object, and that they do the commit or rollback of the transaction, correct?

                        Comment


                        • #13
                          No, the Services and DAOs don't start/commit/rollback the transaction. The Transaction manager does that.
                          We configure the transaction demarcation at the service level using Spring (XML or Java).
                          So the generated method interceptor of the Service call for transactions starts/commits/rollbacks the transaction.

                          Code:
                          <bean id="hibernateTransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
                              <property name="sessionFactory" ref="sessionFactory"/>    
                          </bean>
                          
                          <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean" >
                              <property name="dataSource" ref="dataSource"/>
                          </bean>
                          
                          <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" />
                          
                          
                          @Transactional(propagation = Propagation.REQUIRED)    
                          public class SomeServiceImpl implements SomeService {
                              private DetailsDao detailsDao;
                              public SearchResult<Details> findDetails(...){
                                  return detailsDao.findDetails(...);
                              }
                          }
                          
                          @Transactional(propagation = Propagation.MANDATORY) 
                          public class DetailsDaoImpl extends JdbcDaoSupport implements DetailsDao {
                          	public SearchResult<Details> findDetails(...)	
                          }
                          We base our DAOs on these Spring classes:
                          org.springframework.jdbc.core.support.JdbcDaoSupport
                          org.springframework.orm.hibernate3.support.HibernateDaoSupport

                          Here is the DAOs Spring configuration:

                          Code:
                          <bean id="DetailsJdbcDao" class="DetailsJdbcDaoImpl">
                          	<property name="dataSource" ref="dataSource"/>
                          </bean>    
                          
                          <bean id="DetailsHibernateDao" class="DetailsHibernateDaoImpl">
                          	<property name="sessionFactory" ref="sessionFactory"/>
                          </bean>
                          My vision is to have also the SQL Datasource participate in the transactions managed by the transaction manager and to configure its transaction demarcation like for any other Service using Spring Transaction annotation.
                          We do have the DMI classes configured with Spring and transaction demarcations, but that doens't influence how the dsRequest.execute() uses the database connections.
                          Maybe it helps also to look at my post about using the Spring DataSourceUtils class. See http://forums.smartclient.com/showthread.php?t=16902

                          Comment


                          • #14
                            OK, we previously understood you to say that you'd like to provide your own JDBC Connection object to SQLDataSource, such that SQLDataSource would no longer attempt to create its own Connection, and would not attempt to start or commit transactions on the Connection.

                            Are you now saying you're looking for automatic integration with Spring's transaction demarcation system (this is very different).

                            Comment


                            • #15
                              Yes. Integration with String transaction demarcation system is what we would need and I find it quite powerful extension to the framework.

                              Is this integration already supported for HibernateDataSources?

                              Comment

                              Working...
                              X