Daniel Kutac · Jul 3, 2018 go to post

Thank you Alexander,

I tried to search community for this error but apparently I did not use correct keywords as I could not find previous posts with this very problem.

At least we have a workaround as explained in links you provided.

Dan

Daniel Kutac · Jan 5, 2018 go to post

Evgeny,

are there any plans to port it to Angular2+ ? e.g. connecting to ngx-charts?

Daniel Kutac · Dec 27, 2017 go to post

Soufiane,

supposing you have successfully been able to add the token to your client (this depends on ate respective framework) call for Cache resources (via REST API), then on Cache side, if that's where your data (resources) are sitting, you can use something like this:

set accessToken=##class(%SYS.OAuth2.AccessToken).GetAccessTokenFromRequest(.tSC)  
   // decode token data into JSON object
   $$$THROWONERROR(tSC,##class(%SYS.OAuth2.AccessToken).GetIntrospection($$$APP,accessToken,.jsonObjectAT))
   /* service specific check */
   // check whether the request is asking for proper scope for this service
   if '(jsonObjectAT.scope["special-deals") set reason=..#HTTP404NOTFOUND throw
      
   /* finally */
   // validate signed access token (JWT)
   if '(##class(%SYS.OAuth2.Validation).ValidateJWT($$$APP,accessToken,,,.jsonObjectJWT,.securityParameters,.tSC)) {
    set reason=..#HTTP401UNAUTHORIZED
    $$$ThrowOnError(tSC)
   }
 
perhaps you shall try to look at this post - https://community.intersystems.com/post/angular-client-demo-using-oauth2-authorization-server-protect-caché-based-resources, it also contains a link to the angular based project and contains implementation of sample Cache REST service.
 
Dan
Daniel Kutac · Dec 13, 2017 go to post

I think grant types are not used by he resource server, only by Confidential and Public clients.

Daniel Kutac · Nov 14, 2017 go to post

Soufiane,

briefly, perhaps not 100% correctly - use Google for more details, claims are characteristics provided by OIDC (OpenID Connect) server that describe authenticated user. e.g. Caché by default supports these claims (and more):

preferred_username, email, email_verified, name, phone_number, phone_number_verified, iss, sub, aud, exp, auth_time, ...

claims can be used by the access_token to provide additional information about the user passed to the resource server when calling REST method. Some claims are mandatory, some are optional. You can provide optional claims by the SetClaimValue() method.

Dan

Daniel Kutac · Oct 30, 2017 go to post

Evgeny, consider using OAuth2 with OpenID Connect as the first choice.

Dan

Daniel Kutac · Oct 12, 2017 go to post

Hi Praveen,

this is not going to be an exhausting answer but rather a summary of choices you have.

First thing to answer: are you working with a legacy application, that stored data in globals, not using our Cache persistent classes? In this case, you would like to follow Sean's globals to classes mapping guide.

Another option, suitable in cases where you have a mix of persistent classes and only some data stored directly in globals, you may consider using custom SQL queries. In such query you implement code that iterates over your global nodes and expose result as SQL resultset. You can then call query as a standard stored procedure. see Cache online reference for mode details here.

There is one more option too, which could be used in some special cases when global is a simple structure. In such case you could create a new persistent class definition and simply override the storage generated during its compilation to reflect your global structure. This is less flexible than using SQL mapping mentioned as first choice, but could be easier for you.

HTH

Daniel Kutac · Sep 20, 2017 go to post

there is an easy solution to your issue. Simply use a Cache Task Manager. Create a new task, and within code, instantiate Ensemble service Ens.Director,

e.g.

Set tSC=##class(Ens.Director).CreateBusinessService("your service configration name",.tService)

If ($$$ISERR(tSC)) Quit
Set tSC=tService.ProcessInput(%request,.output)
If ($$$ISERR(tSC)) Quit
If $IsObject($G(output)) {

   // do whatever you want here

}

Daniel Kutac · Aug 3, 2017 go to post

Thanks Alexander,

this seems promising. It works well for Year / MonthYear hierarchy, not working for Year/MonthNumber which I was using. My original hierarchy levels setup allowed me for easy year to year comparison of values for a given month.

Daniel Kutac · Jul 18, 2017 go to post

Noone would give you exact numbers. It really depends on your use case.

However, adding 200 properties to an Ensemble message (not considering other classes as you pass just messages) may either simp0ly mean that you add 200 properties to ONE class or to MANY classes, depending how clever the original design of your production was.

You may, or with the same probability many not, need to change the message design and switch to virtual documents ... it really depends on many factors unique to your particular use case - throughput expected, load of data incoming etc etc... 

Daniel Kutac · Jul 18, 2017 go to post

Use your own custom Projection, put it into your primary class, it runs every time you compile your primary class, in the code you can do whatever you want, e.g. compile other classes.

Daniel Kutac · Jul 14, 2017 go to post

Jose, $lb() holds STORED values of you object instance. If your opened instance modified property(ies) then I see no point of looking into stored data, just serialize you IN-MEMORY values to JSON.

On the other hand, if a process A opened and modified instance of the object and without saving and you want to serialize the same instance from process B, then again, there is no difference between opening an object instance or using some custom serialization directly from stored data.

It is not good practice anyway to keep objects opened for a long time without saving their new values.

lastly, my comment about JSON array was that JSON array doesn't need to know the name in the name:value pair so you can easily write a custom JSON serializer to serialize directly $lb() into JSON array.

 

 

maybe I missed your original business case need, can you explain why current implementation is not good enough for you?

