sábado, 21 de fevereiro de 2015

Override Backbone toJSON

Salve galera,

Outro dia precisei sobrescrever o toJSON do Backbone Model.. fica ai a dica de como fazer

   // method override
    toJSON: function () {

        if (this.beforePost)
            this.beforePost();

        // call the "super" method
        var json = Backbone.Model.prototype.toJSON.call(this);

        // here manipule the json objeto ;)

        return json;
    }
Eu precisava alterar o comportamento para que, quando fosse criado um objeto para o post, alguns atributos mudassem de nome no json, assim:


    // mapper properties to swap values
    properiesMap: [
        { from: 'TaskGroup', to: 'TaskGroupId' },
        { from: 'TaskType', to: 'TaskTypeId' },
        { from: 'UserProfile', to: 'UserProfileId' },
        { from: 'Sprint', to: 'SprintId' },
        { from: 'BacklogItem', to: 'BacklogItemId' },
        { from: 'Status', to: 'Status' },
    ],

    // call before json creation
    beforePost: function() {
        this.attributes['Content'] = $(".form-task").find("[name='Content']").val();
        this.attributes['BacklogItem'].Id = parseInt($("#backlogItemId").val());
    }, 
 // call to create json to post
    toPostJson: function () {

        if (this.beforePost)
            this.beforePost();

        // the original toJSON
        var json = Backbone.Model.prototype.toJSON.call(this);

        for (var i = 0; i < this.properiesMap.length; i++) {
            var it = this.properiesMap[i];
            json[it.to] = this.get(it.from).Id;

            if (it.from != it.to)
                delete json[it.from];
        }

        return json;
    }

Post original: http://www.4minds.com.br/artigo/Override_Backbone_toJSON

quarta-feira, 11 de fevereiro de 2015

Grails 2.3.4 + Spring Security Custon Access Denied Page

Usando o Grails Versão 2.3.4 tive algumas dificuldades até conseguir configurar uma página personalizada de acesso negado. Logo descobri que existia uma configuração para que o mapeamento no UrlMappings surtisse efeito.

Adicione a seguinte linha no Config.groovy

grails.plugin.springsecurity.adh.errorPage = null


E o mapeamento é normal (minhas páginas de erro estão na raiz, junto do index):

         "/"(view:"/index")
        "500"(view:'/500')
        "404"(view:'/404')       
        "403"(view:'/403')                    
        "401"(view:'/403')  

Agora deve funcionar.

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.

quarta-feira, 18 de setembro de 2013

Wake Up Android Screen

Salve galera,

Nesse posto pretendo mostrar como "acordar" a tela do Android quando necessário. Um exemplo de uso seria em uma aplicação que usa alarmes. É meio chato quando um alarme dispara no dispositivo e temos que liga-lo e desbloquear a tela para fazer alguma coisa com o alarme. Bom, aqui vou mostrar como fazer isso ao disparar o alarme, para que quando o usuário pegue o dispositivo, a tela já esteja ligada e desbloqueada. Isso tudo é muito simples. Acompanhem o código abaixo:


public class WakeUpAndroid extends Activity{


    private KeyguardManager keyguardManager;
    private PowerManager powerManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //Disperta a tela
        powerManager = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
        wakeLock = powerManager.newWakeLock((PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP), "TAG");
        wakeLock.acquire();

        //Desbloqueia a tela
        keyguardManager = (KeyguardManager) getApplicationContext().getSystemService(Context.KEYGUARD_SERVICE);
        keyguardLock = keyguardManager.newKeyguardLock("TAG");
        keyguardLock.disableKeyguard();

    }

    @Override
    public void finish() {
        super.finish();
        this.release();
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
        this.release();
    }

    private void release(){

        keyguardLock.reenableKeyguard();

        if (this.wakeLock.isHeld()) {
            this.wakeLock.release();
        }

    }

}


Após usar o recurso temos que libera-lo, caso contrario quando o dispositivo "adormecer" não será ativado o bloqueio de tela.

Até a próxima! abrassss

sexta-feira, 6 de setembro de 2013

Recuperar PID de uma JVM especifica

Salve galera,

