sexta-feira, 19 de setembro de 2014

DJango redirect query

Salve galera,

Como enviar parametros em um redirect no django? Aqui vai uma solução que encontrei:

from django.core.urlresolvers import reverse
from django.http import HttpResponse, HttpResponseRedirect

url_name = reverse('app:url_mapper_name')
return HttpResponseRedirect(url_name + '?id=3')


e é só.

quinta-feira, 18 de setembro de 2014

Jade + Underscore

Salve galera,

Aqui vou mostrar como usar o template javascript underscore dentro de templates jade.

 Primeiro vamos criar os templates jade


layouts/main.jade


doctype html
html
  head
    meta(http-equiv='http-equiv', content-type='Content-type', content='text/html; charset=utf-8')
    link(rel='stylesheet', href='/stylesheets/foundation.css') 
    link(rel='stylesheet', href='/stylesheets/foundation/icons/foundation-icons.css')
    link(rel='stylesheet', href='/stylesheets/style.css')
    title Mobile Mind
      block title 

  body
    header    
      .row
        .large-12.columns
          nav.top-bar(data-topbar)
            ul.title-area
              li.name
                h1
                  a Delicious Food
              li.toggle-topbar.menu-icon
                a
                  span menu

            section.top-bar-section

              ul.left
                li.divider
                li.has-form
                  .row.collapse
                    .large-8.small-9.columns
                      input(type='text', placeholder="Find Stuff...")
                    .large-4.small-3.columns
                      a.alert.button.expand.btn-search(href="#") Search
              ul.right
                li.divider
                li.has-dropdown
                  a(href="#") Categorias
                  ul.dropdown
                    each it in ['A', 'B', 'C', 'D', 'E']
                      li 
                        a(href="#") Categoria #{it}

      
    block content

    footer.row
      .large-12.columns
        hr
        .row
          .large-6.columns
            p 
              @ Copyright Mobile Mind
          .large-6.small-12.columns
            ul.inline-list.right
              li 
                a(href="http://www.mobilemind.com.br", target="_blank") www.mobilemind.com.br

  

  script(src="js/script.js")


index.jade 

extends layouts/main

block title
  |  Store
block content
  
  .row    
    .large-4.small-12.columns
      img(src="http://lorempixel.com/500/500/food")
      .custon-panel-alert
        h3 Delicious Food
        h5.subheader
          | Come eat here!!

      a(href="#")
        .custon-panel-main          
          h6 99 items in your cart      
    
    .large-8.columns
      a(href="#storeItems/50/10") load
    .large-8.columns
      .row.items-main                            

    .large-8.columns
      hr
      .pagination-centered
        ul.pagination
          li.arrow.unavailable
            a(href="#") «
          li.current
            a(href="#") 1
          each it in [2, 3, 4, 5]
            li
              a(href="#") #{it}
          li.unavailable
            a(href="#") …
          each it in [12, 13, 14, 15]
            li
              a(href="#") #{it}
          li.arrow
            a(href="#") »
  
  include extra/item.jade

extra/item.jade 

#item_template.hidden  
  .large-4.small-6.columns
    .item-row
      .panel.item-header
        h5 
          | {{ it.name }}
      .item-body
      img(src="http://lorempixel.com/500/500/food")
      .panel.item-footer
        .large-5.columns
          h6.subheader 
            | {{ it.price }}
        .large-7.columns
          a.button.alert.tiny(href="#") 
            i.fi-shopping-cart.small


Explicando:

Criamos um arquivo de layout principal, que é o main.jade. Depois um index, que usa o layout principal.. e depois o item.jade.. que contém nosso template que será usada no handlebars. Agora, no script.js vamos criar o código de carregamento da listagem de items, via ajax:

script.coffee 

       _.templateSettings = {
      interpolate: /\{\{(.+?)\}\}/g
        }
        template = _.template $('#item_template').html()           
        el = '.items-main'
        $.ajax 
   url: ContextPath + "/store/items?" + $.param {offset: 0, max: 10}
   dataType: 'json'
   success: (data, textStatus, jqXHR) ->     
     for it in data
              $(el).append template({it: it})
   error: (jqXHR, textStatus, errorThrown) ->
            console.log textStatus