Daniel Kutac · Jul 14, 2017 go to post

Jose,

how would you determine names of properties / keys for a JSON name:value pairs without opening an object instance or retrieving those names from somewhere else?

or are you happy to express it as JSON ARRAY ?

Daniel Kutac · Jul 12, 2017 go to post

I work with Cache for decades and never knew about ExtentFunc(). There is always something to learn...

Mike, in Studio use Show Other View to display the generated INT code for the Sample. Employee class. You'll find the ExtentFunc() there. You may need to compile the Sample.Employee class first to re-generate the INT code.

Daniel Kutac · May 30, 2017 go to post

Safeena,

you do not invoke web methods directly. You need to create a client class by consuming a WSDL file that your service exposes. There is a wizard that guides you through the process of client creation. Apart to client class itself the wizard also generates all data types used by a web service. Please consult documentation here.

There are some other option when using Ensemble but I suggest you follow the link above.

Daniel Kutac · May 22, 2017 go to post

what benchmark? populating the data or retrieving populated data? I think the speed of data population is not that important, comparing the standard populate or cos faker. What would be important is ability of the tool to mimic real data at maximum possible extent (e.g. values distribution).

Daniel Kutac · May 17, 2017 go to post

Oh, now I see. I'm using Microsoft Edge as default browser and it displays them OK. Chrome is the troublemaker.

I'll see what can I do to fix it.

Daniel Kutac · May 11, 2017 go to post

Lasse, can you be more specific please? I'll be happy to add more information, but I need to know what are you missing.

Thank you!

Daniel Kutac · Mar 15, 2017 go to post

Thomas,

Hope I understood your question correctly, if not then let me know.

In general, when dealing with XML VDoc documents (files), you need to create a production that uses services based on

EnsLib.EDI.XML.Service.FileService, operations based on EnsLib.EDI.XML.Operation.FileOperation and a routing process - EnsLib.MsgRouter.VDocRoutingEngine. There is no need to do any coding, just supply parameters in the production diagram.

You may need to provide DocSchemaCategory setting for a service, for this, you need to import the XML Schema, using Import button at Ensemble->Interopeate->XML->XML Schema Structures page.

for actual routing, you need to design a rule, and supply path to the document element/attribute that's used to decide where the rule sends document to. I prefer using XPATH expressions for this.

An example of routing rule contents is here:

<ruleDefinition alias="" context="EnsLib.MsgRouter.VDocRoutingEngine" production="tzp.dasta.router.Production">
<ruleSet name="" effectiveBegin="" effectiveEnd="">
<trace value="Document.{/dasta/is/ip/lo/loi/@material}"></trace>
<rule name="">
<constraint name="source" value="Dasta3Zadanka"></constraint>
<constraint name="msgClass" value="EnsLib.EDI.XML.Document"></constraint>
<constraint name="docCategory" value="ds030101"></constraint>
<when condition="Document.{/dasta/is/ip/lo/loi/@material}=&quot;B&quot;">
<send transform="" target="Dasta3Biochemie"></send>
<return></return>
</when>
<otherwise>
<send transform="" target="Dasta3Mikrobiologie"></send>
<return></return>
</otherwise>
</rule>
</ruleSet>
</ruleDefinition>

You can create a VDOC document from a persistent (any, not only persistent) object, as long as it extends also from %XML.Adaptor. First, you serialize your object instance to XML stream or string, and then using ImportFromString/ImportFromLibraryStream (or other - see online reference for EnsLib.EDI.XML.Document class) method you instantiate a VDoc document.

HTH.

Dan

Daniel Kutac · Mar 6, 2017 go to post

May others find it useful:

I created a small dummy java class that implements public static String evaluate() method (with 1 to 5 arguments for my needs), compiled it and made a jar file.

replaced original references to java:com.intersys.xsltgateway.XSLTGateway by my faked ones (Atelier refactor, easy...) in all used XSL stylesheets.

Then I supplied this dummy jar file into a list of external JAR files to the OrangeVolt XSL run configuration. It all worked fine and I eventually received transformed document (with dummy data in places of original isc:evaluate calls).

Just need to remember to put back pointer to original callback handler class before deploying transformation to Cache server.

Daniel Kutac · Mar 3, 2017 go to post

Thank you all for replies,

a few clarifications:

1. I can run the transformation from Cache, using %XML.XSLT2.Tranformer class (and supplying an instance of Cache callback class), this works fine.

2. when there are no isc:evaluate callbacks in the XSL stylesheet, then Atelier runs transformation fine, too.

So, Jamie is right.

PS: this is not an important issue, but I was looking forward to see Eclipse's user friendly debugger in action. But I can live with that limitation, understanding why it is so.

Daniel Kutac · Feb 27, 2017 go to post

hmm, I see...

in that case, can the procedure of creating index be more automated? You know I'm a lazy programmer :)

Daniel Kutac · Feb 27, 2017 go to post

Michael,

wouldn't it be enough just to define datatype that has Getter and Setter methods implemented that perform the encryption/decryption on the fly and transparently for you?

Dan

Daniel Kutac · Jan 19, 2017 go to post

Istvan, what if I have a habit of putting all XSL stylesheets into XDATA blocks?

Daniel Kutac · Dec 27, 2016 go to post

Excellent job!

it took me a little while, though, to figure out all dependencies, namely PYTHON that was not mentioned in the github instructions and fresh enough node.js.

But now everything works as expected now.

One wish: please add a button that would navigate back to the System Management Portal or open the dashboard in a new tab/window.