Jan 24

Integrating Flex, BlazeDS, and Scala/Lift

Tag: AMF, Flex, Remoting, Server Push, blazeds, lift, scala, tutorialDerek Wischusen @ 6:00 am

A short while ago Adobe announced that they would be releasing an open source version of LiveCycle Data Services called BlazeDS. In short, BlazeDS is Java technology that makes it really easy to do HTTP streaming and server-side push to Flex and AIR applications. While this announcement is definitely welcome news, there may be a lot of people out there who thought to themselves, “That’s great, but I don’t use Java.” Well, the good news is that just because BlazeDS uses Java the platform doesn’t mean that you necessarily need to use Java the language to take advantage of it.

In fact, Java the platform supports several different languages, including Groovy, Python, Ruby, and Scala. And, of course, ColdFusion. In theory, it should be pretty straight-forward to integrate any of these languages with BlazeDS.

For the rest of this post I am going to focus on just one of them, Scala. Why Scala? Well, it is because recently I decided that I wanted to broaden my programming language horizons and I’ve found that Scala is both extremely interesting and very powerful. It’s both object-oriented and functional, it has mixin style composition, it has an exceptional implementation of Erlang style Actors for handling concurrency, and much more. Lastly, and perhaps most important for my purposes, there is an excellent webapp framework for Scala called Lift.

All right, let’s get started with integrating Flex, BlazeDS, and Scala/Lift.

Prerequisites – latest versions of:

—–

If you’d like to follow along with source files, here they are.

Source Code:

—–

First, let’s create a Lift project named LiftBlaze:

1. Open a terminal and navigate to the directory where you want to create the project.

2. Enter the following command:

mvn archetype:create -U                                    \
-DarchetypeGroupId=net.liftweb                             \
-DarchetypeArtifactId=lift-archetype-blank                 \
-DarchetypeVersion=0.4                                     \
-DremoteRepositories=http://scala-tools.org/repo-releases  \
-DgroupId=org.rxr.liftblaze -DartifactId=liftblaze

3. Next enter:

cd liftblaze

4. Lastly, enter:

mvn jetty:run

If everything worked properly, then you should see a “Hello World” welcome page at http://localhost:8080/

—–

Next, let’s use Maven to create an eclipse project for us:

1. In a terminal, go to lift linkblaze project and enter:

mvn eclipse:eclipse

You should now be able to import the linkblaze project into Eclipse. Once you have the project imported you will need to add the BlazeDS jars to your build path. These jars are located in {blazeds_folder}\tomcat\webapps\blazeds\WEB-INF\lib.

—–

Now let’s start setting up the Lift project to work with Flex and BlazeDS.

1. Open the web.xml file located in {blazeds_folder}\tomcat\webapps\blazeds\WEB-INF

2. Open the web.xml file located in liftblaze\src\main\webapp\WEB-INF.

3. Copy the contents of the web.xml file from the BlazeDS folder into the web.xml file in the liftblaze Lift project.

At this point, it would be useful to talk a bit about how lift handles HTTP requests. Lift is a view first framework. What this means is that by default lift will try to match an HTTP request against one its views. If it finds one it will do some processing on it, and then render it our as HTML. For more info on how Lift handles HTTP requests, check out this page.

For this project, the entire view is going to be in Flex, so we don’t really Lift want to concerned about the view we just want it to handle our web service calls. To achieve this do the following:

4. Inside you newly merged web.xml file, modify the filter-mapping tag like so:

