Hi,

(another lengthy e-mail, if we're lucky, the last one..)

took a look at how could we achieve backward compatibility for (1)plugins,
(2)filters and (3)page
providers, while developing the public API. After that I'd like two make
two brief comments about
(4)next steps and (5)having JSPWiki installations' "islands"

(1) Plugins

plugins execution is located on DefaultPluginManager and, roughly, looks
like this:

try {
      return plugin.execute( context, params ); // plugin is a WikiPlugin,
context is a WikiContext
  } catch( final PluginException e ) {
      [...]
      throw ( PluginException )e.fillInStackTrace();
  } catch( final Throwable t ) {
      [...]
      throw new PluginException( rb.getString( "plugin.error.failed" ), t );
  }

If the suggested change for the public plugin api signature (context
becoming Context instead of
WikiContext), a plugin coded against "old" (2.11.0.M6 and below) will raise
an AbstractMethodError
here. However, we can bypass that and achieve plugin execution by changing
the above code to:

  try {
      try {
          return plugin.execute( context, params );
      } catch( final AbstractMethodError ame ) {
     log.warn( classname + "uses WikiContext instead of Context in its
execute method");
 log.warn( "Please contact the plugin's author so there can be a new
release of the plugin " +
                    "implementing the method signature" );
          return ( String )plugin.getClass() // this returns the concrete
type implementing the WikiPlugin interface
                                 .getMethod( "execute", Class.forName(
"org.apache.wiki.WikiContext" ), Map.class )
                                 .invoke( plugin, context, params );
      }
  } catch( final PluginException e ) {
      [...]
      throw ( PluginException )e.fillInStackTrace();
  } catch( final Throwable t ) {
      [...]
      throw new PluginException( rb.getString( "plugin.error.failed" ), t );
  }

WikiContext#getEngine() method could also be changed so its signature,
instead of returning an
Engine, returns a WikiEngine. That should allow reaching methods from
WikiEngine not present in
Engine, like, f.ex, all the getXYZManager() methods. However, note that
there are some methods in
WikiEngine that are not longer there, they've been moved to places were
they made sense. These
methods were used mainly for JSPWiki internal operations, so they're
unlikely used in custom
plugins. It's not impossible, though, but this kind of change should be
expected on a minor release
(the ones changing the middle number, i.e., 2.10.6 to 2.11.0).

Another way to solve this, which would avoid the use of reflection is
turning WikiPlugin into an
adapter. Let's say a new interface org.apache.wiki.api.plugin.Plugin is
created next to WikiPlugin,
which contains the proposed public api change:

public interface Plugin {
    String CORE_PLUGINS_RESOURCEBUNDLE = "plugin.PluginResources";
    String execute( Context context, Map< String, String > params ) throws
PluginException;
}

then WikiPlugin could become an adapter:

public interface WikiPlugin extends Plugin {

    /** {@inheritDoc} */
    @Override
    default String execute( final Context context, final Map< String,
String > params ) throws PluginException {
        Logger.getLogger( WikiPlugin.class ).warn(
this.getClass().getName() + " implements deprecated
org.apache.wiki.api.plugin.WikiPlugin" );
        Logger.getLogger( WikiPlugin.class ).warn( "Please contact the
plugin's author so there can be a new release of the plugin " +
                                                   "implementing the new
org.apache.wiki.api.plugin.Plugin interface" );
        return execute( ( WikiContext )context, params );
    }

    String execute( WikiContext context, Map< String, String > params )
throws PluginException;

}

WikiPlugin, although being in the api.plugin package would NOT be part of
the public api, i.e., it
would remain on the jspwiki-main module, whereas the public api would be in
a new jspwiki-api maven
module. I'm more inclined to this, mostly because all interfaces/classes on
the public api are not
prefixed with "Wiki" except for WikiPlugin, and then all the public api
would be uniformly named.
That would please all people like me who are somewhere in-between software
engineers and people
with obsessive-compulsive disorder :-) Jokes aside, the important thing is
that current plugins
would still run with the new API. (And WikiPlugin would eventually be
deleted from the source code)

Why introduce then the first option? Because that would be the way to go
with

(2) Filters

Not surpringsily, filter execution is handled by the different methods on
DefaultFilterManager. By
catching different AbstractMethodError on those methods we can make "old"
filters work alongside
the new API.

(3) Page Providers

This one is trickier as WikiPageProvider and WikiAttachmentProvider have
methods like:

Collection< SearchResult > findPages( QueryItem[] query );

with SearchResult and QueryItem being in the search package, with both of
them to land on the
public api, thus changing their package. Happens the same with at least
Acls, Page/WikiPage
Attachment/WikiAttachment.

What I've thought in this case to make them usable with the new API is a
couple of
WikiPage210AdapterProvider / WikiAttachment210AdapterProvider which would
wrap the 3rd party
implementation (that should be located through a property on the
jspwiki[-custom].properties file).
SearchResult / QueryItem classes would not be moved to the API package, but
copied. The API ones
should be used throughout the code, but the original ones (SearchResult /
QueryItem from search
package) would be kept so that the adapter providers can transform back and
forth from the adapter
provider to 3rd party provider. Also, the calls to the 3rd party provider
would be made using the
same reflection technique as before.

(4) Next steps

Hopefully, no more kilometric e-mails. On the short term, I'm planning to
extract the event
package to its own jspwiki-event maven module, and create a jspwiki-api
maven module. This module
would contain the full public API, although right now only part of it would
be used (Engine, Session
and maybe a few more classes), so it can be discussed and reasoned around
with a more clear focus.

After that, re-introduce API compatibility with plugins (easy) and filters
(a bit more of work but
hopefully doable too without spending too much time on it). It would be
really, *really* nice if
someone volunteered for the page providers: keeping the existing extensions
is gone to take some
time that I was planning to spend on other tasks, so any help with that
would mean more time spent
on the public api.

(5) JSPWiki installations' islands

We don't want to have them, and we strive to avoid them as much as
possible. Said that, I think
they're bound to happen someday. Keeping the backward compatibility is an
ongoing burden. It is
not that we shouldn't have it as a top priority, but that doesn't mean is
the absolute driver.
JSPWiki API hasn't changed in ~7 years. A minor release after introducing
the public API (that
is on 2.12.0 or 3.1.0, whatever we see fit) I plan / like to remove the
backward compatibility
introduced above, as it also means more complexity on the code base. That
would be a breaking
change in the API in about 8-9 years, which I don't find completely
unreasonable.

thoughts?


best regards,
juan pablo

On Sat, Mar 7, 2020 at 11:25 PM Juan Pablo Santos Rodríguez <
juanpablo.san...@gmail.com> wrote:

> Hi Murray,
>
> I'll look into make the current plugins mantain their signature if
> possible. As I wrote else-thread, keep in mind the 6 last
> releases contain code changes that could result in custom plugins /
> filters not working anymore. That would also
> happen on this release, whether the plugin signature changes or not. What
> I wouldn't want to do is to include back
> code that would make [#1] back into [#2]..
>
>
> best regards,
> juan pablo
>
> [#1]:
> https://jspwiki-wiki.apache.org/attach/JSPWiki3APIDesignProposal/highwheel-master.png
> [#2]:
> https://jspwiki-wiki.apache.org/attach/JSPWiki3APIDesignProposal/highwheel-2.11.0.M6-reduced.png
> (original
> image resulted in 36MB, have to scale it to keep the size reasonable, to
> see the full details is better to execute
> the maven plugin..)
>
> On Sat, Mar 7, 2020 at 4:21 AM Murray Altheim <murra...@altheim.com>
> wrote:
>
>>
>> > Hi Murray,
>> >
>> > for plugins, most probably there'll be a signature change on WikiPlugin,
>> > from:
>> > String execute( WikiContext context, Map< String, String > params )
>> throws
>> > PluginException;
>> >
>> > to:
>> > String execute( Context context, Map< String, String > params ) throws
>> > PluginException;
>>
>> Hi Juan Pablo,
>>
>> I realise you can't promise anything, but what I'm asking is that there
>> be an adapter-pattern package that maintains **exactly** the same
>> signature as the existing plugins, if at all possible. If we require
>> people
>> to re-code and ecompile plugins then in many cases they simply won't
>> upgrade JSPWiki, as in many cases they won't have time, don't have
>> the developer time or experience or personnel available, etc. as I
>> mentioned previously.
>>
>> If the changes proposed as part of this public API are merely changes
>> of name and package location (effectively facades over the existing
>> code), then an adapter package should be possible. If not, I can't say
>> I'd advocate for making such a change as I believe it would segregate
>> existing users into two camps: those able to re-code and re-install an
>> update, and those who can't due to existing plugins. That seems an
>> overly high price for the existence of a new public API that doesn't
>> add functionality, i.e., if we don't provide a compatible bridging adapter
>> package.
>>
>> Cheers,
>>
>> Murray
>>
>>
>> ...........................................................................
>> Murray Altheim <murray18 at altheim dot com>                       = =
>> ===
>> http://www.altheim.com/murray/                                     ===
>> ===
>>                                                                    = =
>> ===
>>      In the evening
>>      The rice leaves in the garden
>>      Rustle in the autumn wind
>>      That blows through my reed hut.
>>             -- Minamoto no Tsunenobu
>>
>>
>>
>>

Reply via email to