Andei conversando com o Rafael, sobre uma forma de adicionar suporte a plugins ao JForum esta semana e voltei a pensar nisto …
Java é uma péssima linguagem para aplicações baseadas em plugins …
Claro, é possivel implementar, mas é muito dificil ter por exemplo, o mesmo comportamento que se tem no wordpress, que é fazer o deploy da aplicação com tudo ja rodando, sem ter downtime nenhum, a aplicação ja etectar o plugin, e te permitir ativar ele ainda sem downtime nenhum …
Por padrão, em java, estes “plugins” só seriam detectados no proximo restart, quando se faz um refresh no classpath.
É possivel implementar isto se você escrever o proprio classloader, como o pessoal do JPF (Java Plugin Framework), ou do eclipse fizeram …
Nem em JSP, se for feito um include, como é feito no PHP, isto vai funcionar, por que seria necessário no minimo fazer um “touch” no arquivo principal, para que ele fosse recompilado, e refletisse as alterações …
Ou alguem conhece outra forma de fazer isto?
Como é que uma linguagem voltada a aplicações enterprise, pode dificultar tanto isto?
A unica forma fora a escrita de um classloader proprio que consegui pensar até agora, é fazendo mapeamento reverso …
por exemplo, os plugins rodam em modulos separados (tanto faz ser web ou EJB neste caso), e na inicialização, o plugin se registra na aplicação principal …
mas mesmo assim, isto é trabalho demais para fazer pouca coisa