Atenlção! 

Veja a alteração na sintaxe do undercode definida na váriavel templateSettings. Fazendo essa definição podemos usar as váriaveis no jade com {{ variavel }} (igual ao mustache). Também veja que no template definimos uma div com class hidden, pois como é um template não ficará visivel na página.

Para isso fucionar você deve adicionar as fererências para jquery e underscore em seu projeto bem assim como complilar o coffee e jade de algum modo.. Em outro artigo aqui no blog mostro como fazer toda essa integração usando grails e gulp, ou só gulp e html. 
Isso é um exemplo estrutural.. então para funcionar tem que modificar algumas coisas.

Até a próxima

Grails + sass + jade + handlebars + coffe

Fala galera,

A pouco tempo comecei a usar outras tecnologias otimizadoras no processo de desenvolvimento junto do Grails. São elas:

- sass
- jade
- handlebars
- coffee

Para tal necessidade eu fui atrás de alguns plugins do grails, mas não fiquei satisfeito com alguns deles. Primeiro por que alguns encontram-se desatualizados e com pouca documentação, e ainda tem alguns bugs. Ora, se pararmos para pensar, essas ferramentas são complementares ao desenvolvimento, apenas voltadas para a produtividade, então não se deve perder muito tempo com complexidades na configuração do ambiente. Para resolver o problema eu acabei usando uma estrutura separada do grails para o controle, uma que eu postei aqui no blog a poucos dias.. usando o gulp para realizar a tarefa.

Então foi simples.. Eu criei a seguinte estrutura no projeto grails (dentro de assets):


Para esse projeto uso a versão do grails 2.3.4, e essa versão ainda não trabalha com o plugin assets por padrão.

Crieu meu gulpfile com o seguinte script:



gulp = require 'gulp'
sass = require 'gulp-sass'
jade = require 'gulp-jade'
coffee = require 'gulp-coffee'
handlebars = require 'gulp-handlebars'
concat = require 'gulp-concat'
declare = require 'gulp-declare'
wrap = require 'gulp-wrap'

errorHandler = (err) ->
 console.log err

sources = {}
destinations = {}

sources.sass = 'grails-app/assets/stylesheets/**/*.scss'
sources.coffee = 'grails-app/assets/coffeescripts/**/*.coffee'
sources.jade = 'grails-app/assets/jade/**/*.jade'
sources.handlebars = 'grails-app/assets/templates/**/*.html'
 
destinations.css = 'web-app/css'
destinations.js = 'web-app/js'
destinations.templates = 'grails-app/assets/templates'
destinations.handlebars = 'web-app/js/bi/templates'


watcher = (task) ->
  (evt) ->
   console.log 'run ' + evt.path
   gulp.start task
   
gulp.task 'compile:sass', ->
 gulp.src(sources.sass)
 .pipe(sass({sourceComments: 'normal'}).on('error', errorHandler))
 .pipe(gulp.dest(destinations.css))

gulp.task 'compile:coffee', ->
 gulp.src(sources.coffee)
 .pipe(coffee({bare: true, sourcemap: true}).on('error', errorHandler))
 .pipe(gulp.dest(destinations.js))

gulp.task 'compile:jade', ->
 gulp.src(sources.jade)
 .pipe(jade().on('error', errorHandler))
 .pipe(gulp.dest(destinations.templates))

gulp.task 'compile:handlebars', ->
 gulp.src(sources.handlebars)
 .pipe(handlebars())
 .pipe(wrap('Handlebars.template(<%= contents %>)'))
 .pipe(declare({
  namespace: 'View.templates',
  noRedeclare: true
 }))
 .pipe(concat('templates.js'))
 .pipe(gulp.dest(destinations.handlebars))


gulp.task 'default', ->
 gulp.start 'compile:sass', 'compile:coffee', 'compile:jade', 'compile:handlebars'


gulp.task 'watch:sass', ->
 gulp.watch sources.sass, watcher 'compile:sass'

