Hello Ruslan, 

You are correct, DisplayToLogical() is not called automatically when saving an object. When you are manipulating an object using ObjectScript, the assumption is that the value you are dealing with is already a logical value. If you need to convert from a display value, you can do so explicitly. For instance, if you have a the following class:

Class Test.MyClass Extends %Persistent
{
Property MyDate As %Date;
}

You can convert from display to internal using either of the following:

set myobj = ##class(Test.MyClass).%New()
set myobj.MyDate = ##class(%Date).DisplayToLogical(value)
set myobj.MyDate = ##class(Test.MyClass).MyDateDisplayToLogical(value)

Hello David,

Can you double check that you have the port forwarding set up correctly when you start the container? This is the error you will get if you try to connect via JDBC to a port that was forwarded to something other than the instance's SuperServer port. The SuperServer port is 1972. For instance, if you start the container with:

docker run -p 51776:1972 -p 52776:52773 containers.intersystems.com/intersystems/iris-community:2020.3.0.221.0

You should be able to connect using the connection string: "jdbc:IRIS://localhost:51776/USER/". In general, you should be able to connect via JDBC to the community edition containers.

Hello Scott,

The error is occurring because Caché does not have the certificate chain needed to verify the certificate used by the remote system. The error is:

Error: 20, unable to get local issuer certificate

The first certificate it is missing is:

Issuer: /C=GB/ST=Greater Manchester/L=Salford/O=Comodo CA Limited/CN=AAA Certificate Services

The SSL/TLS configuration has been configured to look for trusted certificates in the file: '/ensemble/TestClin/mgr/LDAPKeyStore/OSUWMC_CA.cer'. This should contain all the certificates in the certificate chain needed for the remote certificate, in PEM encoded format. See the documentation here for more information: https://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY...

I hope this helps!

Hello, 

In order to use the Web Gateway to dispatch requests to an HTTP Service (such as EnsLib.HL7.Service.HTTPService), we need to have a way for the CSP system to know which Service to dispatch the request to. This works by default if the name of the Service is the same as the class name; in this case CSP can just use the class name in the URL to find the configuration item. It sounds like you already have this working. 

If you have multiple Services in the same production using the same class we need a mechanism to distinguish between them. This can be accomplished using the CfgItem URL parameter. Let's say you have two Services using the "EnsLib.HL7.Service.HTTPService" class, named "HL7ServiceA" and "HL7ServiceB". You can distinguish between them by making requests to the following URLs:

/csp/healthshare/NAMESPACE/EnsLib.HL7.Service.HTTPService.cls?CfgItem=HL7ServiceA

/csp/healthshare/NAMESPACE/EnsLib.HL7.Service.HTTPService.cls?CfgItem=HL7ServiceB

Also note that, in order for any of this to work, the "Enable Standard Requests" setting needs to be enabled for the adapter for each of the Services:

https://docs.intersystems.com/irislatest/csp/docbook/Doc.View.cls?KEY=EH...

I hope this helps.

Regards,

Sean Klingensmith

Hi Peter, 

Correlate() simply associates the given XML element with the given ObjectScript class. %XML.Reader allows you to specify multiple element/class associations by calling Correlate() multiple times. Subsequent calls to Next() will return the objects associated with the elements you've correlated, in the order in which they are found in the file. Here is a very basic example using two classes

Here are the classes:

Class Test.A Extends (%RegisteredObject, %XML.Adaptor)
{ 
Property AProp1 As %String(MAXLEN = 64, XMLPROJECTION = "attribute"); 
Property AProp2 As %String(MAXLEN = 64, XMLPROJECTION = "attribute");
}
Class Test.B Extends (%RegisteredObject, %XML.Adaptor)
{ 
Property BProp1 As %String(MAXLEN = 64, XMLPROJECTION = "attribute"); 
Property BProp2 As %String(MAXLEN = 64, XMLPROJECTION = "attribute"); 
}

