Posts na categoria ‘web’

6ago2011

Running Java Web Applications on Heroku Cedar Stack

(0) comentários

Heroku does not officially support Java applications yet. However, the most recently launched stack comes with support for Clojure. Well, if Heroku does run Clojure code, it is certainly running a JVM. Then why can we not deploy regular Java code on top of it?

I was playing with it today and found a way to do that. I admit, so far it is just a hack, but it is working fine. The best (?) part is that it should allow any maven-based Java Web Application to be deployed fairly easy. So, if your project can be built with maven, i.e. mvn package generates a WAR package for you, then you are ready to run on the fantastic Heroku Platform as a Service.

Wait. There is more. In these polyglot times, we all know that being able to run Java code means that we are able to run basically anything on top of the JVM. I’ve got a simple Scala (Lift) Web Application running on Heroku, for example.

There are also examples of simple spring-roo and VRaptor web applications. I had a lot of fun coding on that stuff, which finally gave me an opportunity to put my hands on Clojure. There are even two new Leiningen plugins: lein-mvn and lein-herokujetty. :-)

VRaptor on Heroku

Let me show you what I did with an example. Here is a step-by-step to deploy a VRaptor application on Heroku Celadon Cedar:

  1. Go to Heroku and create an account if you still do not have.
  2. We are going to need some tools. First Heroku gems:
    $ gem install heroku
    $ gem install foreman
    
  3. Then Leiningen, the clojure project automation tool. On my Mac, I installed it with brew:
    $ brew update
    $ brew install leiningen
    
  4. The vraptor-scaffold gem, to help us bootstrap a new project:
    $ gem install vraptor
    

That is it for the preparation. We may now start dealing with the project.

  1. First, we need to create the project skeleton:
    $ vraptor new <project-name> -b mvn
    $ lein new <project-name>
    $ cd <project-name>
    

    The lein command is not strictly necessary, but it helps with .gitignore and other minor stuff.

  2. Now, the secret sauce. This is the ugly code that actually tries to be smart and tricks Heroku to do additional build/compilation steps:
    $ wget https://gist.github.com/raw/1129069/f7ffcda9c42a3004fa8d3c496d4f13887c11ebf4/heroku_autobuild.clj -P src
    

    Or if you do not have wget installed:

    $ curl -L https://gist.github.com/raw/1129069/f7ffcda9c42a3004fa8d3c496d4f13887c11ebf4/heroku_autobuild.clj > src/heroku_autobuild.clj
    
  3. You also need to tweak the Leiningen project definition – project.clj. The template is here. Please remember to adjust your project name. It must be the same that you are using in the pom.xml. Or you may download it directly if you prefer:
    $ curl -L https://gist.github.com/raw/1129081/5790e173307d28a8df256e0aaa5a9fe7757e922f/project.clj > project.clj
    
  4. Unfortunately, Leiningen comes bundled with an old version of the Maven/Ant integration. The embedded maven is currently at version 2.0.8, which is old. The versions of some plugins configured in the default pom.xml from vraptor-scaffold are incompatible with this old version of maven.

    The best way to solve it for now is to remove all <version> tags from items inside the <plugins> section of your pom.xml. This is specific to VRaptor and other frameworks may need different modifications. See below for spring-roo and Lift instructions.

    If even after removing versions from all plugins, you still get ClassNotFoundException: org.apache.maven.toolchain.ToolchainManager errors, try cleaning your local maven repository (the default location is $HOME/.m2/repository). The pom.xml that I used is here.

  5. Now, try the same command that Heroku uses during its slug compilation phase. It should download all dependencies and package your application in a WAR file inside the target directory.
    $ lein deps
    

    Confirm that the WAR was built into target/. It must have the same name as defined in your project.clj.

  6. Create your Heroku/Foreman Procfile containing the web process definition:
    web: lein herokujetty
    

    And test with:

    $ foreman start
    

    A Jetty server should start and listen on a random port defined by foreman. Heroku does the same.

  7. Time to push your application to Heroku. Start editing your .gitignore: add target/ and tmp/, and please remove pom.xml. Important: The pom.xml must not be ignored.
  8. You may also remove some unused files (created by leiningen):
    $ rm -rf src/<project-name>
    # do not remove src/main src/test and src/heroku_autobuild.clj!
    
  9. Create a git repository:
    $ git init
    $ git add .
    $ git commit -m "initial import"
    
  10. Push everything to Heroku and (hopefully) watch it get built there!
    $ heroku create --stack cedar
    $ git push -u heroku master
    
  11. When it ends, open another terminal on the project directory, to follow logs:
    $ heroku logs -t
    
  12. Open the URL that heroku creates and test the application. You may also spawn more instances and use everything Heroku has to offer:
    $ heroku ps:scale web=2
    $ heroku ps:scale web=4
    $ heroku ps:scale web=0
    
  13. Quick tip: you do not have SSH access directly to Dynos, but this little trick is very useful to troubleshoot issues and to see how slugs were compiled:
    $ heroku run bash
    