gulp.task 'watch:coffee', ->
 gulp.watch sources.coffee, watcher 'compile:coffee'


gulp.task 'watch:jade', ->
 gulp.watch sources.jade, watcher 'compile:jade'

gulp.task 'watch:handlebars', ->
 gulp.watch sources.handlebars, watcher 'compile:handlebars'

gulp.task 'watch', ->
 gulp.start 'watch:sass', 'watch:coffee', 'watch:jade', 'watch:handlebars'
  
 

E logo depois (ou antes) de subir meu projeto grails é só executar:

gulp watch

E então ficar atentos com o console do gulp quanto a erros de complilação. E não se esqueça de instalar as dependências usadas no gulp via npm.

Espero que ajude! Abraço

segunda-feira, 1 de setembro de 2014

Classes com CoffeScript

Salve galera,


Vou dar uma help de como criar uma classe javascript com costrutor, atributos e metodos usando coffeescript.

Para o exemplo, vamos criar uma classe Spinner. Vamos crar uma imagem de carregamento nesse site: 





No site selecione a opção PNG sprite, crie seu spinner e faça o download da imagem. Na documentação tem os exemplos de css e também um link para o  javascript, que deve ser algo mais ou menos assim:



(function() {
    SpriteSpinner = function(el, options){
        var self = this,
            img = el.children[0];
        this.interval = options.interval || 10;
        this.diameter = options.diameter || img.width;
        this.count = 0;
        this.el = el;
        img.setAttribute("style", "position:absolute");
        el.style.width = this.diameter+"px";
        el.style.height = this.diameter+"px";        

        return this;
    };
    SpriteSpinner.prototype.start = function(){
        var self = this,
            count = 0,
            img = this.el.children[0];
        this.el.style.display = "";
        self.loop = setInterval(function(){
            if(count == 19){
                count = 0;
            }
            img.style.top = (-self.diameter*count)+"px";
            count++;
        }, this.interval);

        $(this.el).parent().css('display', 'block')
    };
    SpriteSpinner.prototype.stop = function(){
        clearInterval(this.loop);
        this.el.style.display = "none";
    };
    document.SpriteSpinner = SpriteSpinner;
})(); 


E com base nesse código vamos criar nossa elegante classe usando coffee:

    class SpriteSpinner

        constructor: (options) ->            
            @el = $(options.el)[0]
            img = @el.children[0]
            @interval = options.interval || 10
            @diameter = options.diameter || img.width
            @count = 0            
            img.setAttribute "style", "position:absolute"
            @el.style.width = @diameter + "px";
            @el.style.height = @diameter + "px";       


        start: ->                     
            count = 0
            self = @
            img = @el.children[0]   
            @el.style.display = ""
            @loop = setInterval (  ->           
                count = 0 if  count == 19
                img.style.top = (-self.diameter * count) + "px"
                count++   
                return
            ), @interval

            $(@.el).parent().css 'display', 'block'
        
        stop: -> 
            clearInterval @loop 
            @el.style.display = "none"   

Detalhes:

No constructor você pode definir os atributos da classe usando o  @, que serão automágicamente criados na complicação para js.

Para usar

    spinner = new SpriteSpinner {interval: 50, el: '#spinnerWrapper'}

    spinner.start()

    setInterval( ->
       spinner.stop()
    , 10000)




Até a próxima!

MVIRAL - SMS em massa

Fala galera,


Acabamos de lançar uma ferramenta para envio de SMS em massa chamada MVIRAL.

Com o MVIRAL você envia SMS em massa para usuários ou grupo de usuários, permitindo ainda a criação de agendamentos e criação de modelos de mensagens. 

Também criamos uma API de integração para softwares de terceiros. É fácil e simples de usar. Acesse e confira http://www.mviral.com.br/


Grails plugin - this expression must be true

Salve galera,


Outro dia me deparei com o erro abaixo no grails 2.3.4. Para resolver basta atualizar o plugin abaixo da seguinte forma:

compile ':plugin-config:0.2.0'


