[Lift] Re: PayPal Subscriptions
Just tested with paypal sandbox and it works, thanks. On Oct 11, 5:59 pm, Timothy Perrett timo...@getintheloop.eu wrote: Ryan, I have pushed the code to master so give it a couple of hours and Hudson should automatically start pulling those changes into 1.1- SNAPSHOT JARs for you. Alternatively do a pull and build locally. Cheers, Tim On 10 Oct 2009, at 01:38, Timothy Perrett wrote: Ryan, Ignore my last email please - i've just tested the change using the IPN simulator and it now handles the Cancel message properly by passing Empty. The change is on my branch here: http://github.com/dpp/liftweb/commit/451dd3cb97e562a063da5cfe046badf1... Cheers, Tim On Oct 10, 1:05 am, Timothy Perrett timo...@getintheloop.eu wrote: Ryan, Looking at it, the strange thing is actually why it compiles now, not why it doesn't compile with the change you suggested. Given: for (info - buildInfo(resp, r); // stat is going to be a Box[PaypalTransactionStatus.Value] anyway // because of L489. stat - info.paymentStatus) yield { actions((stat, info, r)) true } So, it appears that adding the Box[] to the partial function definition would just make the type exactly right. Im starting to write some mock tests etc as this is going to need testing programatically. More to come soon. Cheers, Tim On Oct 9, 7:03 pm, Ryan Donahue donahu...@gmail.com wrote: Here's a diff showing the changes I made. Notice I added a case to the SimplePaypal.actions method that I'd think would fail compilation but does not. On Fri, Oct 9, 2009 at 1:08 PM, Ryan Donahue donahu...@gmail.com wrote: Well, I am a scala newb, but I know maven all too well. I ran mvn clean install from the lift-paypal dir to install lift-paypal-1.1- SNAPSHOT.jar to my local repo. To be sure, I changed the signature as follows which does cause errors: def actions: PartialFunction[(PayPalInfo, Req), Unit] Change back to def actions: PartialFunction[(Box[PaypalTransactionStatus.value], PayPalInfo, Req), Unit] and no errors. On Fri, Oct 9, 2009 at 12:35 PM, Timothy Perrett timo...@getintheloop.euwrote: Hey Ryan, How *exactly* did you locally do the build? If you had done the install of your altered lift-paypal then you would certainly get a compile error because the signature has changed. The new syntax should be: object MyIPN extends PaypalIPN { def actions = { case (Full(CompletedPayment), info, req) = // do something } } The only exclusion would be if you had a implicit conversion to Box PaypalTransactionStatus types that were unboxed. Cheers, Tim On Oct 9, 3:46 pm, Ryan Donahue donahu...@gmail.com wrote: Tim, I locally changed the PaypalIPN.actions method return type to trait PaypalIPN { def actions: PartialFunction[(Box [PaypalTransactionStatus.Value], PayPalInfo, Req), Unit] } Apparently this does not cause any compilation errors for user implementing their own IPN handler as follows object MyIPN extends PaypalIPN { import PaypalTransactionStatus._ def actions = { case (CompletedPayment, info, req) = // do something } } This is not good since I assume the result is that the case won't match anymore but we won't have a compilation error to tell us to change our code. Maybe I missed something, I am a scala newbie :) -Ryan On Oct 8, 3:57 pm, Timothy Perrett timo...@getintheloop.eu wrote: Ok cool, I'll take a look at this tomrrow all being well. Thanks for the feedback Cheers, Tim Sent from my iPhone On 8 Oct 2009, at 20:43, Ryan Donahue donahu...@gmail.com wrote: I created the ticket:http://github.com/dpp/liftweb/issues/ #issue/88 I do receive the payment_status field for PDT. I bet in practice you will never receive a payment_status value other than Completed, because if the payment was not completed PayPal would not redirect the user's browser back to your PDT URL. However, I have not verified this and do check the payment status in my PDT code anyway (how could I verify that it will never happen?). So I would prefer that both were consistent, but just boxing the IPN payment status will be fine too :) On Thu, Oct 8, 2009 at 2:49 PM, Timothy Perrett timo...@getintheloop.eu wrote: Im not married to the current API, so breaking changes are OK as there are only a handful of people using this code right now. To be honest, this whole situation just underlines the need for mocking in this module of lift... i've been meaning to do it since the beginning but just never got round to it and lack of general demand. Just about why they have a different signature... if memory serves that would be because PaypalTransactionStatus is not supplied for PDT. So whilst I see your point about them being consistent, im
[Lift] Re: PayPal Subscriptions
Tim, I locally changed the PaypalIPN.actions method return type to trait PaypalIPN { def actions: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), Unit] } Apparently this does not cause any compilation errors for user implementing their own IPN handler as follows object MyIPN extends PaypalIPN { import PaypalTransactionStatus._ def actions = { case (CompletedPayment, info, req) = // do something } } This is not good since I assume the result is that the case won't match anymore but we won't have a compilation error to tell us to change our code. Maybe I missed something, I am a scala newbie :) -Ryan On Oct 8, 3:57 pm, Timothy Perrett timo...@getintheloop.eu wrote: Ok cool, I'll take a look at this tomrrow all being well. Thanks for the feedback Cheers, Tim Sent from my iPhone On 8 Oct 2009, at 20:43, Ryan Donahue donahu...@gmail.com wrote: I created the ticket:http://github.com/dpp/liftweb/issues/#issue/88 I do receive the payment_status field for PDT. I bet in practice you will never receive a payment_status value other than Completed, because if the payment was not completed PayPal would not redirect the user's browser back to your PDT URL. However, I have not verified this and do check the payment status in my PDT code anyway (how could I verify that it will never happen?). So I would prefer that both were consistent, but just boxing the IPN payment status will be fine too :) On Thu, Oct 8, 2009 at 2:49 PM, Timothy Perrett timo...@getintheloop.eu wrote: Im not married to the current API, so breaking changes are OK as there are only a handful of people using this code right now. To be honest, this whole situation just underlines the need for mocking in this module of lift... i've been meaning to do it since the beginning but just never got round to it and lack of general demand. Just about why they have a different signature... if memory serves that would be because PaypalTransactionStatus is not supplied for PDT. So whilst I see your point about them being consistent, im not sure there is value in having a Box parameter that would always be Empty? For IPN however, boxing sounds good to me. Should just be a case of: Box !! info.paymentStatus Would you be happy with that? If you could raise a ticket for this issue i'll patch it tomorrow and commit the code on a branch related to that ticket. One the code goes through review then it will make it into the master branch all being well. Cheers, Tim On 8 Oct 2009, at 18:52, Ryan Donahue wrote: Yeah, I noticed my email got mangled. It would make sense to me if PaypalIPN.actions and PaypalPDT.pdtResponse were consistent. trait PaypalPDT { def pdtResponse: PartialFunction[(PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(PayPalInfo, Req), Unit] } If matching the status is just too convenient to lose, then how about this. trait PaypalPDT { def pdtResponse: PartialFunction[(Box [PaypalTransactionStatus.Value], PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), Unit] } Either would be an API breaking change for the paypal module, but at least it'd be caught be the compiler. What do you think? On Thu, Oct 8, 2009 at 1:33 PM, Timothy Perrett timo...@getintheloop.eu wrote: The parameters were pretty mangled in your email... Which one would you propose is more generic that the current status one we have? Alternatively, it sounds to me like we might need to add some kind of special case match statement. Thoughts? Cheers, tim On 8 Oct 2009, at 13:14, Ryan Donahue wrote: Hi Tim, Looking at Table 2. Summary of subscription variables of the page you reference, payment_status is not included for messages with a txn_type of subscr_ signup, subscr_ cancel, subscr_ modify, or subscr_eot. This matches the results I see in testing with PayPal Sandbox. Neither subscr_signup or subscr_cancel include the payment_status. Below are the parameters from two messages I have received (they contain fake user info generated by PayPal Sandbox, so no security/ privacy concerns). params from subscr_signup message: btn_id - List(1070963), test_ipn - List(1), charset - List (windows-1252), address_country - List(United States), item_name - List(Pro Account), recurring - List(1), address_state - List(CA), amount3 - List(9.99), address_street - List(1 Main St), verify_sign - List(Ab4im9HUsk1pOL1dlUXJxEoipQcaAJQqV047JE2KENGFX4meCETo.KLt), address_status - List(confirmed), period3 - List(1 M), subscr_date - List(05:01:02 Oct 08, 2009 PDT), first_name - List(Test), address_country_code - List(US), address_city - List(San Jose), mc_currency - List(USD), mc_amount3
[Lift] Re: PayPal Subscriptions
Well, I am a scala newb, but I know maven all too well. I ran mvn clean install from the lift-paypal dir to install lift-paypal-1.1-SNAPSHOT.jar to my local repo. To be sure, I changed the signature as follows which does cause errors: def actions: PartialFunction[(PayPalInfo, Req), Unit] Change back to def actions: PartialFunction[(Box[PaypalTransactionStatus.value], PayPalInfo, Req), Unit] and no errors. On Fri, Oct 9, 2009 at 12:35 PM, Timothy Perrett timo...@getintheloop.euwrote: Hey Ryan, How *exactly* did you locally do the build? If you had done the install of your altered lift-paypal then you would certainly get a compile error because the signature has changed. The new syntax should be: object MyIPN extends PaypalIPN { def actions = { case (Full(CompletedPayment), info, req) = // do something } } The only exclusion would be if you had a implicit conversion to Box PaypalTransactionStatus types that were unboxed. Cheers, Tim On Oct 9, 3:46 pm, Ryan Donahue donahu...@gmail.com wrote: Tim, I locally changed the PaypalIPN.actions method return type to trait PaypalIPN { def actions: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), Unit] } Apparently this does not cause any compilation errors for user implementing their own IPN handler as follows object MyIPN extends PaypalIPN { import PaypalTransactionStatus._ def actions = { case (CompletedPayment, info, req) = // do something } } This is not good since I assume the result is that the case won't match anymore but we won't have a compilation error to tell us to change our code. Maybe I missed something, I am a scala newbie :) -Ryan On Oct 8, 3:57 pm, Timothy Perrett timo...@getintheloop.eu wrote: Ok cool, I'll take a look at this tomrrow all being well. Thanks for the feedback Cheers, Tim Sent from my iPhone On 8 Oct 2009, at 20:43, Ryan Donahue donahu...@gmail.com wrote: I created the ticket:http://github.com/dpp/liftweb/issues/#issue/88 I do receive the payment_status field for PDT. I bet in practice you will never receive a payment_status value other than Completed, because if the payment was not completed PayPal would not redirect the user's browser back to your PDT URL. However, I have not verified this and do check the payment status in my PDT code anyway (how could I verify that it will never happen?). So I would prefer that both were consistent, but just boxing the IPN payment status will be fine too :) On Thu, Oct 8, 2009 at 2:49 PM, Timothy Perrett timo...@getintheloop.eu wrote: Im not married to the current API, so breaking changes are OK as there are only a handful of people using this code right now. To be honest, this whole situation just underlines the need for mocking in this module of lift... i've been meaning to do it since the beginning but just never got round to it and lack of general demand. Just about why they have a different signature... if memory serves that would be because PaypalTransactionStatus is not supplied for PDT. So whilst I see your point about them being consistent, im not sure there is value in having a Box parameter that would always be Empty? For IPN however, boxing sounds good to me. Should just be a case of: Box !! info.paymentStatus Would you be happy with that? If you could raise a ticket for this issue i'll patch it tomorrow and commit the code on a branch related to that ticket. One the code goes through review then it will make it into the master branch all being well. Cheers, Tim On 8 Oct 2009, at 18:52, Ryan Donahue wrote: Yeah, I noticed my email got mangled. It would make sense to me if PaypalIPN.actions and PaypalPDT.pdtResponse were consistent. trait PaypalPDT { def pdtResponse: PartialFunction[(PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(PayPalInfo, Req), Unit] } If matching the status is just too convenient to lose, then how about this. trait PaypalPDT { def pdtResponse: PartialFunction[(Box [PaypalTransactionStatus.Value], PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), Unit] } Either would be an API breaking change for the paypal module, but at least it'd be caught be the compiler. What do you think? On Thu, Oct 8, 2009 at 1:33 PM, Timothy Perrett timo...@getintheloop.eu wrote: The parameters were pretty mangled in your email... Which one would you propose is more generic that the current status one we have? Alternatively, it sounds to me like we might need to add some kind of special case match statement. Thoughts? Cheers, tim On 8
[Lift] Re: PayPal Subscriptions
Here's a diff showing the changes I made. Notice I added a case to the SimplePaypal.actions method that I'd think would fail compilation but does not. On Fri, Oct 9, 2009 at 1:08 PM, Ryan Donahue donahu...@gmail.com wrote: Well, I am a scala newb, but I know maven all too well. I ran mvn clean install from the lift-paypal dir to install lift-paypal-1.1-SNAPSHOT.jar to my local repo. To be sure, I changed the signature as follows which does cause errors: def actions: PartialFunction[(PayPalInfo, Req), Unit] Change back to def actions: PartialFunction[(Box[PaypalTransactionStatus.value], PayPalInfo, Req), Unit] and no errors. On Fri, Oct 9, 2009 at 12:35 PM, Timothy Perrett timo...@getintheloop.euwrote: Hey Ryan, How *exactly* did you locally do the build? If you had done the install of your altered lift-paypal then you would certainly get a compile error because the signature has changed. The new syntax should be: object MyIPN extends PaypalIPN { def actions = { case (Full(CompletedPayment), info, req) = // do something } } The only exclusion would be if you had a implicit conversion to Box PaypalTransactionStatus types that were unboxed. Cheers, Tim On Oct 9, 3:46 pm, Ryan Donahue donahu...@gmail.com wrote: Tim, I locally changed the PaypalIPN.actions method return type to trait PaypalIPN { def actions: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), Unit] } Apparently this does not cause any compilation errors for user implementing their own IPN handler as follows object MyIPN extends PaypalIPN { import PaypalTransactionStatus._ def actions = { case (CompletedPayment, info, req) = // do something } } This is not good since I assume the result is that the case won't match anymore but we won't have a compilation error to tell us to change our code. Maybe I missed something, I am a scala newbie :) -Ryan On Oct 8, 3:57 pm, Timothy Perrett timo...@getintheloop.eu wrote: Ok cool, I'll take a look at this tomrrow all being well. Thanks for the feedback Cheers, Tim Sent from my iPhone On 8 Oct 2009, at 20:43, Ryan Donahue donahu...@gmail.com wrote: I created the ticket:http://github.com/dpp/liftweb/issues/#issue/88 I do receive the payment_status field for PDT. I bet in practice you will never receive a payment_status value other than Completed, because if the payment was not completed PayPal would not redirect the user's browser back to your PDT URL. However, I have not verified this and do check the payment status in my PDT code anyway (how could I verify that it will never happen?). So I would prefer that both were consistent, but just boxing the IPN payment status will be fine too :) On Thu, Oct 8, 2009 at 2:49 PM, Timothy Perrett timo...@getintheloop.eu wrote: Im not married to the current API, so breaking changes are OK as there are only a handful of people using this code right now. To be honest, this whole situation just underlines the need for mocking in this module of lift... i've been meaning to do it since the beginning but just never got round to it and lack of general demand. Just about why they have a different signature... if memory serves that would be because PaypalTransactionStatus is not supplied for PDT. So whilst I see your point about them being consistent, im not sure there is value in having a Box parameter that would always be Empty? For IPN however, boxing sounds good to me. Should just be a case of: Box !! info.paymentStatus Would you be happy with that? If you could raise a ticket for this issue i'll patch it tomorrow and commit the code on a branch related to that ticket. One the code goes through review then it will make it into the master branch all being well. Cheers, Tim On 8 Oct 2009, at 18:52, Ryan Donahue wrote: Yeah, I noticed my email got mangled. It would make sense to me if PaypalIPN.actions and PaypalPDT.pdtResponse were consistent. trait PaypalPDT { def pdtResponse: PartialFunction[(PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(PayPalInfo, Req), Unit] } If matching the status is just too convenient to lose, then how about this. trait PaypalPDT { def pdtResponse: PartialFunction[(Box [PaypalTransactionStatus.Value], PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), Unit] } Either would be an API breaking change for the paypal module, but at least it'd be caught be the compiler. What do you think? On Thu, Oct 8, 2009 at 1:33 PM, Timothy Perrett timo...@getintheloop.eu wrote: The parameters were pretty mangled in your email
[Lift] Re: PayPal Subscriptions
Hi Tim, Looking at Table 2. Summary of subscription variables of the page you reference, payment_status is not included for messages with a txn_type of subscr_ signup, subscr_ cancel, subscr_ modify, or subscr_eot. This matches the results I see in testing with PayPal Sandbox. Neither subscr_signup or subscr_cancel include the payment_status. Below are the parameters from two messages I have received (they contain fake user info generated by PayPal Sandbox, so no security/ privacy concerns). params from subscr_signup message: btn_id - List(1070963), test_ipn - List(1), charset - List (windows-1252), address_country - List(United States), item_name - List(Pro Account), recurring - List(1), address_state - List(CA), amount3 - List(9.99), address_street - List(1 Main St), verify_sign - List(Ab4im9HUsk1pOL1dlUXJxEoipQcaAJQqV047JE2KENGFX4meCETo.KLt), address_status - List(confirmed), period3 - List(1 M), subscr_date - List(05:01:02 Oct 08, 2009 PDT), first_name - List(Test), address_country_code - List(US), address_city - List(San Jose), mc_currency - List(USD), mc_amount3 - List(9.99), residence_country - List(US), payer_email - List(buyer1_1254939630_...@gmail.com), address_name - List(Test User), txn_type - List(subscr_signup), payer_status - List(verified), subscr_id - List (S-8X87353621486401E), last_name - List(User), payer_id - List (JMM2RTLNU5RPJ), reattempt - List(1), notify_version - List(2.8), custom - List(2), address_zip - List(95131), receiver_email - List (seller_1254749970_...@gmail.com), business - List (seller_1254749970_...@gmail.com) params from subscr_cancel message: btn_id - List(1070963), test_ipn - List(1), charset - List (windows-1252), address_country - List(United States), item_name - List(Pro Account), recurring - List(1), address_state - List(CA), amount3 - List(9.99), address_street - List(1 Main St), verify_sign - List(AvpXEetWAO5JsntihTfwE4HykmNlAsappICrYh6PaVgG3JJUYLtOnqVU), address_status - List(confirmed), period3 - List(1 M), subscr_date - List(05:06:19 Oct 08, 2009 PDT), first_name - List(Test), address_country_code - List(US), address_city - List(San Jose), mc_currency - List(USD), mc_amount3 - List(9.99), residence_country - List(US), payer_email - List(buyer1_1254939630_...@gmail.com), address_name - List(Test User), txn_type - List(subscr_cancel), payer_status - List(verified), subscr_id - List (S-8X87353621486401E), last_name - List(User), payer_id - List (JMM2RTLNU5RPJ), reattempt - List(1), notify_version - List(2.8), custom - List(2), address_zip - List(95131), receiver_email - List (seller_1254749970_...@gmail.com), business - List (seller_1254749970_...@gmail.com) Thanks, Ryan On Oct 7, 6:18 pm, Timothy Perrett timo...@getintheloop.eu wrote: Ryan, The PayPal stuff is pretty much my baby - its awesome that your using it in production! See what your saying - its been a while since I did anything with PayPal; what fields *are* returned when the transaction is canceled? Or, specifically, the question is what behaviour do you need? Lets start there and then I can work on a solution - it was my understanding that all responses from paypal had the payment_status field; im using the reference here:http://is.gd/43po4can you detail the type of transaction you've been seeing this behaviour on? Cheers, Tim On 7 Oct 2009, at 20:56, Ryan Donahue wrote: I'm receiving IPN updates from PayPal when a subcription is created and when it is canceled. However, the cancel message never make it to my actions method. Apparently, the cancel message does not include the payment_status. I think this results in the message being dropped on the floor because of the for-comprehension on line 458 in Paypal.scala. Would appreciate any help. By the way, we've been using the paypal module in production for a couple months now (a very small app for selling a partner-branded version of our screen recorder). Thanks, Ryan --~--~-~--~~~---~--~~ 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: PayPal Subscriptions
Arg, looks like the param listings in my message got formatted as previous message quotes. Hopefully, it is clear enough. On Oct 8, 8:14 am, Ryan Donahue donahu...@gmail.com wrote: Hi Tim, Looking at Table 2. Summary of subscription variables of the page you reference, payment_status is not included for messages with a txn_type of subscr_ signup, subscr_ cancel, subscr_ modify, or subscr_eot. This matches the results I see in testing with PayPal Sandbox. Neither subscr_signup or subscr_cancel include the payment_status. Below are the parameters from two messages I have received (they contain fake user info generated by PayPal Sandbox, so no security/ privacy concerns). params from subscr_signup message: btn_id - List(1070963), test_ipn - List(1), charset - List (windows-1252), address_country - List(United States), item_name - List(Pro Account), recurring - List(1), address_state - List(CA), amount3 - List(9.99), address_street - List(1 Main St), verify_sign - List(Ab4im9HUsk1pOL1dlUXJxEoipQcaAJQqV047JE2KENGFX4meCETo.KLt), address_status - List(confirmed), period3 - List(1 M), subscr_date - List(05:01:02 Oct 08, 2009 PDT), first_name - List(Test), address_country_code - List(US), address_city - List(San Jose), mc_currency - List(USD), mc_amount3 - List(9.99), residence_country - List(US), payer_email - List(buyer1_1254939630_...@gmail.com), address_name - List(Test User), txn_type - List(subscr_signup), payer_status - List(verified), subscr_id - List (S-8X87353621486401E), last_name - List(User), payer_id - List (JMM2RTLNU5RPJ), reattempt - List(1), notify_version - List(2.8), custom - List(2), address_zip - List(95131), receiver_email - List (seller_1254749970_...@gmail.com), business - List (seller_1254749970_...@gmail.com) params from subscr_cancel message: btn_id - List(1070963), test_ipn - List(1), charset - List (windows-1252), address_country - List(United States), item_name - List(Pro Account), recurring - List(1), address_state - List(CA), amount3 - List(9.99), address_street - List(1 Main St), verify_sign - List(AvpXEetWAO5JsntihTfwE4HykmNlAsappICrYh6PaVgG3JJUYLtOnqVU), address_status - List(confirmed), period3 - List(1 M), subscr_date - List(05:06:19 Oct 08, 2009 PDT), first_name - List(Test), address_country_code - List(US), address_city - List(San Jose), mc_currency - List(USD), mc_amount3 - List(9.99), residence_country - List(US), payer_email - List(buyer1_1254939630_...@gmail.com), address_name - List(Test User), txn_type - List(subscr_cancel), payer_status - List(verified), subscr_id - List (S-8X87353621486401E), last_name - List(User), payer_id - List (JMM2RTLNU5RPJ), reattempt - List(1), notify_version - List(2.8), custom - List(2), address_zip - List(95131), receiver_email - List (seller_1254749970_...@gmail.com), business - List (seller_1254749970_...@gmail.com) Thanks, Ryan On Oct 7, 6:18 pm, Timothy Perrett timo...@getintheloop.eu wrote: Ryan, The PayPal stuff is pretty much my baby - its awesome that your using it in production! See what your saying - its been a while since I did anything with PayPal; what fields *are* returned when the transaction is canceled? Or, specifically, the question is what behaviour do you need? Lets start there and then I can work on a solution - it was my understanding that all responses from paypal had the payment_status field; im using the reference here:http://is.gd/43po4canyou detail the type of transaction you've been seeing this behaviour on? Cheers, Tim On 7 Oct 2009, at 20:56, Ryan Donahue wrote: I'm receiving IPN updates from PayPal when a subcription is created and when it is canceled. However, the cancel message never make it to my actions method. Apparently, the cancel message does not include the payment_status. I think this results in the message being dropped on the floor because of the for-comprehension on line 458 in Paypal.scala. Would appreciate any help. By the way, we've been using the paypal module in production for a couple months now (a very small app for selling a partner-branded version of our screen recorder). Thanks, Ryan --~--~-~--~~~---~--~~ 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: PayPal Subscriptions
Yeah, I noticed my email got mangled. It would make sense to me if PaypalIPN.actions and PaypalPDT.pdtResponse were consistent. trait PaypalPDT { def pdtResponse: PartialFunction[(PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(PayPalInfo, Req), Unit] } If matching the status is just too convenient to lose, then how about this. trait PaypalPDT { def pdtResponse: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), Unit] } Either would be an API breaking change for the paypal module, but at least it'd be caught be the compiler. What do you think? On Thu, Oct 8, 2009 at 1:33 PM, Timothy Perrett timo...@getintheloop.euwrote: The parameters were pretty mangled in your email... Which one would you propose is more generic that the current status one we have? Alternatively, it sounds to me like we might need to add some kind of special case match statement. Thoughts? Cheers, tim On 8 Oct 2009, at 13:14, Ryan Donahue wrote: Hi Tim, Looking at Table 2. Summary of subscription variables of the page you reference, payment_status is not included for messages with a txn_type of subscr_ signup, subscr_ cancel, subscr_ modify, or subscr_eot. This matches the results I see in testing with PayPal Sandbox. Neither subscr_signup or subscr_cancel include the payment_status. Below are the parameters from two messages I have received (they contain fake user info generated by PayPal Sandbox, so no security/ privacy concerns). params from subscr_signup message: btn_id - List(1070963), test_ipn - List(1), charset - List (windows-1252), address_country - List(United States), item_name - List(Pro Account), recurring - List(1), address_state - List(CA), amount3 - List(9.99), address_street - List(1 Main St), verify_sign - List(Ab4im9HUsk1pOL1dlUXJxEoipQcaAJQqV047JE2KENGFX4meCETo.KLt), address_status - List(confirmed), period3 - List(1 M), subscr_date - List(05:01:02 Oct 08, 2009 PDT), first_name - List(Test), address_country_code - List(US), address_city - List(San Jose), mc_currency - List(USD), mc_amount3 - List(9.99), residence_country - List(US), payer_email - List(buyer1_1254939630_...@gmail.com), address_name - List(Test User), txn_type - List(subscr_signup), payer_status - List(verified), subscr_id - List (S-8X87353621486401E), last_name - List(User), payer_id - List (JMM2RTLNU5RPJ), reattempt - List(1), notify_version - List(2.8), custom - List(2), address_zip - List(95131), receiver_email - List (seller_1254749970_...@gmail.com), business - List (seller_1254749970_...@gmail.com) params from subscr_cancel message: btn_id - List(1070963), test_ipn - List(1), charset - List (windows-1252), address_country - List(United States), item_name - List(Pro Account), recurring - List(1), address_state - List(CA), amount3 - List(9.99), address_street - List(1 Main St), verify_sign - List(AvpXEetWAO5JsntihTfwE4HykmNlAsappICrYh6PaVgG3JJUYLtOnqVU), address_status - List(confirmed), period3 - List(1 M), subscr_date - List(05:06:19 Oct 08, 2009 PDT), first_name - List(Test), address_country_code - List(US), address_city - List(San Jose), mc_currency - List(USD), mc_amount3 - List(9.99), residence_country - List(US), payer_email - List(buyer1_1254939630_...@gmail.com), address_name - List(Test User), txn_type - List(subscr_cancel), payer_status - List(verified), subscr_id - List (S-8X87353621486401E), last_name - List(User), payer_id - List (JMM2RTLNU5RPJ), reattempt - List(1), notify_version - List(2.8), custom - List(2), address_zip - List(95131), receiver_email - List (seller_1254749970_...@gmail.com), business - List (seller_1254749970_...@gmail.com) Thanks, Ryan On Oct 7, 6:18 pm, Timothy Perrett timo...@getintheloop.eu wrote: Ryan, The PayPal stuff is pretty much my baby - its awesome that your using it in production! See what your saying - its been a while since I did anything with PayPal; what fields *are* returned when the transaction is canceled? Or, specifically, the question is what behaviour do you need? Lets start there and then I can work on a solution - it was my understanding that all responses from paypal had the payment_status field; im using the reference here:http://is.gd/43po4can you detail the type of transaction you've been seeing this behaviour on? Cheers, Tim On 7 Oct 2009, at 20:56, Ryan Donahue wrote: I'm receiving IPN updates from PayPal when a subcription is created and when it is canceled. However, the cancel message never make it to my actions method. Apparently, the cancel message does not include the payment_status. I think this results in the message being dropped on the floor because of the for-comprehension on line 458 in Paypal.scala
[Lift] Re: PayPal Subscriptions
I created the ticket: http://github.com/dpp/liftweb/issues/#issue/88 I do receive the payment_status field for PDT. I bet in practice you will never receive a payment_status value other than Completed, because if the payment was not completed PayPal would not redirect the user's browser back to your PDT URL. However, I have not verified this and do check the payment status in my PDT code anyway (how could I verify that it will never happen?). So I would prefer that both were consistent, but just boxing the IPN payment status will be fine too :) On Thu, Oct 8, 2009 at 2:49 PM, Timothy Perrett timo...@getintheloop.euwrote: Im not married to the current API, so breaking changes are OK as there are only a handful of people using this code right now. To be honest, this whole situation just underlines the need for mocking in this module of lift... i've been meaning to do it since the beginning but just never got round to it and lack of general demand. Just about why they have a different signature... if memory serves that would be because PaypalTransactionStatus is not supplied for PDT. So whilst I see your point about them being consistent, im not sure there is value in having a Box parameter that would always be Empty? For IPN however, boxing sounds good to me. Should just be a case of: Box !! info.paymentStatus Would you be happy with that? If you could raise a ticket for this issue i'll patch it tomorrow and commit the code on a branch related to that ticket. One the code goes through review then it will make it into the master branch all being well. Cheers, Tim On 8 Oct 2009, at 18:52, Ryan Donahue wrote: Yeah, I noticed my email got mangled. It would make sense to me if PaypalIPN.actions and PaypalPDT.pdtResponse were consistent. trait PaypalPDT { def pdtResponse: PartialFunction[(PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(PayPalInfo, Req), Unit] } If matching the status is just too convenient to lose, then how about this. trait PaypalPDT { def pdtResponse: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), LiftResponse] } trait PaypalIPN { def actions: PartialFunction[(Box[PaypalTransactionStatus.Value], PayPalInfo, Req), Unit] } Either would be an API breaking change for the paypal module, but at least it'd be caught be the compiler. What do you think? On Thu, Oct 8, 2009 at 1:33 PM, Timothy Perrett timo...@getintheloop.euwrote: The parameters were pretty mangled in your email... Which one would you propose is more generic that the current status one we have? Alternatively, it sounds to me like we might need to add some kind of special case match statement. Thoughts? Cheers, tim On 8 Oct 2009, at 13:14, Ryan Donahue wrote: Hi Tim, Looking at Table 2. Summary of subscription variables of the page you reference, payment_status is not included for messages with a txn_type of subscr_ signup, subscr_ cancel, subscr_ modify, or subscr_eot. This matches the results I see in testing with PayPal Sandbox. Neither subscr_signup or subscr_cancel include the payment_status. Below are the parameters from two messages I have received (they contain fake user info generated by PayPal Sandbox, so no security/ privacy concerns). params from subscr_signup message: btn_id - List(1070963), test_ipn - List(1), charset - List (windows-1252), address_country - List(United States), item_name - List(Pro Account), recurring - List(1), address_state - List(CA), amount3 - List(9.99), address_street - List(1 Main St), verify_sign - List(Ab4im9HUsk1pOL1dlUXJxEoipQcaAJQqV047JE2KENGFX4meCETo.KLt), address_status - List(confirmed), period3 - List(1 M), subscr_date - List(05:01:02 Oct 08, 2009 PDT), first_name - List(Test), address_country_code - List(US), address_city - List(San Jose), mc_currency - List(USD), mc_amount3 - List(9.99), residence_country - List(US), payer_email - List(buyer1_1254939630_...@gmail.com), address_name - List(Test User), txn_type - List(subscr_signup), payer_status - List(verified), subscr_id - List (S-8X87353621486401E), last_name - List(User), payer_id - List (JMM2RTLNU5RPJ), reattempt - List(1), notify_version - List(2.8), custom - List(2), address_zip - List(95131), receiver_email - List (seller_1254749970_...@gmail.com), business - List (seller_1254749970_...@gmail.com) params from subscr_cancel message: btn_id - List(1070963), test_ipn - List(1), charset - List (windows-1252), address_country - List(United States), item_name - List(Pro Account), recurring - List(1), address_state - List(CA), amount3 - List(9.99), address_street - List(1 Main St), verify_sign - List(AvpXEetWAO5JsntihTfwE4HykmNlAsappICrYh6PaVgG3JJUYLtOnqVU), address_status - List(confirmed), period3 - List(1 M), subscr_date - List(05:06:19 Oct 08, 2009 PDT), first_name - List(Test), address_country_code - List(US
[Lift] PayPal Subscriptions
I'm receiving IPN updates from PayPal when a subcription is created and when it is canceled. However, the cancel message never make it to my actions method. Apparently, the cancel message does not include the payment_status. I think this results in the message being dropped on the floor because of the for-comprehension on line 458 in Paypal.scala. Would appreciate any help. By the way, we've been using the paypal module in production for a couple months now (a very small app for selling a partner-branded version of our screen recorder). Thanks, Ryan --~--~-~--~~~---~--~~ 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: Alternate Lift builds?
The default profile we have is just so that a developer doesn't have to provide the release version when invoking maven on the command line. I didn't want to require more typing :) Taken that you can inject special project.version via -D but what about having other dependent modules using that special version as well? You'd still need to have them controlled by injecting special property. I'm not sure what you are asking. Are you referring to submodules within one project? If so, your module POMs would also use the property. For example, our module POMs have: parent version${releaseVersion}/version ... /parent ... version${releaseVersion}/version ... In this scenario, apart from the pom.xml growing bigger, do you foresee any distinct disadvantage opting for the profile path (instead of property injection)? I think of profiles as way to adjust the build according to the environment in which the build is occurring (in my case developer's machine versus hudson CI) rather than for per-version/per-branch adjustment. But, I don't see any disadvantages for using a profile other than release version seems to be one good candidate for singling out. At utipu, passing a releaseVersion property to maven means we can quickly/easily make new branches that are ready for CI. It also helps in cutting releases, because we don't have to make any commits to repository to change a release version from 1.0-SNAPSHOT to 1.0. I stated in my first response that this approach may or may not be appropriate for a framework for two reasons: (1) If you are building the framework from source and using the result in other projects locally, you might have to specify the version in the maven command line when building the framework (this really depends on what value you use for the releaseVersion in the default profile); and (2) I haven't seen anybody else do it this way. On Mon, Sep 21, 2009 at 10:10 AM, Indrajit Raychaudhuri indraj...@gmail.com wrote: Ryan, Your comment: (we just use dev so local developers' .war files are built as utipu-dev.war) made me perceive that you go for manual build for dev. But, yes, point accepted. Taken that you can inject special project.version via -D but what about having other dependent modules using that special version as well? You'd still need to have them controlled by injecting special property. In this scenario, apart from the pom.xml growing bigger, do you foresee any distinct disadvantage opting for the profile path (instead of property injection)? Cheers, Indrajit On 21/09/09 7:18 PM, Ryan Donahue wrote: In fact it works for multiple Hudson builds. We have serveral hudson builds running concurrently: one for the currently released version, one for the trunk, and others for customer-specific builds. Only one maven profile is needed for the Hudson builds because these builds pass the version in to maven. On Mon, Sep 21, 2009 at 9:42 AM, Indrajit Raychaudhuri indraj...@gmail.com mailto:indraj...@gmail.com wrote: Ryan, Nice workflow! But I guess this works better when one is a Hudson build and the other a manual build. What David was looking for is involves two Hudson builds. Do you think this would serve the purpose using Maven profile (mvn -P instead of mvn -D)? http://github.com/dpp/liftweb/commit/45dc2e55bd37104aa2a56990914b38a1895b18f6 Cheers, Indrajit On 21/09/09 6:28 PM, Ryan Donahue wrote: We pass the release version into maven from hudson. In the POM: version${releaseVersion}/version In the hudson build's maven goals and options field: -DreleaseVersion=1.1-SNAPSHOT Actually, we go a little further by creating a hudson build property called releaseVersion. Then the maven options include: -DreleaseVersion=${releaseVersion}. This results in a prompt whenever you do a manual build, allowing you to change the releaseVersion property (good for release builds). If you go this route, you'll want to have at least 2 profiles in the POM, one for hudson builds invoked when the releaseVersion property is present and a default profile for developers that sets the releaseVersion property to some default (we just use dev so local developers' .war files are built as utipu-dev.war). We use this strategy for utipu.com http://utipu.com (not a lift app) as well as for our internal lift apps. It works well for us, but may or may not be appropriate for a framework build. On Sep 18, 7:38 pm, David Pollakfeeder.of.the.be...@gmail.com mailto:feeder.of.the.be...@gmail.com wrote: Folks, Is there a clean and easy way that anyone knows of to have Hudson do alternate builds from different Git branches and put
[Lift] What's the best way to get the current request URL
I want to capture the the current request URL, so I can redirect back to it at a later point. What's the best way to get at the URL? The answer is probably obvious, but I can't seem to find it. Thanks, Ryan --~--~-~--~~~---~--~~ 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: What's the best way to get the current request URL
Does that include the query string? On Wed, Sep 16, 2009 at 11:21 AM, harryh har...@gmail.com wrote: S.uri On Sep 16, 9:35 am, Ryan Donahue donahu...@gmail.com wrote: I want to capture the the current request URL, so I can redirect back to it at a later point. What's the best way to get at the URL? The answer is probably obvious, but I can't seem to find it. Thanks, Ryan --~--~-~--~~~---~--~~ 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: Checking if request is over SSL
Never mind, I found it. HTTPRequest.scheme will contain either http or https. On Sep 9, 2:46 pm, Ryan Donahue donahu...@gmail.com wrote: Previously I would check whether the request was over SSL by getting the HttpServletRequest and calling its isSecure method. Now that servlets have been abstracted to be just another http provider, is there a way to find this out using Req or HTTPRequest? Thanks, Ryan --~--~-~--~~~---~--~~ 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] Searching this Group
Search this group doesn't always work. I found this by searching for the term fade, recalling a discussion Marius posted about fading out messages. Search this group does not find the discussion, but you can find the discussion by changing the search criteria to fade group:liftweb and use the Search Groups button. Here's a very short screencast (28sec) showing the problem and solution: http://www.utipu.com/app/tip/id/15703/ I hope this helps somebody else find what they are looking for. Maybe it's why there are so many duplicate questions 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: why ajaxButton not submit the form
The problem you are encountering may be related to this (see David's response): http://groups.google.com/group/liftweb/browse_thread/thread/f8c6a2a4cee52dc6/ On Aug 24, 5:16 am, pravin pravinka...@gmail.com wrote: Hi i have form with text box and Submit button(with ajax Submit button) But when i submit the button form is not submitting so i am not able to get the value of text box.. onclick function get called... Just i want to show text value in response with ajax ... how can i do this --~--~-~--~~~---~--~~ 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: Notes from 8/19/09 Lift Committers Call - LIFT SESSION REPLICATION DISCUSSION
Marius, this sound like a very good idea. This would allow the app developer to decide whether to spend the extra time thinking about serialization/session replication. If you don't need it, then you don't use the compiler plugin and just continue building lift apps as you have been. If you do need it, then you use the plugin and you'll have compiler errors or warnings telling you where you need to make use of LiftSerializable. If the serializing problems are handled, would there be any reasons not to attach the lift objects to the HttpSession to support existing session replication mechanisms such as Tomcat's? On Aug 23, 1:45 pm, marius d. marius.dan...@gmail.com wrote: Hmmm .. I'm wondering if we can write a Scala compiler plugin that transform functions provided to Lift's S/SHtml function etc. into a richer FunctionX implementation that knows how to serialize it's members. We could restrict the types that as LiftSerializable on top of primitives, Calenars, SessionVar/RequestVar etc. If users need their own classes to be LiftSerilizable they would have to implement LiftSerializable trait. Thoughts? Br's, Marius On Aug 23, 8:30 pm, marius d. marius.dan...@gmail.com wrote: At a first glace Java serialization is needed because of its awareness of the reference graph. But in the same time it does not perform well. One way might be the byte level instrumentation that would induce code to figure out the reference graph and know how to stream-ify it using a given efficient protocol. But that induces risks and it involves tons of work. I think would be doable though. The problem is not really the technology of propagating session information to other nodes. That's the easiest part, but tough one is figuring out the low level reference graph and serialization semantics. This is why JINI, JavaSpaces, JGroups, CORBA, JXTA, you name it, are unlikely to help solving the fundamental problem. Br's, Marius On Aug 23, 8:16 pm, Arthur avand...@gmail.com wrote: On Sun, Aug 23, 2009 at 7:04 PM, David Pollakfeeder.of.the.be...@gmail.com wrote: On Sun, Aug 23, 2009 at 4:50 AM, Kevin Wright kev.lee.wri...@googlemail.com wrote: I'm wondering if we can't leverage JavaSpaces to handle a lot of this stuff. From my experience with the technology it seems to be a pretty good fit for the problem. Two reasons: - JavaSpaces is as far as I know, GPL and we will not mix any GPL into Lift JavaSpaces is just the specification. There are two implementations I know of: BlitzJavaSpaces (BSD) and GigaSpaces (proprietary?). I don't have hands on experience with either. - It doesn't solve the issue with low-level session replication which relies on serialization of the session data for transfer to another app server instance. Arthur --~--~-~--~~~---~--~~ 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: Has anyone tried Stax?
I'm not so concerned about the lack of session replication from a scalability point of view. Sticky sessions will get you a long way. Plus I've learned my lesson about over-engineering for scalability before you need to. However, it'd be nice to choose a path that could scale in the rare event it's needed. Stax, lacking sticky sessions, probably isn't such a path for a lift app. It seems GAE also does not support sticky sessions. If you need seamless fail over or need to do rolling updates, then lack of session replication becomes an issue (btw, I don't need either of these at the moment). Wicket is able to support session replication with its detachable models. The developer still needs to be careful about references when implementing a model's load method, but this is easily done by using @SpringBean to get weak references to Spring proxies. So, what are the differences between the wicket style - binding an anonymous inner class that extends a base component class - and the lift style - binding a function which is really just an anonymous inner class? One difference is that Wicket's base component classes do a good job of reinforcing the use of detachable models. A second difference is that lift doesn't have an easy built-in way to get weak references to unserializable resources such as mapper objects containing database connections. I don't have a solution, but thought I'd chime in since I have some Wicket experience. On Aug 18, 5:44 pm, Meredith Gregory lgreg.mered...@gmail.com wrote: Guys, This really seems like a weakness. Can someone walk me through the issues on the lift committers call, tomorrow? Best wishes, --greg On Tue, Aug 18, 2009 at 1:51 PM, Viktor Klang viktor.kl...@gmail.comwrote: On Tue, Aug 18, 2009 at 4:22 PM, marius d. marius.dan...@gmail.comwrote: On Aug 18, 5:05 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: You set whether you want a shared server, or dedicated/various speeds. In any case, is there room to entertain the thought of at some point adding support in Lift to propogate sessions across instances? (Is it easier now that it's been decoupled from servlets?) No it is not easier. The fundamental problem in distributing lift sessions is the bound functions. Sure, functions are serializable but their references may not be. For instance one can bind an ajax anonymous function and that functions can have a bunch of other references inside potentially other lambdas etc. Viktor was doing in the past some research to integrate with Terracotta but there were some issues. So consistently distributing Lift sessions in a clustered environment is a challenge but of course good ideas are more then welcome. Yeah, it really was a can of worms... - Ryan Donahuedonahu...@gmail.com wrote: Is anybody using Stax for anything more than prototyping or examples? If so, what has your experience been? Stax doesn't seem to fit lift very well, but I'd like to find out I'm wrong. Specifically, it does not support sticky sessions: http://developer.stax.net/forum/topics/initial-questions. I assume a Stax app shares resources with others on the same server, so you'd likely need to scale to additional servers sooner than normal. However, the lack of sticky sessions effectively caps a stateful lift app to one server. -- Viktor Klang Rogue Scala-head Blog: klangism.blogspot.com Twttr: viktorklang -- L.G. Meredith Managing Partner Biosimilarity LLC 1219 NW 83rd St Seattle, WA 98117 +1 206.650.3740 http://biosimilarity.blogspot.com --~--~-~--~~~---~--~~ 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: how to construct a table with a set number of columns
You could do something like this. Snippet: def func(xhtml: NodeSeq): NodeSeq = { val foos = Foo.findAll(...) val rowSize = (S.attr(rowSize) openOr 10).toInt val rowNum = (foos.size + rowSize - 1) / rowSize List.range(0, rowNum).foldLeft(Util.emptyNodeSeq)((ns, i) = { val start = i*rowSize val end = start+rowSize ns ++ bind(list, xhtml, row - row(foos.slice(start, end)) _) }) } private def row(foos:List[String])(xhtml: NodeSeq) : NodeSeq = foos.foldLeft(Util.emptyNodeSeq)((ns, foo) = ns ++ bind(foo, xhtml, name - foo.name)) Then your template can use table/tr/td or it could just use floating divs that wrap over when necessary: table lift:MyPage.func rowSize=10 tr list:row tdfoo:name//td /list:row /tr /lift:MyPage.func /table OR lift:MyPage.func list:row div class=cellfoo:name//div /list:row /lift:MyPage.func For an empty NodeSeq that works in the foldLeft I've had to create the following. Anybody know a better way? object Util { val emptyNodeSeq : NodeSeq = NodeSeq.fromSeq(Seq(xml:group/ xml:group)) } On Aug 18, 2:58 pm, harryh har...@gmail.com wrote: I have a List[Foo] and I want to construct a table with 10 columns and however many rows necessary to contain all the Foos. I feel like I should do something like so, but it's not quite right yet: table lift:MyPage.func tdfoo:name//td /lift:MyPage.func /table def func(xhtml: NodeSeq): NodeSeq = { val cells: List[NodeSeq] = Foo.findAll(...).flatMap(foo = { bind(foo, xhtml, name - foo.name) }) // then reduce the list of cells putting in trs in appropriate places, but not sure how. } --~--~-~--~~~---~--~~ 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: how to construct a table with a set number of columns
Ah yes, flatMap, of course. That will clean up some of my code, thanks. On Aug 18, 4:16 pm, harryh har...@gmail.com wrote: Ah, perfect! Thx! Incidentally, I simplified in two places by instead of doing this: List.range(0, rowNum).foldLeft(Util.emptyNodeSeq)((ns, i) = { }) doing this: List.range(0, rowNum).flatMap(i = { }) (simlar change in the row function) -harryh On Aug 18, 3:52 pm, Ryan Donahue donahu...@gmail.com wrote: You could do something like this. Snippet: def func(xhtml: NodeSeq): NodeSeq = { val foos = Foo.findAll(...) val rowSize = (S.attr(rowSize) openOr 10).toInt val rowNum = (foos.size + rowSize - 1) / rowSize List.range(0, rowNum).foldLeft(Util.emptyNodeSeq)((ns, i) = { val start = i*rowSize val end = start+rowSize ns ++ bind(list, xhtml, row - row(foos.slice(start, end)) _) }) } private def row(foos:List[String])(xhtml: NodeSeq) : NodeSeq = foos.foldLeft(Util.emptyNodeSeq)((ns, foo) = ns ++ bind(foo, xhtml, name - foo.name)) Then your template can use table/tr/td or it could just use floating divs that wrap over when necessary: table lift:MyPage.func rowSize=10 tr list:row tdfoo:name//td /list:row /tr /lift:MyPage.func /table OR lift:MyPage.func list:row div class=cellfoo:name//div /list:row /lift:MyPage.func For an empty NodeSeq that works in the foldLeft I've had to create the following. Anybody know a better way? object Util { val emptyNodeSeq : NodeSeq = NodeSeq.fromSeq(Seq(xml:group/ xml:group)) } On Aug 18, 2:58 pm, harryh har...@gmail.com wrote: I have a List[Foo] and I want to construct a table with 10 columns and however many rows necessary to contain all the Foos. I feel like I should do something like so, but it's not quite right yet: table lift:MyPage.func tdfoo:name//td /lift:MyPage.func /table def func(xhtml: NodeSeq): NodeSeq = { val cells: List[NodeSeq] = Foo.findAll(...).flatMap(foo = { bind(foo, xhtml, name - foo.name) }) // then reduce the list of cells putting in trs in appropriate places, but not sure how. } --~--~-~--~~~---~--~~ 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: Test mail
I use a fake smtp server called Dumbster: http://quintanasoft.com/dumbster/ If run.mode is development or test, my app starts an embedded instance of dumbster on an unused port and configures Mailer to connect to that port. Any email sent by the app is received by dumbster (and not relayed). If run.mode=development, I use ActorPing to periodically iterate over the received messages and log them. If run.mode=test, then I leave the messages alone so unit tests can check the message count and inspect the messages. Here's some code to get started. Put this somewhere it'll get executed early (e.g. in Boot): Props.mode match { case Props.RunModes.Test = LocalSmtp.start(mailPort.get, LocalSmtp.Mode.Queue) case Props.RunModes.Development = LocalSmtp.start(mailPort.get) } And here's a wrapper around Dumbster's SimpleSmtpServer for easy access to the messages and logging and some other tricks to pop messages as they are read: object LocalSmtp extends Actor { private var server : Box[SimpleSmtpServer] = Empty private val log = LogBoot.loggerByName(LocalSmtp) private val logInterval = Helpers.TimeSpan(Helpers.seconds(5)) var mode : Mode.Value = Mode.Log var port : Int = 7725 object Mode extends Enumeration { val Queue = Value(1, Queue) val Log = Value(2, Log) } def start(port:Int) : Unit = { this.port = port start } def start(port:Int, mode:Mode.Value) : Unit = { this.port = port this.mode = mode start } override def start = { restartServer if (mode == Mode.Log) { ActorPing.scheduleAtFixedRate(this, LogMessagesEvent, logInterval, logInterval) } super.start } override def exit = { stopServer super.exit } private def restartServer { stopServer server = Full(SimpleSmtpServer.start(port)) } private def stopServer { server.map(_.stop) server = Empty } def messages : Iterator[SmtpMessage] = { server match { case Full(s) = { import Conversions._ val msgs = new IteratorWrapper(s.getReceivedEmail.asInstanceOf [java.util.Iterator[SmtpMessage]]) restartServer msgs } case _ = Seq[SmtpMessage]().elements } } def msgCount = server match { case Full(s) = s.getReceivedEmailSize case _ = 0 } def act = { loop { react { case LogMessagesEvent = if (msgCount 0) for(msg - messages) { log.info(RECEIVED EMAIL ---) log.info(From: + msg.getHeaderValue(From)) log.info(To: + msg.getHeaderValue(To)) log.info(Subject: + msg.getHeaderValue(Subject)) log.info(Body: + msg.getBody) log.info (--) } case Scheduled = log.info(LocalSmtp logging is scheduled) case any = log.error(LocalSmtp actor received invalid event: +any.asInstanceOf[Object].getClass.getName) } } } case object LogMessagesEvent } On Aug 17, 3:41 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: How can I test mailing when offline? (Besides having a switch in my program to output mailed emails.)It would be nice if you could have all mails logged, with all their headers and body, and whether it was sent, preferably to a separate log file. --~--~-~--~~~---~--~~ 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] IE8 and single-field forms
Apparently if your form has only one text field (input tag w/ type=text) and one button tag, IE8 does not include the button as a field in the post, but only includes the text field. Here's the IE8 bug report: https://connect.microsoft.com/IE/feedback/ViewFeedback.aspx?FeedbackID=389736 The result is that my function that is bound to the button is not called when processing the post. I've worked around it by adding another input tag of type=text and style=display:none (hidden field didn't fix it). Anyway, just wanted to post a heads up and see if anybody else has come across this. The relevant code is below. Template: lift:MemberSnippet.sendConfirmation form=POST fieldset legendConfirm Email Address/legend pFirst, we need to confirm your email address so we know it's yours./p labelEmail Address:/labelbr/signup:email/br/ signup:submit/ /fieldset /lift:MemberSnippet.sendConfirmation Snippet: //note that my SForm.button is just the same as SHtml.submit but I use a button instead of input w/ type=submit def sendConfirmation(xhtml:NodeSeq) : NodeSeq = { def doConfirm() : Any = { if (email.is.length 0) { try { MemberSystem.confirmEmailAddress(email.is) notice(Your confirmation email will be sent in a few moments.) hideForms.set(true) } catch { case MemberSystem.InvalidEmailAddressException(msg) = error(The email address you provided +msg) case MemberSystem.EmailAddressAlreadyInUseException = error(The email address you provided is already being used by another member) case _ = error(We were unable to send to this email address, please try another) } } else { error (Email address is required) ; Empty} } if (!hideForms.is) bind(signup, xhtml, email - FocusOnLoad(SForm.text(email.is, email(_))), submit - SForm.button(Send Confirmation, doConfirm)) else Nil } --~--~-~--~~~---~--~~ 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: Modularization of Lift code
-1 for adding modules by dropping in a jar Suppose the jar supplies multiple Lift modules and I only want to use one, or suppose I want to use some other class in the jar and don't want to use any of its Lift modules. Adding a module to a Lift app really should be an explicit action by the developer, closer to what Tim does by putting MyModule.init in Boot. However, this does have a couple shortcomings: (1) Does not provide a mechanism for supplying templates in the module and (2) Hides the LiftRules additions from the developer which could result in confusion when troubleshooting (did this module prepend or append to dispatch? which module's dispatchers are executing first? etc.) So what about putting something like this in Boot: LiftRules.modules.append(MyModule) or LiftRules.modules.prepend(new MyModule) where MyModule extends LiftModule and LiftModule is a trait like: trait LiftModule { /* * Specify where to search for snippets, views, etc */ def lookupPackage : String /* * Specify where to search for templates */ def templates : Box[String] // or maybe this has a nice default value /* * Override this to provide LoanWrappers that will be added by S.addAround */ def SWrappers : List[LoanWrapper] = List() /* * Override this to provide dispatchers that will be added by * LiftRules.dispatch.append */ def dispatchers : List[LiftRules.DispatchPF] = List() /* * Override this to provide dispatchers that will be added by * LiftRules.statelessDispatchTable.append */ def statelessDispatchers : List[LiftRules.DispatchPF] = List() // Etc. Basically there would be an overrideable method for each type of // thing you can add to LiftRules with nice defaults where possible. A module // developer only overrides the methods needed for their module. } On Jul 28, 4:18 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: The first suggestion was reflection... I'm not pushing the idea, just throwing in an alternative. But the xml route doesn't have to be xml--it could be a plain text file like /META-INF/.liftboot etc. Or you could search all jars for net.liftweb.BootXX or net.liftweb.XX that implements a trait OnBoot... The point is, there's no shortage of ways (if there's a will :) ) but they all have a certain cost of course. Dynamic loading _means_ searching for Something. That takes time, and it puts some requirement on the library author--but it takes the requirement off the user. - Timothy Perretttimo...@getintheloop.eu wrote: Hey Naftoli, Lift has a general aversion to xml configs... Is there another route? Cheers, Tim On 28/07/2009 20:47, Naftoli Gugenheim naftoli...@gmail.com wrote: What I was suggesting is that instead of having to write Lib.init in Boot, Lift should look in Lib.jar for say /boot.xml which would tell Lift to execute Lib.init for you on startup. I think that would accomplish what you want, at the cost of lift searching through the jars. --~--~-~--~~~---~--~~ 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: Modularization of Lift code
More spitballing... Tim, I really don't know which LiftRules stuff would need to be included. For other types of environment changes, the trait could have onLoad and onUnload methods. Heiko, Maybe it is possible to make such a change without breaking API, though I am still fairly new to Lift and not at all familiar enough with LiftRules yet. All the LiftRules public methods could simply manipulate a default internal LiftModule that is always in LiftRules.modules. These are probably big changes, but I see great benefit to well- defined modules. It would facilitate sharing functionality with each other. Could even set up a LiftModule site where you can share and find modules. -Ryan On Jul 29, 7:55 am, Heiko Seeberger heiko.seeber...@googlemail.com wrote: Just a quick and dirty reply: In order to get OSGi support LiftRules should delegate *everything* to a Collection of LiftModules. LiftModules can be added to and removed from this collection anytime. Heiko 2009/7/29 Timothy Perrett timo...@getintheloop.eu Ryan, I agree with you for the most part - certainly making it explicit would be my preference also. Im not 100% sure that we would need to replicate all the LiftRules functionality as a trait for plugins, as that's just one aspect of how a plugin could change the environment. Your point about making the developer aware what the plugin actually did is a good one though - no one likes black boxes. Perhaps the plugin developer would need to implement some kind of descriptor trait... Meaning that their actual code just uses the normal LiftRules infrastructure, but during the loading process perhaps just Log.debug it to death showing exactly how the environment has been modified or something? Just spitballing... Cheers, Tim On 29/07/2009 12:31, Ryan Donahue donahu...@gmail.com wrote: -1 for adding modules by dropping in a jar Suppose the jar supplies multiple Lift modules and I only want to use one, or suppose I want to use some other class in the jar and don't want to use any of its Lift modules. Adding a module to a Lift app really should be an explicit action by the developer, closer to what Tim does by putting MyModule.init in Boot. However, this does have a couple shortcomings: (1) Does not provide a mechanism for supplying templates in the module and (2) Hides the LiftRules additions from the developer which could result in confusion when troubleshooting (did this module prepend or append to dispatch? which module's dispatchers are executing first? etc.) So what about putting something like this in Boot: LiftRules.modules.append(MyModule) or LiftRules.modules.prepend(new MyModule) where MyModule extends LiftModule and LiftModule is a trait like: trait LiftModule { /* * Specify where to search for snippets, views, etc */ def lookupPackage : String /* * Specify where to search for templates */ def templates : Box[String] // or maybe this has a nice default value /* * Override this to provide LoanWrappers that will be added by S.addAround */ def SWrappers : List[LoanWrapper] = List() /* * Override this to provide dispatchers that will be added by * LiftRules.dispatch.append */ def dispatchers : List[LiftRules.DispatchPF] = List() /* * Override this to provide dispatchers that will be added by * LiftRules.statelessDispatchTable.append */ def statelessDispatchers : List[LiftRules.DispatchPF] = List() // Etc. Basically there would be an overrideable method for each type of // thing you can add to LiftRules with nice defaults where possible. A module // developer only overrides the methods needed for their module. } On Jul 28, 4:18 pm, Naftoli Gugenheim naftoli...@gmail.com wrote: The first suggestion was reflection... I'm not pushing the idea, just throwing in an alternative. But the xml route doesn't have to be xml--it could be a plain text file like /META-INF/.liftboot etc. Or you could search all jars for net.liftweb.BootXX or net.liftweb.XX that implements a trait OnBoot... The point is, there's no shortage of ways (if there's a will :) ) but they all have a certain cost of course. Dynamic loading _means_ searching for Something. That takes time, and it puts some requirement on the library author--but it takes the requirement off the user. - Timothy Perretttimo...@getintheloop.eu wrote: Hey Naftoli, Lift has a general aversion to xml configs... Is there another route? Cheers, Tim On 28/07/2009 20:47, Naftoli Gugenheim naftoli...@gmail.com wrote: What I was suggesting is that instead of having to write Lib.init in Boot, Lift should look in Lib.jar for say /boot.xml which would tell Lift to execute Lib.init for you on startup
[Lift] Re: Modularization of Lift code
LiftRules.addToEnviroment(com.mypackage), and the com.mypackage conforms to a known standard / format with some special traits that we call loading methods on. This isn't really any different then building a module by extending LiftModule trait except that the known standard / format' is actually documented by the LiftModule trait itself and can be checked by compiler when you add LiftRules.modules.append(MyModule) to your Boot class. Regarding OSGi, I don't see a good case for using it when you just want to build a regular Lift app. Maybe if you're trying to build the next great CMS or Wordpress, but I personally won't use OSGi w/ Lift anytime soon. However, the modules themselves could be responsible for loading snippets, views, and templates. The base LiftModule trait could define and implement a findSnippet method (and findView, findTemplate) that uses current Lift technique for finding snippets. If you want to build an OSGi module then you override findSnippet. --~--~-~--~~~---~--~~ 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: JPA, Hibernate, c3p0
The shutdown method works. Thanks. On Jul 9, 5:16 pm, Ryan Donahue donahu...@gmail.com wrote: Thanks, I'll try it tomorrow and let you know. On Thu, Jul 9, 2009 at 5:14 PM, Derek Chen-Beckerdchenbec...@gmail.com wrote: Whoops. Forgot about this one. I just pushed a fix in scalajpa 1.2-SNAPSHOT that adds a shutdown method to LocalEMF. Please let me know if that works as expected or if there are any other issues. Derek On Thu, Jul 9, 2009 at 2:05 PM, Ryan Donahue donahu...@gmail.com wrote: Hi Derek, just wondering if you've had a chance to look at this yet? On Jun 29, 12:57 pm, Ryan Donahue donahu...@gmail.com wrote: Thanks, there's no rush. I'm starting a week-long vacation tomorrow, so I wouldn't be able to try any changes until then anyway. On Jun 26, 11:20 am, Derek Chen-Becker dchenbec...@gmail.com wrote: I'll look at adding a hook. Derek On Fri, Jun 26, 2009 at 6:43 AM, Ryan Donahue donahu...@gmail.com wrote: I'm using JPA and Hibernate for persistence, and I've configured Hibernate to usec3p0for connection pooling. I'm using scalajpa as follows: object em extends LocalEMF(persistenceUnit) with ThreadLocalEM When Tomcat reloads the app, the following is logged: A C3P0Registry mbean is already registered. This probably means that an application usingc3p0was undeployed, but not all PooledDataSources were closed prior to undeployment. This may lead to resource leaks over time. Please take care to close all PooledDataSources. So I thought I would just add a function to LiftRules.unloadHooksto close the EntityManagerFactory, however I can't find any way to access the underlying factory. LocaEMF has an emf val, but it is private. Any ideas? --~--~-~--~~~---~--~~ 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: JPA, Hibernate, c3p0
Thanks, there's no rush. I'm starting a week-long vacation tomorrow, so I wouldn't be able to try any changes until then anyway. On Jun 26, 11:20 am, Derek Chen-Becker dchenbec...@gmail.com wrote: I'll look at adding a hook. Derek On Fri, Jun 26, 2009 at 6:43 AM, Ryan Donahue donahu...@gmail.com wrote: I'm using JPA and Hibernate for persistence, and I've configured Hibernate to use c3p0 for connection pooling. I'm using scalajpa as follows: object em extends LocalEMF(persistenceUnit) with ThreadLocalEM When Tomcat reloads the app, the following is logged: A C3P0Registry mbean is already registered. This probably means that an application using c3p0 was undeployed, but not all PooledDataSources were closed prior to undeployment. This may lead to resource leaks over time. Please take care to close all PooledDataSources. So I thought I would just add a function to LiftRules.unloadHooks to close the EntityManagerFactory, however I can't find any way to access the underlying factory. LocaEMF has an emf val, but it is private. Any ideas? --~--~-~--~~~---~--~~ 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] JPA, Hibernate, c3p0
I'm using JPA and Hibernate for persistence, and I've configured Hibernate to use c3p0 for connection pooling. I'm using scalajpa as follows: object em extends LocalEMF(persistenceUnit) with ThreadLocalEM When Tomcat reloads the app, the following is logged: A C3P0Registry mbean is already registered. This probably means that an application using c3p0 was undeployed, but not all PooledDataSources were closed prior to undeployment. This may lead to resource leaks over time. Please take care to close all PooledDataSources. So I thought I would just add a function to LiftRules.unloadHooks to close the EntityManagerFactory, however I can't find any way to access the underlying factory. LocaEMF has an emf val, but it is private. Any ideas? --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---