Excellent. Your reasons for using POJOs make perfect sense, and none of them have any relevance for me, which means that for my apps -- which are relatively pure Scala -- I'm on the right track.
Thanks again. This really helps. Now if I could just get Hibernate to permit one entity to manipulate another without going through an EntityManager, I'd be in heaven. Chas. Kris Nuttycombe wrote: > I'm not sure it's that thorough; it's just a copy/paste from my app. :) > > The reason that the entities are POJOs is simple; the Lift app is simply > a small internal administrative interface for a much larger Java EE > application. I've toyed with the possibility of porting as much of the > main app as possible to Scala, but there's just no time to do it. Also, > I really love having good refactoring support in the IDE, and it's just > not there yet for scala alone, much less hybrid scala/java projects. > > Kris > > On Wed, Jan 14, 2009 at 3:05 PM, Charles F. Munat <c...@munat.com > <mailto:c...@munat.com>> wrote: > > > Kris, > > Thank you much for this very thorough exegesis. I'll study it and will > try to wrap my tiny brain around it. I really appreciate the effort you > put into it. > > One question... why did you choose to implement the entities as POJOs > instead of as Scala objects? I've been working with the latter without > too much difficulty, and I'd like to avoid writing Java as much as > possible. Is there some advantage to using POJOs? > > Chas. > > Kris Nuttycombe wrote: > > Hi, Chas, > > > > Sorry it's taken me so long to respond to this - I've been pretty > buried > > for the past week. > > > > Here's an example of what I'm doing: > > > > > > trait Binding { > > def apply(xhtml : NodeSeq) : NodeSeq = xhtml > > } > > > > trait EntityBinding[+T] extends Binding { > > def entity : T > > } > > > > trait SubscriptionEventBinding extends > EntityBinding[SubscriptionEvent] { > > abstract override def apply(xhtml : NodeSeq) : NodeSeq = { > > val transTemplate = chooseTemplate("event", > "transactions", xhtml) > > > > bind("event", super.apply(xhtml), > > "scheduleDate" -> h(entity.getScheduleDate), > > "transactions" -> > > Group(entity.getTransactions.toSeq.flatMap(_(transTemplate))) > > ) > > } > > } > > > > trait BillingEventBinding extends > > EntityBinding[SubscriptionBillingEvent] with > SubscriptionEventBinding { > > abstract override def apply(xhtml : NodeSeq) : NodeSeq = { > > bind("event", super.apply(xhtml), > > "detail" -> <span>Charges: ${entity.getCharge}; > Discount: > > ${entity.getDiscount}</span>, > > "type" -> h("Billing")) > > } > > } > > > > trait CancellationEventBinding extends > > EntityBinding[SubscriptionCancellationEvent] with > SubscriptionEventBinding { > > abstract override def apply(xhtml : NodeSeq) : NodeSeq = { > > bind("event", super.apply(xhtml), > > "detail" -> <div>Reason: {entity.getReason}<br/>Final > > Balance: {entity.getFinalBalance}</div>, > > "type" -> h("Cancellation")) > > } > > } > > > > Then, in the appropriate scope, I import the correct implicit: > > > > implicit def entityToEventBinding(e : SubscriptionEvent) : > Binding = { > > e match { > > case b : SubscriptionBillingEvent => new > > BillingEventBinding { override val entity = b } > > case c : SubscriptionCancellationEvent => new > > CancellationEventBinding { override val entity = c } > > case _ => throw new IllegalStateException("Unbindable > event > > " + e.getClass + " (" + e + ")") > > } > > } > > > > All of the entity classes are JPA entities implemented in Java. If I > > have a different set of bindings for a different context, I simply > > create a separate trait. The nice thing about this approach is > that the > > traits are stackable over an inheritance hierarchy, as above. > > > > With this in place, I can just treat my entity as a binding > context on > > its own: > > > > object Subscriptions { > > object current extends SessionVar[Box[Subscription]](Empty) > > } > > > > ... stuff that populates the SessionVar > > > > def events(xhtml : NodeSeq) : NodeSeq = { > > > > > > Subscriptions.current.is.map(_.events.toSeq.flatMap(_(xhtml))).openOr(h("No > > subscription to display events for.")) > > } > > > > > > Kris > > > > > > On Fri, Jan 9, 2009 at 5:29 PM, Charles F. Munat <c...@munat.com > <mailto:c...@munat.com> > > <mailto:c...@munat.com <mailto:c...@munat.com>>> wrote: > > > > > > That sounds kinda smart. Is there any chance you could post > some example > > code? > > > > Chas. > > > > Kris Nuttycombe wrote: > > > Oh, I'm not complaining about the way User is handled - my > > response was > > > more about the general hate towards MVC upthread. Having a > sensible > > > default for a standard use case is great, even when I'll > probably > > never > > > use the default. > > > > > > In my Lift app, my shortcut to different renderings (well, > different > > > bindings, really) is to keep all the binding logic for a > specific > > case > > > in a trait and have an implicit conversion from my model > to the > > > appropriate trait in the relevant scope. You still have to > do the > > work, > > > but it makes the bindings a lot easier to reuse. > > > > > > Kris > > > > > > On Fri, Jan 9, 2009 at 4:46 PM, Charles F. Munat > <c...@munat.com <mailto:c...@munat.com> > > <mailto:c...@munat.com <mailto:c...@munat.com>> > > > <mailto:c...@munat.com <mailto:c...@munat.com> > <mailto:c...@munat.com <mailto:c...@munat.com>>>> wrote: > > > > > > > > > I don't see how you're any worse off if the model can > render > > itself in > > > one way. And if that way is a common > standards-compliant way, > > such as > > > rendering to XML, and you include semantic > information, then > > you can > > > layer any other layers you want on top to do the > mapping to > > the 30 > > > different contexts. > > > > > > Saying that an object should know how to render itself > to some > > > universally recognized format is not the same as > saying that > > that solves > > > all rendering issues. > > > > > > Is there some shortcut to 30 different renderings that I'm > > missing, or > > > do you have to do the work either way? > > > > > > Chas. > > > > > > Kris Nuttycombe wrote: > > > > If you want to render a model 30 different ways in 30 > > different > > > > contexts, it kind of sucks though, doesn't it? > > > > > > > > Or what if, shock horror, you don't know how the > eventual > > system is > > > > going to want to render the model (i.e., the person > doing the > > > rendering > > > > won't be able to change the model code.) Not too > uncommon, I > > > don't think... > > > > > > > > Kris > > > > > > > > On Sun, Jan 4, 2009 at 9:58 AM, Michael <mike.sr > <http://mike.sr> > > <http://mike.sr> <http://mike.sr> > > > > <http://mike.sr>@gmail.com <http://gmail.com> > <http://gmail.com> > > <http://gmail.com> <http://gmail.com>> > > > wrote: > > > > > > > > > > > > > Also I was looking at the sample model > source code > > (User, > > > ProtoUser) > > > > > and saw presentation logic mixed in it. > Shouldn't the > > > business and > > > > > model logic be kept separated from the > presentation > > logic > > > or is there > > > > > a Lift strategy it? > > > > > > > > Hmm, a model that can render itself ... That sounds > > like this > > > crazy > > > > paradigm called object-oriented programming. > Some radicals > > > say it has > > > > some advantages over the more procedural style > of MVC. > > > > > > > > -- Michael > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---