For the new mail binding I need to define a new class MailBuilder. I put that in a package org.openhab.binding.mail.builder and added that package to Export in MANIFEST.MF. From my understanding other bundles should now be able to use that.
In a .rules-file I used import org.openhab.binding.mail.builder.MailBuilder and tried val mail = new MailBuilder(”Test“). That results in an error null.
I can’t answer your specific question but if this is something that is exposed in Rules, shouldn’t it be an Action? You can look at how MQTT2 built its mqttPublish Action. From the rule the user doesn’t import the class like in the old 1.x way, but has a system call to get a handle for the Action.
e. g.
val mqttActions = getActions("mqtt","mqtt:systemBroker:embedded-mqtt-broker")
mqttActions.publishMQTT("mytopic","myvalue")
This is how Actions are required to be accesses in NGRE I believe. Other bindings have implemented Actions like this too; i think Hue is one of them.
@J-N-K, I’m working on creating a ConditionType and ActionType. I think what you may be missing are ConfigDescriptionParameters, but that may be what you’re doing with your builder. Have you pushed your code to a repo?
import org.openhab.binding.mail.builder.MailBuilder
import org.apache.commons.mail.Email
rule "mailtest"
when
Time cron "30 19 17 * * ?"
then
val mailAction = getActions("mail", "mail:smtp:087d5265")
val mail = new MailBuilder("foo@bar.zinga")
mail.withSubject("Test Subject").withText("test text")
mailAction.sendMail(mail.build)
end
The builder will be extended with withAttachment, withHtmlContent and probably others. MailBuilder.build returns a Email (sendMail action currently accepts String and build an Email to test the other components). The rule fails on new MailBuilder with error during execution: null. Since the MailBuilder itself works fine inside java, I guess it is not properly imported to the rule.
val date = new Date() works fine if I import java.util.Date, so the problem seems to be that the rule engine is not able to import the class.
I would be really surprised if the maintainers accept a binding with actions that can’t be used in the new rule engine. Also, IMO using the builder in a rule will overly complicates things. I suggest you recreate the functionality of the old action. In Paper UI, it would look something like this…
IIRC you have to go for a ThingAction. Similar to the MQTT binding. Add a static method to retrieve a MailBuilder instance. To send the mail the builder should maybe provide a send() method instead of a build() method.
I did that, but it doesn’t work (have a look at my latest code). The mailBuilder-method should return a MailBuilder but it doesn’t.
import org.openhab.binding.mail.builder.MailBuilder
rule "mailtest"
when
Time cron "00 32 15 * * ?"
then
val mailAction = getActions("mail", "mail:smtp:087d5265")
mailAction.sendMail(mailAction.mailBuilder("jan@janessa.me").withSubject("Test"))
end
results in
2019-03-03 15:31:17.651 [INFO ] [.e.s.m.c.i.ModelRepositoryImpl:287 ] - Validation issues found in configuration model 'test.rules', using it anyway:
The method sendMail(ThingActions, Object) from the type SendMailAction refers to the missing type Object
The method mailBuilder(ThingActions, String) from the type SendMailAction refers to the missing type Object
2019-03-03 15:32:00.084 [ERROR] [.m.r.r.i.engine.ExecuteRuleJob:69 ] - Error during the execution of rule 'mailtest': 'withSubject' is not a member of 'Object'; line 26, column 25, length 60
If I remove the .withSubject-part, the validation issues are still there, and it fails with
2019-03-03 15:34:00.031 [ERROR] [.m.r.r.i.engine.ExecuteRuleJob:69 ] - Error during the execution of rule 'mailtest': An error occurred during the script execution: Cannot resolve proxy: java:/Objects/org.openhab.binding.mail.builder.MailBuilder#org.openhab.binding.mail.builder.MailBuilder
So the whole issue really is that the new class cannot be resolved. If I just use String (e.g. for the recipient and use the builder inside the ThingAction-method), the mail is sending out perfectly fine.
Short feedback: I am missing the annotations for the mailBuilder method in your code. And my proposal was to add the send() method to the MailBuilder class. Do not introduce a second action for it. In other words: Get rid of the sendMail action. I will take a closer look into your code tomorrow.
I did some research and found this piece of documentation. But I am afraid that it tells us the desired builder solution will not work out-of-the-box (see ActionOutput annotation). We probably have to extend the framework for using own classes in rules.
Usually the type should be the fully qualified Java type, but in the future it will be extented to support further types.
On the other hand there is a reference to some examples in the magic bundle.
I did try returning a HashMap, casting to the new class and so on. But it does not work out for me. Do you think we should proceed with the “classic” actions and come back to the builder when the core has been enhanced?
I think in general it is a bad idea to introduce something new and deprecate it shortly afterwards.
If we cannot use a builder pattern we can try at least to keep it simple and use separate methodd and try to keep the method chaining by returning the ThingActions instance in all methods. Might that work? If not we have to live with it.
For this I would need to store the already set data for the mail in a private member of SendMailAction. Unfortunately getActions is not thread-safe, we always get the same ThingActions (SendMailAction)-instance for a given thing. We might run into trouble if two rules try to send mail via the same server at the same time.
I still do not understand why it is not working. Maybe you have an idea. I tried @ActionOutput(name = "mailBuilder", type = "org.openhab.binding.mail.builder.MailBuilder"), which is a fully qualified java class, which is also exported from the bundle (code updated in GitHUB). My rule is then (without vaildation errors)
import org.openhab.binding.mail.builder.MailBuilder
rule "test2"
when
Time cron "0 04 17 * * ?"
then
val mailAction = getActions("mail", "mail:smtp:test")
val MailBuilder mailBuilder = mailAction.mailBuilder("foo@bar.zinga").get("retval") as MailBuilder
mailBuilder.send
end
but results in
2019-03-05 17:04:00.045 [ERROR] [.m.r.r.i.engine.ExecuteRuleJob:69 ] - Error during the execution of rule 'test2': Could not cast org.openhab.binding.mail.builder.MailBuilder@30a0673a to void; line 8, column 35, length 69
I don’t understand what ExecuteRuleJob tries to cast to void. Unfortunately I can’t properly debug that since I cannot (or don’t know how to) run core bundles within the same IDE as the addon.
Sry for letting you alone with this problem. I tinkered around a little bit more on my own but to be honest I yet did neither find a proper solution nor the right place in the core framework where to start to implement a fix for it. Very sad.
In the end it looks like we have to switch back to the conventional way.