<filter-mapping>
  <filter-name>LiftFilter</filter-name>
  <url-pattern>/webservices/*</url-pattern>
</filter-mapping>

Now Lift will only handle requests that start with webservices. In a later step we will tell Lift how to route these calls so that they invoke methods on a class that we will define.
5. Copy {blazeds_folder}\tomcat\webapps\blazeds\WEB-INF\flex into liftblaze\src\main\webapp\WEB-INF

6. Inside the flex folder, open the messaging-config.xml file and add the following:

 <destination id="notifications">
     <channels>
         <channel ref="my-streaming-amf"/>
     </channels>
 </destination>

This is the messaging destination that our Lift app will publish to and that our Flex app will subscribe to.

—–

All right, let’s start adding some Scala code to our lift project.

1. In Eclipse, create a package called org.rxr.liftblaze.actor

2. In this package, create a Scala Class called Notifier and add the following code to it:

package org.rxr.liftblaze.actor;

import flex.messaging.MessageBroker
import flex.messaging.messages.AsyncMessage
import flex.messaging.util.UUIDUtils
import scala.actors._
import scala.actors.Actor._
import compat.Platform._
import net.liftweb.util._
import org.rxr.liftblaze.model.Notification

class Notifier extends Actor {

  val msgBroker = MessageBroker.getMessageBroker(null)
  val clientID = UUIDUtils.createUUID()
  val msg = new AsyncMessage() 

  var notificationsSent = 0;

  def act{

    ActorPing.schedule(this, Notify, 500L)

    loop {
      react {

        case Notify =>
          msg.setDestination("notifications")
          msg.setClientId(clientID)
          msg.setMessageId(UUIDUtils.createUUID())
          msg.setTimestamp(currentTime)
          msg.setBody(new Notification(notificationsSent, "Hello from Scala/Lift", new java.util.Date()))
          msgBroker.routeMessageToService(msg, null)
          notificationsSent+=1
          println("notification sent at " + currentTime)
          ActorPing.schedule(this, Notify, 500L)       

        case "stop" =>
          exit()
      }
    }
  }

}

case object Notify

This is class that does the majority of the work in this simple application. The first thing to note about it is that it is a Scala Actor. I don’t want to go into too much detail about Actors here. For this tutorial we can grossly oversimplify and say that an Actor is kind of like a thread that can send and receive messages. If you want to get the full story you can click on the preceding link.

Here is a very brief explanation of what is happening in this class. When the Notifier Actor is started (you’ll see where this happens later) the act method is called. The first thing inside the act method is a call to the ActorPing.schedule helper method. This method basically says that I want to send a Notify message to this Actor in 500 milliseconds. Next comes loop which simply creates a loop and then react which has case statements that are used to handle incoming messages. So, when react receives a Notify or a “stop” message all of the code for that case is executed.

When a Notify is received a message is published to the “notifications” destination that we created earlier in the message-config.xml file. Once the message is sent, there is another call to ActorPing.schedule which will send another Notify message in 500 milliseconds. So, until a “stop” method is received, the Notifier Actor will publish a notification every 500 milliseconds.

The body of the message that is being published is a custom Scala class called Notification. One of the benefits of BlazeDS is that you can use the AMF protocol to send strongly typed objects from the server to your Flex client. So I can have BlazeDS serialize my Notification class in Lift down into AMF binary and then have it reappear as a Notification class in Flex, which is pretty handy. Though I have found that there is one small trick to creating classes in Scala that will serialize properly. To illustrate, let’s create the Notification class next.

3. Create a Scala Class named Notification in 0rg.rxr.liftblaze.model and add the following code,

package org.rxr.liftblaze.model

import java.util.Date

class Notification(var id: Int, var message: String, var timesent: Date)
{
    def getId = id
    def setId(id: Int) = this.id = id

    def getMessage = message
    def setMessage(m: String) = message = m

    def getTimesent = timesent
    def setTimesent(t: Date) = timesent = t
}

The main thing to take note of here is that I am using methods that are named like Java (the language) getters and setters, rather than variables. This is because the Scala compiler takes variables defined in Scala and turns them into methods in Java. So,

val greeting = "Hello"

in Scala becomes

public String greeting()
{
  return "Hello"
}

in Java. The same goes for var (FYI, vals are immutable variables, while vars are mutable). So, member variables in Scala won’t serialized by BlazeDS because they turn into methods in Java. The solution, as I have already shown, is just to use methods in Scala that are named like Java getters and setters.

Now that we’ve seen who is sending the messages in Lift (the Notifier Actor) and what is being sent (the Notification class), let’s create the class that starts and stops the Notifier.

4. In org.rxr.liftblaze.controller create a Scala Class called WebServices and then add the following code

package org.rxr.liftblaze.controller

import net.liftweb.http._
import javax.servlet.http.{HttpServlet, HttpServletRequest , HttpServletResponse, HttpSession}
import org.rxr.liftblaze.actor.Notifier

class WebServices (val request: RequestState,val httpRequest: HttpServletRequest) extends SimpleController {

  def start_feed = {
    WebServices.notifier.start()
    XmlResponse(<start_feed success="true"/>)
  }

  def stop_feed = {
    WebServices.notifier ! "stop"
    XmlResponse(<stop_feed success="true"/>)
  }
}

object WebServices {
  val notifier = new Notifier()
}

This is class is pretty much self explanatory. The start_feed method calls start on our Notifier Actor, which as we discussed causes the Notifier to send out a Notification every 500 milliseconds. The stop_feed method sends a “stop” message to the Notifier, which causes it to exit. Both methods return a simple XML response.

We’re almost done with the Lift app, just one more thing to do. In a previous step we modified the web.xml file so that Lift would only handle requests that start with webservices. Now we just need to tell Lift how to process/route those request so that they call the method in our WebServices class. To do this we need to modify the Boot class.

5. Open the Boot class located in bootstrap.liftweb and modify it thusly

package bootstrap.liftweb

import net.liftweb.util._
import net.liftweb.http._
import Helpers._
import org.rxr.liftblaze.controller.WebServices
import javax.servlet.http.{HttpServlet, HttpServletRequest , HttpServletResponse, HttpSession}

/**
  * A class that's instantiated early and run.  It allows the application
  * to modify lift's environment
  */
