perplexed by jndi connection used in conjunction with dbloanwrapper and squerylrecord

47 views
Skip to first unread message

E. Biggs

unread,
Mar 20, 2011, 3:56:13 PM3/20/11
to Lift
Hello Lift People,

I'm having a strange issue with this stack:

oracle, jetty, c3p0, jndi, dbloanwrapper, squerylrecord

I'm not sure if this issue is specific to just oracle, though as I
haven't tried it with other servers.

The unexpected behavior I'm seeing, is this exception gets thrown with
over 90% of the requests, the rest of the times, the request is served
as expected.

java.lang.RuntimeException: Exception while executing statement : You
can't operate on a closed Connection!!!

I seem to have isolated the issue down to the only possible
explanation being that for some reason the connection is returned to
the pool before it should be. The reason I believe this to be true is
when I get a reference to the connection myself without relying on
lift/squerylrecord to do it, everything seems to work just fine.

Interestingly, when I rely on lift's own connection pooling everything
works just fine as well. This perplexes me because it would seem that
the framework would be returning connections to the pool at the same
time whether it be jndi or the built in connection pooling.

Now, I realize that an issue like this needs a sample project, so i've
whipped one up and put it here:
http://ebiggs.com/jndiconnfail.zip

You will need to edit src/main/jetty/jetty-env.xml and src/main/scala/
test/KickTheTires.scala with your connection parameters.

If you want to see if it works with other databases you'll probably
have to modify the sbt project. I don't know if the problem is only
with oracle or not (I suspect not?!)

You'll need to to an sbt run to kick the tires to create the schema
and populate it with sample data

Then index.html ought to demonstrate the problem and index2.html ought
to demonstrate the fact that the pool works as expected outside of the
lift/squerylrecord framework.

Thanks for any attention to this issue.

E. Biggs

unread,
Mar 21, 2011, 1:09:42 PM3/21/11
to Lift
Well I've been investigating this on my own and it seems to be some
strange incompatibility with using a jndi datasource with
squerylrecord's support for DB.use. But for some reason DB.use works
just fine if you use a DBVendor/ConnectionManager instead.

in the squerylrecord source (https://github.com/lift/framework/blob/
master/persistence/squeryl-record/src/main/scala/net/liftweb/
squerylrecord/SquerylRecord.scala) there is a
SessionFactory.externalTransactionManagementAdapter that's just using
DB.currentConnection (which when I call it myself gives me a perfectly
usable connection - so I have no way of timely identifying how/why
this may or may not be a bug.)

In the meantime, using the SquerylRecord.initWithSquerylSession option
instead of SquerylRecord.init, and then adding a
RecordTypeMode.transaction LoanWrapper to s.around seems to be a
satisfactory alternative to DB.use. But I'd like to use DB.use if i
can. I'll leave up my http://ebiggs.com/jndiconnfail.zip in case
anybody wants to tackle this issue, it's certainly beyond me at this
time.

E. Biggs

unread,
Mar 22, 2011, 4:34:11 PM3/22/11
to Lift
Only seen one download of this in my webserver log, so I thought I'd
post my boot.scala here for easy reference. Is this not sufficient for
making squerylrecord use DB.use for accessing a jndi datasource?

1) tell the DefaultConnectionIdentifier the appropriate jndi name.
2) call SquerylRecord.init() with the appropriate adapter.
3) use DefaultConnectionIdentifier with the DB.buildLoanWrapper and
add it to S.around

Did I miss anything?

If not, shall I open a bug report?

