[Lift] Re: Trouble with lift, GAE, JPA, adding child records

2009-05-19 Thread ngug

Sorry for the delay in responding. My question was not about
transaction API, my question was a practical one: If form processing
is split into a bunch of little anonymous functions, how can you put
them in a try/finally?

On May 15, 1:59 pm, Derek Chen-Becker dchenbec...@gmail.com wrote:
 EntityManager has a getTransaction method that you can use along with the
 constructor I mentioned previously to explicitly begin and end transactions
 in your code.

 derek

 On Fri, May 15, 2009 at 11:45 AM, ngug naftoli...@gmail.com wrote:

  One entity group per transaction is a GAE requirement. But my question
  about handling transactions was more specific - because form
  processing is specified piecemeal in separate closures, you can't
  use the normal try/finally. It seems a little too much effort to
  create a hidden field before and after every form/subform.
  Thanks.
  P.S. Sorry about the triple post. Opera Mobile (well, Google) didn't
  tell me the post was successful like it usually does, so I thought it
  didn't go through. (I thought the list is moderated and you would
  filter the extras just in case.)

--~--~-~--~~~---~--~~
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 lift, GAE, JPA, adding child records

2009-05-19 Thread ngug

Thanks for the fast response! Okay, a couple of things:
1.
 Well, typically the form callbacks are just setting values. If they're more 
 ...
(I take that to mean that setting entity properties does not require a
transaction? I thought that in JPA entities are generally monitored
for modifications? Is that a mistake?)
Look at my code for setting the location.
def bindLocation(loc: NatureLocationType) = {
  var l = loc
  bind(location, chooseTemplate(each, location, xhtml),
  id - SHtml.hidden(()= l = NatureLocationType.lookup
(loc.id)),
  name - SHtml.text(l.name, l.name = _),
  allowStreet - SHtml.checkbox(l.allowStreet, l.allowStreet =
_),
  allowHospital - SHtml.checkbox(l.allowHospital,
l.allowHospital = _),
  allowDoctor - SHtml.checkbox(l.allowDoctor, l.allowDoctor =
_),
  allowEquipment - SHtml.checkbox(l.allowEquipment,
l.allowEquipment = _),
  removeBtn - SHtml.submit(?(Remove), ()=removeLocation(l))
  )
}
Because the entity manager is closed after each request, the location
has to be reloaded in order to be modified. So loading it has to be
done in a transaction, but can I end the transaction before I set the
properties?

2.
In the mean time I made my own whole-form processor. Unfortunately
it's a little verbose to use.
Here's the code (currently only supports text boxed and check boxes,
and string values and boolean values, but it's very easy to extend):

import scala.xml.{Group, Elem, NodeSeq}
import scala.collection.mutable.{Map = mMap}

import net.liftweb.http.SHtml
import net.liftweb.util.{Helpers, Full, Empty}
import Helpers._


abstract class FormProcessor(prefix: String) {
  def text(attrs: (String, String)*)(init: String, action:
String=Unit) = SHtml.text(init, action, attrs:_*)
  def text: (String,String=Unit)=NodeSeq  = text()_
  def checkbox(attrs: (String, String)*)(init: Boolean, action:
Boolean=Unit) = SHtml.checkbox(init, action, attrs:_*)
  def checkbox: (Boolean, Boolean=Unit)=NodeSeq = checkbox()_

  val stringValues: mMap[String, String] = mMap.empty[String, String]
  val strings = mMap.empty[String, (String,String=Unit)=NodeSeq]

  val booleanValues = mMap.empty[String, Boolean]
  val booleans = mMap.empty[String, (Boolean,Boolean=Unit)=NodeSeq]

  def bind(xhtml: NodeSeq) = {
def transform(node: NodeSeq): NodeSeq = {
  put
  node match {
case Elem(`prefix`, label, _, _, _*) if strings.keys contains
label =
  strings(label)(stringValues(label), stringValues(label) = _)
case Elem(`prefix`, label, _, _, _*) if booleans.keys contains
label =
  booleans(label)(booleanValues(label), booleanValues(label) =
_)
   case other = other
  }
}
Helpers.bind(prefix, Full(transform _), Empty, xhtml) ++
  Seq(SHtml.hidden(()=get))

  }

