go to post Richard Schilke · Mar 6, 2023 Hi Luis, This is awesome, and just what I was currently engaged with Support about! Talk about good timing... A couple of questions: In your "broadcast" routine, you have the read of the Websocket in IRIS like: Set data= ws.Read(, .status, ) The docs say that the format of that call is: method Read(ByRef len As %Integer = 32656, ByRef sc As %Status, timeout As %Integer = 86400) as %String Won't that mean that if your WebSocket is open (but the user is out to lunch), you will hang for 86400 seconds before returning? Second, do you know what the licensing impact on IRIS is for this? Say there was 100 notification targets,. Would the system take out 100 License Units in this loop? Thanks! Richard
go to post Richard Schilke · Apr 30, 2021 So now, it doesn't look like the request is ever even making it to IRIS. We're using IIS 7 on a Microsoft Server, but I thought the request would be straight mapped to CSPGateway by IIS, but maybe I need to configure IIS not to reject the request as well?
go to post Richard Schilke · Apr 30, 2021 I should also say that my Data Classes are inheriting from AppS.REST.Model.Proxy, and access via Postman works perfectly.
go to post Richard Schilke · Apr 30, 2021 Thanks Matthew! Can you help with how you would enable CORS handling using Apps.REST? I've done a few things, but with not much luck: In AppS.REST>Handler, I added Cors = "true" to each of the <Route> elements in UrlMap, and then added the over-ride ClassMethod OnHandleCorsRequest as well, with the standard default processing: ClassMethod OnHandleCorsRequest(pUrl As %String) As %Status{Do %response.SetHeader("Access-Control-Allow-Origin","*") Do %response.SetHeader("Access-Control-Allow-Credentials","true") Do %response.SetHeader("Access-Control-Allow-Methods","GET, PUT, POST, DELETE, PATCH, OPTIONS") Do %response.SetHeader("Access-Control-Allow-Headers","Access-Control-*, Content-Type, Authorization, Accept, Accept-Language, X-Requested-With, Origin") Quit $$$OK}
go to post Richard Schilke · Apr 30, 2021 Thanks Matthew! Can you help with how you would enable CORS handling using Apps.REST? I've done a few things, but with not much luck: In AppS.REST>Handler, I added Cors = "true" to each of the <Route> elements in UrlMap, and then added the over-ride ClassMethod OnHandleCorsRequest as well, with the standard default processing: ClassMethod OnHandleCorsRequest(pUrl As %String) As %Status{Do %response.SetHeader("Access-Control-Allow-Origin","*") Do %response.SetHeader("Access-Control-Allow-Credentials","true") Do %response.SetHeader("Access-Control-Allow-Methods","GET, PUT, POST, DELETE, PATCH, OPTIONS") Do %response.SetHeader("Access-Control-Allow-Headers","Access-Control-*, Content-Type, Authorization, Accept, Accept-Language, X-Requested-With, Origin") Quit $$$OK}
go to post Richard Schilke · Aug 12, 2020 @Timothy Leavitt - stuck again. I'm in ClassMethod UserInfo, and found out some interesting things. First off, I was wrong about the REST service using the session cookie from the Zen application when it is called from the Zen application. Displaying the %session.SessionId parameters for each call shows that they are all different, and not the same as the SessionId of the Zen application calling the REST service. So the idea that it holds a license for 10 seconds can't be correct, as it seems almost immediate. I run 20 REST calls to different endpoints in a loop, and I saw a single License increase. You said I should be able to expose the session cookie of the Zen application, but I don't see a way to do that either. I can't even find a way to see the header data in the UserInfo ClassMethod of the current REST call. Sorry to be a pest...but since you''re giving answers, I'll keep asking questions! Have a nice evening...
go to post Richard Schilke · Aug 12, 2020 @Timothy Leavitt - thanks so much for the response. The Action worked perfectly with your corrections! I will take your advice and work with the %session/headers in the context object, since that makes the most sense. What are the plans (if any) to enable features in a resultset such as pagination, filters, and sorting? Users are horrible, aren't they? No matter what good work you do, they always want more! I appreciate what you have done here, and it will save my company probably hundreds of hours of work, plus it is very elegant...
go to post Richard Schilke · Aug 12, 2020 @Timothy Leavitt , I will be looking for it. I'm trying to do something with a custom Header that I want to provide for the REST calls. Do I have access to the REST Header somewhere in the service that I can pull the values, like a %request? And in something of an edge case, we're calling these REST services from an existing ZEN application (for now as we start a slow pull away from Zen), so the ZEN app gets a %Session created for it, and then calls the REST service. It seems that Intersystems is managing the License by recognizing that the browser has a session cookie, and it doesn't burn a License for the REST call - that's very nice (but I do have a request in to the WRC about whether that is expected behavior or not so I don't get surprised if it gets "fixed"!). Does that mean your REST service can see that %Session, as that would be very helpful, since we store User/Multi-tenant ID, and other important things in there (the %Session, not the cookie).
go to post Richard Schilke · Aug 12, 2020 @Timothy Leavitt , have you had a chance to see if this error I'm getting on Actions was resolved?
go to post Richard Schilke · Aug 10, 2020 Wow - I think that means I can handle all my Use Cases with that capability. Nice! Thanks again!
go to post Richard Schilke · Aug 10, 2020 I posted an issue with my source to Github. Surfaced another issue this week-end. (I remember when I used to take week-ends off, but no whining!) So I have a multiple linked series of classes in Parent/Child relationships: DocHead->DocItems->DocItemsBOM->DocItemsBOMSerial So if I wanted to express all of this in a JSON object, I would need to make the "Default" mapping the one that exposes all the Child Properties, because it looks like I can't control the Mapping of the Child classes from the Parent class. This doesn't bother me, as I had already written a shell that does this, and your Proxy/Adaptor makes it work even better, but just wanted to check that the Parent can't tell the Child what Proxy the child should use to display its JSON. It's even more complicated than that, as sometimes I want to show DocHead->DocItems (and stop), while, in other Use Cases, I have to show DocHead, DocItems, and DocItemsBOM (and stop), while in other Use Cases, I need the entire stack.
go to post Richard Schilke · Aug 8, 2020 @Timothy Leavitt, I've run into another issue. The proxy is setup and working great for general GET access. But since my system is a multi-tenant, wide open queries are not a thing I can use, so I decided to try to use a defined class Query in the data class Lookups.Terms: Query ContactsForClientID(cClientOID As %String) As %SQLQuery{SELECT * FROM Lookups.TermsWHERE ClientID = :cClientOIDORDER BY TermsCode} Then I setup the Action Mapping in my proxy class RESTProxies.Lookups.Terms.Base: XData ActionMap [ XMLNamespace = "http://www.intersystems.com/apps/rest/action" ]{<actions xmlns="http://www.intersystems.com/apps/rest/action"><action name="byClientID" target="class" method="GET" modelClass="Lookups.Terms" query="Lookups.Terms:ContactsForClientID"><argument name="clientid" target="cClientOID" source="url"/></action></actions>} And I invoked this using this URL in a GET call using Postman (last part only): terms_base/$byClientID?clientid=290 And the result: 406 - Client browser does not accept the MIME type of the requested page. In the request, I verified that both Content-Type and Accept are set to application/json (snip from the Postman): So what have I missed?
go to post Richard Schilke · Aug 8, 2020 That did the trick - thank you so much! Best practice check: When I have a data class (like Data.DocHead) that will need multiple Mappings (Base, Expanded, Reports), then the recommended way is to use the proxy class and have a different proxy class for Data.DocHead for each mapping? For example, RESTProxies.Data.DocHead.Base.cls would be the proxy for the Base mapping in Data.DocHead, while RESTProxies.Data.DocHead.Expanded.cls would be the proxy for the Expanded mapping in Data.DocHead, etc. (the only difference might be the values for the JSONMAPPING and RESOURCENAME prameters)? I'm fine with that, just checking that you don't have some other clever way of doing that...
go to post Richard Schilke · Aug 7, 2020 This is really cool, and we will be using this in a big way. But I have encountered an issue I can't fix. I took one of my data classes (Data.DocHead) and had it inherit from AppS.REST.Model.Adaptor and %JSON.Adaptor, set the RESOURCENAME and other things and tested using Postman and it worked perfectly! Excellent! Due to the need to have multiple endpoints for that class for different use cases, I figured I would set it up using the AppS.REST.Model.Proxy, so I created a new class for the Proxy, removed the inheritance in the data class (left %JSON.Adaptor), deleted the RESOURCENAME and other stuff in the data class. I used the same RESOURCENAME in the proxy that I had used in data class originally. I compiled the proxy class, and get the message: ERROR #5001: Resource 'dochead', media type 'application/json' is already in use by class Data.DocHead > ERROR #5090: An error has occurred while creating projection RestProxies.Data.DocHead:ResourceMap. I've recompiled the entire application with no luck. So there must be a resource defined somewhere that is holding dochead like it was still attached to Data.Dochead via a RESOURCENAME, but that parameter is not in that class anymore. How do I clear that resource so I can use it in the proxy?