Announcement

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

    Using HttpServletRequest in child DSRequests w/o RPCManager(=Standalone) in 5.1p

    Hi Isomorphic,

    I'm using recent 5.1p. Currently I'm building a standalone servlet (to be hit by a wget cronjob).
    This works nicely so far. Now I have a child-DSRequest I spawn in the servlet.
    This request hits an already existing DataSource/OperationId with existing DMI code.
    This DMI code does checks on session variables, but my servletRequest is always null and therefore the checks on servletRequest.getSession().getAttribute() don't work.

    My question is how to transfer the servletRequest I get from
    Code:
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {...}
    to sub-Requests I initiate.
    Code:
    mySubRequest.setRequestContext(new RequestContext(this, request, response));
    did not work (and is undocumented).
    Is there some way to do this in standalone usage? Perhaps create a RPCManager in the servlet?

    Thank you & Best regards
    Blama

    #2
    Hello Blama,

    Internally, when a DSRequest is executed for a DMI the request context on that DSRequest will be passed over to the DMI DataSource and the request, response and servletRequest on there will then be used in the DMI method invocation. Setting the RequestContext on the DSRequest before execution should be enough in order to pass the servlet request over to the DMI method.

    The RequestContext has a couple of static methods available in order to create a RequestContext instance, see RequestContext.instance()

    Have you verified that the httpServletRequest.getSession().getAttribute() works fine in the servlet itself?

    Could you prove the full code for a small test case please?

    Comment


      #3
      Hi Isomorpic,

      I did not try with the instance()-method, but with new and an undocumented constructor. I'll retry tomorrow with the instance()-method.
      Please note that DSRequest.setRequestContext() is not documented - is it safe to use it?

      Best regards
      Blama

      Comment


        #4
        DSRequest.setRequestContext() is safe to use for now. We will look into having it documented.

        We've produced a quick test case which successfully manages to pass the HttpServletRequest to the DMI class/method as an argument. In order to proceed we need to see all of your source code or a simple test case which is failing. Also could you verify that the httpServletRequest is available in the servlet itself. Could this be an issue related to the servlet container you are using?

        Comment


          #5
          Hi Isomorphic,

          I can confirm that the objects in question are available after using DSRequest.setRequestContext(RequestContext.instance()).

          See this example:

          web.xml:
          Code:
              <servlet>
                  <servlet-name>AddToSupplyItemServlet</servlet-name>
                  <servlet-class>com.smartgwt.sample.server.listener.AddToSupplyItemServlet</servlet-class>
              </servlet>
              <servlet-mapping>
                  <servlet-name>AddToSupplyItemServlet</servlet-name>
                  <url-pattern>/AddToSupplyItemServlet</url-pattern>
              </servlet-mapping>
          log4j.isc.config.xml (might be a good addition to the BuiltInDS sample as well in order not to clutter the server log):
          Code:
              <category name="com.isomorphic.datasource.PoolableDataSourceFactory">
                <priority value="INFO" />
              </category>
          
              <category name="com.isomorphic.pool.ISCKeyedObjectPool">
                <priority value="INFO" />
              </category>
              
              <category name="com.isomorphic.sql.SQLDataSource">
                <priority value="INFO" />
              </category>


          supplyItem.ds.xml:
          Code:
              <serverObject lookupStyle="new" className="com.smartgwt.sample.server.listener.SupplyItem" />
              <operationBindings>
                      <operationBinding operationType="fetch" operationId="myFetch" serverMethod="myFetchMethod" />
                      <operationBinding operationType="add" operationId="myAdd" serverMethod="myAddMethod" />
              </operationBindings>


          AddToSupplyItemServlet.java:
          Code:
          package com.smartgwt.sample.server.listener;
          
          import java.io.IOException;
          import java.util.HashMap;
          import java.util.LinkedHashMap;
          
          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          
          import com.isomorphic.datasource.DSRequest;
          import com.isomorphic.datasource.DSResponse;
          import com.isomorphic.datasource.DataSource;
          import com.isomorphic.log.Logger;
          import com.isomorphic.servlet.RequestContext;
          
          public class AddToSupplyItemServlet extends HttpServlet {
              private static final long serialVersionUID = -536025913450167992L;
          
              @Override
              public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  try {
                      addData(request, response);
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
          
              @Override
              public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  doGet(request, response);
              }
          
              private void addData(HttpServletRequest request, HttpServletResponse response) throws Exception {
                  Logger l = new Logger(com.isomorphic.sql.SQLDataSource.class);
                  if (request.getSession() == null)
                      l.warning("addData: request.getSession() Is Null");
                  else
                      l.warning("addData: request.getSession() Is Not Null");
          
                  DSRequest dsRequest = new DSRequest("supplyItem", DataSource.OP_ADD);
                  dsRequest.setOperationId("myAdd");
          
                  HashMap<String, Object> valueMap = new LinkedHashMap<String, Object>();
                  valueMap.put("itemName", "New");
                  valueMap.put("SKU", "2");
                  valueMap.put("category", "cat2");
                  valueMap.put("unitCost", 2);
                  dsRequest.setValues(valueMap);
          
                  dsRequest.setRequestContext(RequestContext.instance(request, response));
                  DSResponse dsResponse = dsRequest.execute();
          
                  if (dsResponse.statusIsSuccess()) {
                      l.warning("AddToSupplyItemServlet: IS SUCCESS");
                  } else
                      l.warning("AddToSupplyItemServlet: IS ERROR");
              }
          };


          SupplyItem.java:
          Code:
          package com.smartgwt.sample.server.listener;
          
          import javax.servlet.http.HttpServletRequest;
          
          import com.isomorphic.datasource.DSRequest;
          import com.isomorphic.datasource.DSResponse;
          import com.isomorphic.log.Logger;
          
          public class SupplyItem {
          
              public DSResponse myAddMethod(DSRequest request, HttpServletRequest servletRequest) throws Exception {
                  Logger l = new Logger(com.isomorphic.sql.SQLDataSource.class);
          
                  if (request == null)
                      l.warning("myAddMethod: request Is Null");
                  else
                      l.warning("myAddMethod: request Is Not Null");
          
                  if (servletRequest == null)
                      l.warning("myAddMethod: servletRequest Is Null");
                  else {
                      l.warning("myAddMethod: servletRequest Is Not Null");
                      if (servletRequest.getSession() == null)
                          l.warning("myAddMethod: servletRequest.getSession() Is Null");
                      else
                          l.warning("myAddMethod: servletRequest.getSession() Is Not Null");
                  }
          
                  return request.execute();
              }
          
              public DSResponse myFetchMethod(DSRequest request, HttpServletRequest servletRequest) throws Exception {
                  return request.execute();
              }
          }


          Resulting log:
          Code:
           INFO  RequestContext - URL: '/AddToSupplyItemServlet', User-Agent: 'Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36': Safari with Accept-Encoding header
           WARN  SQLDataSource - addData: request.getSession() Is Not Null
           DEBUG DSRequest - Caching instance 14 of DS 'supplyItem' from DSRequest.getDataSource()
           DEBUG DSRequest - Caching instance 14 of DS supplyItem
           DEBUG DeclarativeSecurity - Processing security checks for DataSource null, field null
           DEBUG DeclarativeSecurity - Request is not a client request, ignoring security checks.
           DEBUG ConfigParser - Matched var name: webRoot //ONLY THERE WITH setRequestContext
           DEBUG ConfigParser - value after substitution: C:\Users\myuser\workspace\lib\smartgwtpower-5.1p\samples\built-in-ds\war/WEB-INF/applicationContext.xml //ONLY THERE WITH setRequestContext
           WARN  SQLDataSource - myAddMethod: request Is Not Null
           WARN  SQLDataSource - myAddMethod: servletRequest Is Not Null
           WARN  SQLDataSource - myAddMethod: servletRequest.getSession() Is Not Null
           DEBUG DeclarativeSecurity - Processing security checks for DataSource null, field null
           DEBUG DeclarativeSecurity - Request is not a client request, ignoring security checks.
           DEBUG AppBase - [builtinApplication.myAdd] No userTypes defined, allowing anyone access to all operations for this application
           DEBUG AppBase - [builtinApplication.myAdd] No public zero-argument method named '_myAdd' found, performing generic datasource operation
           INFO  SQLDataSource - [builtinApplication.myAdd] Performing add operation with
              criteria: {itemName:"New",SKU:"2",category:"cat2",unitCost:2}    values: {itemName:"New",SKU:"2",category:"cat2",unitCost:2.0}
           DEBUG SQLValuesClause - [builtinApplication.myAdd] Sequences: {itemID=__default}
           INFO  SQLDriver - [builtinApplication.myAdd] DSRequest has no DSTransaction set, when testing if we should join a transaction - transaction will not be joined
           DEBUG PoolableSQLConnectionFactory - [builtinApplication.myAdd] DriverManager fetching connection for HSQLDB via jdbc url jdbc:hsqldb:hsql://localhost/isomorphic
           DEBUG PoolableSQLConnectionFactory - [builtinApplication.myAdd] Passing JDBC URL only to getConnection
           DEBUG PoolableSQLConnectionFactory - [builtinApplication.myAdd] makeObject() created an unpooled Connection '1206484780'
           DEBUG SQLConnectionManager - [builtinApplication.myAdd] Borrowed connection '1206484780'
           INFO  SQLDriver - [builtinApplication.myAdd] Executing SQL query on 'HSQLDB' using connection '1206484780': INSERT INTO supplyItem (SKU, category, itemName, unitCost, itemID) VALUES ('2', 'cat2', 'New', 2.0, null)
           DEBUG SQLDriver - [builtinApplication.myAdd] SequenceMode is not JDBC_DRIVER, skipping search for generated values
           DEBUG HSQLDBDriver - [builtinApplication.myAdd] fetchLastRow data - primaryKeysPresent: {}sequencesNotPresent: [itemID]
           INFO  SQLDriver - [builtinApplication.myAdd] Executing SQL query on 'HSQLDB' using connection '1206484780': CALL IDENTITY()
           INFO  SQLDataSource - [builtinApplication.myAdd] primaryKeys: {itemID=3966}
           DEBUG DeclarativeSecurity - [builtinApplication.myAdd] Processing security checks for DataSource null, field null
           DEBUG DeclarativeSecurity - [builtinApplication.myAdd] Request is not a client request, ignoring security checks.
           DEBUG ServerObject - [builtinApplication.myAdd] Couldn't find a public method named: fetch on class: com.smartgwt.sample.server.listener.SupplyItem
           DEBUG DataSourceDMI - [builtinApplication.myAdd] DataSourceDMI: no public method name: fetch available on class: com.smartgwt.sample.server.listener.SupplyItem - defaulting to builtin operations.
           DEBUG AppBase - [builtinApplication.myAdd, builtinApplication.null] No userTypes defined, allowing anyone access to all operations for this application
           DEBUG AppBase - [builtinApplication.myAdd, builtinApplication.null] No public zero-argument method named '_null' found, performing generic datasource operation
           INFO  SQLDataSource - [builtinApplication.myAdd, builtinApplication.null] Performing fetch operation with
              criteria: {itemID:3966}    values: {itemID:3966}
           INFO  SQLDataSource - [builtinApplication.myAdd, builtinApplication.null] derived query: SELECT $defaultSelectClause FROM $defaultTableClause WHERE $defaultWhereClause
           INFO  SQLDriver - [builtinApplication.myAdd, builtinApplication.null] Executing SQL query on 'HSQLDB' using connection '1206484780': SELECT COUNT(*) FROM supplyItem WHERE (supplyItem.itemID=3966)
           INFO  DSResponse - [builtinApplication.myAdd] DSResponse: List with 1 items
           DEBUG DSRequest - [builtinApplication.myAdd] About to free up resources for request of type fetch on DataSource supplyItem
           DEBUG DSRequest - [builtinApplication.myAdd] Ignoring freeResources call because this is not a primary request!
           DEBUG DSRequest - [builtinApplication.myAdd] Ignoring freeQueueResources call because this is not a primary request!
           INFO  DSResponse - DSResponse: List with 1 items
           DEBUG DSRequest - About to free up resources for request of type add on DataSource supplyItem
           DEBUG SQLDriver - Freeing SQLDriver dbConnection 1206484780 for SQLDriver instance 987890179
           DEBUG SQLConnectionManager - About to close JDBCConnection with hashcode "1206484780"
           INFO  DSResponse - DSResponse: List with 1 items
           DEBUG DSRequest - About to free up resources for request of type add on DataSource supplyItem
           DEBUG DSRequest - Ignoring freeResources call because they have already been freed
           DEBUG DSRequest - Ignoring freeQueueResources call because they have already been freed
           WARN  SQLDataSource - AddToSupplyItemServlet: IS SUCCESS
          As you can see I used the undocumented RequestContext.instance(request, response). Is it safe to use this as well? Do you suggest to use another overload - the currently doc'd methods ("for JSP", "for Servlets/Filters") don't match my use case.
          FYI: DSRequest.setRequestContext is still undocumented.

          Is this only needed for session or also in other cases a suggested best practice in DataSource standalone usage?
          Please note the italic lines (DEBUG ConfigParser) in the log. These are only there when using setRequestContext(). Is this expected?

          Best regards
          Blama

          Comment


            #6
            Glad you got it working. We've now added documentation surrounding these classes and more specifically RequestContext.instance() and when to use it.

            In regards to the ConfigParser logging, that looks normal as there will be a slightly different code path executed where there is a RequestContext available on the request.

            Comment


              #7
              Hi Isomorphic,

              I'm a bit confused about your post#4.
              It is documented in 5.1p, but not in 6.0p. Additionally, Eclipse shows both DSRequest.setRequestContext() and DSRequest.getRequestContext() as deprecated using 6.0p (v11.0p_2016-09-27) vs 5.1p (v10.1p_2016-09-27).

              Could you explain what to do here?

              Thank you & Best regards
              Blama

              Comment


                #8
                Hi Isomorphic,

                could you please have a look at this?

                Thank you & Best regards
                Blama

                Comment


                  #9
                  We're still looking at the APIs and whether this API removal happened due to a merge problem or was an intended change.

                  Comment


                    #10
                    The correct APIs to use are DSRequest.getContext() and DSRequest.setContext(), as it is now in 6.0+ versions. We will update the javadoc for 5.1 as well.

                    Comment


                      #11
                      Hi Isomorphic,

                      thanks for clarifying. I changed my code accordingly and it is working as before.

                      Thank you & Best regards
                      Blama

                      Comment

                      Working...
                      X