Yeah, that is the conclusion I came to, dynamic binding for the win, I
think :).
On 4 Mar 2015 18:47, <[email protected]> wrote:

> (if it's just a regular ThreadLocal, you should be able to get its value
> through (.get tx))
>
> To elucidate briefly, I mean something like this:
>
> (def ^:dynamic *tx*)
>
> ;; elsewhere
> (binding [*tx* (.get tx)]
>    ...do stuff
>    ...cleanup)
>
> a with-tx macro would make this pattern reusable throughout your code.
>
> On Wednesday, March 4, 2015 at 1:43:36 PM UTC-5, [email protected]
> wrote:
>>
>> Ah I think I understand now! Is it possible to dereference the connection
>> and "hold on" to the thread local state? If so, then dynamically binding
>> the transactional connection and doing all of your work within that context
>> might be a good solution. You can also write a macro to do this,
>> closing/doing cleanup of the connection before exiting the dynamic scope of
>> your transaction.
>>
>> On Wednesday, March 4, 2015 at 1:15:02 PM UTC-5, Colin Yates wrote:
>>>
>>> Hi Adrian, and thanks for replying.
>>>
>>> I understand your point, but the subtlety is that a transactional
>>> connection is per function invocation where as the database component
>>> is per Component lifecycle - passing the db around isn't sufficient
>>> here.
>>>
>>> Spring plumbing binds a transactional connection to a thread local and
>>> then passes a connection proxy around - accessing that proxy magically
>>> (through the use of the lovely AOP) resolves to the current
>>> thread-local transactional connection.
>>>
>>> I don't see any option other than to re-implement that in Clojure or
>>> pass an explicit 'unit-of-work' around but it all feels wrong in
>>> Clojure.
>>>
>>> The problem at the moment is that the implementation of each protocol
>>> will execute in separate transactions.
>>>
>>>
>>>
>>>
>>> On 4 March 2015 at 18:06,  <[email protected]> wrote:
>>> > Having never used Spring (or anything else resembling the style of
>>> code you
>>> > presented) I don't really know if I'm understanding what you're
>>> asking.
>>> >
>>> > However, it might be useful to wrap your database in a component. I do
>>> this
>>> > for Datomic all of the time, and the boilerplate looks something like
>>> this:
>>> > https://gist.github.com/aamedina/a1ca5e97c1a5d73fe141. I'm not sure
>>> exactly
>>> > how this would fit into JDBC, but I'm sure you can figure it out if
>>> you
>>> > think it would be worthwhile.
>>> >
>>> > I then pass the database component to any other component in my system
>>> that
>>> > I know will make use of it. If used in a middleware-like scenario
>>> (where an
>>> > arbitrary function is passed to the component, possibly composed with
>>> other
>>> > functions, and invoked elsewhere), I usually have a convention where I
>>> pass
>>> > a map of options as an argument to the handler, and make the database
>>> a
>>> > value in that map.
>>> >
>>> >
>>> > On Wednesday, March 4, 2015 at 12:58:58 PM UTC-5, Colin Yates wrote:
>>> >>
>>> >> Hi,
>>> >>
>>> >> I am looking for the Clojure equivalent of:
>>> >>
>>> >> class Whatever {
>>> >>     @Transactional
>>> >>     void doSomething(IDoSomething one, IDoSomethingElse two) {
>>> >>       one.doSomething()
>>> >>       two.doSomething()
>>> >>     }
>>> >> }
>>> >>
>>> >> where both one and two are dependency injected with a proxy which
>>> resolves
>>> >> to a thread local database connection. In addition, one might itself
>>> have a
>>> >> collaborator which itself has a collaborator which needs a
>>> datasource.
>>> >>
>>> >> So far I have two protocols:
>>> >>
>>> >> (defprotocol IDoSomething
>>> >>  (do-something [this ...])
>>> >>
>>> >> (defprotocol IDoSomethingElse
>>> >>  (do-something [this ...])
>>> >>
>>> >> Each protocol may have a number of implementations, one of which is a
>>> JDBC
>>> >> implementation:
>>> >>
>>> >> (defrecord JdbcIDoSomething [db]
>>> >>   (do-something [this ...] ...))
>>> >>
>>> >> The problem is that the calling code only gets provided an
>>> IDoSomething
>>> >> and an IDoSomethingElse and it wants to do something like:
>>> >>
>>> >> (let [one (->JdbcDoSomething db) two (->JdbcDoSomethingElse db)]
>>> >>   (with-transaction [tx db]
>>> >>     (do-something one)
>>> >>     (do-something-else two)))
>>> >>
>>> >> The problem here is that the implementations of do-something and
>>> >> do-something-else won't have access to the local bound 'tx', they
>>> will have
>>> >> their own 'db'.
>>> >>
>>> >> I realise the general argument is to be explicit and pass a db as the
>>> >> first argument to the protocol but this isn't appropriate in this
>>> case as
>>> >> there are validly multiple implementations. I could abstract a
>>> >> 'unit-of-work' and pass that as the first argument to the protocols
>>> but that
>>> >> seems a bit painful.
>>> >>
>>> >> Also, these protocols may be used quite far away from where the
>>> database
>>> >> code lives and passing a parameter all the way through the call stack
>>> is
>>> >> painful.
>>> >>
>>> >> I am using Stuart Sierra's components if that makes any difference.
>>> >>
>>> >> I can't be the first person to run into this but google is
>>> surprisingly
>>> >> unhelpful which makes me think I have missed something fundamental,
>>> and that
>>> >> I have something upside down.
>>> >>
>>> >> What do you all do?
>>> >>
>>> >>
>>> > --
>>> > You received this message because you are subscribed to the Google
>>> > Groups "Clojure" group.
>>> > To post to this group, send email to [email protected]
>>> > Note that posts from new members are moderated - please be patient
>>> with your
>>> > first post.
>>> > To unsubscribe from this group, send email to
>>> > [email protected]
>>> > For more options, visit this group at
>>> > http://groups.google.com/group/clojure?hl=en
>>> > ---
>>> > You received this message because you are subscribed to the Google
>>> Groups
>>> > "Clojure" group.
>>> > To unsubscribe from this group and stop receiving emails from it, send
>>> an
>>> > email to [email protected].
>>> > For more options, visit https://groups.google.com/d/optout.
>>>
>>  --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to [email protected]
> Note that posts from new members are moderated - please be patient with
> your first post.
> To unsubscribe from this group, send email to
> [email protected]
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Clojure" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to [email protected]
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
--- 
You received this message because you are subscribed to the Google Groups 
"Clojure" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to