  def put: Unit
  def get: Unit
}

And here's some usage:
def bindLocation(loc: NatureLocationType) = {
  var l = loc
  val form = new lrbcol.FormProcessor(location) {
strings += (name - text)
booleans ++= Map(allowStreet-checkbox,
 allowHospital-checkbox,
 allowDoctor-checkbox,
 allowEquipment-checkbox)
def put {
  stringValues(name) = l.name
  booleanValues ++= Map(allowStreet - l.allowStreet,
allowHospital - l.allowHospital,
allowDoctor - l.allowDoctor,
allowEquipment - l.allowEquipment)
}
def get = transaction {
  val l = NatureLocationType.lookup(loc.id)
  l.name = stringValues(name)
  l.allowStreet = booleanValues(allowStreet)
  l.allowHospital = booleanValues(allowHospital)
  l.allowDoctor = booleanValues(allowDoctor)
  l.allowEquipment = booleanValues(allowEquipment)
}
  }

  bind(location,
   form.bind(chooseTemplate(each, location, xhtml)),
   removeBtn - SHtml.submit(?(Remove), ()=removeLocation
(NatureLocationType.lookup(loc.id)))
  )
}
If you have a better way of implementing it, let me know. Feel free to
include it in lift, unmodified or modified.


3.
I'll put it in the next post because it's somewhat separate.

On May 19, 3:20 pm, Derek Chen-Becker dchenbec...@gmail.com wrote:
 Well, typically the form callbacks are just setting values. If they're more
 complex than that then you would need a try/catch in each function. I don't
 think that the current form processing code has any facility for a per-form
 exception handler, although that might be a useful feature.

 Derek

 On Tue, May 19, 2009 at 1:09 PM, ngug naftoli...@gmail.com wrote:

  Sorry for the delay in responding. My question was not about
  transaction API, my question was a practical one: If form processing
  is split into a bunch of little anonymous functions, how can you put
  them in a try/finally?

  On May 15, 1:59 pm, Derek Chen-Becker dchenbec

[Lift] Re: Trouble with lift, GAE, JPA, adding child records

2009-05-19 Thread ngug

בה using the FormProcessor, all my exceptions seem to have
disappeared. Now I have a problem, that although seems to be a
separate problem is very much intertwined with everything else and I
think it's really one issue.

The page basically looks like this:
Nature Name: [text field]

Locations:
Name   Allow St. Addr   Allow Hosp. Addr   Allow
Doc.   Allow Eqpmt Loc
[text field]  [X]
[X]   [  ]
[   ][[Remove button]]
 
[[Insert Row button]]
[[Save button]]