Caused by IllegalArgumentException: [Assertion failed] - this expression must be true
->>  340 | newInstance in org.grails.plugin.config.AbstractConfigHelper$ConfigObjectProxy
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|    111 | doCall    in org.grails.plugin.config.DefaultConfigHelper$_enhanceConfigObjectClass_closure3
|     44 | doCall .  in GrailsJadeGrailsPlugin$_closure1
|    756 | invokeBeanDefiningClosure in grails.spring.BeanBuilder
|    584 | beans . . in     ''
|    527 | invokeMethod in     ''
|    262 | run . . . in java.util.concurrent.FutureTask
|   1145 | runWorker in java.util.concurrent.ThreadPoolExecutor
|    615 | run . . . in java.util.concurrent.ThreadPoolExecutor$Worker
^    745 | run       in java.lang.Thread

quinta-feira, 28 de agosto de 2014

gulp + jade + handlebars + sass + coffee

Salve  galera,

Nesses últimos dias venho explorando tecnologias ligadas a nodejs, e com isso me deparei com um "novo" mundo repleto de novas possibilidades, novas ideias, novos paradigmas e novas ferramentes!

Com isso, estava eu seguindo um tutorial de integração entre jade, handlebars, coffee e backbone. Mas como o tutorial além de antigo destinava-se para desenvolvedores com mais conhecimento sobre essas ferramentas, não consegui prosseguir, e para conseguir o que pretendia precisei "garimpar" e montar minha ideia a partir de outros lugares obscuros da internet (mentira, googlei mesmo! ;) )

Para começo eu precisava de uma ferramente de buil que executasse os seguintes passos:

  1. Compilação do templete jade para html (para usar no handlebars)
  2. Compilação do template handlebars para js (para otimização)
  3. Compilação do sass para css
  4. Compilação do coffee para js
  5. Deploy do html na pasta de destino
Além do processo de build, eu ainda precisava de um "auto-build", por questões óbivias de produtividade, como em oferecido em ferramentes como grails, rails ou django. Foi então que lembrei que nas minhas leituras dos últimos dias achei um blog bem interessante chamado blog.lambda3.com.br, e em um de seus artigos li uma lista de ferramentas usadas com com nodejs, entre elas uma ferramente de build chamada gulp gulpjs.com e logo fui atrás desse cara para ver se poderia fazer minha configuração de buid. E eis que construi o seguinte script:




gulp = require 'gulp' 
sass = require 'gulp-sass'
jade = require 'gulp-jade'
coffee = require 'gulp-coffee'
handlebars = require 'gulp-handlebars'
concat = require 'gulp-concat'
declare = require 'gulp-declare'
wrap = require 'gulp-wrap'

errorHandler = (err) ->
 console.log err

sources = {}
destinations = {}

sources.sass = 'src/styles/**/*.scss'
sources.coffee = 'src/scripts/**/*.coffee'
sources.jade = 'src/jade/**/*.jade'
sources.html = 'src/html/**/*.html'
sources.handlebars = 'src/compiled-templates/**/*.html'
 
destinations.css = 'dist/css'
destinations.js = 'dist/js'
destinations.templates = 'src/compiled-templates'
destinations.base = 'dist/'
destinations.handlebars = 'dist/js'


watcher = (task) ->
  (evt) ->
   console.log 'run ' + evt.path
   gulp.start task
  
 
gulp.task 'compile:sass', ->
 gulp.src(sources.sass)
 .pipe(sass({sourceComments: 'normal'}).on('error', errorHandler))
 .pipe(gulp.dest(destinations.css))

gulp.task 'compile:coffee', ->
 gulp.src(sources.coffee)
 .pipe(coffee({bare: true, sourcemap: true}).on('error', errorHandler))
 .pipe(gulp.dest(destinations.js))

gulp.task 'compile:jade', ->
 gulp.src(sources.jade)
 .pipe(jade().on('error', errorHandler))
 .pipe(gulp.dest(destinations.templates))

gulp.task 'compile:handlebars', ->
 gulp.src(sources.handlebars)
 .pipe(handlebars())
 .pipe(wrap('Handlebars.template(<%= contents %>)'))
 .pipe(declare({
  namespace: 'View.templates',
  noRedeclare: true
 }))
 .pipe(concat('templates.js'))
 .pipe(gulp.dest(destinations.handlebars))