Já precisaram recuperar o PID de uma JVM especifica? Dependendo de como o aplicativo Java  foi iniciado, e se tivermos mais do que um aplicativo rodando, a missão se torna meio complexa e enrolada. Abaixo um código Java que identifica o PID de uma JVM especifica. Precisamos do utilitário jps do java, encontrado na pasta bin do jdk. Ao executarmos o jps, como saída temos o PID das JVM's em execução, junto com um identificador do processo, que são os argumentos passados para a JVM. Por exemplo, um Glassfish apresenta o nome ASMain ao lado do PID, enquanto o ActiveMQ apresenta o nome aqtivemq.jar ao lado do PID. Então é de responsabilidade do programa que precisa usar o recurso saber o nome gerado de antemão. Para ter essa informação é só rodar o aplicativo que se quer controlar, depois rodar o jps e ver as saidas. Abaixo um código que identifica se determinado aplicativo está sendo executado e pega seu PID



 public boolean hasJavaProcess() throws IOException {


        String glassfishProcessName = "ASMain";
        File file = new File(System.getenv("JAVA_HOME"), "bin");

        if (System.getProperty("os.name").toLowerCase().contains("windows")) {
            file = new File(file, "jps.exe");
        } else {
            file = new File(file, "jps");
        }

        String pid = null;

        Runtime runtime = Runtime.getRuntime();
        Process process = runtime.exec("\"" + file.getAbsolutePath() + "\"");
        InputStream in = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(in));
        String line = null;

        while ((line = reader.readLine()) != null) {
            if (line.contains(glassfishProcessName )) {
                pid = line.replace(glassfishProcessName , "").replace(" ", "");
                break;
            }
        }
        reader.close()
 
       return pid != null;
    }

Ah, mais uma coisa.. Para uma melhor analise dos processos Java em execução, junto do jps você pode rodar a jvisualvm, que da informações mais detalhadas sobre o que está em rodando.

Até pode parecer meio tosco deselegante, mas todas as soluções que encontrei na net eram piores, ao meu ver, pois dependiam de alguma interação com o sistema operacional, usando um ps no Linux ou o tasklist no Windows. Essa solução que criei foi bem por acaso, pois nem conhecia o jps.. mas pensei que poderia ter alguma coisa útil entre aqueles milhões de programas na pasta do sdk. E assim, solucionei o problema e fiquei bem feliz com isso! ;)

Até a próxima!

ActiveMQ Stop Windows

Salve galera,

Por padrão, quando rodamos o ActiveMQ no Windows ficamos com um prompt "pendurado" na sua execução, e ao darmos um Ctrl+C nesse prompt o shutdown do ActiveMQ é chamado. Mas e quando não temos prompt? Ou quando queremos iniciar e parar o ActiveMQ por meio de uma outra aplicação? O que se faz? Bom, como precisei disso, tive que dar uma vasculhada na documentação. Só para comentar, não precisa nem dizer que nos *nix esse problema não existe, pois já temos o start e stop por padrão no script de inicialização.

A solução para o Windows é iniciar o ActiveMQ ativando o conector jmx como no exemplo abaixo:


    

                     
                       
                    


    




Temos que adicionar o parâmetro useJmx="true" no broker e também em managementContext o parâmetro createConnector="true". Com isso podemos chamar o comando abaixo para parar o ActiveMQ no Windows, sem precisar enviar um Ctrl+C para o prompt.

activemq-admin.bat stop



Espero que ajude! Abraço

Spring Security + Container DataSource

Salve galera,

A coisa anda meio corrida e ultimamente, com isso ando meio sem tempo para escrever coisas novas aqui, mas como tudo é passageiro, até a turbulência, essa semana consegui um tempinho.

Nesse post vou dar uma dica na configuração do Spring Security. Quando usamos um banco de dados para fazer a autenticação do Spring Security precisamos informar um cada source como esse:


    
        
            
            
        
    


    
        
        
        
        
    



Isso funciona muito bem, mas se usamos um DataSource fornecido por um Container teremos a configuração do banco (driver, url, usuário, senha) em vários lugares, como no Container, no persistence.xml, no security-app-context.xml, e claro que não queremos isso. Então, para usar o DataSource do Container nas configurações do Spring Security você deve fazer o seguinte:

Primeiro, configure um bean via jndi-lookup, assim (lookup no glassfish):





E depois informe esse bean para a configuração de segurança do Spring, assim:

    
        
            
            
        
    


Rápido e rasteiro, era isso. Até a próxima!