And you can add/remove locations, e.g. for nature Hospital Visitation
you would have one location, called Location or Hospital which is
only allowed to be a hospital (when you enter the request you'll get
drop-downs). A Food delivery might have a From and a To, which
can be street addresses, hospital rooms, or even a doctor's office,
but it wouldn't let you select an equipment location.
Now, this app is being rewritten, after I started it in PHP. In the
PHP version (I didn't know how to use multiple submit buttons then)
adding and removing rows was done via a link, so it discarded any
modifications you made to locations. (I'm trying to stay away from
relying on Javascript). Now, with Lift, they are buttons, and so any
modifications you make to locations are saved to the datastore
immediately upon pressing them, because the page needs to reload with
these locations. But neither of these behaviors is optimal. Really, it
should keep track of your changes but only send them to the datastore
when you explicitly press Save. But the page can get reloaded via
Remove/Insert Row in between.
Okay, so I made another RequestVar to hold pending new rows and rows
pending removal, and it shows the page as if they were added and
removed. But what happens if you modify the properties of a location
and then insert a row? Modifying the location that that field was
mapped to is pointless, because we don't want to merge it yet, but
we're going to have to reload it from the datastore in a future
request cycle, before we are able to merge it, because it doesn't seem
to be able to merge an entity that was detached the last time the
entity manager was closed.
What am I supposed to do? Store everything in a fake (never persisted)
nature/locations and then copy all the differences to the managed
entity when processing the Save submit button?
I hope you understand my question, let me know what needs
clarification.
Thanks a ton!

--~--~-~--~~~---~--~~
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 lift, GAE, JPA, adding child records

2009-05-19 Thread ngug

P.S. I wrote a method to handle the boilerplate of opening/closing/
checking whether to rollback transactions. Shouldn't ScalaJPA have
such a method? Or does it?
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: Trouble with lift, GAE, JPA, adding child records

2009-05-19 Thread ngug



On May 19, 4:31 pm, Derek Chen-Becker dchenbec...@gmail.com wrote:
 It should already. The closeEM method on both LocalEM and JndiEM checks to
 see if the transaction has been marked rollback only and should handle
 committing/rollback there. If it doesn't then it's a bug.
But we're talking about userTx==true. I mean this:
  private def transaction(prog: =Unit) {
val tx = EntityManager.getTransaction
try {
  tx.begin
  prog
  tx.commit
} finally {
  if(tx.isActive)
tx.rollback
}
  }
...
def get = transaction {
  val l = NatureLocationType.lookup(loc.id)
  l.name = stringValues(name)
  l.allowStreet = booleanValues(allowStreet)
  l.allowHospital = booleanValues(allowHospital)
  l.allowDoctor = booleanValues(allowDoctor)
  l.allowEquipment = booleanValues(allowEquipment)
}
(continued below)

 Also, for your first question:

 (I take that to mean that setting entity properties does not require a

  transaction? I thought that in JPA entities are generally monitored
  for modifications? Is that a mistake?)

 In the context of a form processing function, the JPA entity is in a
 detached state at the point that its members are being updated because the
 session that it was loaded in (when the form rendered) is now closed. The
 transaction is only required when you perform the merge of the detached
 object into a new session to save the entity data. Whether or not the entity
 is actually monitored is an implementation detail, since the spec only says
 that when the entity is merged it should save data back to the database, but
 it doesn't specify how that is done. Any exceptions related to JPA should
 only occur during the flush, or possibly the merge if the JPA provider does
 an eager flush to the database. This is why I added the mergeAndFlush,
 persistAndFlush, and removeAndFlush methods, so that you would have a
 definite place to wrap in a try/catch. If you're doing multiple ops then
 you'll need to merge your entire block of merge,persist,remove and flush
 methods in a try/catch. Does that make sense? I know that sometimes the
 lifecycle of these things can take a few tries to wrap your head around, so
 if this isn't clear let me know and I'll try to rephrase.

I understand you, and that's what I thought too, but I got an
exception when I tried to merge a detached entity! If I could get an
entity in one request, close the EM, and in the next request just
modify it and merge it it would be great, but so far I haven't managed
to. If you can't think of any explanation offhand I'll try to
reproduce it in an isolated snippet.
Thanks!


 Derek

 On Tue, May 19, 2009 at 2:07 PM, ngug naftoli...@gmail.com wrote:

  P.S. I wrote a method to handle the boilerplate of opening/closing/
  checking whether to rollback transactions. Shouldn't ScalaJPA have
  such a method? Or does it?
  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: Trouble with lift, GAE, JPA, adding child records

2009-05-19 Thread ngug

I actually started my code by editing the AuthorOps snippet from
ymnk's GAE version of it. He does reload the nature before editing it:
// Hold a val here so that the id closure holds it when we re-enter
this method
bind(author, xhtml,
   id - SHtml.hidden(() =
findAuthor(author) match {
  case Some(a) = authorVar(a)
  case None =}),
   name - SHtml.text(author.name, author.name=_),
   submit - SHtml.submit(?(Save), doAdd))
findAuthor looks up the the author based on the id in the authorVar
RequestVar, and then sets that back into the authorVar. I wondered why
he did that, and then thought I understood...
Thanks!
On May 19, 5:01 pm, Derek Chen-Becker dchenbec...@gmail.com wrote:
 On the first part, I could add a withTx method to LocalEM that would handle
 wrapping the tx for you, if that's OK. Something like:

 def withTx[T] (f : = T)

 Then you could do

 MyEM.withTx {
   prog

 }

 And it would handle the rollback. How does that sound?

 As for the second, if you're getting an exception on the merge I'd really
 like to see the Exception (and code, if possible). Off the top of my head
 the only time that should happen is if you have a constraint violation or
 something similar that would throw and exception even if you were operating
 on a non-detached entity. Take a look at the JPA Demo Library app. It does
 detached object merge all of the time for editing authors and books.

 Derek

 On Tue, May 19, 2009 at 2:42 PM, ngug naftoli...@gmail.com wrote:

  On May 19, 4:31 pm, Derek Chen-Becker dchenbec...@gmail.com wrote:
   It should already. The closeEM method on both LocalEM and JndiEM checks
  to
   see if the transaction has been marked rollback only and should handle
   committing/rollback there. If it doesn't then it's a bug.
  But we're talking about userTx==true. I mean this:
   private def transaction(prog: =Unit) {
     val tx = EntityManager.getTransaction
     try {
       tx.begin
       prog
       tx.commit
     } finally {
       if(tx.isActive)
         tx.rollback
     }
   }
  ...
          def get = transaction {
           val l = NatureLocationType.lookup(loc.id)
           l.name = stringValues(name)
           l.allowStreet = booleanValues(allowStreet)
           l.allowHospital = booleanValues(allowHospital)
           l.allowDoctor = booleanValues(allowDoctor)
           l.allowEquipment = booleanValues(allowEquipment)
         }
  (continued below)

   Also, for your first question:

   (I take that to mean that setting entity properties does not require a

transaction? I thought that in JPA entities are generally monitored
for modifications? Is that a mistake?)

   In the context of a form processing function, the JPA entity is in a
   detached state at the point that its members are being updated because
  the
   session that it was loaded in (when the form rendered) is now closed. The
   transaction is only required when you perform the merge of the detached
   object into a new session to save the entity data. Whether or not the
  entity
   is actually monitored is an implementation detail, since the spec only
  says
   that when the entity is merged it should save data back to the database,
  but
   it doesn't specify how that is done. Any exceptions related to JPA should
   only occur during the flush, or possibly the merge if the JPA provider
  does
   an eager flush to the database. This is why I added the mergeAndFlush,
   persistAndFlush, and removeAndFlush methods, so that you would have a
   definite place to wrap in a try/catch. If you're doing multiple ops then
   you'll need to merge your entire block of merge,persist,remove and flush
   methods in a try/catch. Does that make sense? I know that sometimes the
   lifecycle of these things can take a few tries to wrap your head around,
  so
   if this isn't clear let me know and I'll try to rephrase.

  I understand you, and that's what I thought too, but I got an
  exception when I tried to merge a detached entity! If I could get an
  entity in one request, close the EM, and in the next request just
  modify it and merge it it would be great, but so far I haven't managed
  to. If you can't think of any explanation offhand I'll try to
  reproduce it in an isolated snippet.
  Thanks!

   Derek

   On Tue, May 19, 2009 at 2:07 PM, ngug naftoli...@gmail.com wrote:

P.S. I wrote a method to handle the boilerplate of opening/closing/
checking whether to rollback transactions. Shouldn't ScalaJPA have
such a method? Or does it?
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: Trouble with lift, GAE, JPA, adding child records

2009-05-15 Thread ngug

One entity group per transaction is a GAE requirement. But my question
about handling transactions was more specific - because form
processing is specified piecemeal in separate closures, you can't
use the normal try/finally. It seems a little too much effort to
create a hidden field before and after every form/subform.
Thanks.
P.S. Sorry about the triple post. Opera Mobile (well, Google) didn't
tell me the post was successful like it usually does, so I thought it
didn't go through. (I thought the list is moderated and you would
filter the extras just in case.)

