I'm not sure how closely you've looked at the code I posted for
JNDIResource, but my intention was essentially to create a subclass of
RequestVar customized for managing JNDI resources that provided ways
to override both initialization and cleanup of the resource. I thought
that RequestVar would be appropriate because I don't want some of
those resources (specifically transactions) to be hanging around
longer than a request; this work is an extension of the JPA stuff that
Derek's been doing to enable JTA-type persistence units instead of
just resource-local.

In this case, I'm managing two types of interdependent resources,
EntityManagers and UserTransactions. I can't use an EntityManager
without being within the scope of an active UserTransaction. So
cleanup is one issue, but so is initialization - when I obtain an
EntityManager instance, I want it to be guaranteed that an active
UserTransaction is available. The thing that's really hackish about my
implementation of cleanupFunc is that I'm depending upon the call to
cleanupFunc that occurs in the implementation of AnyVar#is that's
nominally intended to register the cleanup function for the default
value. Since dflt is a call-by-name parameter, I can't extensibly tack
a call to an additional initialization function on there, and I can't
put the call to the initialization in the constructor because that's
not guaranteed to be called on every request; in the AnyVar#is
function right where cleanupFunc is called is about the only place I
could figure out that would reliably do that setup.

Kris

On Mon, Sep 29, 2008 at 2:12 PM, David Pollak
<[EMAIL PROTECTED]> wrote:
> Kris,
>
> If your goal is to have some cleanup function added at the end of the
> request, you can do the following:
>
> trait Cleanable {def cleanup: Unit}
>
> class MyStuff {
>   var needsCleanup: Can[Cleanable] = Empty
>
>   S.addCleanupFunc(() => needsCleanup.foreach(_.cleanup))
> }
>
> So, in the above code, if you assign some value to needsCleanup, it will be
> cleaned up at the end of the request.
>
> Does this help point you in the right direction?
>
> Thanks,
>
> David
>
> On Mon, Sep 29, 2008 at 11:46 AM, Kris Nuttycombe
> <[EMAIL PROTECTED]> wrote:
>>
>> I'm not opposed to that design, but I do think that it's a little
>> unexpected that any declaration of a RequestVar essentially creates a
>> singleton. This is probably once again something that could be solved
>> with a bit better documentation. It's surprising to use a class in a
>> pattern where one would ordinarily expect to create independent
>> instances and to get singletons instead.
>>
>> What other mechanisms exist to bind to Lift's lifecycle hooks?
>> RequestVar does essentially what I need it to do in my hack, but
>> relying upon the internal implementation of AnyVar makes me a little
>> queasy.
>>
>> Kris
>>
>> On Mon, Sep 29, 2008 at 12:14 PM, David Pollak
>> <[EMAIL PROTECTED]> wrote:
>> > Kris,
>> >
>> > You are correct that RequestVar and SessionVar reference the same
>> > underlying
>> > data no matter what instances they are part of.  There are a bunch of
>> > design
>> > reasons for this.  If you have a bunch of instance variables that have
>> > different things that need cleaning up, I'd suggest not using
>> > RequestVar.
>> >
>> > Sorry,
>> >
>> > David
>> >
>> > On Sat, Sep 27, 2008 at 11:34 AM, Kris Nuttycombe
>> > <[EMAIL PROTECTED]> wrote:
>> >>
>> >> For the record, here's my ugly-ass workaround, depending upon the fact
>> >> that cleanupFunc is called to obtain the cleanup function at the same
>> >> time that the default value is set.
>> >>
>> >> import javax.naming.InitialContext
>> >> import net.liftweb.util.{Can,Full,Log}
>> >> import net.liftweb.http.RequestVar
>> >>
>> >> object JNDIResource {
>> >>  val context = new InitialContext()
>> >> }
>> >>
>> >> import JNDIResource._
>> >>
>> >> abstract class JNDIResource[T](val name: String) extends
>> >> RequestVar[T](context.lookup(name).asInstanceOf[T]) {
>> >>
>> >>  // This is way too dependent upon an implementation detail of the
>> >> superclass.
>> >>  override def cleanupFunc : Can[() => Unit] = {
>> >>    Log.debug("Initializing JNDI resource " + name + "(" + this.is +
>> >> ")")
>> >>    initialize(this.is) //this will result in a recursive call, but
>> >> the the order of operations is such that it will take the other
>> >> branch.
>> >>
>> >>    Full(() => {
>> >>        Log.debug("Releasing JNDI resource " + name + "(" + this.is +
>> >> ")")
>> >>        dispose(this.is)
>> >>      })
>> >>  }
>> >>
>> >>  /**
>> >>   * Subclasses should override this method to provide initialization
>> >> of the resource
>> >>   */
>> >>  protected def initialize(resource : T) {
>> >>  }
>> >>
>> >>  /**
>> >>   * Subclasses should override this method to provide cleanup on the
>> >> resource
>> >>   */
>> >>  protected def dispose(resource: T) {
>> >>  }
>> >> }
>> >>
>> >>
>> >
>> >
>> >
>> > --
>> > Lift, the simply functional web framework http://liftweb.net
>> > Collaborative Task Management http://much4.us
>> > Follow me: http://twitter.com/dpp
>> > Git some: http://github.com/dpp
>> >
>> > >
>> >
>>
>>
>
>
>
> --
> Lift, the simply functional web framework http://liftweb.net
> Collaborative Task Management http://much4.us
> Follow me: http://twitter.com/dpp
> Git some: http://github.com/dpp
>
> >
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to liftweb@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to