E por que não usar o JPF?
não é esta a ideia do post, estava apenas reclamando da complexidade exigida para isto em uma linguagem, onde isto deveria ser nativo
mas sim, o JPF é uma boa solução para isto (mesmo eu achando, que mesmo usando ele, plugins são complexos demais para se escrever, tanto para ele quanto para o eclipse, para o eclipse as coisas ainda se justificam por toda a plataforma envolvida).
uma coisa que deveria ser estupidamente fácil, o hotdeploy de plugins, é extremamente complexa para ser implementada em java
mas veja bem, eu disse complexa demais, e não impossivel de implementar …
Felizmente, pelo menos por enquanto, a bomba ta na mão do rafael
Eu não tenho certeza que tal capacidade deveria ser responsabilidade da linguagem. Existem avanços que podem ser feitos na área de carga de classes, mas o essencial para suportar aplicações baseadas em componentes já existe.
Nunca tinha ouvido falar do JPF. Mas qual a vantagem de escolher ainda outra plataforma de componentes se OSGi já existe, é um padrão aberto, com diferentes implementações (muitas de código-aberto como Eclipse Equinox, rojeto do qual tive o prazer de participar), e com forte adoção da indústria? Ou seja, vocês consideraram OSGi? Quais limitações vocês encontraram?
Finalizando, é necessário não esquecermos que não basta uma plataforma dinâmica – os componentes precisam ser escritos de forma a suportar tal dinamismo, e isso aumenta a complexidade. Por exemplo, componentes precisam estar preparados para liberar recursos que foram adquiridos quando forem desinstalados e fazer a coisa certa quando outros componentes são instalados/desinstalados.
Alguma sugestão de como deveria ser esse suporte?
valeuz…
Fala Rodrigo,
Eu sugiro você consultar os seguintes tópicos:
- OSGI
- JSR 291: Dynamic Component Support for JavaTM SE
- Projeto OSCAR : http://forge.objectweb.org/projects/oscar/
Há também um conceito que não é muito explorado, se eu entendi seus pontos, você também pode dar uma olhada em Dynamic Proxies(java.lang.reflect.Proxy), que existe desde do JDK1.3, e que são super utilizados por exemplo no JBoss Application Server para realizar algumas mágicas.
[]
Edgar
E desde quando aplicações enterprise tem plugins? Aplicações enterprise geralmente são enormes blocos monolíticos
Opa, tranqüilo?
A JSR 291 seria sim uma ótima solução built-in para este problema de plugins
o JPF que comentei antes é uma implementação de OSGI derivada do código do eclipse
o projeto OSCAR eu não conhecia, valeu a dica …
)
ja os proxies não resolveriam muito o problema de hot deploy, eles ja que eles não iriam adicionar coisas novas no classpath (eu uso bastante isto para fazer um tipo de AOP simplificado, acho que o JBoss e o Spring fazem a mesma coisa
de qualquer forma, qualquer uma das implementações de OSGI, implementa o próprio classloader, o qe eu considero trabalho demais pra pouca coisa, mas mesmo assim, elas ja estando prontas são utilizáveis
o problema seria ter que implementar isto na unha …
valeu as dicas.
PS.: diego, nem sempre elas são enormes blocos monolíticos
Mesmo por que com EJBs ou WebServices jBPM ou BPEL da pra fazer algumas coisinhas bastante dinâmicas, e adaptáveis …
o problema (sem utilizar uma implementação OSGI destas), seria fazer isto sem utilizar um container EJBs, utilizando apenas um container web por exemplo …
Acho que na primeira vez que eu precisar implementar assim, vou de OSCAR ou JPF, vou testar os dois, valeus mesmo …
Hum… este tipo de plugin dinâmico seria útil no desenvolvimento, mas será que seria uma boa idéia você subir partes desconexas da aplicação em um ambiente corporativo? Digo, nesses ambientes, muitas vezes há um processo mais burocrático de testes e homologação, pois um serviço fora-do-ar ou funcionando incorretamente em produção podem causar prejuízos sérios! Quando a aplicação inteira é testada e instalada como um bloco monolítico, pelo menos você evita uma série de problemas relacionadas com versionamento e configuração.
Porém, nem só de grandes corporações vive uma linguagem de programação, né
O Java realmente requer certos truques para este tipo de coisa. O OSGi (core do Eclipse) e a plataforma Netbeans implementam estes truques, mas usá-los não é a coisa mais fácil do mundo. Mas acho que este é um problema de qualquer linguagem compilada estaticamente – e executada como um único processo -, e não específico do Java.
Hoje, essas plataformas baseadas em plugins utilizam XML para especificar os descritores dos seus módulos. Uma alternativa poderia ser utilizar linguagens interpretadas, como por exemplo Groovy, para este tipo de ‘cola’. Tanto para a descrição do módulo quanto, talvez, as rotinas de inicialização e descarga, que normalmente são feitas por alguma classe especificada no XML. Porém, isto à princípio não dispensaria alguma ‘mágica’ com classloaders (a não ser que todo o módulo fosse especificado em alguma linguagem dinâmica que pudesse ser recarregada sob demanda, claro).
Na InfoQ tem uma apresentação sobre linguagens dinâmicas na JVM, que inclui também o assunto de Hot Deploy. Eles admitem que a JVM não tem um suporte bom para este tipo de coisa, mas pretendem mudar isto no futuro. http://www.infoq.com/news/2007/03/dynamic-lanuages-jvm
vc está fazendo uma tempestade em um copo d’agua…
qual linguagem compilada que vc conhece que é facil implementar uma estrutura de plugins… ?
já implementast plugins em c ? em delphi ?
se vc for observar… e comparar… vai verificar que Java é uma mãe nesse quisito…
agora se for comparar a linguagens de scripting… prq nao usa a JSR de Scripting e programa seus plugins em groovy ?
prq fora isso… nao tem como comparar…
Tetsuo, valeu a dica do artigo na infoQ, e eu tinha esquecido das linguagens dinâmicas, elas seriam a solução perfeita para o que eu estava pensando em fazer (não sei se perfeitas para o jforum
)
mas não sei se concordo com tudo o que você falou, ja que grandes corporações, normalmente tem a exigencia de 100% de uptime para todos os sistemas, e qualquer tipo de atualização ou correção em java, exige algum downtime …
O que não acontecia por exemplo quando eu trabalhava com sistemas em coldfusion (sim, eram sistemas grandes, mesmo a linguagem não sendo grande coisa) …
o único downtime necessário era quando algum upgrade no banco de dados era necessário … e mesmo assim precisava ser agendado e em algum dia entre as 3 e 4 da manha, e mesmo desta forma sempre tinha alguem reclamando que o sistema tinha estado offline naquele horario …
se precisassemos de algum downtime para adicionar funcionalidades naquele ambiente a utilização do sistema teria sido quase inviabilizada (este é um dos motivos que fez com que eles demorassem mais de 4 anos para aceitar começar a utilizar java para este tipo de sistema) …
mas existem casos e casos
novamente, valeu por me lembrar da possibilidade de utilizar linguagens dinâmicas
Offtopic: Em Delphi(TM) você poderia usar os “run-time packages”, que são melhores que DLL’s.
Dyego, não acho que seja tempestade em copo d’agua …
e em delphi, e C é bastante fácil, simplesmente load em uma dll …
em delphi mais fácil ainda, se for utilizado o suporte a módulos do delphi (uma dll alterada), onde é possivel carregar objetos da dll diretamente …
para plugins, delphi é tão fácil quanto uma linguagem de scripting, com a unica excessão para atualização de plugins, que no caso do delphi precisa avisar o programa primeiro para ele fazer o unload da biblioteca …
mas o java ter este problema, solucionavel com “gambiarras”, quer dizer, bibliotecas apropriadas, não faz ela ser pior do que qualquer outra …
E mesmo assim, eu continuo usando java como a minha linguagem principal, até por que é possível contornar este tipo de problemas, com uma certa dificuldade, mas é possível …
o unico ponto é, é mais difícil do que deveria ser …
Pelo menos na minha opinião, mas como o Edgar apontou, a idéia da JSR 291 é solucionar, pelo menos em parte, este problema
Utilizar Dll’s com acesso dinamico a metodos é algo realmente assustador… bem diferente de vc fazer acesso via uma interface propriamente preparada…
O conceito de fazer em delphi carregando dlls parece bem simples sim… mas dae até fazer essa dll se encaixar na sua arquitetura e interagir com ela… se torna um “mundo de dor e sofrimento”… agora se voce precisa de modulos totalmente separados … que nao tenhao nenhuma interação entre eles… ae fazer dll’s como modulos é realmente bem simples… complique um pouco e voce verá que bela “estrutura” para se construir modulos
Outra coisa… eu construi um “micro container” para fazer deployment da mesma app em varias portas diferentes… (no caso meu containerzinho só faz deploy de app’s que usao sockets) , tive que implementar hotdeployment… mas nem por isso precisei escrever um classloader… e sim carregar OUTRO classloader com informacoes especificas (classpath etc…etc..)… funciona que eh uma maravilha… e nao foi tao complicado assim…
minha sugestao de abordagem:
Quando forem introduzidos novos plugins… carrege um novo classloader… se for na carga inicial… use o mesmo classloader que vc jah tem…
vai simplificar em 1000x as coisas…
boa idéia esta de simplesmente fazer um classloader filho, resolve boa parte dos problemas que eu tinha pensado …
, mas não são exatamene dlls, uma dll só exporta metodos, uma runtime-package pode exportar objetos/classes, …
agora este comentário é só pra incomodar mesmo: as runtime packages do delphi ainda ficam mais fáceis de trabalhar, e eu ja usei isto bastante
mas vamos parar de falar de delphi
Esta solução de simplesmente um classloader filho, junto com um File Monitor da vida para notificação de alterações em um diretório deve resolver meu problema, e vai ser muito mais simples do que usar algo derivado de OSGI, que é excelente, mas acho que é um canhão para matar uma mosca …
Valeu as dicas, continuo achando que podia ser mais simples, mas esta solução que tu sugeriu ja fica fácil o suficiente para ser implementada
PS.: edgar, valeu por me lembrar do nome disto, eu tinha chamado de modulos
Rafael (respondendo apenas agora por que por algum motivo extranho teus comentários sempre são classificados como spam pelo askimet
)
JPF é baseado em OSGI, o código inicial foi extraido da engine de plugins do eclipse (o equinox
) não sei exatamente qual a diferença entre eles atualmente …
eu concordo que para algo como o OSGI, é necessária toda esta complexidade, tanto na plataforma quanto na escrita dos componentes, mas voltamos a pecar no maior problema do Java como plataforma (pelo menos na minha opinião), as soluções são sempre complexas, tentando resolver os problemas do mundo, mas tornando extremamente difícil desenvolver 80% das aplicações, para beneficiar os 20% que realmente precisam de toda esta complexidade …
Parece que estão aprendendo isto (vide EJB 3), e espero que a JSR 291 siga a mesma linha do EJB3 e torne a coisa fácil o suficiente para ser utilizada em 80% dos casos, porem, flexível o suficiente para ser utilizada pelos 20% restantes que precisam dos recursos adicionais …
eu concordo que este tipo de capacidade não precisa ser responsabilidade da linguagem, mas a plataforma precisa dar suporte fácil a isto (estão trabalhando nisto nesta JSR).
enquanto isto muito obrigado pelas ideias :d
acho que ja consigo resolver o problema de forma razoavelmente fácil :d
Rodrigo, a complexidade é inerente a qualquer aplicação Java baseada em componentes que sejam dinamicamente instaláveis/removíveis. Se queres apenas componentes isolados, que nunca consumam serviços um do outros, tudo bem, não precisas disso. Mas se há interação entre os componentes (e normalmente há), é necessário escrever cada componente de forma que seja capaz de lidar com o caso de outro componente (do qual consome ou para o qual provê serviços) aparecer ou ir embora a qualquer momento. E isso não é trivial, não importando qual a tecnologia em uso (OSGI, ou JPF ou feita-em-casa). É basicamente uma SOA local, intra-VM. O teu código tem que estar preparado para que um serviço sendo referenciado pare de responder porque o componente provendo o serviço foi desinstalado. E também ser capaz de consumir um serviço de interesse que seja provido por um componente que acabou de ser instalado (descoberta).
Talvez seja possível projetar-se uma API que faça esse ‘bookkeeping’ de forma mais ou menos automática, livrando o programador desse trabalho, mas aí o código fica preso à plataforma de componentes, a não ser que coisas como aspectos ou injeção de dependências sejam usados.
Sobre JPF: pegar um padrão e estendê-lo de forma que o resultado seja incompatível com o padrão é uma grande besteira na minha opinião. Mas pelo que vi, JPF é um fork do sistema de plug-ins do Eclipse pré-OSGi (Eclipse 2.1 ou anterior), ou seja, na época em que se usava o Plug-in Manifest (plugin.xml) para declarar as dependências entre plug-ins. Talvez na época que JPF foi iniciado, ele fosse interessante (porque o runtime do Eclipse não era dinâmico), mas agora que Eclipse roda em OSGi e suporta instalação/remoção dinâmica de plug-ins, é difícil ver alguma relevância nele.
Urubatan, em que sentido vc acha que o OSGi é um canhão p/ matar uma mosca? Não confundam OSGi c/ o Eclipse workbench!
Se for c/ relação ao tamanho, o download do equinox runtime 3.3 M6 (http://download.eclipse.org/eclipse/equinox/drops/S-3.3M6-200703231616/index.php) tem só 4.3MB, e isso porque ele vem c/ o jetty jasper embutido
Se tirarmos os “acessórios”, deixando só o container básico de plugins (que era a discussão inicial desse post), o tamanho fica bem menor.
Além disso, se não estou enganado, o OSGi foi projetado inicialmente p/ poder rodar em dispositivos bastante restritos.
> Se for c/ relação ao tamanho, o download do equinox runtime 3.3 M6
> tem só 4.3MB
O framework OSGi, que tem tudo que precisas para fazer uma aplicação OSGi pura, tem 900K.
>Além disso, se não estou enganado, o OSGi foi projetado inicialmente p/ poder rodar em
> dispositivos bastante restritos.
Exato. O framework roda no Java Foundation profile. Inicialmente era o único foco, agora é um dos focos.
Acho que vocês estão pedindo pra roda ser reinventada. Vamos imaginar o maven 2. Quando eu peço pra rodar um plugin, ele tem que localiza-lo no repositório e executá-lo, certo?
Qual a mágica? Plexus! Plexus! Plexus, o container IoC mais antigo do mercado!
http://plexus.codehaus.org/
Urubatan,
Por coincidência, eu fiz algo usando o plexus mais recente (que incorpora o classworlds) fazendo um programa ser executado usando como único critério os dados do artifact M2. Dinâmico é brincadeira
Ainda não sei se posso publicar. Segredos industriais. Mas a idéia, ah, isso eu posso revelar
Alguém teria um exemplo de aplicação dedsktop utilizando o Equinox para modularizazr ela em plugins? Sei que existem algumas do mercado, mas queria um exemplo mais simples, por exemplo um frame como aplicacao principal e um plguing que adicione um botao. Para ter uma idéia de como fazer. Falo do Equinox, pois pesquisei e parece ser um bom chute investir nele como ferramenta OSGi, aceito sugestão de outras estruturas.
Obrigado.