--~--~-~--~~~---~--~~
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 lift, GAE, JPA, adding child records

2009-05-14 Thread ngug

In any case, how would I handle transactions manually? An SHtml.hidden
before and after every form? It's confusing because SHtml lumps the
get and set side by side when they happen in two different requests
and the entity needs to be reloaded in between. In any case, GAE seems
to require tighter control of transactions because two entity groups
can't be modified (accessed?) in one transaction.

--~--~-~--~~~---~--~~
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 lift, GAE, JPA, adding child records

2009-05-14 Thread ngug

In any case, how would I handle transactions manually? An SHtml.hidden
before and after every form? It's confusing because SHtml lumps the
get and set side by side when they happen in two different requests
and the entity needs to be reloaded in between. In any case, GAE seems
to require tighter control of transactions because two entity groups
can't be modified (accessed?) in one transaction.

--~--~-~--~~~---~--~~
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 lift, GAE, JPA, adding child records

2009-05-14 Thread ngug

In any case, how would I handle transactions manually? An SHtml.hidden
before and after every form? It's confusing because SHtml lumps the
get and set side by side when they happen in two different requests
and the entity needs to be reloaded in between. In any case, GAE seems
to require tighter control of transactions because two entity groups
can't be modified (accessed?) in one transaction.

--~--~-~--~~~---~--~~
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: Constantly Ajax Request ?

