Announcement

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

    Using DSrequests from a new thread at Server side

    Hi,
    I am using SmartGWT version 12.1-p20200926.

    I have an UPDATE operation type with DSRequest handled at server side component.

    From within the server side service, I want to start a new ASYNC thread and have my handling code included in the new thread.
    The handling code will make further DataSource requests to accomplish the task. I would want to start a transaction, make new DataSource request, execute the requests and commit the whole transaction in the newly spawned thread.

    How can I do this?

    Thanks & Regards.

    #2
    See Standalone DataSource Usage. Same approach as if you were running our server product outside of a servlet engine entirely.

    Just a note that most servlet containers consider it a violation to start your own thread - you generally need to coordinate with existing thread pools (eg via Quartz, etc).

    Comment


      #3
      Hi,
      Thanks for the prompt reply.
      I would definitely be using an existing thread pool of the application.

      Using the standalone Data Source Usage, how do we ensure same transaction for multiple operations?

      Comment


        #4
        By reading the docs we just referred you to.

        There is literally a major overview called Standalone DataSource Usage and it covers your questions.

        Comment


          #5
          Hi,

          I tried the way it is described in Standalone DataSource Usage.

          I have a Spring application where I use a DSRequest to call a method at server side Service.
          In the method:

          Code:
           public DSResponse copyAdjustments(final DSRequest priceAdjustmentDSRequest, final RPCManager rpcManager) throws ApplicationException {
          
                  log.info("copyAdjustment - Start");
                  final long jobId = jobSQLService.add("CopyAdjustments", BatchJobStatusConstants.IN_PROGRESS);
          
                  // Process the copy adjustment logic in another thread
                  taskExecutor.execute(() -> {
                      // boolean value to control whether to mark the job is failed in the finally block
                      boolean exception = true;
                      try {
                          handleCopyAdjusments();
                          exception = false;
                      } catch (final ApplicationException e) {
                          // Handle exceptions, send back the exception as the job note
                          exception = false;
                          log.error("Error copying adjustments", e);
                          jobSQLService.update(jobId, BatchJobStatusConstants.ERROR, e.getMessage());
                      } finally {
                          // Mark the job as error if something else went wrong
                          if (exception) {
                              jobSQLService.update(jobId, BatchJobStatusConstants.ERROR);
                          }
                      }
                  });
          
                  // Handle all the three lists with PriceAdjustment data in a single transaction
          
                  hdwStdAdjustmentData.setData(jobId);
                  return hdwStdAdjustmentData;
          
              }
          Please note that the threadPoolExecutor is a Spring managed pol and is injected in this service.

          Then on the handleCopyAdjsutment method:

          Code:
          handleCopyAdjustment(){
          DsTransaction dsTransaction = new DSTransaction();
          List<Object> tobeAddedList = methodFetch1(dsTransaction);
          
          if (CollectionUtils.isNotEmpty(toBeAddedList)) {
                          for (final Map<String, Object> rec : toBeAddedList) {
                              final DSRequest addRequest = new DSRequest(DSConst.PriceAdjustmentSQL.DATASOURCE, DSOperationType.UPDATE.getValue());
                              addRequest.setDsTransaction(dsTransaction);
                              addRequest.setOperationId(DSConst.PriceAdjustmentSQL.ADD_ADJUSTMENT_OPERATION);
                              addRequest.setValues(rec);
                              addRequest.execute();
                          }
          
                      }
          
          
          
          }
          Although the fetches work fine and fetches the complete list.
          But when I go to UPDATE operation call in the loop, it gives me:
          [HTML]
          java.lang.Exception: RequestContext is missing the ServletContext. Please ensure you privide either a PageContext, a Servlet, or a ServletContext to your RequestContex.instance() call.
          [/HTML]
          I have also added the following in my server.properties file : standalone.spring.applicationContext:$webRoot/WEB-INF/applicationContext.xml and the path to application context is correct. Still I am getting the same error.

          Please help.

          Comment


            #6
            Please never post just an exception without a stack trace or any surrounding logs. You have been reminded many times of the diagnostics you need to post, but you inexplicably omit them basically every time, even in situations like this where it is very obvious that it means no one can help you.

            Comment


              #7
              Hi,
              This is the exception trace I got from the server console:

              Caused by: java.lang.Exception: RequestContext is missing the ServletContext. Please ensure you privide either a PageContext, a Servlet, or a ServletContext to your RequestContex.instance() call.
              at com.isomorphic.rpc.ServerObject.<init>(ServerObject.java:223)
              at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:236)
              at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:64)
              at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:3002)
              at com.XXX.YYY.server.services.impl.ZZZ.handleCopyAdjusments(ZZZ.java:1084)


              Thanks.

              Comment


                #8
                Hi,
                Just adding to the above logs, the
                webRoot:
                entry in server.properties is
                _AUTODETECT_
                .

                I changed the webroot to absolute path of the webroot. Still the same problem.

                Also, the logs pasted above were the only ones I get from the server console. Please let me know in case some more detail is required form my side.
                Last edited by sidharth1917; 8th Nov 2020, 23:48.

                Comment


                  #9
                  Hi,

                  Please let me know if any other input is required from my side. I was expecting a reply on this one.
                  Is there any other information I should provide which would help you in guiding me through this?

                  Thanks

                  Comment


                    #10
                    We've made some changes so that standalone usage would be possible without providing the RequestContext, which will be available in nightly builds since Nov 11 (tomorrow), but you don't have to wait for it. In your case providing valid RequestContext is a proper way. You should call setContext(RequestContext) on all nested requests providing the context of the main request, like this:
                    Code:
                    // schematic
                    nestedRequest.setContext(primaryRequest.getContext());
                    
                    // in your code
                    addRequest.setContext(priceAdjustmentDSRequest.getContext());
                    Let us know please how it worked for you.
                    Last edited by Isomorphic; 10th Nov 2020, 01:05.

                    Comment


                      #11
                      Thanks for the reply.
                      I will try this and will update.

                      Comment


                        #12
                        I made following changes to my code:

                        Code:
                         public DSResponse copyAdjustments(final DSRequest priceAdjustmentDSRequest, final RPCManager rpcManager) throws ApplicationException {
                        
                                log.info("copyAdjustment - Start");
                                final long jobId = jobSQLService.add("CopyAdjustments", BatchJobStatusConstants.IN_PROGRESS);
                        
                                // Process the copy adjustment logic in another thread
                                taskExecutor.execute(() -> {
                                    // boolean value to control whether to mark the job is failed in the finally block
                                    boolean exception = true;
                                    try {
                                        handleCopyAdjusments(priceAdjustmentDSRequest.getContext());
                                        exception = false;
                                    } catch (final ApplicationException e) {
                                        // Handle exceptions, send back the exception as the job note
                                        exception = false;
                                        log.error("Error copying adjustments", e);
                                        jobSQLService.update(jobId, BatchJobStatusConstants.ERROR, e.getMessage());
                                    } finally {
                                        // Mark the job as error if something else went wrong
                                        if (exception) {
                                            jobSQLService.update(jobId, BatchJobStatusConstants.ERROR);
                                        }
                                    }
                                });
                        
                                // Handle all the three lists with PriceAdjustment data in a single transaction
                        
                                hdwStdAdjustmentData.setData(jobId);
                                return hdwStdAdjustmentData;
                        
                            }
                        Then in the handleCopyAdjustment method:

                        Code:
                         handleCopyAdjustment(RequestContext context){
                        DsTransaction dsTransaction = new DSTransaction();
                        List<Object> tobeAddedList = methodFetch1(dsTransaction);
                        
                        if (CollectionUtils.isNotEmpty(toBeAddedList)) {
                                        for (final Map<String, Object> rec : toBeAddedList) {
                                            final DSRequest addRequest = new DSRequest(DSConst.PriceAdjustmentSQL.DATASOURCE, DSOperationType.UPDATE.getValue());
                                            addRequest.setDsTransaction(dsTransaction);
                                            addRequest.setOperationId(DSConst.PriceAdjustmentSQL.ADD_ADJUSTMENT_OPERATION);
                                            addRequest.setValues(rec);
                                            addRequest.setContext(context);
                                            addRequest.execute();
                                        }
                        
                                    }
                        
                        
                        
                        }
                        Still it is giving the same Exception:

                        Caused by: java.lang.Exception: RequestContext is missing the ServletContext. Please ensure you privide either a PageContext, a Servlet, or a ServletContext to your RequestContex.instance() call.
                        at com.isomorphic.rpc.ServerObject.<init>(ServerObject.java:223)
                        at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:236)
                        at com.isomorphic.datasource.DataSourceDMI.execute(DataSourceDMI.java:64)
                        at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:3002)
                        at com.assaabloy.protech.server.services.impl.PriceAdjustmentSQLServiceImpl.addAdjustments(PriceAdjustmentSQLServiceImpl.java:507)
                        ... 14 common frames omitted



                        Please note I have not updated to latest framework nightly build. Shall I do that to make this work?

                        Regards.
                        Last edited by sidharth1917; 11th Nov 2020, 06:38.

                        Comment


                          #13
                          You should not need the latest nightly, but if you did update, it's likely that you will avoid this exception even if you choose not to implement passing the RequestContext around (although that is good for other reasons).

                          As far as trying to further troubleshoot this issue, we would need a standalone test case to look further.

                          Comment


                            #14
                            Hi,
                            I have updated my SmartGWT version to "12.1-p20201111".
                            The code remains the same as I posted in my last reply. Also, I have the context setting in place. With the version change I am now getting the following error:

                            Caused by: java.lang.IllegalStateException: No SessionManager
                            at org.eclipse.jetty.server.Request.getSession(Request.java:1403)
                            at org.eclipse.jetty.server.Request.getSession(Request.java:1378)
                            at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:279)
                            at com.isomorphic.datasource.DSRequest.trackTimings(DSRequest.java:7217)
                            at com.isomorphic.datasource.DSRequest.recordTimingData(DSRequest.java:7232)
                            at com.isomorphic.datasource.DSRequest.recordTimingData(DSRequest.java:7229)
                            at com.isomorphic.datasource.DSRequest.execute(DSRequest.java:2748)
                            at com.YYY.aaa.server.services.impl.XXX.handleCopyAdjusments(XXX.java:1087)
                            Just in case you guys can make out something from this changed exception and suggest why is it not working?
                            Otherwise, I will work on creating a standalone example.

                            Thanks

                            Comment


                              #15
                              We have fixed this problem, which is specific to Jetty. We have also added a server.properties flag - DSRequest.allowReturnTimingData - to allow you to completely switch off timing gathering globally. Please try with tomorrow's build (that dated November 16th) and let us know if you still have problems.

                              Regards,
                              Isomorphic Software Support

                              Comment

                              Working...
                              X