spring-roo on Heroku

Once you understand the process for a VRaptor application, it should be easy for others as well. Just follow the simple step-by-step here, to create a simple spring-roo maven application.

Then, before running lein deps or foreman start, you must adjust your pom.xml, to remove plugins incompatible with the older mvn that is bundled in Leiningen. Here is the pom.xml that I am using (with some of the plugins downgraded).

You can see my spring-roo application running on Heroku here.

Scala/Lift on Heroku

The same for Scala/Lift: follow the instructions to bootstrap an application with maven. One simple change to the pom.xml is required. My version is here.

You also need to turn off the AUTO_SERVER feature of H2 DB. It makes H2 automatically starts a server process, which binds on a tcp port. Heroku only allows one port bound per process/dyno, and for the web process, it must be the jetty port.

To turn it off, change the database URL inside src/main/scala/bootstrap/liftweb/Boot.scala. I changed mine to a in-memory database. The URL must be something similar to jdbc:h2:mem:<project>.db.

My Lift application is running on Heroku here.

I hope it helps. Official support for Java must be in Heroku’s plans, but even without it yet, we’ve got a lot of possibilities.


Filed under: cloud, heroku, java, jetty, spring, vraptor, web Tagged: clojure, cloud, deploy, development, heroku, java, paas, platform, ruby, web
2set2010

Palestra Nginx Linuxcon 2010

(0) comentários
Participei do Linuxcon 2010, muito bom por sinal. Devido ao trabalho, fui somente no segundo dia (01/09), minha palestra estava marcada para as 15:00, cheguei lá por volta as 12:20, ainda tinha que almoçar e dar um tapa final nos slides. Assim que entrei e peguei minha credencial, encontrei com o Maddog e enquanto todos [...]
14set2009

Palestra: Web Performance Client Side

(0) comentários

215987893_f665d2fa1dHá algumas semanas tive a oportunidade de palestrar internamente em dois eventos aqui na Locaweb:

  • Locaweb Tech Day: um evento de dia inteiro que ocorre a cada 2 meses, onde cada pessoa pode palestrar sobre um assunto de interesse;
  • Palestras Técnicas: ocorre às quintas-feiras, durando 1 hora. Uma pessoa por semana palestra sobre um assunto técnico.

Nas duas oportunidades palestrei sobre como fazer um site ficar mais rápido, e abrir num “estalo”. O título das palestras foi: Web Performance Client Side.

Se você já parou pra pensar em otimização de um website, vai perceber que o lado server side (sua aplicação Rails, PHP, etc) conta na velocidade de carregamento, mas na prática representa muito pouco. Isto acontece porque uma requisição é processada pelo servidor em 200 milisegundos, digamos, enquanto o mesmo site pode levar 10 segundos para carregar no browser. Então qualquer otimização que ocorra em server-side só vai afetar a quantidade de pessoas que podem acessar seu site ao mesmo tempo. Não afeta a velocidade individual que cada pessoa vai ter ao navegar nas páginas de seu site.

E para melhorar a velocidade client-side, a que realmente importa na maioria das vezes, existem várias técnicas inteligentes e interessantes. Na apresentação que coloquei no SlideShare, você pode pegar um apanhado com as últimas técnicas para desenvolvimento web com vistas à performance no browser.

Existe muita coisa mesmo na apresentação, e é imperdível pra quem trabalha com Desenvolvimento Web.

Veja a apresentação sobre Web Performance Client Side no SlideShare. Ou baixe o PDF, mas para isso você precisa ter conta no SlideShare.