class Boot {
  def boot {

    val dispatcher: LiftServlet.DispatchPf = {
     // if it's a web service, pass it to the web services invoker
     case RequestMatcher(r, ParsePath("webservices" :: c :: _, _,_),_, _) => invokeWebService(r, c)
    }
    LiftServlet.addDispatchBefore(dispatcher)

  }

  private def invokeWebService(request: RequestState, methodName: String)(req: HttpServletRequest): Can[ResponseIt] =
    createInvoker(methodName, new WebServices(request, req)).flatMap(_() match {
    case Full(ret: ResponseIt) => Full(ret)
    case _ => Empty
  })
}

This code is taken directly from the examples included with the Lift source code. In Basic terms, this code matches a request that starts with webservices and passes the request and method name to be invoked to the invokeWebService method. This method the calls createInvoker which invokes the method on our WebServices class. So, for example http://localhost:8080/webservices/start_feed would call the start_feed method on the WebServices class. You can read more about how this code works here.

That’s it for the Lift App. All in all there really isn’t that much code. Though, of course, this app is pretty simple. Regardless of how simple this app is, I would say that in the short time that I have been using Scala I have found it to be the most concise statically typed language that I have ever used.

—–

Now let’s create the Flex App in Flex Builder.

1. Create a new Flex Project (File -> New -> Flex Project)

2. Fill in the rest as follows:

Project name: LiftBlaze

Application type: Web Application

Application server type: J2EE

Use remote object access service: check this

Root folder: {liftblaze_lift_app}\src\main\webapp

Root URL: http://localhost:8080/

Context root: /

Output folder: {liftblaze_lift_app}\src\main\webapp

Output folder URL: http://localhost:8080/

3. Once you have everything filled out, click Finish

All right, now that we have the project created let’s add some code to it.

4. Open LiftBlaze.mxml and add the following code:

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="vertical" >
    <mx:Script>
        <![CDATA[
        	import org.rxr.liftblaze.model.Notification;
          	import mx.messaging.events.MessageEvent;

            private function messageHandler(message: MessageEvent): void
            {
            	var notification : Notification = message.message.body as Notification;
                pushedValue.htmlText = "<b>id:</b> " + notification.id + " <b>Date:</b> " + notification.timesent;
            }    

        ]]>
    </mx:Script>

    <mx:Consumer
    	id="consumer"
    	destination="notifications"
    	message="messageHandler(event)"
    	channelConnect="trace(event)"
        channelFault="trace(event)"
        fault="trace(event)" />

    <mx:HTTPService
    	id="startFeed"
    	url="webservices/start_feed"
    	result="consumer.subscribe()" />
    <mx:HTTPService
    	id="stopFeed"
    	url="webservices/stop_feed"
    	result="consumer.unsubscribe()" />

 	<mx:Button
 		label="Subscribe to 'notifications'"
 		click="startFeed.send({stop_cache: new Date().getMilliseconds()})"
 		enabled="{!consumer.subscribed}"/>

	<mx:Button
		label="Unsubscribe from 'notifications'"
		click="stopFeed.send({stop_cache: new Date().getMilliseconds()})"
		enabled="{consumer.subscribed}"/>

    <mx:TextInput id="pushedValue" width="300"/>