gulp.task 'copy:html', ->
 gulp.src(sources.html)
 .pipe(gulp.dest(destinations.base))

gulp.task 'default', ->
 gulp.start 'compile:sass', 'compile:coffee', 'compile:jade', 'compile:handlebars','copy:html' 


gulp.task 'watch:sass', ->
 gulp.watch sources.sass, watcher 'compile:sass'

gulp.task 'watch:coffee', ->
 gulp.watch sources.coffee, watcher 'compile:coffee'


gulp.task 'watch:jade', ->
 gulp.watch sources.jade, watcher 'compile:jade'

gulp.task 'watch:handlebars', ->
 gulp.watch sources.handlebars, watcher 'copy:handlebars'

gulp.task 'watch:html', ->
 gulp.watch sources.html, watcher 'copy:html'

gulp.task 'watch', ->
 gulp.start 'watch:sass', 'watch:coffee', 'watch:jade', 'watch:handlebars','watch:html' 


Coloque esse conteúdo em um arquivo .coffee e execute chamando gulp watch para o auto deploy ou apenas gulp para executar o build completo, que no caso está definido na task default. Lembrando que a instalação dos componetes declarados nos "require" devem ser feitos via npm. Ex.:

npm install gulp --save-dev

Certamente isso deve ajudar quem está começando, assim como eu.

Até a próxima!

quinta-feira, 24 de julho de 2014

Drop foreign key MySQL

Primeiro temos que saber o nome da chave. Para isso podemos usar:

use information_schema;

select TABLE_NAME,COLUMN_NAME,CONSTRAINT_NAME, REFERENCED_TABLE_NAME,REFERENCED_COLUMN_NAME from KEY_COLUMN_USAGE where REFERENCED_TABLE_NAME = 'table_name';

Ou usar:

show create table table_name;

Agora que sabemos o nome podemos remover

alter table table_name drop foreign key key_name;

terça-feira, 3 de junho de 2014

Dump Mysql import many files

Fala galera,

Aqui um comando simples mas muito útil que precisei para importar um dump do mysql com vários arquivos e vários bancos de dados. Para executar tem que estar dentro da pasta do dump

find . -name '*.sql' | awk '{ print "source",$0 }' | mysql -u root -p --batch

terça-feira, 6 de maio de 2014

Django custon tags

Salve galera,

Nesse post vou mostrar como criar tags customizadas usando o Django. Para isso temos que criar um arquivo, que vamos chamar de app_extras.py dentro de um diretório chamado templatetags um nível abaixo de nossa aplicação. Por exemplo.: Se nossa aplicação se chamar osapp então ela ficará dentro da pasta osapp, como na imagem abaixo:


Dentro do arquivo app_extras.py vamos criar uma tag para formatação de data/hora que recebe como parametro um valor temporal e um formato para formatação:

from django import template
from datetime import datetime

register = template.Library()

@register.simple_tag(name="dateformat")
def dateformat(value, format):
    if value is None:
        return "-"
    try:
        return value.strftime(format)
    except Exception, e:
        return "-"


Para usar nossa tag temos antes que carrega-la na página:

{% load app_extras %}

Então podemos fazer a formatação de um valor:

{% dateformat form_data.begin_date '%d/%m/%Y %H:%M' %}


Rápido e limpo! Até a próxima.

Django + UTF

Salve galera,

Ao começar a desenvolver com o Django tive alguns problemas com a codificação dos caracteres e então achei a seguinte solução:

Em ambiente de desenvolvimento usando o webserver embarcado do Django, temos que alterar o arquivo manage.py adicionando o seguinte conteúdo:

import sys
reload(sys)
sys.setdefaultencoding("utf-8")

Em ambiente de produção usando o Apache e o modulo WSGI, temos que alterar o arquivo wsgi.py, o qual referenciamos na configuração do Django no httpd.conf, adicionando as mesmas linhas:

import sys
reload(sys)
sys.setdefaultencoding("utf-8")


E isso deve resolver o problema de codificação. Até a próxima.

