Hi Lorraine,

A few questions to help us get a clearer picture:

  • Which component is generating the 5005 error? Is it the router or the business operation?
  • Can you post a screenshot or the source code for your routing rule?
  • Is your router calling a transformation or just passing the file through unchanged?
  • What happens if you remove all logic from your router and just change it to do a simple "send" with no transformation?

-Marc

what would be the best way to block user access to certain portions of the website or entire pages?

In Caché/CSP terms, you would define a custom resource that represents the pages/sections that require different privileges, then assign access to that resource to a role, and assign that role to any users that should be allowed access.  In your CSP page you would then check if the current user has the necessary privileges and act accordingly.

This short tutorial gives a more detailed overview:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=TSQS_Authorization

It sounds like you might be able to avoid the problem of converting to XML and creating an EnsLib.EDI.XML.Document if you were able to access fields in your persistent message class from your routing rule logic?

If your persistent message class has discrete properties, you can still refer to these directly in a routing rule condition even without the VDoc style GetValueAt().

If your message object has references to repeating child objects and you need to get to a deeper level such as checking a property of the Nth child object you can do this by creating a custom function and passing it the Document object as a parameter.

Does it need to be a binary executable or would a batch file work? It is possible to execute a Caché routine/method from a Windows command line or batch file by invoking the Caché binary and passing it the name of what you want to execute.

The docs give this example for freezing and thawing the database for backups:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...
 

CD C:\InterSystems\E20131\mgr\
..\bin\cache -s. -B -V -U%SYS ##Class(Backup.General).ExternalThaw()

The high-level steps are:

  1. Create a Java class using the APIs provided by your JMS server (ActiveMQ, RabbitMQ, etc.) and create a JAR file. JMS is a standardized API, not a protocol, so there is not one universal JMS client that will work with all JMS servers.
  2. Use the Java Gateway wizard to generate COS proxy classes for your Java class
  3. Setup a Java Gateway Service in your production. Make sure it points to your custom JAR file and the JAR file provided by the JMS server vendor.
  4. Create a custom business service or operation that calls the COS proxy class methods.
  5. When adding the service or operation to the production, configure it to point to the Java Gateway Service and use the correct Java class

For a Business Operation, you'll just use the usual approach: the message map points to a custom method. The custom method then calls the COS proxy class methods for your Java class. The BO class should extend Ens.BusinessOperation and use the adapter EnsLib.JavaGateway.OutboundAdapter.

For a Business Service, there's an out of the box adapter, EnsLib.JavaGateway.InboundAdapter. You just need to create a custom Operation that extends Ens.Business service and uses EnsLib.JavaGateway.InboundAdapter as it's adapter. This is quite nice, because EnsLib.JavaGateway.InboundAdapter handles most everything automatically. Your Java class just needs to implement a set of methods defined by the Inbound Adapter. See the class reference for EnsLib.JavaGateway.InboundAdapter for more details:
 *             .Connect(pJGClientConnectSpec,pTimeout,pInbound)
 *             .Disconnect(pInbound)
 *             .IsConnected(pInbound)
 *             .getErrorText() [returns empty string if no error on previous method call]
 *             .ReceiveMessage(pTimeout) [inbound only; pMsgIn return needs not be populated if timed out]
 *             .SendResponse(pMsgOut) [inbound only, optional-needed if OnProcessInput will return an object]
 *             .SendMessage(pMsgOut,pGetReply,pResponseTimeout) [outbound only; pMsgIn return needs not be populated if no responses are anticipated]

I've created some sample code including a production and Java classes. It includes a generic class that implements most of the necessary methods using standard JMS API methods and provides an ActiveMQ-specific subclass that uses the ActiveMQ proprietary methods to initiate the connection.

As always, this is sample code for demonstration purposes only and is not production ready.

Alerts (Ens.AlertRequest) are treated like any other message in Ensemble -- you can transform them to different message types and route them to an outbound business operation.

Have a look at the docs regarding alerts here:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

And the docs regarding file adapters here:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

One approach you can consider is to transform the Ens.AlertRequest into an Ens.StreamContainer and then use an EnsLib.File.PassthroughOperation to write it out to a file:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

If you need to write the alert to a file in a structured format, you can consider creating a RecordMap for your output format, transform the Ens.AlertRequest into your custom RecordMap object, and then use EnsLib.RecordMap.Operation.FileOperation to write it out to the file:
http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

You can use the Enumerate stored procedure in the Ens.Job class to get a list of running Ensemble jobs (config items) in the current namespace. If you need to get other system level details about the process, the "job" field is the same as the process id from %SYS.ProcessQuery.

From a SQL query tool you can call it with:
call Ens.Job_Enumerate()

From my earlier comment: %syPidtab.inc includes a list of Job Types and their corresponding IDs.

Hi Joe,

I assume that CreateTextMessage is being called from a custom Business Operation similar to what's outlined in this chapter.

If you are passing an HL7 message to the Business Operation, and your operation's message map looks like this:

XData MessageMap
{
<MapItems>
  <MapItem MessageType="EnsLib.HL7.Message">
    <Method>SendEmail</Method>
  </MapItem>
  ...
</MapItems>
}

...then your SendEmail method can use the GetValueAt() method of the EnsLib.HL7.Message object to retrieve a field value using the same syntax that you use in DTL. Have a look at the docs for EnsLib.HL7.Message and specifically GetValueAt.

It would look something like this:

Method SendEmail(myMessage As EnsLib.HL7.Message, Output pResp As ResponseClass) As %Status {
    set myEmail=myMessage.GetValueAt("PID:13(1).4")
    set msg=..CreateTextMessage(myEmail)
    ...

Here's a sample for creating a proxy object and outputting it as JSON:

Set tProxy = ##class(%ZEN.proxyObject).%New()
Set tProxy.Property1 = "Some value 1"
Set tProxy.Property2 = "Some value 2"
Set tSC=##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.tStream,.tProxy)
Write "Result (blank means no error):",$System.Status.GetErrorText(tSC),!
Write "JSON output:",!
Do tStream.OutputToDevice()

This produces the following output:

Result (blank means no error):
JSON output:
{
        "Property1":"Some value 1",
        "Property2":"Some value 2"
}