</mx:Application>

What we’ve create here is an app that has a very simple UI that consists of two buttons and a text input field. The app also has two HTTPServices and Consumer. A couple of things to take note of here. First, the Consumer subscribes to the “notifications” destination, the same destination that our Notifier Actor publishes its messages to. Second, the HTTPServices make calls to webservices/start_feed and webservices/stop_feed. If you’ll recall we set up our Lift app so that these calls would be routed to invoke the methods in our WebServices class.

We just need to add one last piece of code to get everything working properly. In our Lift app the Notifier Actor sends out instances of the Notification class that we created. Now we need to create a corresponding Notification class in our Flex app so that when we receive the data in Flex it will show up as strongly typed class.

5. Create a Class named Notification in org.rxr.liftblaze.model and add the following code

 package org.rxr.liftblaze.model
{
    [Bindable]
    [RemoteClass(alias="org.rxr.liftblaze.model.Notification")]
    public class Notification
    {
        public var id : int;
        public var timesent : Date;
        public var message: String;

        public function Notification()
        {
            super();
        }

    }
}

You’ll notice that this class has the same attributes as the Scala Notification class in our Lift app. The key to mapping this class to our Scala class is the RemoteClass metadata tag located just above the class definition. This tag is used to tell Flex the fully qualified name of the server side class that this class maps to.

—–

That should be it. You now be able to boot up you Lift app, launch the Flex app, click the “Subscribe to ‘notifications’” to start the Notifier Actor and subscribe to the Consumer to the notifications destination. You should then see id number and the time in the text input field get automatically updated every 0.5 seconds. You can the click the “Unsubscribe from ‘notifications’” to stop the Notifier actor and the Consumer to unsubscribe from the notifications destination.

Pretty exciting. With these three technologies it’s really easy to automatically push data from the server to the client in real time. This is obviously a trivial example, but I think it should be relatively straight forward to scale this approach up for more sophisticated apps.

That wraps this up. Please let me know if you have any questions.