Django + http authentication

Salve galera,

Dica de como habilitar a autenticação do Django no Apache. As três linhas abaixo no httpd.conf já fazem o Django trabalhar no Apache com autenticação:

WSGIScriptAlias /opt/app/wsgi.py
WSGIPythonPath /opt/app/webapp
WSGIPassAuthorization On


 E instalar o módulo WSGI:

LoadModule wsgi_module modules/mod_wsgi.so


Se estiver usando o framework REST rest_framework e quiser uma autnticação básica, é só delarar no settings.py:

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ),

    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ), 
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.UnicodeJSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    )
}

Aqui o wsgi.py caso alguém precise:

import os
import sys

reload(sys)

sys.setdefaultencoding("utf-8")


os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()


E era isso! Até a próxima.

Tomcat + Spring + ActiveMQ Embedded Broker + Redelvery

Salve galera!

Não vou fazer um tutorial gigante de como configurar o ActiveMQ com Spring por que já existem vários por ai. Mas vou colocar as configurações necessárias para subir um Broker Embedded usando Spring num servidor Apache Tomcat trabalhando com Redelivery Messages.

Versões 

A versão current do ActiveMQ é 5.9. Não consegui fazer funcionar na última versão no Spring, então tive que usar a versão 3.1.1.RELEASE. A versão do Tomcat usada foi 7.0.41.

Maven Dependências 

Nessa relação deve ter coisas desnecessárias, mas como uso bastante coisa do Spring nesse projeto que fiz vou colocar a lista completa que já contempla MVC, JPA, Hibernate e tudo mais.

 3.1.1.RELEASE
 1.6
 2.5.0
 1.6.1


 
        

        
            javax
            javaee-api
            6.0
            provided
              

        

        
            javax.servlet.jsp
            jsp-api
            2.1
            provided
        

        
            javax.servlet
            jstl
            1.2
                                     

        

        
            org.springframework
            spring-context
            ${spring.version}           
        

        
            org.springframework
            spring-context-support
            ${spring.version}           
        

        
            org.springframework
            spring-core
            ${spring.version}                     
        

        
            org.springframework
            spring-web
            ${spring.version}
        

        
            org.springframework
            spring-beans
            ${spring.version}
        

        
            org.springframework
            spring-oxm
            ${spring.version}
        

        
            org.springframework
            spring-orm
            ${spring.version}
        

        
            org.springframework
            spring-webmvc
            ${spring.version}
          

        
            org.springframework
            spring-aspects
            ${spring.version}
                    

        
            org.springframework
            spring-tx
            ${spring.version}
             

        
            org.springframework.security
            spring-security-config
            ${spring.version}
        

        
            org.springframework.security
            spring-security-web
            ${spring.version}
          

        
            org.springframework.security
            spring-security-taglibs
            ${spring.version}
                     

        
            org.springframework.security
            spring-security-core
            ${spring.version}
          

        
            org.springframework
            spring-jms
            ${spring.version}
                     

        
            javax.servlet
            com.springsource.javax.servlet
            ${servlet-api.version}
            provided
        

        
            com.thoughtworks.xstream
            xstream
            1.3.1
        

             

        
            junit
            junit
            4.7
            test
        
     
        

        
            org.hibernate
            hibernate-entitymanager
            4.2.0.Final
        

        
            org.hibernate
            hibernate-validator
            4.2.0.Final           
         

        
            org.hibernate
            hibernate-c3p0
            4.2.0.Final
             

        
            org.hibernate
            hibernate-ehcache
            4.2.0.Final
               

        
            c3p0
            c3p0
            0.9.1.2
        
                                   
        
            net.sf.ehcache
            ehcache-core
            2.5.0
        
                            
        

        
            javassist
            javassist
            3.4.GA
               

        

        
            log4j
            log4j
            1.2.17           
        

        
            org.slf4j
            slf4j-api
            ${slf4j.version}           
        

        
            org.slf4j
            jcl-over-slf4j
            ${slf4j.version}           
        

        
            org.slf4j
            slf4j-log4j12
            ${slf4j.version}           
                             

        
            commons-io
            commons-io
            1.4
               
     
        
            cglib
            cglib
            2.2
                            

        
            org.apache.xbean
            xbean-spring
            3.6           
        
       
        
            org.apache.activemq
            activemq-all
            5.9.1           
                     

        
            org.apache.activemq
            activemq-pool
            5.9.1           
          

        
            javax.jms
            com.springsource.javax.jms
            1.1.0
                                                                                                                                                                  
                        
    
