Herman Slagman · Oct 5, 2017 go to post

Recently we've found out that Cache is getting stricter with regards to it's TCP licensing.

To be recognized as a SOAP message, it needs to have a SOAPACTION header and proper SOAP Envelopes.

After we had fixed that, license consumption went back to normal.

HTH

Herman Slagman · Sep 18, 2017 go to post

What version of Cache are you running ?

We had a similar issue with %Open, it was a bug:

there was a leak in $ZE variable, which was fixed by change DLP3616 - Object Storage - 
complete object initialization when %LoadData fails. The change now reset $ZE="" on start 
of %LoadData method.
2016.2.1 (Build 803_0_16949U)

Maybe it is related

Herman Slagman · Sep 8, 2017 go to post

> But with same reasoning you may ask why is Java, JavaScript  or C, C# not changed?

Java, C# and JavaScript have major new features every two to three years

I'm not talking about taking away old features, but adding new ones.

A major overhaul of Cache (Mumps) was when Objects, ProcedureBlocks and the $List were introduced, that didn't break anything.

Adding native JSON support was also very important.

Herman Slagman · Sep 7, 2017 go to post

While I find your initiative very praiseworthy, it's a shame ISC doesn't do anything anymore at COS.

There could be a lot of modernization/expansion on the language itself (your declarative efforts), but also on the object level (Design by Contract to name one) but also on the level of protocols (GRPC, MQTT, GraphQL)

Herman Slagman · Jul 12, 2017 go to post

..Method can be a instance method as well as a class method within the context of an instance, that's the syntax.

An instance method needs the instance (object) it belongs to, if you would like to 'job' that to another process, then in some way the object would need go go along with that (aka Beam Me Up Scotty ;-)) and that's not supported by Cache'.

If you have an instance method in your class that doesn't need the instance, you probably want to change that to a class method.

Herman Slagman · Jul 11, 2017 go to post
Do ##class(%Dictionary.ClassDefinition).%DeleteId("Test.Class")Set ClassDef=##class(%Dictionary.ClassDefinition).%New()Set ClassDef.Name="Test.Class"Set ClassDef.Super="%Persistent"Set ClassDef.ProcedureBlock=1Set MethDef=##class(%Dictionary.MethodDefinition).%New()Set MethDef.Name="Name"Set MethDef.ReturnType="%String"; Uncomment for ClassMethod; Set MethDef.ClassMethod=1Set MethDef.FormalSpec="First:%Boolean,Second:%String=""Default"""Do MethDef.Implementation.WriteLine($Char(9)_"If First Return 1")Do MethDef.Implementation.WriteLine($Char(9)_"Return Second")Set MethDef.parent=ClassDefDo ClassDef.Methods.Insert(MethDef)Do ClassDef.%Save()
Herman Slagman · Jun 14, 2017 go to post

You can use XSLT to do this:

ClassMethod Run()
{
  Set XML=##class(%Dictionary.CompiledXData).%OpenId(..%ClassName(1)_"||XML").Data
  Set XSLT=##class(%Dictionary.CompiledXData).%OpenId(..%ClassName(1)_"||XSLT").Data
  Set sc = ##class(%XML.XSLT.Transformer).TransformStream(XML, XSLT, .Result,, .Params,)
  Do Result.OutputToDevice()
}
XData XML{
<?xml version="1.0" encoding="UTF-8" ?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV='http://schemas.xmlsoap.org/soap/envelope/'>
  <SOAP-ENV:Header>
<SomeCustomHeader/> </SOAP-ENV:Header>
  <SOAP-ENV:Body><SomeCustomBody/></SOAP-ENV:Body>
</SOAP-ENV:Envelope>
}
XData XSLT{
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
  <xsl:strip-space elements="*"/>
  <xsl:template match="@*|node()">
   <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
   </xsl:copy>
  </xsl:template>
</xsl:stylesheet>
}

 

Herman Slagman · Mar 22, 2017 go to post

That's a clever hybrid way of using BPL to do the plumbing and COS to execute the logic.

Because I strongly advise against 'programming' in BPL. I've seen BPLs that tried to implement complex logic in multi-level deep-nested loops and conditions that were absolutely un-maintainable.

Herman Slagman · Mar 22, 2017 go to post

Couple of things I'm not sure of:

  • what is pCompletionKey  used for? Can that be used as a unique reference for that invocation of SendRequestAsync?
  • Is there such a thing as a sleep "Status" to use as Quit for OnRequest? Or do I need to loop until done? Will HANG in this case release the resources used by the process?
  • if the target operation responds with an error is that handled by OnResponse or only OnError?

The CompletionKey is a 'tag' which you can attach to each async call. So you can distinguish them in the OnResponse by that tag.

Just 'Quit' the OnRequest, Ensemble will call the OnResponse when needed.

At the end (all Requests have responded or an optional time-out has occurred) the OnComplete will be called.

If the target operation has responded with a error-message in the Response message it will be in the OnResponse.

(I think) the OnError will be called if the target operation exits with a status code of not $$$OK

Herman Slagman · Mar 17, 2017 go to post

using a Command Pipe would be the way to achieve this:

Set Command="git status"
Set Pipe="|CPIPE|"
Open Pipe:(Command:"R"):0
If '$Test Return "Cannot open CommandPipe to "_Command
For  {
    Use Pipe Read Line If $ZEOF Quit
    Set Lines($Increment(Lines))=$ZStrip(Line,"<>W")
}
Close Pipe

Herman Slagman · Oct 18, 2016 go to post

I think your findings are very worrying.

