I have a method that I need to test. I would like to do so from the console. Here is the method, as well as some metadata from the class:
Include HS.Common
Class Custom.class Extends Ens.BusinessOperation
{
Parameter ADAPTER = "EnsLib.EMail.OutboundAdapter";
Property Adapter As EnsLib.EMail.OutboundAdapter;
Method SendMessage(pSubject As %String, pMessage As %String, pEmailAddresses) As %Status
{
set tSC=$$$OK
set tMailMessage=##class(%Net.MailMessage).%New()
do tMailMessage.To.Insert($PIECE(pEmailAddresses,",",1))
for tI=2:1:$LENGTH(pEmailAddresses,",") {
do tMailMessage.Cc.Insert($PIECE(pEmailAddresses,",",tI))
}
set tMailMessage.Subject=pSubject
set tMailMessage.Charset="iso-8859-1"
set tSC=tMailMessage.TextData.Write(pMessage)
quit:'tSC
Set tSC1=..Adapter.SendMail(tMailMessage)
if 'tSC1 {
//Log warning about being unable to send mail.
do $SYSTEM.Status.DecomposeStatus(tSC1,.err)
$$$LOGWARNING("Could not send email: "_err(err))
kill err
}
quit tSC
}
...other methods here...
}
but when I perform this command:
set tResult = ##class(Custom.class).SendMessage("Test Subject","Test Message","my#email.com")
I get this error:
Set tSC1=..Adapter.SendMail(tMailMessage)
^
<NO CURRENT OBJECT>zSendMessage+11^Custom.class.1
I tried instantiating adapter, much like the property definition, before calling the method but that did not work. How can I call this method from a console session?
this method is an instance method, and you can't call it directly just for some class. Before, you should create an object, and then for that object, you can call any instance methods. But you still trying to call Ensemble classes, it is not so easy, because you should prepare environment, such as configured and started Ensemble Production, your class should be added as an Operation, configured and activated.
set oper=##class(Custom.class).%New("configName")
where configName - name for that operation in your production, by default it is same as class name (e.g. "Custom.class"). And now you can call your method.
write oper.SendMessage("testSubj","test body","my#mail.com")
But I would not recommend such way. It would be better if you test it through production, just sent test messages to this operation.
Related
How does coroutines default scope work if i do not specify anything. lets take a look at this example:
class MyAppCompatActivity:AppCompatActivity{
fun getContact() {
GlobalScope.launch {
val contact = contacts.getContact() // suspended function
withContext(Dispatchers.Default) {
phoneContact.value = contact }
}
}
}
which simply updates the UI when a contact is retrieved. this is added to the global scope of so the coroutine life span can be that of the entire application.
but lets do the same thing again without a globalScope:
class MyAppCompatActivity:AppCompatActivity{
fun getContact() {
launch {
val contact = contacts.getContact() // suspended function
withContext(Dispatchers.Default) {
phoneContact.value = contact }
}
}
}
what is the lifespan of getContact now that i have removed the globalScope ? is it tied to the MyAppCompatActivity scope ?
Your code will fail to compile because launch must be called on a CoroutineScope object. This object specifies the lifespan of the coroutine. Since your activity does not implement a scope it will fail to compile or call a completely unrelated launch function.
I don't think this is a good idea anymore, as it looks like they're just functions for testing (doesn't launch coroutines). Maybe this was an API available previously, but now you should be using lifecycleScope to scope a coroutine to a fragment or activity, and viewModelScope to scope them to a View Model's life cycle. These are properties available in those classes by already.
Here's what I see when I try to use launch:
Is there any environment variable or something how to change the maxVarCharLength like tablePrefix in JobRepositoryFactoryBean.java?
I couldn't find any config class where this setter method is called
public void setMaxVarCharLength(int maxVarCharLength) {
this.maxVarCharLength = maxVarCharLength;
}
It is up to you to call this method in order to set the maxVarCharLength property. The JobRepositoryFactoryBean will then use the value you set to create the JobRepository. You can find an example here: https://docs.spring.io/spring-batch/4.0.x/reference/html/job.html#configuringJobRepository
I load an assembly and from that a class of the object I want to create. From that class I check for interfaces (mono_class_get_interfaces) and find the interface class I want (IDispose).
I create the object with mono_object_new and call mono_runtime_object_init directly afterward. I then call mono_object_castclass_mbyref to cast the object to an interface reference. Then I retrieve the interface method I want to call (Dispose) from the interface class with mono_class_get_method_from_name.
I call mono_object_get_virtual_method to make sure I have the correct implementation and then try to call it with mono_runtime_invoke using the interface MonoObject * reference and the interface virtual method MonoMethod * (args = NULL) -> which is unsuccessful.
I have also tried to call mono_method_get_unmanaged_thunk with the same parameter, that doesn't work either.
In both cases I get a value back for the exception argument. Problem is, I haven't found a way to look inside the exception...
Question is:
Is the sequence of calls correct to work with managed interfaces and call the correct (most specific) interface methods?
How to get more information on the MonoException (I assume the MonoObject * returned by invoke is a MonoException instance)?
There is no need to invoke any castclass function to cast a managed reference to an 'interface reference': the value is the same.
Once you have your IDispose MonoClass* pointer, you should get the MonoMethod* for the method you want to call and pass that to mono_object_get_virtual_method(). The result of this function is what you should pass to mono_runtime_invoke().
For the exception, you can invoke the get_Message method method, for example, or any of the methods you'd call to deal with it if you were in C# code.
Simple tested code below, str is a MonoString*:
icloneable_class = mono_class_from_name (mono_get_corlib (), "System", "ICloneable");
iface_method = mono_class_get_method_from_name (icloneable_class, "Clone", 0);
iface_impl_method = mono_object_get_virtual_method (str, iface_method);
exc = NULL;
obj = mono_runtime_invoke (iface_impl_method, str, NULL, &exc);
The method is correctly invoked and exc will be NULL.
I define a variable my_reg_file in function post_access() (this function is a vr_ad hook for implementing side effects):
//file1.e
extend TIMER_LOAD_0 vr_ad_reg {
post_access(direction : vr_ad_rw_t) is first {
var my_reg_file : TIMER vr_ad_reg_file =
get_parents()[0].as_a(TIMER vr_ad_reg_file);
....
};
};
Then I extend this function in another e file:
//file2.e
extend TIMER_LOAD_0 vr_ad_reg {
post_access(direction : vr_ad_rw_t) is also {
start my_reg_file.some_tcm();
};
};
I get a compilation error:
*** Error: No such variable 'my_reg_file'
Why post_access() does not recognizes the variable my_reg_file? Thank you for your help.
Note: file1.e is imported before file2.e
my_reg_file is a local variable, of that specific method layer, and is not shared with other method layers.
I think the only way to communicate between method layers are:
a. using the result saved variable which can be accessed from any method layer.
b. using a struct member.
Another solution, which seems even better, is to add a separate method to this subtype, e.g. get_my_reg_file(), which will return the desired value, and then call this method where this value is needed, instead of using the local variable.
I'm using Rebus. In the AutofacContainerAdapter (https://github.com/rebus-org/Rebus/blob/master/src/Rebus.Autofac/AutofacContainerAdapter.cs) they are calling the following line of code:
builder.Register(a => MessageContext.GetCurrent()).ExternallyOwned();
How can setup my MessageHandler constructor so that Autofac can find back this type? If I understand it correctly, when I use IMessageContext in my constructor, it won't be passed because there is no .As<IMessageContext>() in the code above.
Looking at: https://github.com/rebus-org/Rebus/blob/master/src/Rebus/MessageContext.cs shows:
public static IMessageContext GetCurrent()
{
}
So that registers as IMessageContext. If you don't explicitly state otherwise, a lambda registration implicitly registers as the return type of the lambda.