polygene-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Niclas Hedhman <nic...@hedhman.org>
Subject Re: javax.script
Date Fri, 14 Apr 2017 02:00:07 GMT
Sandro, and everyone else who might be interested;

In Polygene, we allow a single method of an interface to be implemented by
a scripting language. The following code;

    @Mixins( ScriptMixin.class )
    public interface SomeService
    {
        String doSomething( String arg );
    }

will be implemented by a language defined at startup. The following
bootstrap selects JavaScript

    module.services( DomainType.class ).setMetaInfo( Scripting.JAVASCRIPT );

and we can put the implementation in a SomeService.js file;

    function doSomething( arg ) {
        return "Some Hello";
    }

The following is the injected scope,

    mixinBindings.put( "Polygene", spi );
    mixinBindings.put( "application", application );
    mixinBindings.put( "layer", layer );
    mixinBindings.put( "module", module );
    mixinBindings.put( "This", thisComposite );
    mixinBindings.put( "state", state );
    mixinBindings.put( "objectFactory", module.objectFactory() );
    mixinBindings.put( "unitOfWorkFactory", module.unitOfWorkFactory() );
    mixinBindings.put( "valueBuilderFactory", module.valueBuilderFactory()
);
    mixinBindings.put( "transientBuilderFactory",
module.transientBuilderFactory() );
    mixinBindings.put( "serviceFinder", module.serviceFinder() );
    mixinBindings.put( "typeLookup", module.typeLookup() );

which gives the script a great deal of freedom to do anything.

So, currently an interface can't be implemented by multiple scripting
languages, but I intend to change that too. We currently don't have
metaInfo on methods, but once we do, I intend to extend the declaration of
Scripting down to the method level, in which case different methods could
be implemented in different languages. Why would anyone do that? I don't
know...

In general, the Polygene scripting scope is probably much smaller than most
uses of Java Scripting API, so the problems are probably reduced as well.

Cheers
Niclas