21 Responses to “Integrating Flex, BlazeDS, and Scala/Lift”

  1. jason says:

    Getting a BuildFailureException error “command line returned non-zero value:1″ while trying to cal mvn jetty:run. Everything else up to that point looks ok.

    Though all the lines mvn archetype:create -U are a little confusing? Are they returns at the end or do we leave the \ or something else?

  2. Derek Wischusen says:

    Hi Jason –
    Yeah those slashes are confusing. They are meant to indicate that you should enter the entire command on one continuous line (in other words you should ignore the line breaks). Like so:

    mvn archetype:create -U -DarchetypeGroupId=net.liftweb -DarchetypeArtifactId=lift-archetype-blank -DarchetypeVersion=0.4 -DremoteRepositories=http://scala-tools.org/repo-releases -DgroupId=org.rxr.liftblaze -DartifactId=liftblaze

    I hope this helps.

  3. Justin says:

    What OS was all this done on? OS X?

  4. Derek Wischusen says:

    Windows, though I do not think that any of it should be OS specific.

  5. Derek Wischusen says:

    Jason – I just reproduced the error that you encountered. The issue is in test/scala/LiftConsole.scala. This file imports scala.tools.nsc.MainGenericRunner, which is part of the scala-compiler.jar. This jar is not automatically included in the build path by Maven. So, you can either delete this import and the line below that reads MainGenericRunner.main(args) or you can add the jar to your build path.

    Derek

  6. Justin says:

    ok, I’m having the same error, how do I add that file to the build path? I’m not sure what the build path is.

  7. Derek Wischusen says:

    Justin –

    You can add a dependency for the scala-compiler.jar inside the pom.xml file in the Lift app. Like so,

    <dependency>
    <groupId>org.scala-lang</groupId>
    <artifactId>scala-compiler</artifactId>
    <version>${scala.version}</version>
    </dependency>

  8. phil swenson says:

    has anyone attempted BlazeDS with rails? Will it require tomcat?

  9. Mike H says:

    Great tutorial!

    I have one small issue: when the flex client makes the request to /webservices/start_feed, it immediately starts to query /webservices, for some kind of ‘ping’ operation. This causes lift to return a 404 error, and the client throws these exceptions:

    [ChannelFaultEvent faultCode="Channel.Ping.Failed" faultString="error" faultDetail=" url: 'http://127.0.0.1:8080/webservices''" channelId="my-streaming-amf" type="channelFault" bubbles=false cancelable=false eventPhase=2]

    Do you know how lift is supposed to respond to this ping/handshake mechanism?

  10. Derek Wischusen says:

    Hi Mike –

    It looks to me like you modified the url-pattern for the MessageBrokerServlet rather than for the LiftServlet. The url-pattern for the MessageBrokerServlet should read as follows:

    <servlet-mapping>
    <servlet-name>MessageBrokerServlet</servlet-name>
    <url-pattern>/messagebroker/*</url-pattern>
    </servlet-mapping>

    and the url-pattern for the LiftServlet should read:

    <filter-mapping>
    <filter-name>LiftFilter</filter-name>
    <url-pattern>/webservices/*</url-pattern>
    </filter-mapping>

    Best regards,
    Derek

  11. Mike H says:

    Hm, both of the filter definitions exist in the web.xml, so I’m not sure what is going on. One more quick question:

    What was the channel definition you used for my-streaming-amf destination? You didn’t explicitly mention it, so I created this one (in the services-config.xml)

    Is this similar to what you had?

    Thanks,
    Mike

  12. Mike H says:

    Oops, the XML got consumed by wordpress :(

    This is my channel definition:

    <channel-definition id=”my-streaming-amf” class=”mx.messaging.channels.HTTPChannel”>

    <endpoint url=”http://{server.name}:{server.port}/webservices” class=”flex.messaging.endpoints.HTTPEndpoint”/> </channel-definition>

  13. Derek Wischusen says:

    Ahhh, I see the issue. The error that you encountered is the result of the Consumer attempting to make a call to the webservices URL. Your channel definitions should read as follows:

    - <channel-definition id=”my-streaming-amf” class=”mx.messaging.channels.StreamingAMFChannel”>
    <endpoint url=”http://{server.name}:{server.port}/{context.root}/messagebroker/streamingamf” class=”flex.messaging.endpoints.StreamingAMFEndpoint” />
    </channel-definition>
    - <channel-definition id=”my-amf” class=”mx.messaging.channels.AMFChannel”>
    <endpoint url=”http://{server.name}:{server.port}/{context.root}/messagebroker/amf” class=”flex.messaging.endpoints.AMFEndpoint” />
    - <properties>

    Thank you for pointing out that my-streaming-amf channel definition was missing. I’ll add it to the tutorial.

  14. Mike H says:

    Finally got it to work :) Thanks for this tutorial! Just a couple tips for people who are struggling:

    1) Before running the web server (via mvn jetty:run), make sure to run mvn clean. The scala eclipse plugin uses an old version of the compiler, and the compile/runtime mismatch will cause strange errors. To do this, all the org.* needs to be under the defined in the pom.xml.

    2) You have to mvn install:install-file some of the flex-* jars, or it will give build errors.

    3) Make sure the service endpoint is defined correctly (previous comment)

    That’s all I have so far, thanks again

    2)

  15. ESME - A Social Messaging Experiment for the Enterprise… | Les Aventures de Techiemaque... says:

    [...] Integrating Flex, BlazeDS, and Scala/Lift [...]

  16. Abesh says:

    Thank you for this amazing post.
    I’m a scala newbie but quite fluent in Flex.
    I’ve followed every step you mentioned and all goes well till Boot.scala where it returns the following four errors :

    method Full is not a case class constructor, nor does it have an unapply/unapplySeq method Boot.scala liftblaze/src/main/scala/bootstrap/liftweb line 27 Scala Problem
    method RequestMatcher is not a case class constructor, nor does it have an unapply/unapplySeq method Boot.scala liftblaze/src/main/scala/bootstrap/liftweb line 19 Scala Problem
    not found: value r Boot.scala liftblaze/src/main/scala/bootstrap/liftweb line 19 Scala Problem
    not found: value ret Boot.scala liftblaze/src/main/scala/bootstrap/liftweb line 27 Scala Problem

    Can you please tell me what am i doing wrong ?

  17. Kevin Lamse says:

    There have been a few stumbling blocks. For the moment, it would be nice to know now to do #2 above. What is the command to accomplish the following: mvn install:install-file some of the flex-* jars
    I tried the following:
    mvn install:install-file -Dfile=/Users/klamse/software/blazeds_020108/tomcat/webapps/blazeds/WEB-INF/lib/flex-messaging-common.jar \
    -DpomFile=pom.xml \
    -Dpackaging=jar

    However, how this seem to to put the jar into the following:
    ~/.m2/repository/org/rxr/liftblaze/liftblaze/1.0-SNAPSHOT
    > ls
    liftblaze-1.0-SNAPSHOT.jar

    Any suggestions for us non-maven users?

    Thanks.

  18. Darren Hague says:

    To anyone having trouble getting this example code to work:

    1. To get the Flex libraries into a Maven project, see the guide here: http://code.google.com/p/fna/wiki/blazedsXdocletSpringHibernateMvnArchetype

    2. For the latest version of /lift/ (0.9 as I write this):
    (a) the ActorPing calls need a TimeSpan(500L) instead of just plain 500L.

    (b) Boot.scala and WebServices.scala should be updated to match the coding style in the “sites/example” folder of the /lift/ source distribution.

    Cheers!

  19. Gerbrand on ICT » Combining Flex and Scala using Liftweb and BlazeDS says:

    [...] setup a sample project that uses Flex and Scala. I followed the excellent tutorial on FlexOnRails: Integrating Flex, BlazeDS, and Scala/Lift. The tutorial helps a lot explaining how to set up your sample project. Unfortunately the tutorial [...]

  20. Gerbrand van Dieijen says:

    First of, Darren, thanks for the great tutorial!
    After some tweaking I got it compiled.

    http://www.gerbrand-ict.nl/2009/01/combining-flex-and-scala-using-liftweb-and-blazeds/

    Unfortunately, I get a Nullpointer exception, MessageBroker.getMessageBroker(null) returns Null. Might be configuration error, I hope to get that fixed soon, I’ll update the page then.

  21. Neil Strachan says:

    I am looking forward to trying out this tutorial. I recently developed an interest in Flex, and BlazeDS looks very useful if I can get it to work with Scala. One thing I noticed that may make things smoother: rather than explicitly declaring get and set methods, you could use the annotation @scala.reflect.BeanProperty for the fields. I haven’t tried it yet, but will advise on the results when I set this up.

    Neil

Leave a Reply

Purchase levitra online
Buy valium cheap online
Buy generic propecia uk
Purchase phentermine without prescription
Overnight tramadol no prescription
Prescription viagra uk
No prescription cialis online
Viagra in usa
Viagra 50mg side effects
Prednisone dosages
Viagra shop online
Levitra 20mg
Phentermine canada no prescription
Best way to take tramadol
Propecia uk pharmacy
Buy viagra in canada online
Buy tramadol hcl
Prescription phentermine online
Prednisone tablets 10 mg
Best viagra alternative
Buy viagra uk online
Prednisone 40 mg
Cialis side effects
Low price viagra
Buy generic cialis uk
Cheap levitra no prescription
Get viagra
Tramadol cod delivery
Tramadol dosage
Xanax no rx
Xanax price per pill
Valium pill 10mg
Low price cialis
Phentermine 37.5mg
Cheapest place to buy viagra online
Tramadol for sale
Phentermine 37.5 buy online
Valium online pharmacy
Buy cialis online from canada
Ordering propecia from canada
Viagra professional online
Viagra ordering
Levitra canada
Generic viagra sales
Valium without prescription uk
Viagra cheapest
Viagra purchase uk
Prescription free viagra
Tramadol no prescription required
Buying prednisone online
Best viagra dose
Where can i buy cialis without a prescription
Where to buy viagra in england
Buy phentermine hcl 37.5 no prescription
10mg valium effects
Where to buy cialis safely
Viagra canada online
Genuine viagra online
Where to buy propecia in canada
Best way to buy viagra online
Phentermine diet pills without prescription
Buy xanax canada
Buy propecia
Prednisone 20mg side effects
Generic cialis uk
Viagra in the philippines
Discount viagra india
Generic xanax xr
Xanax 1 mg dose
Tramadol india
Phentermine buy australia
Phentermine hcl without prescription
Viagra express delivery
Levitra price
Viagra online shop
40 mg prednisone side effects
Phentermine 37.5 wholesale
Viagra generic cheap
Buy phentermine no rx
Mail order phentermine
How to buy valium without a prescription
Buy cialis viagra
Cialis dosage 20mg
Viagra canadian online pharmacy
Generic cialis overnight
Online prescriptions xanax
Get tramadol prescription
Buy viagra uk no prescription
Buy viagra online uk no prescription
Best levitra prices
Levitra online buy
Cheap cialis viagra
Cialis price
Where to buy cialis online
Propecia price australia
Where to buy phentermine cheap
Phentermine hcl no prescription
Cheap cialis india
Buy valium europe
Where to buy viagra online
Order tramadol cod
Phentermine 37.5 mg
Order tramadol online overnight
Prescription propecia
Best price cialis
Best price tramadol
Order phentermine online no prescription
Canada viagra no prescription
Tramadol without prescription overnight delivery
Dose of xanax
Generic cialis tadalafil
Cheap cialis
Canada viagra
Buy xanax cheap online
Buy xanax 2mg no prescription
Cheap cialis pills
Cialis over the counter
Purchase viagra online without prescription
Purchase xanax
Buy generic cialis online
Viagra for sale online
Levitra online cheap
Xanax 1mg
Viagra fast delivery
Cheap 37 5 phentermine
Buy tramadol cod
Viagra prescription
Get viagra prescription
Pfizer viagra price
10mg prednisone
100mg tramadol effects
Purchase phentermine
Order viagra without prescription
Buy viagra from canada
Phentermine 37.5mg side effects
Prednisone online
Viagra price canada
Xanax bars dosage
Cheap valium online
Buy phentermine no script
Buy brand name viagra
Where can i buy viagra without a prescription
Purchase tramadol without prescription
Tramadol free shipping
Where to buy levitra online
Buy cheap viagra online uk
Xanax bars effects
Buying viagra in new zealand
Xanax bars side effects
Tramadol without prescription
Xanax overnight cod
Propecia best prices
Buy phentermine 37.5mg online
No prescription valium
Cialis 20 mg dosage
Buy generic xanax no prescription
Viagra 50 mg online without prescription
Valium cheapest
Buy generic valium online
Viagra in the uk
Discount viagra usa
Cheap viagra online without prescription
Viagra super active
Generic tramadol
Xanax 0.5 mg
Buy levitra
Buying cialis
Where can i buy viagra in the uk
Buy viagra australia
Viagra dosage information
Viagra no prescription online
Phentermine 37.5 pills
Xanax online cheap
Cialis 20mg
Cialis soft tabs online
Buy viagra online in australia
Purchase cialis without a prescription
Where to buy cialis without prescription
Buying cialis online without a prescription
Viagra cheap no prescription
Order tramadol online cod
Buy valium no rx
Real phentermine without prescription
Valium 10 mg
Buy generic phentermine online
Viagra canada mastercard
Viagra discount coupons
Xanax with no prescription
Phentermine purchase online
Buy cheap valium online
Ordering cialis online
Valium generic
Cialis prices uk
Propecia ireland
Viagra online without prescription reviews
Propecia generic online
Cialis prescription cost
Order tramadol overnight
Levitra samples
Viagra discount prices
Propecia cheap
Buy female viagra without prescription
How to buy phentermine online
Online valium without prescription
Cialis for sale
Buy generic cialis
Viagra pharmacy uk
Viagra without prescription uk
Pharmacy tramadol
Buying viagra in london
Tramadol pharmacy
Viagra generic
Cheap tramadol cod
Cialis ordering
Generic viagra 100mg
Buy levitra online canada
Cialis online canadian pharmacy
Cheapest online cialis
Buy pfizer viagra without prescription
Cialis uk sales
Cheap 100mg viagra
Buy valium without prescription uk
Xanax no prescription overnight
Levitra on sale
Prednisone tablets
Cost of viagra 50mg
Valium from india
Levitra us
Prescription viagra canada
Propecia generic canada
Tramadol online overnight
Xanax for sale without prescription
Xanax buy uk
Buy viagra in england
Viagra lowest prices
Order xanax cod
Propecia information
Valium drug side effects
Valium online uk
Cheap xanax for sale
Cheapest cialis professional
Valium online fast delivery
Viagra indian pharmacy
Prescription valium
Propecia 1mg generic
Cialis 10mg side effects
Discount viagra online
Generic levitra uk
Buy xanax overnight
Viagra sale uk