I must confess I didn't do any Atelier testing myself (I don't like Eclipse, too premature, not enough time).

But six to four months later that some of these issues  you reported still have no sign of progress...

Also that there is no 'formal' feedback of issues or roadmaps on Atelier.

Personally I think that ISC jumped on the Eclipse bandwagon five years too late. My choice in these days would have  been Electron/Atom/MS VC but also keeping in mind that it could be totally different in four to five years time.  

Herman Slagman · Sep 22, 2016 go to post

Or have a look at Restlet which can produce Swagger as well as RAML, it's still undetermined which will be the defacto standard for API documentation.

Herman Slagman · Sep 20, 2016 go to post

I don't agree with you.

You might be right if you were talking about for-loops in the 'traditional' way:
For var=start:step:end { ... }

'While' would be very awkward, the condition would be Sub'="", but that would break the logic of the $Order which needs a Sub="" to start with.

The argumentless-For isn't really a For, it's more like a Loop statement, in fact that's what I asked for in one of my yearly wish-lists to ISC.

Loop {
    Do whatever you need to do
    Continue if needed
    Quit if needed
}

Furthermore I wouldn't use Stackoverflow as a authorative source (in any sense, but certainly not) for COS/Mumps.
I think there are far more COS/Mumps experienced developers in this gremium.

It would be very interesting to see if we could come up with some sort of 'For Each' construct.
Because that's what we are really interested in: For Each Subscript in ^Trans: do something or equivalent to $Query;
For Each DataNode in ^Trans do something

Herman Slagman · Sep 19, 2016 go to post

It's probably more about semantics then syntax, but the correct way of using HTTP methods would be:

Create a resource: POST

Replace a resource completely: PUT

Update one or more properties: PATCH

Herman Slagman · Sep 19, 2016 go to post

The obvious answer would be 'it depends' ;-)

But essentially that is true, if you want out-of-the box Ensemble supported functionality (HL7, DICOM, etc) then it would be hard to match that within a reasonable time-frame and budget. Also if you want an all-purpose routing engine Ensemble would be hard to beat.

But if you have a specific problem in mind, a custom solution could be a better option.

IMHO Ensemble's queuing mechanism is pretty dumb, a custom queue could be more intelligent and dynamic, with dynamic actor pools and auto-start/stop queues.

Also stuff such as itinerary based routing, true publish and subscribe and complex event processing could then be an option (if needed).

And, also important, standard Caché is much cheaper then Ensemble (let alone HealthShare).

Herman Slagman · Sep 19, 2016 go to post

Set Sub1=""
For  {
       Set Sub1=$Order(^Trans(Sub1))
      If Sub1="" Quit
      Write Sub1,!
      Set Sub2=""
      For  {
            Set Sub2=$Order(^Trans(Sub1,Sub2))
            If Sub2="" Quit
            Write ?3,Sub2,!
            Set Sub3=""
            For  {
                   Set Sub3=$Order(^Trans(Sub1,Sub2,Sub3))
                   If Sub3="" Quit
                   Write ?6,Sub3," = "
                   Set Data=(^Trans(Sub1,Sub2,Sub3))
                   Write Data,!
            }
       }
 }

Herman Slagman · Sep 18, 2016 go to post

That being said I wonder what ISC strategy/policy will be in the future.

Cache and Ensemble are in the 'Platform division', HealthShare in the 'Healthcare division'.

HL7v2 is traditionally supported by Ensemble that won't change, but the rumour is that all health related features and products will be in HS only (e.g. FHIR).

Does this mean that health related Ensemble implementations will have to upgrade to HS eventually ?

Herman Slagman · Sep 18, 2016 go to post

Hi Mike,

I really appreciate your Newbies work,  but I wouldn't use the Do <space><space> dot syntax.

It's a very obscure syntax, only used in Mumps. Using 'traditional' For-loops is much more in line with what today's programmers would expect.

Herman Slagman · Sep 10, 2016 go to post

I doubt if it makes sense having Caché on the Pi. It's just too heavy.
Supporting different IoT protocols on the server (as a hub or controler) makes more sense to me.

With MQTT, ZWave, ZigBee, gRPC adaptors Ensemble could well be the controller to control then all ;-)

Herman Slagman · Sep 10, 2016 go to post

It depends on what you want to achieve with FHIR. After all it's an open specification and implemented in (sort of) REST and JSON (or XML).

If you only need a limited sub-set and don't need to transform to other formats such as HL7v2/3, or need other parts of HS, then you can easily implement it yourself.

Herman Slagman · Sep 4, 2016 go to post

Mike,

Please elaborate. What do you mean by an 'extract' from a database.

JSON is about data, not classes or methods.

Herman Slagman · Aug 26, 2016 go to post

It's a little confusing: you want to do integration tests with a unit test framework, that doesn't sound right.

I'm not a big fan of unit testing, but for integration tests you'll need mockup services to emulate the 'outside' world. We use Soap Sonar, SoapUI and Cache services to just do that.

Herman Slagman · Aug 26, 2016 go to post

What would be example business cases that require more then one projection of a class ?

If the adaptor would provide both a JSON string and an JSON object, you could manipulate the object in order to get a different projection.

Our JSON implementation did just that, 99% the default one was used, but if we needed some more filtering of certain properties they could be removed (or added for that matter) from the object and then transformed to a JSON string. 

Herman Slagman · Aug 26, 2016 go to post

I think that ISC should have implemented the JSON support for existing classes the same as they've done for XML. Through a mixin adaptor class and accompanying property class. That way the projection to JSON is far more controllable.