Re: [Lift] Maven projects generating with old Lift versions?
Right, I know about the breaking change, but I'm not immediately sure how that's relevant here since the command I pasted seems to use generate. Here's what I've just found. This script works fine: #!/bin/sh mvn archetype:generate \ -DarchetypeRepository=http://scala-tools.org/repo-snapshots \ -DremoteRepositories=http://scala-tools.org/repo-snapshots \ -DarchetypeGroupId=net.liftweb \ -DarchetypeArtifactId=lift-archetype-blank \ -DarchetypeVersion=2.0-SNAPSHOT \ -DgroupId=$1 \ -Dversion=1.0-SNAPSHOT -DartifactId=$2 \ This one doesn't and fetches 0.8: #!/bin/sh mvn archetype:generate \ -DarchetypeRepository=http://scala-tools.org/repo-snapshots \ -DremoteRepositories=http://scala-tools.org/repo-snapshots \ -DarchetypeGroupId=net.liftweb \ -DarchetypeVersion=2.0-SNAPSHOT \ -DgroupId=$1 \ -Dversion=1.0-SNAPSHOT -DartifactId=$2 \ This spares me from having to remember lift-archetype-blank or any of the other lift-archetype-blah names, since I just select them from the menu. But it isn't generating with up-to-date data, despite using the new method. What am I missing? Now that I pay closer attention to the output, I see that it is creating an old archetype when I use the menu. Am I using archetype:create and just not knowing it when I don't explicitly state on the command line that I want a blank project? If so then Maven should perhaps make that a bit more intuitive. :) On 03/02/2010 02:07 PM, Jeppe Nejsum Madsen wrote: Nolan Darilek writes: OK, I must be missing something. I copied this almost verbatem from the mini-guide on the Wiki, modified it and made it a shell script. Here's what I have: #!/bin/sh mvn archetype:generate -DarchetypeGroupId=net.liftweb \ -DarchetypeVersion=2.0-SNAPSHOT \ -DremoteRepositories=http://scala-tools.org/repo-snapshots \ -DgroupId=$1 \ -DartifactId=$2 When I run this, then select either blank or basic from the menu, I get what appears to be outdated code. Specifically, it wants to fetch Lift 0.8. What am I missing? It's been a while since I've generated a fresh project. This works: mvn archetype:generate \ -DarchetypeRepository=http://scala-tools.org/repo-snapshots \ -DremoteRepositories=http://scala-tools.org/repo-snapshots \ -DarchetypeGroupId=net.liftweb \ -DarchetypeArtifactId=lift-archetype-blank \ -DarchetypeVersion=1.1-SNAPSHOT \ -DgroupId=com.mypackage \ -DartifactId=myproject \ -Dversion=1.0-SNAPSHOT Have a look here: http://www.mail-archive.com/liftweb@googlegroups.com/msg15034.html /Jeppe -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Maven projects generating with old Lift versions?
OK, I must be missing something. I copied this almost verbatem from the mini-guide on the Wiki, modified it and made it a shell script. Here's what I have: #!/bin/sh mvn archetype:generate -DarchetypeGroupId=net.liftweb \ -DarchetypeVersion=2.0-SNAPSHOT \ -DremoteRepositories=http://scala-tools.org/repo-snapshots \ -DgroupId=$1 \ -DartifactId=$2 When I run this, then select either blank or basic from the menu, I get what appears to be outdated code. Specifically, it wants to fetch Lift 0.8. What am I missing? It's been a while since I've generated a fresh project. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: First comet steps
Just wondering if anyone had any thoughts on this? I still can't bind fields in an embedded template. They're returned as is, not transformed. Not sure what I'm doing wrong. On 02/23/2010 11:33 AM, Nolan Darilek wrote: Cool, thanks for all your help here. It's been quite a bit to digest, and I finally got around to revisiting this problem today. So I'm not sure why my initial attempts to return a from the render method failed, but today that seems to work. Need to see if Firefox is doing anything odd with caching, because I seem to have lots of odd problems of this sort. In the meantime, I'll poke at things with Curl before claiming that they don't work. I'm trying to create a cleaner design based on returning lift:embed, but I'm still having problems, even after Curl. :) Here's what I have thus far. My status.html: Imports templateshidden/importing.html, returned by comet render: NameCompleteTotalStatus And part of my ImportMonitor code: class ImportMonitor extends CometActor { ... def render = { if(importsCount == 0) No imports are currently in progress. else { bind("import", , "name" -> "Name" ) } } ... } I've tried a variety of things at that bind call. What it ultimately does is returns my template as is, including the . I also tried eager_eval="true" on the embed element, but with no luck. Thoughts on what I'm missing? I feel like binding keeps tripping me up. I understand the concept, in essence, but it seems like this should work to me and I don't see why it isn't. Thanks for being such a newbie-friendly community. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: First comet steps
Cool, thanks for all your help here. It's been quite a bit to digest, and I finally got around to revisiting this problem today. So I'm not sure why my initial attempts to return a from the render method failed, but today that seems to work. Need to see if Firefox is doing anything odd with caching, because I seem to have lots of odd problems of this sort. In the meantime, I'll poke at things with Curl before claiming that they don't work. I'm trying to create a cleaner design based on returning lift:embed, but I'm still having problems, even after Curl. :) Here's what I have thus far. My status.html: Imports templateshidden/importing.html, returned by comet render: NameCompleteTotalStatus And part of my ImportMonitor code: class ImportMonitor extends CometActor { ... def render = { if(importsCount == 0) No imports are currently in progress. else { bind("import", , "name" -> "Name" ) } } ... } I've tried a variety of things at that bind call. What it ultimately does is returns my template as is, including the . I also tried eager_eval="true" on the embed element, but with no luck. Thoughts on what I'm missing? I feel like binding keeps tripping me up. I understand the concept, in essence, but it seems like this should work to me and I don't see why it isn't. Thanks for being such a newbie-friendly community. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] First comet steps
I wrote my first comet actor today. Pretty neat stuff, and it was less difficult and painful than I expected. :) I'm having a bit of an issue figuring out how to render exactly what I want, though. My comet actor tracks a series of data imports, and since the import statuses change pretty rapidly, it makes more sense to poll at regular intervals and redraw the entire table of imports or perhaps the individual row than it does to do something more complex--at least for now. What I want to do, though, is display the table but only if there are imports active. If there are none, just display a paragraph stating that none are currently in progress. My issue is that since import statuses are displayed in a table, and since there may be two or three, I seem to either be able to display an empty table or nothing at all. Here's my template: NameCompleteTotalStatus If I try putting the table into another template and having ImportMonitor return , I seem to get nothing. If I move the into the , I get an entire table for each individual import. The only thing that occurs to me is to define the in the code of my render method. Is this my only option? Or am I missing something obvious? Also, how are comet actors timed out? I notice that if I kill the Firefox tab, I still get my printlns from the actor on my console, and I don't see the debugging code around my unsubscription mechanism triggered. Should I be doing something else to get localShutdown triggering, or does that happen when the sessions are cleaned up? If shutdown methods are only run on session expiration, is there any other way to tell a master publishing actor that it doesn't have to do any work on the behalf of a listener that no longer pays attention? Thanks. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Binding to a Map
On 02/10/2010 12:00 PM, Naftoli Gugenheim wrote: I mean to wrap the whole flatMap: case false => NodeSeq.fromSeq(user.accounts.flatMap... Gotcha. I now have: case false => NodeSeq.fromSeq( user.accounts.flatMap({ case (_, account) => bindAccountFields(in, account, false) }).toSeq ) } and that seems to have done it. I like type safety, but sometimes it's a PITA. :) Thanks for the help. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Binding to a Map
On 02/10/2010 11:18 AM, Naftoli Gugenheim wrote: If adding .toSeq or a : NodeSeq type annotation don't trigger the implicit, wrap it with NodeSeq.fromSeq(...). Also, you can do ...flatMap{case (_, account) => bindAccountFields(in, account, false)} Cool. I made the following changes, but still get the same error: user.accounts.isEmpty match { case true => You have no accounts configured. case false => user.accounts.flatMap({ case (_, account) => NodeSeq.fromSeq( bindAccountFields(in, account, false) ) }) } [error] /home/nolan/Projects/Utterance2/src/main/scala/info/thewordnerd/utterance/snippet/Manage.scala:67: type mismatch; [error] found : Iterable[scala.xml.Node] [error] required: scala.xml.NodeSeq [error] case false => user.accounts.flatMap({ [error] ^ [error] one error found Thanks for the partial function tip. I'm starting to learn some of Scala's more functional corners and recently read up on those, but didn't think to use them there. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Binding to a Map
I have a Lift app that's managing its own domain objects in a MongoDB. At one point I had an object with a list of embedded objects and all worked well. My users had many accounts, and I did something like: private def bindAccountFields(in:NodeSeq, a:Account, isNewAccount:Boolean):NodeSeq = {...} Then, from my Manage.render snippet: user.accounts.isEmpty match { case true => You have no accounts configured. case false => user.accounts.flatMap(bindAccountFields(in, _, false)) } I recently wanted to change User.accounts to a Map[String, Account], since accounts are named and should have unique names. So I did that, and changed the above to: user.accounts.isEmpty match { case true => You have no accounts configured. case false => user.accounts.flatMap((v:Tuple2[String, Account]) => bindAccountFields(in, v._2, false)) } Except, try though I might, I can't seem to eliminate this error: [error] /home/nolan/Projects/Utterance2/src/main/scala/info/thewordnerd/utterance/snippet/Manage.scala:67: type mismatch; [error] found : Iterable[scala.xml.Node] [error] required: scala.xml.NodeSeq [error] case false => user.accounts.flatMap((v:Tuple2[String, Account]) => bindAccountFields(in, v._2, false)) [error] ^ [error] one error found bindAccountFields hasn't changed at all. I'm just changing the collection I iterate over to call it, and the parameter it was passed. Am I missing something obvious? The whole "binding snippets to a collection" thing seems like magic to me. The getting started guide shows it done, but unless I read carelessly, it really doesn't explain how binding works in that situation. Are prefixes bound in order such that each time I call, say, in a form I get the next value bound there? Does that hold true such that I can have an Account.edit and Account.render snippet, both of which bind to , only the edit snippet binds a text field while the render snippet just displays text? So I'd then have to call the snippets in the order I've bound them? Obviously that wouldn't be advisable if my assumption is true, I'm just trying to understand how this particular bit of magic works. :) Thanks. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Can sessions do this?
On 01/23/2010 11:32 AM, Marius wrote: Well that just the standard session behavior but if you want JSESSIONID in the URL yu should probbaly turn off cookies in Jetty (or whatever container you have). Thus the URL's from the page would be something like: http://my.app;JSESSIONID=sdiofcxm?{params here} That'd be perfect, and is one aspect of the whole user token thing. Is it possible to disable this on an app-by-app basis? Can I put something in Boot.scala or web.xml to disable cookie-based sessions just for this app? LiftSession has by default an inactivity period of 30 minutes. However you can configure the sessions expiration interval from /WEB-INF/ web.xml And again, this is perfect. This is why I'm trying to (ab)use sessions in this manner, they already encapsulate most of the behaviors I need, and the less code I have to write myself, the better. Rrgarding your initial 3 points: 1. Visiting the app without a session ID param shouldn't generate a new session. Basically, index.html will just be mostly static, providing info on the service itself. /*marius - It does by default. A request without a sessionid will create a HTTP session*/ Right, I get this. So my question is, can I stipulate that visitors to /index.html *don't* generate a session? The default index page is just a blurb about the service. To create an account, the user has to poke it via XMPP, and if the user doesn't do this then there's no sense creating a session for them. 2. If the "config" command is sent via XMPP, the bot should first search all sessions for any matching the user's JID, destroying one if it exists. It should then create another, passing the user back a URL to the app with a jsessionid parameter. So I need to somehow associate arbitrary properties with sessions and find one based on those. Note that the sessions still need to be addressable via unique strings to maintain some level of security. /*marius - If you need to know the list of active Lift sessions you can use SessionMaster.sessionWatchers. Lift would send your actor a SessionWatcherInfo message containing a Map[String, LiftSession] You can put properties on a session most recommendable using Lift's SessionVar. */ And I can set and access these properties from outside of snippets or the HTTP lifecycle? Here's pseudocode that may help illustrate some of what I'm trying to accomplish. Note that I'm totally making up Lift APIs here just to get the concepts across. This would be code that matches incoming XMPP messages to commands, so this is not running in the web app itself: message.getBody match { ... case "config" => val old = SessionPool.find("owner", message.getFrom) // Does user have a session already? if(old != None) old.get.destroy // User requests new session so invalidate old to prevent hijack. val session = session.new session.setSessionVar("owner", new SessionVar(message.getFrom)) message.reply("Please visit ",session.getURL," to configure your account.") ... } I'm studying LiftSession.scala and see SessionMaster.getSession. Can I set otherId to the JID of the session's owner? So I could replace SessionPool.find in the above code with: SessionMaster.getSession("", Some(message.getFrom)) or am I misunderstanding? I'm also not clear on how to create a blank session so I have a URL to hand back to the user. I know that this is normally done by the incoming HTTP request, but in this instance I want the XMPP command to prepare a fresh session for the user to visit. 3. Visiting a URL with a jsessionid parameter should whipe out any sessions set in cookies. /*marius - I'm not sure I understand this one.*/ Well, if I can disable cookie-based sessions in this app then it's a non-issue. Thanks for all the help so far. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Can sessions do this?
On 01/23/2010 09:34 AM, Marius wrote: LiftSessions have nothing to do with logins; they are bound to the container's HTTP session. But in a JEE container this is bound with JSESSIONID and if I understood correctly you don't want that. I think that I do, but I don't know for sure. Basically, I want to associate properties with an HTTP connection such that I can use snippets, comet, etc. And I want those associations to be secure, more or less. So I thought that I could base my app's security model on the user getting IMed a URL like http://my.app/?JSESSIONID=sdiofcxm,vnweioprhsdfjk, going to that URL and changing their settings. If they don't visit that URL for half an hour or so, the session dies and it becomes invalid, so someone can't use browser history on a shared computer to access another's settings. Similarly, getting IMed a new URL invalidates the old, so the user has at least two ways of locking out others when using shared computers. LiftSession.scala manages sessions in Lift. Yeah, I've looked at that, but I just wasn't clear on whether or not what I was trying was remotely possible. I recognize that it's kind of an edge case, so I thought that those with more knowledge could at least point me in the right direction--or, at least, in a direction more substantial than LiftSession.scala. :) I hate to re-invent the wheel if I don't have to, and the access token stuff I did in Ruby seems very much like externally referenced HTTP sessions. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
Re: [Lift] Re: Can sessions do this?
Yeah, certainly I can duplicate the access token stuff from the Ruby port and set up a scheduled function to clean them out every half hour or so. I just wondered if I could hook into the session infrastructure since a) that already does exactly what I need and b) I don't need sessions for traditional logins. On 01/23/2010 02:49 AM, Marius wrote: Lift session management works based on session id denominated by cookies or url-rewriting. However Lift support stateless requests processing. You could look into LiftRules.statelessDispatchTable for having scala functions process your request and then return a LiftResponse, or LiftRules.statelessRewrite for rewriting requests very early thus transforming them into some other forms. Br's, Marius On Jan 23, 4:52 am, Nolan Darilek wrote: I'm porting an app I've written in Ruby over to Scala and Lift, and I'm wondering if Lift and Java's sessions can accomplish what I'm attempting. The app is mostly XMPP-based, though there is a web interface for configuration. Both run in the same process, because some changes from the web interface need to be reflected instantly in the XMPP interface, and I'd rather not have a separate message-passing layer out-of-process. Users don't log in with a username and password. Instead, they send an XMPP command and are sent a temporary URL. The URL vanishes after a certain timeout, and can also be reset by resending the command. In Ruby, I generate a GUID which I periodically time out, tracking last access times via the web app. I'm wondering, though, if Lift's sessions can achieve this? I'm not immediately sure where to look, but if anyone could give me pointers for the following requirements, that'd rock. 1. Visiting the app without a session ID param shouldn't generate a new session. Basically, index.html will just be mostly static, providing info on the service itself. 2. If the "config" command is sent via XMPP, the bot should first search all sessions for any matching the user's JID, destroying one if it exists. It should then create another, passing the user back a URL to the app with a jsessionid parameter. So I need to somehow associate arbitrary properties with sessions and find one based on those. Note that the sessions still need to be addressable via unique strings to maintain some level of security. 3. Visiting a URL with a jsessionid parameter should whipe out any sessions set in cookies. Actually, since the web configuration interface is just two forms, I'm likely fine with disabling cookie-based sessions entirely and just passing around jsessionids if that would make things easier. Can anyone offer any pointers as to where to begin looking? Or am I totally off base here? I tried glancing over LiftSession, but that left me even more confused as to whether or not an XMPP app can create sessions and pass off their URLs. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Can sessions do this?
I'm porting an app I've written in Ruby over to Scala and Lift, and I'm wondering if Lift and Java's sessions can accomplish what I'm attempting. The app is mostly XMPP-based, though there is a web interface for configuration. Both run in the same process, because some changes from the web interface need to be reflected instantly in the XMPP interface, and I'd rather not have a separate message-passing layer out-of-process. Users don't log in with a username and password. Instead, they send an XMPP command and are sent a temporary URL. The URL vanishes after a certain timeout, and can also be reset by resending the command. In Ruby, I generate a GUID which I periodically time out, tracking last access times via the web app. I'm wondering, though, if Lift's sessions can achieve this? I'm not immediately sure where to look, but if anyone could give me pointers for the following requirements, that'd rock. 1. Visiting the app without a session ID param shouldn't generate a new session. Basically, index.html will just be mostly static, providing info on the service itself. 2. If the "config" command is sent via XMPP, the bot should first search all sessions for any matching the user's JID, destroying one if it exists. It should then create another, passing the user back a URL to the app with a jsessionid parameter. So I need to somehow associate arbitrary properties with sessions and find one based on those. Note that the sessions still need to be addressable via unique strings to maintain some level of security. 3. Visiting a URL with a jsessionid parameter should whipe out any sessions set in cookies. Actually, since the web configuration interface is just two forms, I'm likely fine with disabling cookie-based sessions entirely and just passing around jsessionids if that would make things easier. Can anyone offer any pointers as to where to begin looking? Or am I totally off base here? I tried glancing over LiftSession, but that left me even more confused as to whether or not an XMPP app can create sessions and pass off their URLs. -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] More AJAX issues
Hello. Sorry for being the squeaky wheel on this one, but I'm really at a loss with no way to know if this is an issue with me, or with how I'm doing things in Lift. I've also been at this particular problem for a bit under a day now, and am running out of things to try and words to google. I think I figured out yesterday's issue--likely should have set onclick to an anonymous function returning false to prevent the browser from running it in a new DOM--but I've decided to chage my approach slightly. For various reasons, I'm now trying to use a with an onBlur handler which submits the value, a JSON string, to a function via jsonCall. Here is my entire function, still with a few rough edges as I add in the various AJAX bits: def updatePosition(pos:Any):JsCmd = pos match { case p:Map[String, Double] => GeoNode.nearestTo(p("lat"), p("lon")) match { case Some(node) => val nodes = node.within(0.001).remove(n => n.ways.size == 1) val nodeList = { nodes.map(n => n.latitude, "lon" -> n.longitude)}>{n.name(None, None).getOrElse("Unnamed node")} ) } println(nodeList) Replace("location", node.nearestWay match { case Some(w) => On {w.name.getOrElse("Unnamed way")}. case None => No nearby ways }) & Replace("nearby", nodeList) case _ => Replace("location", Thar be dragons! (You don't appear to be on any current maps.) } case _ => println(pos) Alert("Unexpected geolocation API response from browser.") } No matter what I try, I can't get the alert() to trigger when I tab off the . The println outputs what appears to be a sane value. I've inspected the element in Firebug, and everything appears as I'd expect. I've saved the entire page body with everything inserted, and everything looks fine there too. I've even done up a simple HTML document to make sure this behaves as I'd expect, and it does exactly what I think it should. So, what am I missing? Is embedded JS in a Replace call not run or something odd like that? -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] jsonCall for clickable links
Hello, all. I'm sure this is an incredibly silly mistake on my part, but I've never really done AJAX until playing with Lift and am at a loss as to what's going wrong. I'm dusting off my old geolocation web app. My current goals are two-fold: set an initial position based on the browser, then generate links to update that position based on nearby points. Thus far I have the first goal working quite nicely. A snippet registers a javascript callback to call a Lift function, and my page is being updated correctly. Here's what I have: def update(in:NodeSeq):NodeSeq = Script(JsRaw( """loc.onUpdate = function(lat, lon) { """+SHtml.jsonCall(JsObj("lat" -> JsVar("lat"), "lon" -> JsVar("lon")), updatePosition _)._2.toJsCmd+"""; }""" )) The problem arises when I try calling my updatePosition function from an SHtml.a link, like so: val nodeList = {nodes.map(nd => {SHtml.a( nd.name(None, None).getOrElse("Unnamed way"), SHtml.jsonCall( JsObj("lat" -> nd.latitude, "lon" -> nd.longitude), updatePosition _ )._2 )})} Ultimately, this function returns a JsCmd that performs two Replaces. First, that seems just a bit ugly to me, with the escape within an escape and all. Is there any way of eliminating that, short of placing the into the template? Ideally this should handle the case where there are no nearby nodes, in which case there'd be a No nearby points of interest. instead of the enclosing , but I haven't coded that yet. Next, clicking on these links doesn't work, and I get a "parent is null" error from Firebug. I'm guessing that this new call is registered in the context of a new, blank document, and hence can't perform any of the Replace commands that work fine when this function is used in the context of a callback in an existing document? If so, do I need another Shtml function to make the jsonCall occur in the current DOM? Finally, any idea as to why the link names appear as quoted strings (I.e. "Unnamed way" instead of just Unnamed way)? I'm guessing it may have to do with the embedded escape, but I'm not entirely certain. Thanks in advance, this is such a helpful and patient community, especially with newbies like myself. :) -- You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to lift...@googlegroups.com. To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/liftweb?hl=en.
[Lift] Re: Automatic background AJAX: best way to do it?
On 08/01/2009 11:53 AM, David Pollak wrote: > you need to replace ajaxCall with jsonCall... that will Stringify your > JavaScript object. > Ack, OK, that's what I had when I got the huge backtrace. :) So back to where I started, with: def updatePosition(pos:Any):JsCmd = { println("Got ",pos) Alert("Success!") } def update(in:NodeSeq):NodeSeq = Script(JsRaw( """loc.onUpdate = function(lat, lon) { """+SHtml.jsonCall(JsObj("lat" -> JsVar("lat"), "lon" -> JsVar("lon")), updatePosition _)._2.toJsCmd+"""; }""" )) And here's what I get, after an alert box pops up telling me that the server can't be contacted: INFO - Service request (GET) /images/ajax-loader.gif took 29 Milliseconds WARN - Request for /ajax_request/F297873351275ZM3/ failed For input string: "(-~9)7" java.lang.NumberFormatException: For input string: "(-~9)7" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48) at java.lang.Long.parseLong(Long.java:403) at java.lang.Long.parseLong(Long.java:461) at scala.runtime.RichString.toLong(RichString.scala:214) at net.liftweb.util.JSONParser$$anonfun$anInt$4$$anonfun$apply$67.apply(JSON.scala:100) at net.liftweb.util.JSONParser$$anonfun$anInt$4$$anonfun$apply$67.apply(JSON.scala:100) .. It goes on for quite a bit more, which I can happily send if needed. And it never hits my println. I think I even get it with just the Alert() call, and there's nothing apparent on the console to show what's being posted. --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Automatic background AJAX: best way to do it?
OK, having more issues with this. First I tried changing to jsonCall. This results in a huge backtrace, which I don't have at hand ATM but which seems to indicate a parse error in the input string. Strange, as the input seems rather straight-forward, but I thought I'd ensure that I'm not handing the function garbage before claiming that it's broken. Only, I can't seem to figure that out either. Here's what I've got: def updatePosition(pos:String):JsCmd = { println("Got "+pos) Alert(pos) } def update(in:NodeSeq):NodeSeq = Script(JsRaw(""" loc.onUpdate = function(lat, lon) { """+SHtml.ajaxCall(JsObj("lat" -> JsVar("lat"), "lon" -> JsVar("lon")), updatePosition _)._2.toJsCmd+"""; }""")) The generated JS looks fine: // But the println shows that I'm getting handed "[object Object]". Shouldn't it be passed a JSON string? --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Another backtrace on reload
ebApp.scala:46) at sbt.JettyRun$.liftedTree1$1(WebApp.scala:55) at sbt.JettyRun$.run(WebApp.scala:53) at sbt.JettyRun$.apply(WebApp.scala:34) at sbt.WebScalaProject$$anonfun$jettyRunTask$1.apply(ScalaProject.scala:327) at sbt.WebScalaProject$$anonfun$jettyRunTask$1.apply(ScalaProject.scala:327) at sbt.TaskManager$Task.invoke(TaskManager.scala:62) at sbt.impl.RunTask.runTask(RunTask.scala:78) at sbt.impl.RunTask.run(RunTask.scala:31) at sbt.impl.RunTask$.apply(RunTask.scala:16) at sbt.impl.RunTask$.apply(RunTask.scala:15) at sbt.Project$class.run(Project.scala:98) at sbt.Project$class.act(Project.scala:129) at sbt.BasicScalaProject.act(DefaultProject.scala:19) at sbt.Main$$anonfun$11.apply(Main.scala:375) at sbt.Main$$anonfun$11.apply(Main.scala:375) at sbt.Main$.withAction(Main.scala:407) at sbt.Main$.sbt$Main$$handleAction(Main.scala:375) at sbt.Main$.handleInteractiveCommand(Main.scala:364) at sbt.Main$.loop$1(Main.scala:266) at sbt.Main$.interactive(Main.scala:274) at sbt.Main$.startProject(Main.scala:102) at sbt.Main$.run(Main.scala:76) at sbt.Main.run(Main.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at sbt.boot.Boot$.run(Boot.scala:93) at sbt.boot.Boot$.load(Boot.scala:80) at sbt.boot.Boot$.boot(Boot.scala:53) at sbt.boot.Boot$.main(Boot.scala:31) at sbt.boot.Boot.main(Boot.scala) [0m[ [0minfo [0m] [0mStarted selectchannelconnec...@0.0.0.0:8080 [0m [0m[ [0minfo [0m] [34m== jetty-run == [0m [0m[ [32msuccess [0m] [0mSuccessful. [0m [0m[ [0minfo [0m] [0m [0m [0m[ [0minfo [0m] [0mTotal time: 8 s [0m On 06/24/2009 12:49 PM, Naftoli Gugenhem wrote: > I had the same problem a while ago. I'm not sure if I fixed it then, but I > think it had to do with the db still being open possibly. When the code > changes does the servlet get undeployed? > You might need to run derby in server mode. > Lately I've been launching jetty without maven, and to get it to reload > eclipse calls an ant script that touches the context.xml. I'm using h2 in tcp > mode. > Another option is JavaRebel which often obviates the need to redeploy. > Sorry I can't help you better--I'm interested in any more information there > is about this too. > > - > David Pollak wrote: > > I won't have a chance to look at it until next week, but maybe somebody else > could step in here and help. > > On Wed, Jun 24, 2009 at 7:16 AM, Nolan Darilekwrote: > > >> On 06/24/2009 08:54 AM, David Pollak wrote: >> >>> Are you using JNDI or your own connection manager to connect to the >>> >> RDBMS? >> >>> >> I'm new to this, but I'm guessing the latter. In any case, I haven't >> touched whatever values the snapshot sets up in Boot.scala, nor have I >> set any properties, so it's stock Derby. >> >> >>> >> > > -- Nolan Darilek http://thewordnerd.info --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Automatic background AJAX: best way to do it?
On 07/31/2009 12:27 PM, David Pollak wrote: > > loc.onUpdate = function(lat, lon) {ft is XHTML. The above > will not work in XHTML because the code will be escaped into XML. > > Ah, so it does, just looked at the rendered source. Thanks for the fix, and for the new method. --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Automatic background AJAX: best way to do it?
On 07/30/2009 11:26 PM, Naftoli Gugenheim wrote: > Does doubling the brace escape it? Sure does, thanks. --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: New Mapped Fields (MappedTimestamp and MappedMac)
On 07/30/2009 07:53 PM, Peter Robinett wrote: > Are there any other mapped fields you'd like to see? I'll be needing a MappedMap in one of my upcoming projects, basically a way of associating keyword/value pairs with my models. I'd really rather avoid the extra overhead of creating models and associations for these pairs, especially since they are never needed outside of the model itself. In the older Merb incarnation of this project, I just dumped the data to JSON and stored it in a text field on the object, kinda a poor man's document database if you will. :) --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Automatic background AJAX: best way to do it?
On 07/28/2009 07:28 PM, David Pollak wrote: > I'd do the REST API thing. The mechanisms that Lift has for handling > API calls from the browser are numerous, but they are associated with > a session (you can do ajaxCall or a S.buildJsonFunc). Oh cool. When I listened to the podcast interview and heard about fast-pathing AJAX calls, I realized that this was exactly what I wanted, and that there wasn't a need to create a separate URL space just to accomodate this page update functionality--at least, not explicitly in the sense of what I meant by "API." Neat. Thanks for the method pointers, too, that helped me focus my reading a bit. So here's what I have. I have this JS code as an interface to the geolocation API: function Location() { this.lat = 0; this.lon = 0; this.update = function(lat, lon) { this.lat = lat; this.lon = lon; this.onUpdate(lat, lon); }; this.onUpdate = function(lat, lon) {}; } var loc = new Location(); Next I wrote a snippet which needs to set loc.onUpdate to a function that calls into Lift to update the page. I have: class Geolocation { def updatePosition(pos:String):JsCmd = Alert("Got an update: "+pos) def update(in:NodeSeq):NodeSeq = loc.onUpdate = function(lat, lon) { {SHtml.ajaxCall(JsObj("lat" -> JsVar("lat"), "lon" -> JsVar("lon")), updatePosition _)._2} }; } Two issues here. First, how do I get those braces around the JS function containing the ajaxCall into my HTML? Seems like there should be a way to escape braces so I can include them in NodeSeq, but \{ didn't seem to do it. I'm also quite new to JS as well, so perhaps there's a better way to set that callback. All I can come up with is changing the callback signature to accept an object rather than individual values so perhaps I can set it directly to the Lift-generated function, but I think I'd rather have raw values for individual position components for now. 2. Ideally, I'd like for the JsObj to be an actual Map[String, Float]. Is there a way to do this? An included JSON parser that'd convert the string to a type I specify, perhaps? (assuming I'd have to give some sort of hint for Float vs. other numeric types, anyway) Thanks. Wow, this really makes AJAX development something I'd actually enjoy doing. :) --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Automatic background AJAX: best way to do it?
I have a project that will use the geolocation API in Firefox 3.5, Google Gears and other JS frameworks. It will need to keep the user's position updated using the watchPosition API, fetching nearby POIs and such whenever the position changes. I'm actually fairly new to AJAX, and am trying to figure out the best way to do this. Most of the AJAX examples I've seen involve user interaction, such as entering into a text field than removing focus, or waiting on state updates, as with comet. In this case, there's state that may update often or never, and those updates will be triggered by a callback function in the background, with no user interaction into which I can hook. I also don't want to leave a Comet connection open to the app waiting on updates, since the app may see mobile use, and I can't imagine holding open a connection being great for battery life. I'm wondering what the best way to do this would be, while staying fairly close to what Lift offers? Thus far I have two options. 1. Create a REST API and have the Javascript call a specified URL whenever the position changes, inserting the resulting JSON into the page at appropriate places. This works, but seems like it'd involve lots of extra effort, as well as straying away from Lift/Scala's added benefits into the dynamicity of JS, which I'm not entirely comfortable with. 2. Create a hidden JSON form on the page. When the position changes, the JS callback function fills out and submits the form in the background. This seems a bit hackish, with the hidden form and all, but this makes the problem one that is on a bit less shaky Lift ground. I can then use Lift's provided functionality to generate JS for replacing page contents with the results of evaluating the form submission. I'm basically going from the Lift book here. Most ideal, I'd think, would be if there was some way to have my callback function call a snippet directly and be handed back the JS needed, without having to create a separate web service API for this one call. Is the JSON form method the best option here? Or is there some new shiny in 1.1 that isn't documented in the Lift book yet? (or perhaps it *is* documented and I'm just missing it. :) Thanks. -- Nolan Darilek http://thewordnerd.info --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Binding based on attributes
On 07/03/2009 12:01 PM, David Pollak wrote: > > SHtml.text(defaultValue, func, "class" -> "fruitbat", "style" -> > "width: 300px") > Right, this is the classic binding case, but I don't see how to get the element being bound so that instead of setting its value to a variable, I could set a map keyed on the value of the name attribute to its value. > > > You might also be thinking of FuncBindParam: > > if you're input is > > Then FuncBindParam("bar", n => ...) > > n will be so you can use Scala's XML stuff to > extract the myparam attribute and do something with it. In that case, though, I don't appear to get the random field names for added security. The classic bind case is closer to what I'd like, I'm just wondering if there's some way to have the bound element passed to the function so I can use Scala's XML magic to extract attribute values. Perhaps that's the question I should have asked, so thanks for helping me find it. :) --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Binding based on attributes
I'm working on an app that allows users to enter their own form templates, which are rendered to HTML forms and filled out. The results are then captured and encoded for later rendering. So the user might input something like: Name: Is this your first visit? .. Is it possible to bind the various snippets, but perform special handling on their attribute values? So, for instance, I'd bind an S.text() to all , but it'd set a variable based on its name attribute, and perform rough validations based on whether required is set to true? It isn't immediately obvious how to do this, even when digging through the Lift sources. --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Can't embed a snippet
On 06/24/2009 09:40 AM, Derek Chen-Becker wrote: > Wait a second. I have plenty of templates that have multiple elements > in them. What exactly is the problem you're seeing here? > Using 1.1, I have the following in templates-hidden/welcome.html: Welcome Put welcome details here. Running mvn test gives me the following failure report: --- Test set: info.thewordnerd.therascribe.AppTest --- Tests run: 2, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 1.8 sec <<< FAILURE! testXml(info.thewordnerd.therascribe.AppTest) Time elapsed: 1.474 sec <<< FAILURE! junit.framework.AssertionFailedError: Malformed XML in 1 file: src/main/webapp/templates-hidden/welcome.html at junit.framework.Assert.fail(Assert.java:47) at info.thewordnerd.therascribe.AppTest.testXml(AppTest.scala:72) .. From the surefire report: Malformed XML in 1 file: src/main/webapp/templates-hidden/welcome.html :3:70: document must contain exactly one element ^ Surrounding it in a div fixes that. Must be a new addition in 1.1? --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Another backtrace on reload
On 06/24/2009 08:54 AM, David Pollak wrote: > Are you using JNDI or your own connection manager to connect to the RDBMS? > I'm new to this, but I'm guessing the latter. In any case, I haven't touched whatever values the snapshot sets up in Boot.scala, nor have I set any properties, so it's stock Derby. --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Another backtrace on reload
I'm getting this one on server reloads if I have mvn scala:cc running in one terminal and mvn jetty:run in another. Happens whenever I make a code change that gets redeployed: ERROR - Failed to Boot java.lang.NullPointerException: Looking for Connection Identifier ConnectionIdentifier(lift) but failed to find either a JNDI data source with the name lift or a lift connection manager with the correct name at net.liftweb.mapper.DB$$anonfun$3$$anonfun$apply$7.apply(DB.scala:95) at net.liftweb.mapper.DB$$anonfun$3$$anonfun$apply$7.apply(DB.scala:95) at net.liftweb.util.EmptyBox.openOr(Box.scala:372) at net.liftweb.mapper.DB$$anonfun$3.apply(DB.scala:95) at net.liftweb.mapper.DB$$anonfun$3.apply(DB.scala:95) at net.liftweb.util.EmptyBox.openOr(Box.scala:372) at net.liftweb.mapper.DB$.newConnection(DB.scala:89) at net.liftweb.mapper.DB$.getConnection(DB.scala:136) at net.liftweb.mapper.DB$.use(DB.scala:315) at net.liftweb.mapper.Schemifier$.schemify(Schemifier.scala:53) at net.liftweb.mapper.Schemifier$.schemify(Schemifier.scala:36) at bootstrap.liftweb.Boot.boot(Boot.scala:24) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at net.liftweb.util.ClassHelpers$$anonfun$createInvoker$1.apply(ClassHelpers.scala:408) at net.liftweb.util.ClassHelpers$$anonfun$createInvoker$1.apply(ClassHelpers.scala:406) at net.liftweb.http.DefaultBootstrap$$anonfun$boot$1.apply(LiftRules.scala:1041) at net.liftweb.http.DefaultBootstrap$$anonfun$boot$1.apply(LiftRules.scala:1041) at net.liftweb.util.Full.map(Box.scala:330) at net.liftweb.http.DefaultBootstrap$.boot(LiftRules.scala:1041) at net.liftweb.http.LiftFilter.bootLift(LiftServlet.scala:561) at net.liftweb.http.LiftFilter.init(LiftServlet.scala:529) at org.mortbay.jetty.servlet.FilterHolder.doStart(FilterHolder.java:97) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:653) at org.mortbay.jetty.servlet.Context.startContext(Context.java:140) at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1239) at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:517) at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:466) at org.mortbay.jetty.plugin.Jetty6PluginWebAppContext.doStart(Jetty6PluginWebAppContext.java:124) at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:50) at org.mortbay.jetty.plugin.AbstractJettyRunMojo.restartWebApp(AbstractJettyRunMojo.java:446) at org.mortbay.jetty.plugin.AbstractJettyRunMojo$1.filesChanged(AbstractJettyRunMojo.java:407) at org.mortbay.util.Scanner.reportBulkChanges(Scanner.java:486) at org.mortbay.util.Scanner.reportDifferences(Scanner.java:352) at org.mortbay.util.Scanner.scan(Scanner.java:280) at org.mortbay.util.Scanner$1.run(Scanner.java:232) at java.util.TimerThread.mainLoop(Timer.java:512) at java.util.TimerThread.run(Timer.java:462) [INFO] Restart completed at Wed Jun 24 08:43:27 CDT 2009 --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Error shutting down Jetty instance
Works for me. Thanks for the quick fix. --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Error shutting down Jetty instance
I've been getting this huge backtrace when shutting down Jetty. This probably isn't as much of an issue on mvn, but I'm using SBT, and it'd be nice to not need to restart the SBT instance to restart Jetty. I also just tried mvn jetty:run and saw nearly identical behavior, so it doesn't appear to be SBT. Is there a work-around? ERROR - Servlet destruction failure java.lang.RuntimeException: snapshot operation not supported. at scala.Predef$.error(Predef.scala:76) at scala.actors.Scheduler$.snapshot(Scheduler.scala:53) at net.liftweb.http.LiftServlet.destroy(LiftServlet.scala:58) at net.liftweb.http.LiftFilter.destroy(LiftServlet.scala:546) at org.mortbay.jetty.servlet.FilterHolder.destroyInstance(FilterHolder.java:127) at org.mortbay.jetty.servlet.FilterHolder.doStop(FilterHolder.java:107) at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:78) at org.mortbay.jetty.servlet.ServletHandler.doStop(ServletHandler.java:162) at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:78) at org.mortbay.jetty.handler.HandlerWrapper.doStop(HandlerWrapper.java:142) at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:78) at org.mortbay.jetty.handler.HandlerWrapper.doStop(HandlerWrapper.java:142) at org.mortbay.jetty.servlet.SessionHandler.doStop(SessionHandler.java:124) at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:78) at org.mortbay.jetty.handler.HandlerWrapper.doStop(HandlerWrapper.java:142) at org.mortbay.jetty.handler.ContextHandler.doStop(ContextHandler.java:591) at org.mortbay.jetty.webapp.WebAppContext.doStop(WebAppContext.java:498) at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:78) at org.mortbay.jetty.handler.HandlerWrapper.doStop(HandlerWrapper.java:142) at org.mortbay.jetty.Server.doStop(Server.java:281) at org.mortbay.component.AbstractLifeCycle.stop(AbstractLifeCycle.java:78) at sbt.LazyJettyRun$StopServer.stop(WebApp.scala:177) at sbt.JettyRun$$anonfun$stop$1.apply(WebApp.scala:24) at sbt.JettyRun$$anonfun$stop$1.apply(WebApp.scala:24) at scala.Option.foreach(Option.scala:94) at sbt.JettyRun$.stop(WebApp.scala:24) at sbt.WebScalaProject$$anonfun$jettyStopTask$1.apply(ScalaProject.scala:335) at sbt.WebScalaProject$$anonfun$jettyStopTask$1.apply(ScalaProject.scala:335) at sbt.TaskManager$Task.invoke(TaskManager.scala:58) at sbt.impl.RunTask.runTask(RunTask.scala:78) at sbt.impl.RunTask.run(RunTask.scala:31) at sbt.impl.RunTask$.apply(RunTask.scala:16) at sbt.impl.RunTask$.apply(RunTask.scala:15) at sbt.Project$class.run(Project.scala:95) at sbt.Project$class.act(Project.scala:126) at sbt.BasicScalaProject.act(DefaultProject.scala:19) at sbt.Main$$anonfun$10.apply(Main.scala:376) at sbt.Main$$anonfun$10.apply(Main.scala:376) at sbt.Main$.withAction(Main.scala:408) at sbt.Main$.sbt$Main$$handleAction(Main.scala:376) at sbt.Main$.sbt$Main$$handleBatchCommand(Main.scala:343) at sbt.Main$$anonfun$3.apply(Main.scala:118) at sbt.Main$$anonfun$3.apply(Main.scala:118) at sbt.Control$.lazyFold(Control.scala:54) at sbt.Main$.startProject(Main.scala:118) at sbt.Main$.run(Main.scala:76) at sbt.Main.run(Main.scala) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at sbt.boot.Boot$.run(Boot.scala:89) at sbt.boot.Boot$.load(Boot.scala:76) at sbt.boot.Boot$.doLoad$1(Boot.scala:59) at sbt.boot.Boot$.runBatch(Boot.scala:62) at sbt.boot.Boot$.boot(Boot.scala:55) at sbt.boot.Boot$.main(Boot.scala:31) at sbt.boot.Boot.main(Boot.scala) --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Can't embed a snippet
Cool deal, mvn test showed me the issue. Apparently, templates can only have a single element, I had an and a . The book called it a fragment, so this wasn't entirely clear. In any case, I put a div#welcome around it and now it works fine. Thanks for the pointer. --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Can't embed a snippet
On 06/23/2009 09:43 PM, David Pollak wrote: > try /templates-hidden/welcome > --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Can't embed a snippet
OK, finally introducing the first bit of user dynamicity into my app. I want my homepage to contain a bit of homepagy-type intro stuff for logged-out users, but a dashboard-like interface when someone is logged in. So I have this in index.html: Welcome back Thanks for logging in. And the following Home snippet: package info.thewordnerd.therascribe.snippet import scala.xml.NodeSeq import net.liftweb.util._ import info.thewordnerd.therascribe.model._ class Home { def render(in: NodeSeq): NodeSeq = User.currentUser match { case Full(user) => { Thanks again for logging in. } case _ => } } But I get a comment in my rendered HTML telling me that the welcome template isn't found. This happens regardless of whether I refer to it as just welcome or templates-hidden/welcome. My code is inspired by an example from the Mastering Lift book, where a welcome_msg template from templates-hidden is embedded in the homepage. I'm guessing this behavior was changed post 1.0? If so, do I just place welcome.html in my webapp directory now? --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Trouble with menus and CRUDify
On 06/23/2009 11:46 AM, Andrew Scherpbier wrote: > I had the same requirements. What I ended up doing is something along > these lines: > > Sweet, worked very well. Thanks. --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Submenus for model-generated views
This is something I asked in a subthread, but maybe it deserves its own thread in case someone might have the answer but chose to stop reading the original, whose subject line isn't really accurate for this question anyhow. :) I have a model that I'm using CRUDify for. I'd like to link the model into my sitemap such that it has a single top-level menu item pointing to /model/list, at which point the CRUD actions appear. So, basically, I want Model.menus to be a series of submenus beneath a menu named for the model. Thus far I have: val entries = Menu(Loc("Home", List("index"), "Home")) :: Menu(Loc("layouts", List("layout", "list"), "Layouts"), Layout.menus:_*) :: User.sitemap This gives me the Layouts menu item, but it doesn't work. Specifically, I get a 404 when I click on "Layouts", but not a message telling me that /layout/list isn't in the sitemap. From this I assume that /layout/list expects to find a filesystem-based template, and whatever magic the Layout.menus injects isn't taking. I've tried a number of variations. I'm also reading chapter 5 of Mastering Lift. It could be that the answer is there and obvious, but this is all a lot to take in for someone coming from five years of Rails and 1.5 of Merb. :) --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Trouble with menus and CRUDify
Cool, thanks again. Here's another. I'm looking through the Mastering Lift book chapter on sitemaps, and if there's an answer then I don't see it. I have several CRUD objects that I'd like to put in their own submenus. I can't seem to make this happen. If I stick exclusively to Model.menus, it works, but if I do something like: val entries = Menu(Loc("Home", List("index"), "Home")) :: Menu(Loc("layouts", List("layout", "list"), "Layouts"), Layout.menus:_*) :: User.sitemap What I'm expecting to happen is that I'll get a Layouts menu linking to /layout/list, a Loc created by Layout.menus. What actually *does* happen is, apparently, a template lookup of layout/list on the filesystem. I also tried passing Nil as the final argument to Loc, thinking it might defer creation of a link to a template and let Layout.menus set that up, but no luck. --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Re: Trouble with menus and CRUDify
Wow, thanks for the quick response! On 06/22/2009 07:11 PM, David Pollak wrote: > > Try: > > val entries = Menu(Loc("Home", List("index"), "Home")) :: > Layout.menus ::: User.sitemap > > > Note the triple colon (:::) operator. This concatenates two lists. > > Hmm, so why wouldn't I need the ::: before Layout.menus as well? I'm assuming that's a list too, so why isn't list concatenation needed on that end? --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Trouble with menus and CRUDify
I'm setting up my first model with CRUDify, but I'm having a hard time trying to figure out how to insert the auto-generated menus into my sitemap. Currently I have: val entries = Menu(Loc("Home", List("index"), "Home")) :: Layout.menus :: User.sitemap LiftRules.setSiteMap(SiteMap(entries:_*)) This gives: [error] found : List[Product] [error] required: Seq[net.liftweb.sitemap.Menu] [error] LiftRules.setSiteMap(SiteMap(entries:_*)) [error] ^ I've tried various permutations on this, and if I remove Layout.menus, everything compiles. Same thing for User.sitemap. But I can't have both Layout.menus and User.sitemap in the same val or the attempt to set it as the sitemap fails. Any idea what's up? --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Stability of snapshots?
Thanks to those of you who offered pointers with my deployment question yesterday. Think I finally figured out enough to at least get something going, even if I still don't understand all the terminology and distinctions. I'm curious, how stable are the Lift snapshots? Yes, I realize they're called "snapshots" for a reason. :) In looking at the archetype code for 1.0 and 1.1, I've noticed a few differences. As someone new to Lift, with no previous experience with it and no need to launch production apps any time soon, would it make more sense to develop with the snapshots? Or are these highly unstable? Also, do the snapshots depend on Scala 2.8, or can I use them with 2.7.5? I have tried running them, and while they seem to work superficially, I get various exceptions in the console that look rather, uh, suspiciously unimportant :) : > ERROR - [MEMDEBUG] failure java.lang.NoSuchFieldException: refSet at java.lang.Class.getDeclaredField(Class.java:1882) at net.liftweb.http.PointlessActorToWorkAroundBug$$anonfun$act$1$$anonfun$apply$1.apply(LiftServlet.scala:715) at net.liftweb.http.PointlessActorToWorkAroundBug$$anonfun$act$1$$anonfun$apply$1.apply(LiftServlet.scala:707) at scala.actors.Reaction.run(Reaction.scala:78) at net.liftweb.http.ActorSchedulerFixer$$anon$1$$anonfun$execute$1.apply(LiftServlet.scala:668) at net.liftweb.http.ActorSchedulerFixer$$anon$1$$anonfun$execute$1.apply(LiftServlet.scala:668) at net.liftweb.http.ActorSchedulerFixer$$anonfun$20$$anon$2.run(LiftServlet.scala:626) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) I'm assuming based on the name of the Actor class that this isn't anything to worry about, but I could be wrong. I also get an error when shutting down jetty: ERROR - Servlet destruction failure java.lang.RuntimeException: snapshot operation not supported. at scala.Predef$.error(Predef.scala:76) at scala.actors.Scheduler$.snapshot(Scheduler.scala:53) at net.liftweb.http.LiftServlet.destroy(LiftServlet.scala:58) at net.liftweb.http.LiftFilter.destroy(LiftServlet.scala:546) .. Basically, I'm wondering if these are signs of instability that I should avoid, or if they're just mismatches in Scala versions or issues with known work-arounds that I shouldn't let worry me? --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---
[Lift] Deployment questions and little Java web dev experience
Hi, all. I'm new to Lift and have a few questions about using it. For background, I'm coming from Ruby to Scala, having finally been frustrated by some aspects of the former enough to try jumping ship. I know Java syntax, but the simplicity of Ruby has always been a powerful draw for me, so when I used Java I always stayed away from Maven and other cornerstones of the Java tool community. I say all of this not to stir up Ruby vs. Scala drama (because we just don't have enough of that already :P ) but to explain that I'm mistified by much of the Java ecosystem, and a lot of what's out there seems to take it for granted that I know all of this. So please pardon my newbie questions, and feel free to point me to the FM on the subject if there is one, because I've certainly been *trying* to RTFM. :) I also recognize that these topics aren't specific to Lift, but I figure I'm likely to find more proponents of low ceremony in the Scala community than I'd find if I seeked out some more general purpose Java enterprise deployment resource. First...servlets? Web containers? App servers? Oh my. I want to write a few hobbyist apps with Lift and deploy them to my VPS. They may or may not take off, in which case I'd like a solution that can scale to real-world use. Not heavy real-world use, mind you, but I figure a separate VM/port for every app instance is overkill. So what do I need for this? I gather the app server is what handles arranging web apps in a single VM instance, but it's tough cutting through all the enterprise language to figure out which one of these is best for my circumstances, especially since I'm not dealing with legacy code and just want to launch hobbyist/personal projects. And I can't for the life of me figure out whether Tomcat is an app server or something else entirely. This seems so much more complicated than just throwing up a few Mongrels and a load balancer, or reading through the nicely-written Passenger manual and following the step-by-step instructions. I'm sure it has its advantages, I just can't get a grip on how it works. I've also been reading a lot about OSGi and it looks really nice. Am I correct in assuming that OSGi is to Java web apps what Rack is to Ruby ones? OK, maybe not exactly, and I know it's a more general-purpose mechanism (I'm toying with ScalaModules in a desktop app for providing pluggable UIs and other services) but in poking through OSGi articles, I've read a few statements hinting that this is probably the best way to deploy new apps with no legacy dependencies. Is this true? Is an app server actually needed here, or do I just create an OSGi execution environment and start adding bundles? It seems like the way to deploy an app is to build a war file and drop it into a specific directory of your servlet/app server/doohicky-whatamajig serverletcontainerthingie. It also looks as if all apps are installed into the same HTTP namespace, with URL path collisions resolved by editing web.xml and prepending something to the /* for the map elements. Is this accurate? Or is it possible to have the server prepend /myapp or /myapp.war based on the name of the deployed app, then handle the mappings via ProxyPass in the front-end server? That's closer to what I'm used to in Ruby, where the app takes over the URL namespace beneath whatever path you assign it, but it's not clear to me based on what I've read that this happens with Java app servers. Thanks for reading, and again, feel free to respond with a link or google keywords if I'm just missing something obvious. One of the biggest challenges I find myself facing with this move is that most of what I've found assumes a high ceremony->low ceremony migration path, or at least assumes that you've spent enough time in the Java ecosystem at some point to get it. :) --~--~-~--~~~---~--~~ 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 liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~--~~~~--~~--~--~---