And our XML file:

<?xml version="1.0" encoding="UTF-8"?>
<objects>
    <A AProp1="abc" AProp2="def"></A>
    <B BProp1="123" BProp2="456"></B>
</objects>

Now we can read both objects in one pass with the following method:

ClassMethod ReadXML()
{
    set reader = ##class(%XML.Reader).%New()
    do reader.OpenFile("/tmp/test.xml")
    
    do reader.Correlate("A", "Test.A")
    do reader.Correlate("B", "Test.B")
    
    do reader.Next(.obj, .sc)
    if $$$ISOK(sc) && $isobject(obj) {
        zwrite obj
    }
    
    do reader.Next(.obj, .sc)
    if $$$ISOK(sc) && $isobject(obj) {
        zwrite obj
    }
}

In a more complex example, you would probably want to call Next() in a loop, and actually pay attention to the error code, but this should demonstrate the point. 

I hope this helps. 

You can configure matching roles in the /csp/ensdemo Web Application for the custom role you created previously. This would allow you to grant additional privileges, only to the users belonging to the custom role, and only when those users are in this CSP Application.

See the documentation for Matching Roles for more details.

I think the only additional resources you should need (by default) are %DB_ENSDEMO, and %Ens_Portal. You need %Ens_Portal because that is the resource required for the /csp/ensdemo application.

Hello Gery,

There are a couple of ways to do this. Ultimately, what you want is to define a Resource (say my_soap_resource) that controls access to the Web Service, or the CSP Application. You can then create a Role to grant access to that Resource, and assign the Role to your user. For more information on Resources and Roles, see the Caché Security Administration Guide.

Once you have created the Resource, you can use it to control access either to the entire Web Application, or to the individual SOAP Service. You would configure this in the CSP Application if you had a set of pages/Web Services, and you wanted to control access to them by the same resource. If you want more granular control, you can configure the individual page to require this resource.

To configure this at the Web Application level, go to the Web Application definition in the Management Portal:

[System Administration]->[Security]->[Applications]->[Web Applications]

and set your resource (my_soap_resource) in the "Resource Required" field.

To configure access for the individual SOAP service, edit the Test.BS.WSService class, and add the following parameter:

Parameter SECURITYRESOURCE = 'my_soap_resource';

Once this is done, only users with access to this resource will be able to access this SOAP Service. Other users will receive the error: "Illegal CSP Request". There are a couple of things to note:

1) Users will need this resource to do anything with this Web Service, including accessing the WSDL.

2) Users with the %All Role will have permissions on all Resources, so they will be able to access the Web Service, even without being assigned to your custom Role.

3) These restrictions only apply when accessing the Web Service through the CSP Gateway (EnableStandardRequests). When accessing the Web Service through the custom Adapter port, these setting will be ignored. (see the documentation for the SOAP adapter settings).

Hwllo Sansa,

Which version of the ODBC driver are you using? Caché ships with Unicode and 8-bit versions of the ODBC Drivers:

8-Bit:

libcacheodbcu.so

libcacheodbcu35.so

Unicode:

libcacheodbcuw.so

libcacheodbcuw35.so

The 35 files are for the drivers that support ODBC 3.5. Can you make sure that you are using a Unicode build of the driver?

Hello,

The code you included will return a SOAP fault to the client with the specified fault code and message. Since this is a Business Service, it will also log the fault to the Ensemble Event Log, along with the last error the process encountered (%objlasterror). This appears to be where this is where the error message is coming from.

Note that, again, since this is a Business Service, you can use the ReturnStatusFault() or ReturnMethodStatusFault() methods to create and return the SOAP fault instead of creating it manually. This should have the same behavior as your code, except that the fault code and message may be different. See the documentation here:

http://docs.intersystems.com/latest/csp/docbook/DocBook.UI.Page.cls?KEY=...

I'm not really sure that I answered your question. Can you give more information about the problem you are trying to solve?