Announcement

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

    6.1p RESTHandler issues

    Hi Isomorphic,

    as the more general "How to use the RESTHandler servlet" usage problem is solved, I'll open this thread for RESTHandler bugs.

    I'm using default v11.1p_2017-11-01 BuiltInDS with no changes in FF26 Classic Dev mode with Jetty (to explain how I start the system, this should be server-only).

    1) Just calling "http://127.0.0.1:8888/builtinds/sc/RESTHandler/" gives an exception, where I'd expect an error message instead.
    Code:
    java.lang.Exception: The DataSource ID was missing from the request.
        at com.isomorphic.rpc.RestRequestParser.parseRequest(RestRequestParser.java:565)
    ......
    2)
    http://127.0.0.1:8888/builtinds/sc/R...ler/employees/ is working and fetches the whole DS data
    http://127.0.0.1:8888/builtinds/sc/R...er/employees/4 is also working in browser and gets "Charles Madigen"-data
    The same URL called from ARC in Chromium 62 (Advanced REST client 10.0.8-stable from the Chrome Web store) as GET request gives this error:
    Code:
    There was an error parsing JSON data
    Unexpected token < in JSON at position 0
    3) http://127.0.0.1:8888/builtinds/sc/R...dler/employees sent as POST from ARC (not useful without further data for an ADD-operation, but it shows the problem) gives you:
    Code:
    com.isomorphic.js.parser.TokenMgrError: Lexical error at line 1, column 1.  Encountered: "<" (60), after : ""
                    at com.isomorphic.js.parser.JSParserTokenManager.getNextToken(JSParserTokenManager.java:1554)
                    at com.isomorphic.js.parser.JSParser.jj_ntk_f(JSParser.java:1004)
                    at com.isomorphic.js.parser.JSParser.JSDataStructure(JSParser.java:149)
                    at com.isomorphic.js.parser.JSParser.parseDataStruct(JSParser.java:134)
                    at com.isomorphic.js.parser.JSParser.parseDataStruct(JSParser.java:64)
                    at com.isomorphic.js.JSTranslater.fromJS(JSTranslater.java:2143)
                    at com.isomorphic.js.JSTranslater.fromJS(JSTranslater.java:2131)
                    at com.isomorphic.rpc.RestRequestParser.parseRequest(RestRequestParser.java:268)
                    at com.isomorphic.rpc.RPCManager.<init>(RPCManager.java:392)
                    at com.isomorphic.servlet.RESTHandler.processRequest(RESTHandler.java:511)
                    at com.isomorphic.servlet.RESTHandler.doPost(RESTHandler.java:421)
                    at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
                    at com.isomorphic.servlet.BaseServlet.service(BaseServlet.java:176)
                    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
                    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:686)
                    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1494)
                    at com.isomorphic.servlet.CompressionFilter._doFilter(CompressionFilter.java:247)
                    at com.isomorphic.servlet.BaseFilter.doFilter(BaseFilter.java:93)
                    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1474)
                    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499)
                    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
                    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
                    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
                    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
                    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
                    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
                    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
                    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
                    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
                    at org.eclipse.jetty.server.handler.RequestLogHandler.handle(RequestLogHandler.java:68)
                    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
                    at org.eclipse.jetty.server.Server.handle(Server.java:370)
                    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
                    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:960)
                    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1021)
                    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
                    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
                    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
                    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
                    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
                    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
                    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
                    at java.lang.Thread.run(Unknown Source)
    4) HTTP POST from ARC to http://127.0.0.1:8888/builtinds/sc/RESTHandler with data
    Code:
    <request>
        <dataSource>employees</dataSource>
        <operationType>fetch</operationType>
        <startRow>0</startRow>
        <endRow>75</endRow>
        <textMatchStyle>exact</textMatchStyle>
    </request>
    <request>
        <dataSource>employees</dataSource>
        <operationType>fetch</operationType>
        <startRow>75</startRow>
        <endRow>150</endRow>
        <textMatchStyle>exact</textMatchStyle>
    </request>
    The exception I get is:
    Code:
    com.isomorphic.xml.XMLParsingException: [
           "XML parser fatal error: file '(in memory stream)' line 8: org.xml.sax.SAXParseException; lineNumber: 8; columnNumber: 2; Markup im Dokument nach dem Root-Element muss ordnungsgemäß formatiert sein."
    ]
                    at com.isomorphic.xml.XML.parseXML(XML.java:354)
                    at com.isomorphic.xml.XML.parseRestrictedXML(XML.java:149)
                    at com.isomorphic.xml.XML.toDSRecords(XML.java:497)
                    at com.isomorphic.xml.XML.toDSRecords(XML.java:493)
                    at com.isomorphic.rpc.RestRequestParser.parseRequest(RestRequestParser.java:261)
                    at com.isomorphic.rpc.RPCManager.<init>(RPCManager.java:392)
                    at com.isomorphic.servlet.RESTHandler.processRequest(RESTHandler.java:511)
                    at com.isomorphic.servlet.RESTHandler.doPost(RESTHandler.java:421)
                    at javax.servlet.http.HttpServlet.service(HttpServlet.java:755)
                    at com.isomorphic.servlet.BaseServlet.service(BaseServlet.java:176)
                    at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
                    at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:686)
                    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1494)
                    at com.isomorphic.servlet.CompressionFilter._doFilter(CompressionFilter.java:247)
                    at com.isomorphic.servlet.BaseFilter.doFilter(BaseFilter.java:93)
                    at org.eclipse.jetty.servlet.ServletHandler$CachedChain.doFilter(ServletHandler.java:1474)
                    at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:499)
                    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
                    at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
                    at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
                    at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
                    at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
                    at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
                    at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
                    at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
                    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
                    at org.eclipse.jetty.server.handler.RequestLogHandler.handle(RequestLogHandler.java:68)
                    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
                    at org.eclipse.jetty.server.Server.handle(Server.java:370)
                    at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:489)
                    at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:960)
                    at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1021)
                    at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
                    at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
                    at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
                    at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:668)
                    at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
                    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
                    at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
                    at java.lang.Thread.run(Unknown Source)
    Also, one top enclosing <transaction>...</transaction> does not help and results in a different error.
    Here I'm not sure <transaction> is the correct root element, I might have read that in an older version of the documentation.

    Best regards
    Blama

    #2
    Hi Isomorphic,

    with help from #9 in the old thread I found out that the syntax for multi-request calls is:
    Code:
    <transaction>
        <operations>
            <request>
                <dataSource>employees</dataSource>
                <operationType>fetch</operationType>
                <startRow>0</startRow>
                <endRow>1</endRow>
                <textMatchStyle>exact</textMatchStyle>
            </request>
            <request>
                <dataSource>employees</dataSource>
                <operationType>fetch</operationType>
                <startRow>2</startRow>
                <endRow>3</endRow>
                <textMatchStyle>exact</textMatchStyle>
            </request>
        </operations>
    </transaction>
    With this, issue 4) from #1 is solved. Could you add transaction and operations as top enclosing elements in the docs?

    Best regards
    Blama

    Comment


      #3
      Re #2 and #3 these look like ARC is just sending an invalid request. Let us know if you can show that this is not the case.

      Re #1 we don't really see an issue that this totally invalid usage results in an Exception.

      Comment


        #4
        Re: the docs, RestHandler is documented as handling the RestDataSource format, and the format for multiple requests in a single HTTP request is already well documented, for both XML and JSON, on RestDataSource.

        Comment


          #5
          Hi Isomorphic,

          Originally posted by Isomorphic View Post
          Re: the docs, RestHandler is documented as handling the RestDataSource format, and the format for multiple requests in a single HTTP request is already well documented, for both XML and JSON, on RestDataSource.
          OK, thanks. That also explains how I knew about the format in the first place when creating the old thread. Sometimes it is difficult to keep it all together :) (For others finding the thread via search, these are the clientside RestDataSource docs)

          Please note that these docs issues are still open, though.

          Originally posted by Isomorphic View Post
          Re #1 we don't really see an issue that this totally invalid usage results in an Exception.
          You are right in the sense that it is an very basic error and also easy to see what the error is from the stack trace.
          The reason I bring this up is that in my web application, I can shield the 3rd party end user (=the user of my product) from all nasty DB or server error messages with validators etc.
          This also might not be an issue in SmartGWT Mobile apps, as here the application developer also controls the client side code.

          In an API, which belongs to a web application, I don't have this chance, at least not at this low level. To a 3rd party integration developer (=user of my product), which will use my API, this won't look too good. I'm pretty sure this is true for all non intranet-only applications that will make use of the RestHandler servlet.
          So I guess my point is: "Application end points (GUI for web application, API for application integration) should not display stack traces".

          Originally posted by Isomorphic View Post
          Re #2 and #3 these look like ARC is just sending an invalid request. Let us know if you can show that this is not the case.
          OK, I'll retest this soon and come back if I find something.

          Thank you & Best regards
          Blama

          Comment


            #6
            Again, on the exception for a totally invalid URL - this will be shown to a developer, not an end user. Developers understand exceptions.

            Comment


              #7
              Hi Isomorphic,

              as follow up to #1 and your answer #3:
              #1 2) The error here is that ARC expects JSON data and I did not set
              Code:
                          <init-param>
              [B]               <param-name>wrapJSONResponses</param-name>
                             <param-value>false</param-value>[/B]
                      </init-param>
              Here the <script> header in the RESTHandler answer confuses ARC.

              #1 3) I assume the issue was that I did not remove the data from 4) in the body and this caused the error.

              So right now I don't have any issues here, but one enhancement suggestion I'll show in the next post.
              Regarding #1 1) and the Exception/Error message issue, I'd still think error messages are the better solution, but I'm fine with the way it is as well, because nobody complained so far (to be fair, nobody is using the API as of today :)

              Best regards
              Blama

              Comment


                #8
                Hi Isomorphic,

                the enhancement I have in mind is for the "Expanded Raw REST mode URI Syntax". A combination of "Basic raw REST mode" with it would be good, so that this request is possible:
                Code:
                isomorphic/RESTHandler/<DataSource name>[B][/<operationId>][/B][/<primary key value>]
                Then the same rules you mention in "Basic raw REST mode" should apply:
                HTTP verbs are handled as follows:
                • An HTTP GET performs a fetch, with any query params beyond the primary key interpreted as simple criteria.
                • An HTTP DELETE performs a remove, with any query params or posted data beyond the primary key interpreted as simple criteria.
                • An HTTP POST performs an add, with both query params and posted data providing the record field content.
                • An HTTP PUT or PATCH performs an update, with both query params and posted data providing the record field content. However a PUT with no primary key value(s) performs an add, but a PATCH with no primary value values(s) performs a multi-row update, subject to the currently configured allowMultiUpdate settings for updates on that DataSource.
                If there is no matching operationId for the operationType determined by the HTTP verb, an error should be thrown.

                Please note that these docs issues (a small one regarding "Expanded Raw REST mode URI Syntax") are still open.

                Best regards
                Blama

                Comment


                  #9
                  Hi Isomorphic,

                  motivation for #8 is this:
                  Basically every Application that is more than a showcase will use many operationBinding. If these are not accessible, 3rd party integration developers will quite often need to use the request style from #2 with only the /RESTHandler as URL and all data in the POST body.

                  If they need to use this format anyway most of the time, there is little use in also teaching them about (=documenting this in my API documentation) the other format, that will almost never be used. I hope this idea makes sense.

                  Best regards
                  Blama
                  Last edited by Blama; 30 Dec 2017, 04:12. Reason: Removed grammar errors

                  Comment


                    #10
                    Hi Isomorphic,

                    Originally posted by Isomorphic View Post
                    Again, on the exception for a totally invalid URL - this will be shown to a developer, not an end user. Developers understand exceptions.
                    this was now brought to my attention again by a 3rd party that wanted to test the API.
                    I agree that the information is helpful to a developer, but in general it should be the goal to shield all external parties from exceptions and stack traces and only show error messages, IMHO.
                    If I now configured Tomcat to swallow all exceptions in order to not to tell much about the system in use and to appear more professional, the external developer would not know what went wrong.

                    Best regards
                    Blama

                    Comment


                      #11
                      Hi all,

                      this thread is related.

                      Best regards
                      Blama

                      Comment


                        #12
                        Hi Isomorphic,

                        the HTTP code is 200 in this case. Although minor, I'm pretty sure that this is not correct.

                        Best regards
                        Blama

                        Comment

                        Working...
                        X