On Fri, Apr 14, 2017 at 6:09 AM, Sandro Martini <sandro.martini@gmail.com>
wrote:
>
> Hi all,
> even Scala can be used as a scripting language, some time ago I did some
> tests and just for info there should be something related even in Apache
> Pivot sources in the trunk ... but due to the not aderence of Scala
classes
> (by default, unless using specifico annotations) to the Java Beans
> specification it wasn't so much useful (due to our usage in Apache Pivot).
>
> I remember that we had some problems when Running JavaScript code:
> with rhino all was ok, but to have all stuff working with the Java 8 new
js
> engine we did some work (scope of variables ,  bugged implementation of
> some features in old versione of Java 8, etc) ... my friend Roger did most
> of the work so if useful we can ask him.
>
> Just for info 😆.
>
> Bye,
> Sandro
>
>
> Il 09/Apr/2017 06:32, "Niclas Hedhman" <hedhman@gmail.com> ha scritto:
>
> > So, I have an isolated version running. A performance test would be
> > "interesting"...
> >
> > This is now in libraries/scripting and I am dropping the
libraries/lang-*
> > as they are no longer required.
> >
> > Also, there are tons of languages that are integrated into the
javax.script
> > for JVM. These I found by searching on my own,
> >
> > Groovy (Apache)
> > Python (Jython)
> > Ruby (JRuby)
> > Kotlin (Jetbrains)
> > Scheme (Kawa from GNU)
> > R (Renjin)
> > LISP (Armed Bear Common Lisp)
> >
> > but eventually I found
> > https://java.net/projects/scripting/sources/svn/show/trunk/engines
> > And that lists quite a few more languages.
> >
> > Now, I don't intend to test for all of these, but I think we should
enable
> > as many as possible if/when issues are reported. I.e. the ambition is to
> > support them all, but served on a case-by-case basis.
> >
> > I am adding some convenience for common languages.
> >
> > public class Scripting
> > {
> >     public static final Scripting JAVASCRIPT = new Scripting(
> > "nashorn", ".js" );
> >     public static final Scripting ECMASCRIPT = new Scripting(
> > "nashorn", ".js" );
> >     public static final Scripting GROOVY = new Scripting( "groovy",
> > ".groovy" );
> >     public static final Scripting RUBY = new Scripting( "jruby", ".rb"
);
> >     public static final Scripting PYTHON = new Scripting( "python",
".py"
> > );
> >     public static final Scripting KOTLIN = new Scripting( "kotlin",
".kt"
> > );
> >
> >
> > But constructors are public...
> >
> > Currently I have language to be declared on the Composite type;
> >
> >     module.transients( DomainType.class ).setMetaInfo(
> > Scripting.JAVASCRIPT ).withMixins( ScriptMixin.class );
> >
> >
> > But thinking that perhaps it is better to have the script name declared
as
> > MetaInfo
> >
> >     module.transients( DomainType.class ).setMetaInfo( new
> > Scripting("domain.py") ).withMixins( ScriptMixin.class );
> >
> > OR, I could change it to not use any MetaInfo and search for
implementation
> > by extension, and whatever is found is used.
> >
> > Feedback on that is appreciated.
> >
> >
> > Reloading is supported with the interface ScriptReloadable, just like
> > before. Add the interface to the composite type to make it available.
> >
> > Scripting allows redirect of stdout/stderr/stdin, and I support that.
Just
> > add interface ScriptRedirect to the composite type.
> >
> > The following bindings are made to the script environment (if I missed
> > something import, let me know)
> >
> >
> >     mixinBindings.put( "Polygene", spi );
> >     mixinBindings.put( "application", application );
> >     mixinBindings.put( "layer", layer );
> >     mixinBindings.put( "module", module );
> >     mixinBindings.put( "This", thisComposite );
> >     mixinBindings.put( "state", state );
> >     mixinBindings.put( "objectFactory", module.objectFactory() );
> >     mixinBindings.put( "unitOfWorkFactory", module.unitOfWorkFactory()
);
> >     mixinBindings.put( "valueBuilderFactory",
module.valueBuilderFactory()
> > );
> >     mixinBindings.put( "transientBuilderFactory",
> > module.transientBuilderFactory() );
> >     mixinBindings.put( "serviceFinder", module.serviceFinder() );
> >     mixinBindings.put( "typeLookup", module.typeLookup() );
> >
> >
> > FInally, there is support for context attributes, but likely not used
that
> > much. Both ENGINE and GLOBAL attributes are accessible via the
> > ScriptAttributes (ScriptAttributes.All) interface.
> >
> > I find it quite hard to support "invokeMethod" in the invocable
interface,
> > as one first would need to instantiate an object, in those languages
that
> > has objects or equivalent, and then call methods there on. I think thar
> > "invokeFunction" is in reality enough, and other variants of what is
> > possible in "eval()" can be skipped for our purposes.
> >
> > I have tried to update the documentation to the best of my abilities.
More
> > meat is always welcome, as well as testing and docs for other languages,
> > especially those that I mark as supported.
> >
> > This is quite a massive feature that was easy to implement. In 3.1, I
think
> > we should expand this to somehow support other fragments to be
implemented
> > in scripts as well. I think we are really living up to the POLYgene
part.
> >
> >
> > Feedback?
> >
> >
> >
> >
> >
> > On Sun, Apr 9, 2017 at 7:22 AM, Niclas Hedhman <hedhman@gmail.com>
wrote:
> >
> > >
> > > Ok, I will try to figure out if single compile per composite type is
> > > possible. My initial finding is that it is not.
> > >
> > > Expect it to complete today.
> > >
> > > On Apr 8, 2017 20:58, "Paul Merlin" <paulmerlin@apache.org> wrote:
> > >
> > > Having a script scope per composite instance makes sense to me. Script
> > > scopes allows scripts to hold state, we don't want to share state
> > > between composite instances. Just like you said, this is not a
> > > performance issue for Services. And if you need single use composites
> > > then that's probably because you don't want to share their state.
> > >
> > > Ideally we would be able to do the "compilation" once per composite
type
> > > and then "clone" the scope, or use "sub-contexts" for each instance.
> > > Don't know if that's possible using the javax.scripting api though.
> > >
> > >
> > >
> > > Niclas Hedhman a écrit :
> > > > Hi,
> > > > I mentioned yesterday that I am working on putting javax.script as
the
> > > > integration point with JavaScript and Groovy instead of our direct
> > > > dependencies on each.
> > > >
> > > > There is one thing that 'bothers me'; Scopes.
> > > >
> > > > So a single class ScriptMixin will handle the reading and invoking
the
> > > > javax.script side, but what is the scope?
> > > >
> > > > ScriptMixin is the supplied Mixin to any number of Composite Types
for
> > > any
> > > > number of interfaces and methods.
> > > >
> > > > I *could* create one ScriptEngine per method, or per
> > > method.declaringClass,
> > > > or per Composite primary type or per Polygene runtime.
> > > >
> > > > A ScriptEngine has ScriptContexts which in turn holds the Bindings.
The
> > > > Bindings contain the integration objects (accessible in both Java
and
> > > > script language) as well as the script itself. ScriptContext holds 2
> > > > Bindings (GLOBAL and ENGINE), and the handling of them internally is
> > > > non-intuituve.
> > > >
> > > > Now, the question is what is the scope of the script itself? Should
it
> > > be a
> > > > global script per primary type, or should we isolate each composite
> > > > instance with its own script engine? Or should it be a global script
> > > > environment to really open the gates of problems?
> > > >
> > > > I tend to lean on "script engine per composite instance", but it
feels
> > a
> > > > bit heavy-handed. I guess it doesn't matter which one if the use is
> > > > Services, but for short-lived composites it would also mean one
compile
> > > > cycle per creation (==slow?)
> > > >
> > > > Ideas and feedback most welcome.
> > > >
> > > >
> > > > For those who have no idea what I am talking about;
> > > >
> > > > It has been possible to implement the mixin methods of composites in
> > > other
> > > > languages, such as JavaScript and Groovy.
> > > >
> > > > package com.abc.script;
> > > >
> > > > @Mixins( ScriptMixin.class )
> > > > public interface SomeType extends ScriptReloadable
> > > > {
> > > >     String doMyBidding( String whatever );
> > > > }
> > > >
> > > > and then have (for instance) JavaScript in a resource
> > > > com/abc/script/SomeType.js with;
> > > >
> > > > function doMyBidding( whatever ) {
> > > >     return "Great: " + whatever;
> > > > }
> > > >
> > > > and the ScriptReloadable.reloadScript() will recompile it for next
> > time,
> > > > i.e code replacement in runtime.
> > > >
> > > > Inside the script environment, things like serviceFinder,
> > > > valueBuilderFactory and so on are available as global variables.
> > > >
> > > > Cheers
> > >
> > >
> > >
> >
> >
> > --
> > Niclas Hedhman, Software Developer
> > http://zest.apache.org - New Energy for Java
> >




--
Niclas Hedhman, Software Developer
http://polygene.apache.org - New Energy for Java

Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message