2009-05-13 Thread ngug

Well since he may have meant that, to disable it you put in Boot:
LiftRules.enableLiftGC = false

On May 12, 8:01 pm, Timothy Perrett timo...@getintheloop.eu wrote:
 This im aware of - however it just seems more likely that if he
 asked for comet behavior by inserting the comet tag he would
 associate the two. However, the way the original query was worded
 indicated to me at least that he was not expecting the ajax calls...
 hence why i think he's probally talking about the GC page ajax rather
 than a comet call. Generally speaking people tend to exaggerate, hence
 his miss-use of constantly.

 I may be wrong, but i have a hunch...

 Cheers, tim



  Nope... the GC happens once every 75 seconds (by default).  It's not
  constant.

--~--~-~--~~~---~--~~
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 lift, GAE, JPA, adding child records

2009-05-13 Thread ngug

I guess I should include the views too to make it easier to reproduce
the problem. Here is edit.html:

lift:surround with=default at=content
head
titlelift:loc
lift:Natures.newOrEdit
if:editEdit/if:edit
if:newNew/if:new
/lift:Natures.newOrEditnbsp;Nature
/lift:loc/title
/head
h3lift:loc
lift:Natures.newOrEdit
if:editUpdate/if:edit
if:newCreate/if:new
/lift:Natures.newOrEditnbsp;Request Nature/lift:loc/h3

lift:Natures.edit form=GET
nature:id /
fieldsetlegendlift:locName/lift:loc/legend 
nature:name /
/fieldset
fieldsetlegendlift:locLocations/lift:loc/legend
table
thead
tr
thLocation name/th
th colspan=4Allowed locations/th
th/th
/tr
/thead
tr
td/td
tdStreet/td
tdHospital/td
tdDoctor/td
tdEquipment/td
td/td
/tr
nature:locations
each:location
tr
tdlocation:id 
/location:name //td
tdlocation:allowStreet 
//td
tdlocation:allowHospital 
//td

tdlocation:allowDoctorallowDoctorChk/location:allowDoctor/
td

tdlocation:allowEquipmentallowEquipmentChk/
location:allowEquipment/td

tdlocation:removeBtnRemoveBtn/location:removeBtn/td
/tr
/each:location
/nature:locations
tr
td colspan=5/td

tdnature:newLocationinsertLocationBtn/nature:newLocation/
td
/tr
/table
/fieldset
nature:submit /
/lift:Natures.edit
/lift:surround


And here is list.html:

lift:surround with=default at=content
head
titlelift:locNatures List/lift:loc/title
/head
h3Request Natures/h3
table
thead
tr
thlift:locName/lift:loc/th
thlift:locLocations/lift:loc/th
th/th
/tr
/thead
lift:Natures.list
tr
tdnature:name //td
tdnature:locations //td
tdnature:edit //td
tdnature:remove //td
/tr
/lift:Natures.list
a href=editlift:locNew/lift:loc/a
/table
/lift:surround


