Hi,

My preference would be to the simplest for developer and keep the three word (error, failure and success). For that, we can force the return of each function as Map.

After delegate the problematic to each handler. By the way, the GroovyEventHandler that call GroovyBaseScript already support an output as Map or as String :

// GroovyEventHandler.java:117 [1]
<code>
           // check the result
            if (result instanceof Map) {
                Map<String, Object> resultMap = UtilGenerics.cast(result);
                String successMessage = (String) resultMap.get("_event_message_");
                if (successMessage != null) {
                    request.setAttribute("_EVENT_MESSAGE_", successMessage);
                }
                String errorMessage = (String) resultMap.get("_error_message_");
                if (errorMessage != null) {
                    request.setAttribute("_ERROR_MESSAGE_", errorMessage);
                }
                return (String) resultMap.get("_response_code_");
            }
            if (result != null && !(result instanceof String)) {
                throw new EventHandlerException("Event did not return a String result, it returned a " + result.getClass().getName());
            }
            return (String) result;
</code>

If I understand well the problematic, move the return to Map, and improve GroovyEventHandler to support the groovy script return (better than what it did currently) would be cover all case ?

Cheers,
Nicolas

[1] https://github.com/apache/ofbiz-framework/blob/64d012d2c20d76200cedd3e1861b720d55a61398/framework/webapp/src/main/java/org/apache/ofbiz/webapp/event/GroovyEventHandler.java#L117

On 28/04/2023 16:07, Daniel Watford wrote:
Hi Gil,

I don't think we need to go as far as creating a new GroovyBaseClass.

Deprecating GroovyBaseScript:success is still preferred in my opinion,
replacing it with serviceSuccess and scriptSuccess. These two methods could
return separate types which extend from Map and help make it clear whether
the method in the groovyScript is intended by the author to implement a
service or an event handler.

In the rare cases of a current groovy method being used to implement both a
service and an event handler, I think we could do something similar to this
contrived example:

/////////////////////////
// GroovyBaseScript.groovy

interface ServiceResponse extends Map<String, String>

interface EventResponse extends Map<String, String>

ServiceResponse serviceSuccess(....) { ... }
ServiceResponse serviceFail(...) {...}
ServiceResponse serviceError(...) {...}

EventResponse eventSuccess(...) {...}
EventResponse eventFail(...) {...}
EventResponse eventError(...) {...}

//////////////////
// ExampleServiceAndEventImpl.groovy

// Here is the main implementation, initially implemented as a service
handler
ServiceResponse countProducts () {
...
...
return serviceSuccess([stock: 42])

// Here is the event handler implementation, leveraging the service
implementation as an adapter.
EventResponse countProductsEventHandler () {
     ServiceResponse sr = countProducts();
     return eventSuccess("Found ${sr.stock} products");
}

The return type of the above methods help identify whether we are dealing
with a service or event handler. If conversion is needed from one type to
the other, an adapter specific to the business logic can decide how to map
between EventResponses and ServiceResponses.

Thanks,

Dan.

On Fri, 28 Apr 2023 at 14:27, Gil Portenseigne<gil.portensei...@nereide.fr>
wrote:

Hello I got a quick look about it, having two separate class means
having two distinct groovy DSL and need lot of modification that IMO are
not worth the complexity for this subject.

I now only wonder, is it that bad too keep that one exception (about
untyped return) for GroovyBaseScript::success ?

Gil

Le 26/04/2023 à 09:49, Gil Portenseigne a écrit :
Hello,

I like the idea that the developer do not have to sync about which
method to use.

If I understand well what Michael envision, i.e. to use for event a
new GroovyBaseEvent class, and for services/scripts a GroovyBaseScript
class, that both extends a common class for the common code, should be
one way to allow this usage.

But I don't know about IDE integration behavior of such a solution...

Do you think that is worth a look ?

I will just add that there is a chance that project implementation are
using groovy script as the event target (I know some ;) )

Thanks,

Gil

Le 20/04/2023 à 17:13, Michael Brohl a écrit :
To have it even more clear, I would separate logic for events and
services.

The GroovyBaseScript in the service engine package should only be
used for services and there should be another one for events, if
really needed. Mixing both together is bad practice IMO. There seem
to be only 7 controller entries using a groovy script as the event
target.

Best regards,

Michael Brohl

ecomify GmbH -www.ecomify.de


Am 20.04.23 um 16:49 schrieb Jacques Le Roux:
Hi Daniel,

I dont think there is a knowledge about methods being both services
and events. I think there are not (much?) such cases.
Being acquainted to OFBiz logs I did not check the trunk demo log
content (now in Docker);
so I wonder if there are such other cases than
CommunicationEventServices::sendEmail  (colon notation is available
in Groovy 3)
that bots and demo uses could have generated.

I tend to agree about having GroovyBaseScript::success deprecated
and replaced with methods GroovyBaseScript::scriptSuccess
GroovyBaseScript::serviceSuccess and GroovyCaseScript::eventSuccess

I'm not yet acquainted with Codernarc rules, but the changes in
GroovyBaseScript seem straightforward.
And (hopefully) this should not be a big deal to change accordingly
in scripts methods with the help of Codenarc, right ?

My 2 cts

Jacques

Le 19/04/2023 à 18:37, Daniel Watford a écrit :
Hello,

In my opinion, the semantics of calling an event handler vs a service
implementation are different, albeit similar enough that most
handler/implementation authors wouldn't necessarily care how the
code was
called.

The untyped nature of Groovy had allowed a certain degree of
flexibility in
code that GroovyBaseScript#success could be relied upon to prepare a
response appropriate to the calling conventions of an event handler or
service implementation. However over the last decade, possibly
driven by
increased use of linters/static analysers, we have seen a push back
towards
explicit typing, particularly on public methods.

If we continue to adopt the guidance from static analysers and apply
explicit typing to public methods in our groovy code, then we need
to avoid
the black box approach of GroovyBaseScript#success figuring out what
calling conventions (i.e. event or service) are in play and,
instead, a
groovy method should be intentionally written as either a service
or event
handler.

If we have cases where a groovy method is used to provide
implementations
for both a service and an event handler, then we can employ a thin
adapter
layer to convert the result type between the two calling
conventions. Do we
know if many such cases currently exist in OFBiz?

My preference would be to see GroovyBaseScript#success deprecated and
replaced with methods along the lines of
GroovyBaseScript#scriptSuccess and
GroovyCaseScript#eventSuccess that return a Map<String, Object> and
String
respectively.

Thanks,

Dan.

On Wed, 19 Apr 2023 at 16:44, Jacques Le
Roux<jacques.le.r...@les7arts.com>
wrote:

Hi All,

At OFBIZ-12801, we had a discussion with Daniel and Gil about the
described issue (last comments there)
We are unsure of the best solution, so this thread to discuss and
decide.

As Gil reported, Jacopo's comment of the related commit* contains

      <<these helper methods have been enhanced in order to be used by
groovy method executed as services or events in a transparent way.>>

What would be your opinion about a best solution?

TIA

Jacques

*http://svn.apache.org/viewvc?view=revision&revision=1298908


Reply via email to