On Wed, Dec 24, 2014 at 9:30 PM, Howard Lewis Ship <hls...@gmail.com> wrote:
> I don't see why you need to make the var dynamic, as it contains a mutable > value (a promise) itself. > Actually it's not needed. Counterclockwise plugin complained about non-dynamic global var, so I made it dynamic to avoid this warning. > However, this does bring to mind an idea for 5.5, that Tapestry could > define a dynamic Var to contain the registry, and bind that Var whenever it > invokes a Clojure function via the interop. > Great idea! That would make a lot of sense to have instant access to Tapestry services from Clojure runtime. > On Mon, Dec 22, 2014 at 10:51 AM, Ilya Obshadko <ilya.obsha...@gmail.com> > wrote: > > > No, I didn't try getObject() yet. That means the code for injection would > > be a little bit more complex, but I'll explain using "simple" version > from > > the previous message: > > > > https://gist.github.com/xfyre/f6a62b3f63ed01929054 > > > > Line 4: define dynamic global variable as (promise) - it's not available > at > > the time of compilation. > > > > Lines 6-8: this is a Tapestry-mapped function that will be called during > > @Startup phase to "deliver" ObjectLocator instance (after promise was > > delivered, it becomes immutable and can't be mutated anymore). > > > > Lines 10-15: macro that accepts service-bindings in a usual Clojure > > bindings format, like [hibernate-session Session my-service MyService], > > when odd entries are variable names and even entries are class names (in > > Clojure you don't need to use .class). The macro reconstructs this list > so > > Class names are > > converted to getService() calls, and then during let binding (syntax > > unquote on line 15) those services are finally bound to variables for the > > later use. > > > > Lines 19-23 is an example of using this macro. > > > > > > On Sun, Dec 21, 2014 at 10:22 PM, Thiago H de Paula Figueiredo < > > thiag...@gmail.com> wrote: > > > > > On Thu, 18 Dec 2014 20:01:11 -0200, Ilya Obshadko < > > ilya.obsha...@gmail.com> > > > wrote: > > > > > > One more question regarding ObjectLocator. > > >> Turns out it cannot resolve services like Logger, complaining that no > > >> service implements its interface. > > >> Could you suggest how to solve it? > > >> > > > > > > Have you tried getObject() instead of getService()? Logger isn't a > > > Tapestry-IoC service (unless you create it, of course), so you cannot > use > > > getService() to get it. > > > > > > By the way, as someone who wants to learn Clojure, could you please > > > explain your Clojure snippet? :) > > > > > > > > > > > >> On Thu, Dec 18, 2014 at 11:20 PM, Ilya Obshadko < > > ilya.obsha...@gmail.com> > > >> wrote: > > >> > > >> So, my solution for this is actually quite simple: > > >>> > > >>> (ns com.xdance.tapestry.serviceregistry > > >>> > > >>> (:import (org.apache.tapestry5.ioc ObjectLocator))) > > >>> > > >>> > > >>> (def ^:dynamic ^ObjectLocator *tapestry-registry-ref* (promise)) > > >>> > > >>> > > >>> (defn init-registry [^ObjectLocator registry] > > >>> > > >>> "Must be called during service initialization to set up Tapestry > > >>> registry object" > > >>> > > >>> (deliver *tapestry-registry-ref* registry)) > > >>> > > >>> > > >>> (defmacro with-tapestry-services [service-bindings & body] > > >>> > > >>> "Apply service bindings to body" > > >>> > > >>> (let [service-binding-pairs (partition-all 2 service-bindings) > > >>> > > >>> service-binding-exprs (map #(vector (first %1) `(.getService > ( > > >>> deref *tapestry-registry*) ~(second %1))) service-binding-pairs) > > >>> > > >>> service-binding-final (vec (reduce concat > > >>> service-binding-exprs))] > > >>> > > >>> `(let ~service-binding-final ~@body))) > > >>> > > >>> > > >>> The only thing I need to do is to bind init-registry function to > > Tapestry > > >>> service interface and call it during startup phase. There might be > > better > > >>> approaches probably. > > >>> > > >>> On Thu, Dec 18, 2014 at 6:49 PM, Ilya Obshadko < > > ilya.obsha...@gmail.com> > > >>> wrote: > > >>> > > >>> Thanks Howard, that's making a lot of sense. > > >>>> > > >>>> However my initial though was about injecting Clojure globals > > >>>> (specifically, one global containing service registry) during the > call > > >>>> to > > >>>> "require" IFn. I still couldn't find any ways to manipulate initial > > >>>> Clojure > > >>>> environment, although there are obvious workarounds (for example I > > could > > >>>> have a specific function inside Clojure namespace that could be used > > to > > >>>> inject necessary objects using mutable globals). I'm still looking > for > > >>>> more > > >>>> concise and accurate way to do that. > > >>>> > > >>>> On Thu, Dec 18, 2014 at 7:35 AM, Howard Lewis Ship < > hls...@gmail.com> > > >>>> wrote: > > >>>> > > >>>> Actually, Clojure interop with Java is very good, so a Clojure > > function > > >>>>> could be passed a Java object: > > >>>>> > > >>>>> (defn frobnicate-the-request > > >>>>> [^Request request] > > >>>>> (.setAttribute request "xyzzyx" (compute-the-magic-name))) > > >>>>> > > >>>>> The ^Request part is a type hint, it allows the Clojure compiler to > > >>>>> generate proper bytecode to access the methods of the request > without > > >>>>> using > > >>>>> reflection. > > >>>>> > > >>>>> You quickly get used to the leading dot (which itself is sugar > syntax > > >>>>> over > > >>>>> the more primitive interop special form). > > >>>>> > > >>>>> Now, in terms of Clojure interop ... the library I put together ago > > on > > >>>>> a > > >>>>> whim was about efficiently exposing Clojure functions bundled > > together > > >>>>> as > > >>>>> an arbitrary Java interface. > > >>>>> > > >>>>> If you pass the Registry to a Clojure function, it will be quite > > >>>>> capable > > >>>>> of > > >>>>> pulling out whatever it needs. > > >>>>> > > >>>>> A lot of the capabilities of Clojure are very familiar to Tapestry > > >>>>> users: > > >>>>> thread bound values (inside Clojure vars) for example. > > >>>>> > > >>>>> My primary thought about integrating Clojure would be to allow a > > >>>>> Tapestry > > >>>>> app to jump into Clojure to work with the Datomic APIs natively, > > rather > > >>>>> than the Java API to Datomic, which is decidedly second class. > > >>>>> > > >>>>> On Tue, Dec 16, 2014 at 5:24 AM, Thiago H de Paula Figueiredo < > > >>>>> thiag...@gmail.com> wrote: > > >>>>> > > > >>>>> > On Mon, 15 Dec 2014 18:29:22 -0200, Ilya Obshadko < > > >>>>> ilya.obsha...@gmail.com> > > >>>>> > wrote: > > >>>>> > > > >>>>> > > > >>>>> > How are Java objects usually passed to Clojure code? The > > recommended > > >>>>> way? > > >>>>> >>> > > >>>>> >> > > >>>>> >> Java objects are passed to Clojure functions in exactly the same > > way > > >>>>> they > > >>>>> >> are passed to Java method (because internally Clojure function > is > > >>>>> just an > > >>>>> >> implementation of IFn interface, and function call is > invoke(...) > > on > > >>>>> its > > >>>>> >> instance). > > >>>>> >> > > >>>>> > > > >>>>> > Now I was the one who hasn't made a clear question. :) I'm not > > asking > > >>>>> > about how Clojure passes function arguments. I meant when you > call > > >>>>> Clojure > > >>>>> > code from Java code, how do you pass a Java object so it can be > > used > > >>>>> inside > > >>>>> > Clojure code? > > >>>>> > > > >>>>> > But I don't want to pass services to Clojure functions, I'd like > > to > > >>>>> >> inject them into Clojure namespace when clojure.core/require is > > >>>>> executed. > > >>>>> >> > > >>>>> > > > >>>>> > Got it. I have no idea how to do that given my almost no > knowledge > > of > > >>>>> > Clojure. But I guess there's some way of doing that. > > >>>>> > > > >>>>> > > > >>>>> > -- > > >>>>> > Thiago H. de Paula Figueiredo > > >>>>> > Tapestry, Java and Hibernate consultant and developer > > >>>>> > http://machina.com.br > > >>>>> > > > >>>>> > ------------------------------------------------------------ > > >>>>> --------- > > >>>>> > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > > >>>>> > For additional commands, e-mail: users-h...@tapestry.apache.org > > >>>>> > > > >>>>> > > > >>>>> > > >>>>> -- > > >>>>> Howard M. Lewis Ship > > >>>>> > > >>>>> Creator of Apache Tapestry > > >>>>> > > >>>>> The source for Tapestry training, mentoring and support. Contact me > > to > > >>>>> learn how I can get you up and productive in Tapestry fast! > > >>>>> > > >>>>> (971) 678-5210 > > >>>>> http://howardlewisship.com > > >>>>> @hlship > > >>>>> > > >>>>> > > >>>> > > >>>> > > >>>> -- > > >>>> Ilya Obshadko > > >>>> > > >>>> > > >>>> > > >>> > > >>> -- > > >>> Ilya Obshadko > > >>> > > >>> > > >>> > > >> > > >> > > > > > > -- > > > Thiago H. de Paula Figueiredo > > > Tapestry, Java and Hibernate consultant and developer > > > http://machina.com.br > > > > > > --------------------------------------------------------------------- > > > To unsubscribe, e-mail: users-unsubscr...@tapestry.apache.org > > > For additional commands, e-mail: users-h...@tapestry.apache.org > > > > > > > > > > > > -- > > Ilya Obshadko > > > > > > -- > Howard M. Lewis Ship > > Creator of Apache Tapestry > > The source for Tapestry training, mentoring and support. Contact me to > learn how I can get you up and productive in Tapestry fast! > > (971) 678-5210 > http://howardlewisship.com > @hlship > -- Ilya Obshadko