JavaScript Dependency Injection

Ráá, eu de novo!!!

Galera gosto muito de Java e nem tanto assim de JavaScript.

Bem estava eu estudando GWT (que nos ajudam a implementar muitas coisas para web sem escrever nenhuma linha de código JavaScript), porém ainda existem pontos em aberto nele, como por exemplo, falta de suporte a Reflections etc… (por favor, não entrem no mérito do GWT).

Bem na verdade o que eu percebo que o GWT faz é implementar um belo compilador JS para código escrito em Java. Mas por que não aproveitar o melhor dos dois mundos? Pra mim é tedioso programa JS porque precisamos reimplementar código (duplicando) objetos que existem no Java para o JavaScript…, e fazer tela web tudo em Java gera mais código que se fosse feito apenas com JS + JSON (Leia-se EXTJS)

Bem, bolei um mecanismo de JavaScript DI cujo objetivo é serializar objetos Java que existem no servidor para que o cliente web possa tirar proveito disso.

Basicamente:

  1. Você escreve no seu arquivo.js que está lá no WAR:

//@Session(attribute='sampleAttribute') var sessionObject;

  1. Quando o container web recebe a requisição do cliente (GET /file.js), ele injeta a dependência como no Java e manda para o cliente o JS sem a Annotation e com o conteúdo serializado.
var sessionObject = "Sample attribute message by HTTP Session";

Neste exemplo o Container de Dependência buscou da sessão http o atributo ‘sampleAttribute’ e serializou o seu conteúdo de forma que o browser entenda o JavaScript enviado para o cliente.

Saiba mais em: http://svn.sarbarian.com/projects/soa/wiki/JavaScriptDependencyInjection

E ae, o que vocês acharam?

Abraços,

Davi.

Olha, não compreendi qual seria o ganho de produtividade de sua idéia, poderia dar um exemplo mais complexo?

O exemplo complexo virá em breve, mas por exemplo? Você conhece o EXTJS? - Se sim, por exemplo para criar uma grid você precisaria implementar um Record, um DataStore e uma Grid propriamente dita com tudo isso aqui de JavaScript:

Ext.onReady(function(){

    Ext.QuickTips.init();
    
    var xg = Ext.grid;

    // shared reader
    var reader = new Ext.data.ArrayReader({}, [
       {name: 'company'},
       {name: 'price', type: 'float'},
       {name: 'change', type: 'float'},
       {name: 'pctChange', type: 'float'},
       {name: 'lastChange', type: 'date', dateFormat: 'n/j h:ia'},
       {name: 'industry'},
       {name: 'desc'}
    ]);

    var grid = new xg.GridPanel({
        store: new Ext.data.GroupingStore({
            reader: reader,
            data: load('http://localhost:8080/data/sample')
            sortInfo:{field: 'company', direction: "ASC"},
            groupField:'industry'
        }),

        columns: [
            {id:'company',header: "Company", width: 60, sortable: true, dataIndex: 'company'},
            {header: "Price", width: 20, sortable: true, renderer: Ext.util.Format.usMoney, dataIndex: 'price'},
            {header: "Change", width: 20, sortable: true, dataIndex: 'change', renderer: Ext.util.Format.usMoney},
            {header: "Industry", width: 20, sortable: true, dataIndex: 'industry'},
            {header: "Last Updated", width: 20, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'}
        ],

        view: new Ext.grid.GroupingView({
            forceFit:true,
            groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
        }),

        frame:true,
        width: 700,
        height: 450,
        collapsible: true,
        animCollapse: false,
        title: 'Grouping Example',
        iconCls: 'icon-grid',
        renderTo: document.body
    });
});

Com o container de DI, vc precisaria apenas fazer:

Ext.onReady(function(){

    Ext.QuickTips.init();
    
    var xg = Ext.grid;

    //@ColumnDefinition(@Bean(class='com.test.Stock'))
    var colDefinition;

    //@JavaScriptStore(@Session(attribute='sampleUrl'),bean=@Bean(class='com.test.Stock'))
    var storeObject;

    var grid = new xg.GridPanel({
        store: storeObject),
        columns: colDefinition,

        view: new Ext.grid.GroupingView({
            forceFit:true,
            groupTextTpl: '{text} ({[values.rs.length]} {[values.rs.length > 1 ? "Items" : "Item"]})'
        }),

        frame:true,
        width: 700,
        height: 450,
        collapsible: true,
        animCollapse: false,
        title: 'Grouping Example',
        iconCls: 'icon-grid',
        renderTo: document.body
    });
});

Note que a idéia é delegar para @Annotations tarefas repetitivas e/ou tediosas, reaproveitando código.

DWR faz exatamente isto.

[quote=aleck][quote=dbht]
Bem, bolei um mecanismo de JavaScript DI cujo objetivo é serializar objetos Java que existem no servidor para que o cliente web possa tirar proveito disso.
[/quote]

DWR faz exatamente isto.

[/quote]

Realmente ele serializa assim como eu, mas não vi DI via annotation como eu estou propondo… :smiley: Você consegue encontrar um exemplo dessa implementação pelo dwr?

Obrigado,

Davi.

Estou começando a achar a sua idéia interessante…

[quote=dbht]

Realmente ele serializa assim como eu, mas não vi DI via annotation como eu estou propondo… :smiley: Você consegue encontrar um exemplo dessa implementação pelo dwr?

Obrigado,

Davi.[/quote]

Realmente não encontrei nada nativo no DWR. Porém, notei que o filter criado pela aplicação não permite o cache dos arquivos JS e faz um trabalho intenso de leitura e escrita de arquivos, isto certamente pode ocasionar um problema de performance para sistemas com muitos utilizadores.

De qualquer forma, a idéia é muito interessante, e a integração com o extjs deixa ainda mais interessante.

Acho que todo esforço em direção à algo melhor é válido, parabéns.

Mas gostaria de lhe indicar o ZK http://docs.zkoss.org/wiki/Data_Binding_Collection_Data_with_ZUML_Annotations para vc dar uma olhada em seus exemplos.

Vc irá perceber que pode-se construir um sistema inteiro sem nem lembrar que o JS existe; tudo em Java, mesmo dentro dos scripts (não é boa prática fazer isto, mas ele permite e funciona bem) que aliás é opcional.

Talvez o ZK lhe dê algumas idéias.

P.S Acho que por conhecer um pouco do ZK achei o mecanismo complexo e trabalhoso, mesmo com suas anotações.

flws

Fantomas,

Obrigado pelo feedback do ZK. Não conhecia e tentaria explorar ele… Valew!

Aleck,

Legal que você deu uma olhada no código. Realmente tenho um GAP enorme na implementação quanto a performance, fiz uma simulação com 100 anotations em um arquivo de 300 linhas e não foi nada bom… Pretendo verificar como resolver isso, quem sabe até fazer um cache legal de JS já parseado. Tava pensando em também dar uma olhada no JspWriter() para ver como eles fazer a implementação…

Farei um mega-hiper esforço para liberar uma release usável com algumas annotations que processem algo interessando. A princípio farei implementação curinga (json mesmo) e algumas annotations para EXTJS como Action, Form e Store.

Postem sugestões…

Abraços,

Davi.

Você pode implementar um versionamento no js, quando a versão for identica vc irá inserir um include no jsp que aponta para o disco ao invés de enviar novamente o javascript completo para a página, creio que o ganho de performance seria interessante e seria mantido o cache de js do navegador.