22 /**
23 * A class that's instantiated early and run. It allows the
application
24 * to modify lift's environment
25 */
26 class Boot {
27 def boot {
28 DefaultConnectionIdentifier.jndiName = "jdbc/testPool"
29 println("jndi available? " + DB.jndiJdbcConnAvailable_?)
30 if (!DB.jndiJdbcConnAvailable_?)
31 DB.defineConnectionManager(DefaultConnectionIdentifier,
32 new StandardDBVendor(Props.get("db.driver") openOr
"org.h2.Driver",
33 Props.get("db.url") openOr
"jdbc:h2:test",
34 Props.get("db.user"),
Props.get("db.password")))
35
36 SquerylRecord.init(() => new OracleAdapter)
37
38 println("name of Author.name is " +
test.model.Author.name.name)
39
40
41 // where to search snippet
42 LiftRules.addToPackages("test")
43
44 // Build SiteMap
45 val entries = Menu(Loc("Home", List("index"), "Home")) ::
46 Menu(Loc("Home2", List("index2"), "Home2")) :: Nil
47 LiftRules.setSiteMap(SiteMap(entries:_*))
48
49
S.addAround(DB.buildLoanWrapper(DefaultConnectionIdentifier::Nil))
50 S.addAround(new LoanWrapper {
51 def apply[T](f: => T): T =
ultimately(println(S.getAllNotices))(f)
52 })
53 }
54 }

David Pollak

unread,
Mar 24, 2011, 9:26:46 AM3/24/11
to lif...@googlegroups.com
The developer who focuses on the Lift Record/Squeryl integration is off for a few weeks with medical issues.  We're working on recruiting an alternate.  Please sit tight while we find someone who can help you out.

Sorry for the inconvenience.



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




--
Lift, the simply functional web framework http://liftweb.net

E. Biggs

unread,
Mar 24, 2011, 1:28:57 PM3/24/11
to Lift
Thanks David, not a problem... using squeryl's own transactions suits
my needs for the time being.

On Mar 24, 6:26 am, David Pollak <feeder.of.the.be...@gmail.com>
wrote:
> Beginning Scalahttp://www.apress.com/book/view/1430219890

David Whittaker

unread,
Mar 25, 2011, 1:36:09 PM3/25/11
to lif...@googlegroups.com
Could you create an Assembla ticket for this and assign to to me so it doesn't fall through the cracks.

Thanks.

arp

unread,
Jun 29, 2011, 8:44:11 PM6/29/11
to lif...@googlegroups.com
Firstly if posting to this group discussion after such a long time is incorrect my apologies, I found a link to this discussion in ticket #950.

I had been experiencing this problem a few weeks ago and tracked it down to the db connection being cached in a thread local. I changed the following line in the SquerylRecord object:

  private object currentSession extends DynoVar[Session]


to:


  private object currentSession extends RequestVar[Box[Session]](Empty)


By not clearing the DynoVar at the end of the request, the closed Session is used in following requests and fails.


I don't think the above changes are an appropriate solution to this this issue as it places a dependency on webkit. The DynoVar just needs to be cleaned up after the request.


Hope this helps.

David Whittaker

unread,
Jun 30, 2011, 10:37:56 AM6/30/11
to lif...@googlegroups.com
No problem responding to an older thread as far as I'm concerned, and I appreciate that you're looking to help make Squeryl/Record better.

In this case I'm familiar with the issue.  The problem is that there is no way to "plug in" to the Lift transaction lifecycle and be notified when the transaction ends.  While RequestVar would work for most cases,, there is still a pretty large mismatch between how Lift handles transactions and how Squeryl does and after getting some community feedback (https://groups.google.com/group/liftweb/browse_thread/thread/bcba25b3b8b71b1a/211cac563bcd9107) my feeling is that Lift transaction support should be deprecated for Lift 2.5.

Do you have a need for Lift transactions as opposed to Squeryl transactions?  I could still be swayed to keep them but I haven't heard any convincing reasons yet why Lift transaction support is necessary.

-Dave

--
You received this message because you are subscribed to the Google Groups "Lift" group.
To view this discussion on the web visit https://groups.google.com/d/msg/liftweb/-/9dnUQZ8ruUwJ.
Reply all
Reply to author
Forward
0 new messages