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

Reply via email to