Spring Configuration Embedded Broker 

Aqui vou mostrar como configurar o Embedded Broker dentro do arquivo de configurações do Spring, sem precisar declarar nada no server.xml do Tomcat.

http://activemq.apache.org/how-do-i-embed-a-broker-inside-a-connection.html

No applicationContext.xml podemos fazer todas as configurações do Broker:


 

        
            
                   
              

                   
            
        

       

        
            
                
                    
                

                
                    
                

                
                    
                
                                 

           

       

                           
             
           

                                                                

    

 
                           
                   
                   
                   
   

                    

    
                   
        
  



Ou podemos externalizar as configurações e apontar o arquivo usando o brokerConfig:


 

                       

               

               

               

       

                    

    

               

        

    

 

Configuração Topic
    

        

    
Configuração MessageListener
 

     

         

         

         

         

         

                  

             

     
Código do Cnsumidor:
public class TopicConsumer extends SessionAwareMessageListener{

   public void onMessage(Message message, Session session) throws JMSException {

            try {

                //process message

                message.acknowledge(); // consume message

            } catch (Exception e) {               

                session.recover();

                throw new RuntimeException(e);

            }      

   }

}

Código do produtor:
@Service
public class TopicProducer  {

    @Resource(name = "jmsConnectionFactory")

    private ConnectionFactory connectionFactory;

    @Resource(name = "jmsTopicProducerConsumer")

    private Destination destination;

    private Connection connection;

    private Session session;

  public void produce(){

             connection = connectionFactory.createConnection();

            connection.start();

            session = connection.createSession(true, Session.CLIENT_ACKNOWLEDGE);                        TopicSession session

                            = connection.value.createTopicSession(false, Session.CLIENT_ACKNOWLEDGE);

                    TopicPublisher publisher = session.createPublisher((Topic) destination);

           TextMessage message = session.createTextMessage("Message Content");

           publisher.publish(message);

           connection.close();

 }

}

Redelivery Message 

Como podemos ver na configuração estamos criando um objeto redeliveryPolicy que define a política de reentrega das mensagens em caso de falha. Como não estamos trabalhando com mensagens transacionais, segundo a documentação do ActiveMQ, temos que usar o acknowledgeMode = Session.CLIENT_ACKNOWLEDGE. Trecho da documentação:

http://activemq.apache.org/message-redelivery-and-dlq-handling.html

Messages are redelivered to a client when any of the following occurs: 
  • A transacted session is used and rollback() is called. 
  • A transacted session is closed before commit is called. 
  •  A session is using CLIENT_ACKNOWLEDGE and Session.recover() is called. 

 Redelivery com Bridge 

Aqui um detalhe importante! Se estivermos consumindo as mensagens diretamente do Broker onde a mensagem é produzida não precisamos definir no Listener o acknowledgeMode como pode ver na configuração:
  
Mas caso estivermos usando uma Bridge, precisamos definir o tipo de recebimento no Listener para que a reentrega funcione.


Não tão simples mas também não tão complicado. É só prestar atenção nos detalhes que tudo funciona.

Até a próxima!

quinta-feira, 1 de maio de 2014

ava.net.BindException: Address already in use: JVM_Bind + ActiveMQ port 61616

Salve galera!

Volta e meia no Windows 8 (onde testei) ao iniciar o ActiveMQ na porta padrão (61616) a seguinte mensagem é exibida:

ava.net.BindException: Address already in use: JVM_Bind 

Mas ao analisar as portas abertas do Windows não encontramos a porra 61616 aberta. A solução é desativar o ICS (Internet Connection Sharing) nos serviços do Windows que o ActiveMQ volta a funcionar.