Announcement

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

  • How to subclass RESTHandler, process requests and return error messages to API users?

    Hi Isomorphic,

    weeks becoming 1.5 years, but I finally started with my RESTHandler-subclass, hitting some roadblocks (using latest 6.1p).
    I had a look at your RESTHandler.processRequest() implementation.
    For now, I was using a request like in the example, but amended two fields:
    Code:
    <request>
       <userName>myUsername</userName>
        <userToken>1111111111111111111111111111111111111111</userToken>
       <dataSource>T_ROLE</dataSource>
        <operationType>fetch</operationType>
        <startRow>0</startRow>
        <endRow>2</endRow>
        <textMatchStyle>exact</textMatchStyle>
    </request>
    I did @override handleDSRequest() and checked the username and token there, then did setUserId() and setUserRoles() on the RPCManager.
    Here the first problem arises:
    If the user does not exists, the token does not match, etc... I return new DSResponse.setFailure("Some useful errormessage").

    handleDSRequest() is called by your processRequest()-implementation for every request in the call.
    Returning setFailure() makes the processRequest() stop the transactions and returns only -1 or -10 as status and no status message.
    Code:
    <?xml version="1.0" ?>
    <response>
      <status>-1</status>
      <queueStatus>-1</queueStatus>
    </response>
    While I realize that I probably should do the check on the user not in the request, but before though querystring parameters, I do have some problems here, the biggest being "How do I show an error message to the developer using my API". Is it correct that the message from DSResponse.setFailure("Some useful message") is not displayed in the response sent to the browser?

    If I do the users check not in handleDSRequest(), but before in processRequest() or even doPost(), how do I set username and roles?
    If a request fails because of declarative security (e.g. missing role), how do I display this error message?
    I think I know this problem from the normal application and IDACall, where the error messages for queues (not single requests!) are also not displayed, but I might be wrong here.

    Do you suggest overriding handleDSRequest() or processRequest()? I'd very much prefer handleDSRequest(), if I can solve the issues above.

    Also I had a look at your processRequest() implementation (using JD Eclipse) and tried to @override it with just the same code in my Subclass. This fails, as many needed constants are private and not protected. Is this correct?
    Do you have the same minimal override-pseudocode processRequest() you offer for IDACall here in the docs?

    It are many questions, but aggregated as 1st pointers these would suffice:
    1. Is it OK that error messages from setFailure() are not displayed. If so, how to communicate to the API-user?
    2. @Override handleDSRequest() or processRequest()?
    3. If override processRequest(), how exactly? Perhaps you can add pseudocode for this in the docs like you do for IDACall.
    Thank you & Best regards
    Blama

  • #2
    We are considering some improvements in this area to make subclassing RESTHandler more straightforward and easy to understand. We will post back here in the next couple of days.

    Regards,
    Isomorphic Software Support

    Comment


    • #3
      Hi Isomorphic,

      that is great to hear! Will this also cover the error-message topic?

      Thanks a lot,
      Blama

      Comment


      • #4
        Hi Isomorphic,

        this will go into 6.1p, correct?

        Best regards
        Blama

        Comment


        • #5
          Yes, it will go back to 6.1p. The issue with failure messages not being sent back to the client appears to be a bug that only affects the XML format, so, yes, we will be addressing that as well

          Comment


          • #6
            We have now committed these changes on our main development branch and on 6.1. The correct override point for subclasses is now processRestTransaction() - in your case, this would be the appropriate place to set user roles before invoking the super impl to process the requests. We have also fixed the main problem raised in your original post, so messages applied via DSResponse.setFailure(), or simply by throwing an Exception during processing, will now be returned to the client as "data" for REST requests using the XML dataFormat (this was already happening for JSON format).

            Fixes will be in today's (27th October) builds.

            Comment


            • #7
              Originally posted by Isomorphic View Post
              The correct override point for subclasses is now processRestTransaction() - in your case, this would be the appropriate place to set user roles before invoking the super impl to process the requests.
              Hello, I've got an old implementation where I do this via an override of handleDSRequest. Will it still work?

              Comment


              • #8
                This should continue to work, yes, but you should migrate to the new API as soon as you upgrade.

                Comment


                • #9
                  Hi Isomorphic,

                  testing with today's 6.1p I had some severe problems in this area. I saw that the RestHandler docs are updated, so I'm sure I use the new version.
                  I did not see processRestTransaction() in there, neither as override, nor as public method. Therefore, it it also not javadoc'd.

                  Writing these lines I see that the method is indeed in the 7.0d docs. Were the changes just not included in time for today's 6.1p?

                  I also tried the new syntax against 6.1p, please see this request and the whole list of missing libs - even some googlemail libs. I'm pretty sure something is still wrong here:
                  Code:
                  === 2017-10-27 15:18:56,174 [c-12] DEBUG LMSRESTHandler - Wrapping json responses:true
                  === 2017-10-27 15:18:56,175 [c-12] DEBUG LMSRESTHandler - json prefix:null
                  === 2017-10-27 15:18:56,175 [c-12] DEBUG LMSRESTHandler - json suffix:null
                  === 2017-10-27 15:18:56,175 [c-12] DEBUG LMSRESTHandler - Default response data format:null
                  === 2017-10-27 15:18:56,175 [c-12] DEBUG LMSRESTHandler - Raw REST hybridMode default:false
                  === 2017-10-27 15:18:56,195 [c-12] INFO  RequestContext - URL: '/lms/RESTHandler/T_CAPABILITY/fetch', User-Agent: 'null': Unsupported WITHOUT Accept-Encoding header
                  === 2017-10-27 15:18:56,195 [c-12] DEBUG LMSRESTHandler - Defaulting response data format to json
                  === 2017-10-27 15:18:56,207 [c-12] DEBUG RestRequestParser - Parsing json object: '<transaction>
                   <operations>
                      <request>
                           <userName>Administrator</userName>
                        <userToken>mytoken</userToken>
                           <dataSource>T_CAPABILITY</dataSource>
                           <operationType>fetch</operationType>
                           <startRow>0</startRow>
                           <endRow>2</endRow>
                       </request>
                       <request>
                           <userName>Administrator</userName>
                        <userToken>mytoken</userToken>
                           <dataSource>T_ROLE</dataSource>
                           <operationType>fetch</operationType>
                           <startRow>0</startRow>
                           <endRow>2</endRow>
                       </request>
                          </operations>
                    </transaction>'
                  === 2017-10-27 15:18:56,208 [c-12] ERROR InterfaceProvider - Unable to instantiate class 'com.isomorphic.js.parser.JSParser' - check to make sure you have isomorphic_js_parser.jar (and its dependencies: isomorphic_core_rpc.jar, devenv/google-oauth-client-jetty-1.22.0.jar, devenv/jackson-databind-2.8.5.jar, commons-jxpath-1.3.jar, commons-pool-1.6.jar, slf4j-api-1.7.12.jar, devenv/google-http-client-jackson2-1.22.0.jar, commons-lang-2.6.jar, devenv/google-api-services-gmail-v1-rev44-1.22.0.jar, commons-vfs2-2.1.jar, poi-ooxml-schemas-3.17.jar, commons-io-2.5.jar, groovy-sql-2.4.12.jar, devenv/google-api-client-1.22.0.jar, activation.jar, commons-cli-1.4.jar, log4j-1.2.17.jar, commons-collections-3.2.2.jar, xmlbeans-2.6.0.jar, httpclient-4.5.3.jar, velocity-1.7.jar, devenv/jjwt-0.7.0.jar, groovy-jsr223-2.4.12.jar, devenv/jackson-annotations-2.8.0.jar, poi-3.17.jar, commons-collections4-4.1.jar, devenv/jackson-core-2.8.1.jar, hibernate-validator-4.1.0.Final.jar, mail.jar, javax.persistence.jar, commons-codec-1.10.jar, groovy-2.4.12.jar, commons-fileupload-1.3.3.jar, devenv/google-oauth-client-1.22.0.jar, joda-time-2.9.9.jar, httpcore-4.4.6.jar, poi-ooxml-3.17.jar, validation-api-1.0.0.GA.jar, devenv/google-http-client-1.22.0.jar, devenv/google-oauth-client-java6-1.22.0.jar) in your CLASSPATH
                  === 2017-10-27 15:18:56,208 [c-12] ERROR JSTranslater - parse failure: 
                  java.lang.ClassNotFoundException: com.isomorphic.js.parser.JSParser
                  Best regards
                  Blama

                  Comment


                  • #10
                    Yes, sorry, the changes did not make today's 6.1p. Please try with tomorrow's build.

                    Comment


                    • #11
                      Hi Isomorphic,

                      thank you, generally speaking, it is working now. I'm using processRestTransaction() to check for queryString parameters (username, apiToken) and handleDSRequest() to check for operationId presence and an (added) attribute apiAllowed, that marks an operationBinding as accessible via the API.

                      But I do have some problems left. With no further settings isomorphic/RESTHandler/<DataSource name>/id does not work for me and results in the exception I showed in #9, also with all those listed dependencies.
                      Right now, it works for me when using just isomorphic/RESTHandler and all data in the POST-Data.
                      The more easy URL scheme is not really working, yet, IMHO.
                      Also, a wrong (=none existing) DataSource name does result in a hard exception and not in an error message.

                      As feedback to the docs:
                      "acecpts" - typo.

                      Expanded Raw REST mode URI Syntax

                      In addition to the URI syntax discussed above, raw REST mode also acecpts HTTP requests with the syntax:
                      isomorphic/RESTHandler/<operation>[/<operation ID>]
                      I think this is missing the DataSource ID in the URL path.

                      Best regards
                      Blama
                      Last edited by Blama; 2nd Nov 2017, 09:04.

                      Comment


                      • #12
                        Hi Isomorphic,

                        as the general "How to subclass RESTHandler problem is solved", I started a new thread for the issue/exception I get here.

                        I do get error messages for failures sent from new DSResponse.setFailure(String) from handleDSRequest() now.

                        Thank you & Best regards
                        Blama

                        Comment


                        • #13
                          Hi Isomorphic,

                          regarding #11 I can see that you fixed the typo, but did not add the DataSource ID. Are the docs correct the way they are?

                          Best regards
                          Blama

                          Comment


                          • #14
                            We have corrected the URL path in the docs.

                            Regards
                            Isomorphic Software

                            Comment

                            Working...
                            X