--~--~-~--~~~---~--~~
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 lift, GAE, JPA, adding child records

2009-05-13 Thread ngug

Thanks for looking. The stack traces aren't very helpful because they
concern the state which is caused by the previous sequence of events.
Anyway, why is there a transaction taking place in the first place?

--~--~-~--~~~---~--~~
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: Lift works on Google App Engine (within the confines of what's possible)

2009-05-12 Thread ngug

Personally I couldn't find anything free, except for EatJ, which has a
free trial. Apparently you have to restart the server every 6? hours
in trial mode. Anyway, soon after I registered it didn't let me log in
anymore, not sure why.

On Apr 20, 8:56 am, Jeremy Mawson jeremy.mawson.w...@gmail.com
wrote:
 Yes, for those who wish to tinker and share their tinkerings with the world,
 the zero cost entry point* is good.

 I'm also interested in any opinions of which free services are better than
 GAE for Lift apps.

 Cheers
 Jeremy

 * - yes, I know there is a billing model for increased bandwidth and other
 add-ons with GAE.

 2009/4/20 samreid samrr...@gmail.com







  If GAE is not a good home for Lift applications, can you recommend
  some alternate hosts?  Are there any free alternates?

  Thanks,
  Sam Reid

  On Apr 17, 3:57 pm, David Pollak feeder.of.the.be...@gmail.com
  wrote:
   Folks,

   I've just committed a version of Lift (including the Lift Example) that
  runs
   on the Google App Engine.  You can see the running demo at:
 http://liftdemo.appspot.com/

   What's missing:

      - Mapper and Mapper-related stuff.  You can use JPA.
      - Comet.  GAE's lack of thread or message queue support is a huge
      limitation.
      - Actor-based session-shutdown notification is disabled on GAE.
      - There's no session affinity guarantee, so there may be problems with
      migrating sessions (I'll be working with the Google folks on this
  issue)

   Okay... so you can build apps on GAE... I have to wonder... who would
  want
   to?

   GAE gives you a highly scalable platform to build CRUD apps.  Without a
   back-end messaging infrastructure, long running processes, threads,
   inter-session messaging, etc. there's not much in the way of exciting
  apps
   to build.  Here are a list of apps that could not be built with GAE:

      - Twitter (requires a message bus and back-ground processing)
      - Facebook (has many of Twitter's requirements)
      - GoogleTalk
      - A travel site (the 30 second request duration means that looking
  stuff
      up on a back end service is not possible)
      - A multi-player game

   So... on a $100/mo box from CalPop, I can run a service that will scale
  to
   20M requests per day.  If I'm doing 20M requests per day, I've got a
   business where I want more control over my infrastructure than GAE gives
   me.  That might be Amazon EC2 where I can power-up and down boxes at
  will.
   There are also a number of different scalable storage solutions on
  Amazon.
   I just can't for the life of me figure out why anyone would want to put a
   Java/Scala app on GAE.

   Thanks,

   David

   --
   Lift, the simply functional web frameworkhttp://liftweb.net
   Beginning Scalahttp://www.apress.com/book/view/1430219890
   Follow me:http://twitter.com/dpp
   Git some:http://github.com/dpp

 --
 Jeremy Mawson
 Senior Developer | Online Directories

 Sensis Pty Ltd
 222 Lonsdale St
 Melbourne 3000
 E: jeremy.maw...@sensis.com.au

--~--~-~--~~~---~--~~
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 lift, GAE, JPA, adding child records

2009-05-12 Thread ngug

I made the beginnings of a lift app for GAE. It's for a volunteer
medical assistance organization, to manage requests that they get.
Every request has a nature, e.g., transportation, hospital visitation,
etc. Each nature has a OneToMany association with a
NatureLocationType, which means that when you enter the request you
have a different set of location fields depending on the nature. One
screen lets you manage the natures. On the same screen that you edit
the name of the nature you can add, remove, and edit location types
for that nature. I'm new to lift, GAE, and JPA, although familiar with
Scala. So far I'm only working with the dev server.
I started with the lift JPA library demo's (snippet) code
Anyway, after a while I got it pretty functional. (After discovering
that after each request, when it processes the input from the previous
request the same entity object is still in the JVM, but it has become
detached and there's no way to reattach it other than re-looking it up
via its id---why does the entity manager have a shorter lifespan than
the entity?)
However, every now and then I get an error that the object is dirty
but no field are, and sometimes an error that a request completed
without closing the (which?) transaction.
Could someone look at the source code and help me? Thanks, it's really
appreciated.



Here's the source for the snippet class (models below; note that
EntityManager is my name for what the library demo calls Model: object
EntityManager extends LocalEMF(transactions-optional) with
RequestVarEM):

package liftgae1.snippet

import javax.persistence.{EntityExistsException, PersistenceException}

import scala.collection.jcl.Conversions.convertList
import scala.xml.{NodeSeq, Text}

import net.liftweb.http.{RequestVar, SHtml, S, StatefulSnippet}
import S._
import net.liftweb.util.{Helpers, Log}
import Helpers._

import lrbcol.model.{EntityManager, Nature, NatureLocationType}

class Natures /*extends StatefulSnippet*/ {
  /*
  val dispatch: DispatchIt = {
case list = list
case newOrEdit = newOrEdit
case edit = edit
  }*/

  // Set up a requestVar to track the nature object for edits and adds
  private object natureVar extends RequestVar[Nature](new Nature)
  def nature: Nature = natureVar.is
  def nature_=(nature: Nature) = natureVar(nature)
  def hasNature = nature.id != null
  def reloadNature = if(hasNature) try {nature = Nature.lookup
(nature.id).get} catch {case e = println(e)}


  def list(xhtml: NodeSeq): NodeSeq = {
println(In list)
Nature.all foreach println
NatureLocationType.all foreach {l=println(l +  for  +
l.nature)}
Nature.all.flatMap { n = println(Binding with  + n + ,
contained =  + EntityManager.contains(n))
  bind(nature, xhtml,
   name -Text(n.name),
   locations -   Text(n.natureLocationTypes map {_.name}
mkString ,),
   edit -SHtml.link(edit,
 () = nature = n,
 Text(?(Edit))
),
   remove -  SHtml.link(list,
 () = {nature = n; reloadNature;
EntityManager.removeAndFlush(nature)},
 Text(?(Remove))
)
  )
}
  }


  def newOrEdit(xhtml: NodeSeq) =
hasNature match {
  case false = chooseTemplate(if, new, xhtml)
  case _ = chooseTemplate(if, edit, xhtml)
}


  def edit(xhtml: NodeSeq): NodeSeq = {
def doSave() {
  println(In doSave with %s format(nature))
  if (nature.name.isEmpty) {
error(emptyNature, The nature's name cannot be blank)
  } else try {
EntityManager.mergeAndFlush(nature)
redirectTo(list)
  } catch {
case ee: EntityExistsException =
  error(That nature already exists.)
case pe: PersistenceException =
  error(Error adding nature); Log.error(Nature add failed,
pe)
  }
}

def insertLocation() {
  val l = new NatureLocationType
  nature.natureLocationTypes += l
  l.nature = nature
  EntityManager.mergeAndFlush(if(hasNature) l else nature)
}

def removeLocation(l: NatureLocationType) {
  try {
EntityManager.removeAndFlush(l)
  } catch {
case e = e.printStackTrace
  }
}


println(In edit with nature %s. format(nature))

def bindLocation(loc: NatureLocationType) = {
  var l = loc
  bind(location, chooseTemplate(each, location, xhtml),
  id - SHtml.hidden(()= l = NatureLocationType.lookup
(loc.id)),
  name - SHtml.text(l.name, l.name = _),
  allowStreet - SHtml.checkbox(l.allowStreet, l.allowStreet =
_),
  allowHospital - SHtml.checkbox(l.allowHospital,
l.allowHospital = _),
  allowDoctor - SHtml.checkbox(l.allowDoctor, l.allowDoctor =
_),
  allowEquipment - SHtml.checkbox(l.allowEquipment,
l.allowEquipment = _),