23mai2009

Posting and Getting files in ruby/rails

(0) comentários

Today I’m going to show some very short snippet about posting files with ruby, and receiving them in a rails controller.

For all examples I’ll be using the rest-client gem (”sudo gem install rest-client”).

The fist thing we’re going to do is to implement a very basic file post in ruby - there is basically two methods:

  1. You can post the contents of the file straight to the request body (I’m going to call it the “raw way”);
  2. You can pass the file contents as a parameter inside your request, like any other (I’m going to call it the “pretty way”).

One method is not necessarily better than the other, how you should do it depends a lot more on how your target service is implemented.

Posting a file, the “pretty way”:

PRETTY_UPLOAD = "http://localhost:3000/files/upload_pretty/pretty_file.txt"

def self.post
    pretty_resource = RestClient::Resource.new PRETTY_UPLOAD

    pretty_file = "./pretty_file.txt"

    File.open pretty_file, "wb" do |file|
      file.write "some random pretty content"
    end

    pretty_resource.post :file => File.read(pretty_file)
end

Posting a file, the “raw way”:

RAW_UPLOAD = "http://localhost:3000/files/upload_raw/raw_file.txt"

def self.post
    raw_resource = RestClient::Resource.new RAW_UPLOAD

    raw_file = "./raw_file.txt"

    File.open raw_file, "wb" do |file|
      file.write "some random raw content"
    end

    raw_resource.post File.read(raw_file)
end

Now, getting a file - since there is basically just one way to get it, I’ve made just one method - getting a file on ruby:

DOWNLOAD = "http://localhost:3000/files/download/raw_file.txt"

def self.get
    resource = RestClient::Resource.new DOWNLOAD

    downloaded_file = "./downloaded_file.txt"

    response = resource.get
    # you can access the headers (response.headers) or the
    # http response (response.net_http_res) if you need to

    File.open downloaded_file, "wb" do |file|
      file.write response.to_s
    end
end

That’s pretty much all you need on the client side (reading the contents of a regular http request should be no different at all than reading an attached file).

Time to go to the server side, shall we? Here good old rails kicks ass per se.

All I needed to do was to set up a custom route (just to make things more clear):

map.files ':controller/:action/:name.:extension'

Then, for the controller, I’ve set up two methods to receive the posted file - pay attention to the slightly different approach for the “pretty way” and the “raw way” of posting a file.

Receiving a file, the “pretty way”:

def upload_pretty
    file_name = "#{params[:name]}.#{params[:extension]}"
    file_contents = params[:file]
    File.open "tmp/#{file_name}", "wb" do |file|
      file.write file_contents
    end

    render :text => "ok"
end

Receiving a file, the “raw way”:

def upload_raw
    file_name = "#{params[:name]}.#{params[:extension]}"
    file_contents = request.raw_post
    File.open "tmp/#{file_name}", "wb" do |file|
      file.write file_contents
    end

    render :text => "ok"
end

I also provided a method for the client to download back the files, so that you can check on the contents to see that it went through flawlessly:

def download
    file_name = "#{params[:name]}.#{params[:extension]}"
    send_file "tmp/#{file_name}"
    # you can also use: send_data File.read("tmp/#{file_name}")
end

And that’s basically it, as simple as it can be.

As usual, you can download the sample code clicking here.

That’s a very quickly put together piece of code which, most likely, can be greatly improved - but I think it is just good enough to show the basics of how to get and post files on ruby and rails.

Criticism is always welcome.

8abr2009

VRaptor2 on Google App Engine

(0) comentários

With all the recent excitement about Google supporting Java for the App Engine platform, I’m proud to say that VRaptor2 just works, out-of-the-box!

All you have to do is copy the required jars that come in the vraptor distribution, configure the VRaptorServlet (or VRaptorFilter) in web.xml and enable session support in the appengine-web.xml:

<appengine-web-app xmlns="http://appengine.google.com/ns/1.0">
	<application>...</application>
	<version>1</version>
	<sessions-enabled>true</sessions-enabled>

	<!-- ... -->
</appengine-web-app>

Being able to use my favorite Java Web MVC framework, to develop and deploy applications to Google’s cloud infrastructure, is really nice.


Posted in java, vraptor, web

Switch to our mobile site