Pergunta

Estou trabalhando com aplicativos JSF/Facelets muito grandes que usam o Spring para gerenciamento de DI/Bean. Meus aplicativos têm estrutura modular e atualmente estou procurando abordagens para padronizar a modularização.

Meu objetivo é compor um aplicativo da Web de vários módulos (possivelmente dependendo um do outro). Cada módulo pode conter o seguinte:

  • Aulas;
  • Recursos estáticos (imagens, CSS, scripts);
  • Modelos de facelet;
  • FEIDO MANGETIDO - Contextos de aplicativos de primavera, com solicitação, sessão e feijões escondidos por aplicativos (alternativa é feijão gerenciado pela JSF);
  • Servlet API Stuff - servlets, filtros, ouvintes (isso é opcional).

O que eu gostaria de evitar (quase a todo custo) é a necessidade de copiar ou extrair recursos do módulo (como modelos de facelets) para a guerra ou estender o web.xml Para servlets, filtros, etc. do módulo, deve ser suficiente para adicionar o módulo (jar, pacote, artefato, ...) ao aplicativo da web (WEB-INF/lib, bundles, plugins, ...) para estender o aplicativo da Web com este módulo.

Atualmente, resolvo esta tarefa com uma solução de modularização personalizada que é fortemente baseada no uso de recursos de pathes de classe:

  • Recursos especiais Servlet serve recursos estáticos da ClassPath Resources (JARS).
  • O resolvedor de recursos especiais do Facelets permite o carregamento de modelos de facelet dos recursos do ClassPath.
  • Spring carrega contextos de aplicativos por meio do padrão classpath*:com/acme/foo/module/applicationContext.xml - Isso carrega contextos de aplicativos definidos nos frascos do módulo.
  • Finalmente, um par de servlets e filtros delegadores delegará o processamento de solicitação para os servlets e filtros configurados em contextos de aplicação da primavera a partir de módulos.

Nos últimos dias, li muito sobre osgi e estava considerando, como (e se) eu poderia usar o OSGI como uma abordagem de modularização padronizada. Eu estava pensando em como as tarefas individuais poderiam ser resolvidas com osgi:

  • Recursos estáticos - os pacotes osgi que desejam exportar recursos estáticos registrar um ResourceLoader Instâncias com o contexto do pacote. Um central ResourceServlet Usa esses carregadores de recursos para carregar recursos de pacotes.
  • Modelos de Facelet - semelhantes a acima, um central ResourceResolver usa serviços registrados por pacotes.
  • Feijão gerenciado - Eu não faço ideia Como usar uma expressão como #{myBean.property} E se myBean é definido em um dos pacotes.
  • Serviço API Stuff - Use algo como WebExtender/Pax Web para registrar servlets, filtros e assim por diante.

Minhas perguntas são:

  • Estou inventando uma bicicleta aqui? Existem soluções padrão para isso? Encontrei uma menção de fatias de primavera, mas não consegui encontrar muita documentação sobre isso.
  • Você acha que Osgi é a tecnologia certa para a tarefa descrita?
  • Meu esboço do aplicativo OSGI está mais ou menos correto?
  • Como o feijão gerenciado (especialmente o escopo de solicitação/sessão) deve ser tratado?

Eu seria geralmente grato por seus comentários.

Foi útil?

Solução

O que você pretende fazer parece factível, com algumas advertências:

A camada de visualização: Primeiro, sua camada de visão parece um pouco exagerada. Existem outras maneiras de modularizar os componentes JSF usando componentes personalizados que evitarão as dores de cabeça envolvidas na tentativa de criar algo tão dramático como feijão gerenciado de ligação tardia.

Os próprios módulos: Segundo, seus módulos não parecem particularmente modulares. Sua primeira lista de marcadores faz parecer que você está tentando criar aplicativos da Web interoperáveis, em vez de módulos em si. Minha idéia de um módulo é que cada componente tem um objetivo bem definido e mais ou menos discreto. Tipo, como ex subjacentes vi. Se você estiver seguindo a rota do OSGI, devemos definir modular assim: Modular, por causa desta discussão, significa que os componentes são trocados a quente-isto é, eles podem ser adicionados e removido sem quebrar o aplicativo.

Dependências: Estou um pouco preocupado com a sua descrição dos módulos como "possivelmente dependendo um do outro". Você provavelmente (espero) já sabe disso, mas suas dependências devem formar um gráfico acíclico direcionado. Depois de introduzir uma dependência circular, você está pedindo um mundo de mágoa em termos da eventual manutenção do aplicativo. Uma das maiores fraquezas de Osgi é que isso não Evite dependências circulares, por isso cabe a você aplicar isso. Caso contrário, suas dependências crescerão como Kudzu e engasgarão gradualmente o restante do ecossistema do seu sistema.

Servlets: FuhgedDaboudit. Você não pode ser um aplicativo da Web em um aplicativo da Web, até que a especificação Servlet 3.0 esteja em produção (como Pascal apontou). Para lançar um servlet de utilitário separado, você precisará colocá -lo em seu próprio aplicativo.


Ok, tanto para as advertências. Vamos pensar sobre como isso pode funcionar:

Você definiu seu próprio módulo JSF para fazer ... o que exatamente? Vamos dar um propósito definido e bastante trivial: uma tela de login. Então você cria sua tela de login, com a ligação tardia usando osgi no seu aplicativo e ... então o quê? Como o aplicativo sabe a funcionalidade de login, se você não a definiu na sua página .jspx? Como o aplicativo sabe navegar para algo que não pode saber está?

Existem maneiras de contornar isso usando o condicional inclui e similares (por exemplo, <c:if #{loginBean.notEmpty}>), mas, como você disse, as coisas ficam um pouco peludas quando o seu loginbean gerenciado existe em outro módulo que ainda não foi apresentado ao aplicativo. De fato, você receberá uma exceção do servlet, a menos que exista o LoginBean. Então, o que você faz?

Você define uma API em um de seus módulos. Todos os grãos gerenciados que você pretendem compartilhar entre os módulos devem ser especificados como interfaces nesta camada de API. E todos os seus módulos devem ter implementações padrão de qualquer uma dessas interfaces que eles pretendem usar. E essa API deve ser compartilhada entre todos os módulos interoperáveis. Em seguida, você pode usar OSGI e Spring para conectar os grãos especificados com sua implementação.

Preciso reservar um momento para apontar que não é assim que eu abordaria esse problema. De jeito nenhum. Dado algo como simples como uma página de login, ou mesmo tão complicada quanto um gráfico de ações, eu prefiro pessoalmente criar um componente JSF personalizado. Mas se o requisito for "eu quero que meus grãos gerenciados sejam modulares (ou seja, hot-swappable etc)", esta é a única maneira que eu sei para fazê-lo funcionar. E nem tenho certeza vai trabalhar. Esta troca de email Sugere que é um problema em que os desenvolvedores da JSF começaram a trabalhar.

Normalmente, considero os feijões gerenciados como parte da camada de visualização e, como tal, os uso apenas para visualizar a lógica e delegar todo o resto da camada de serviço. Tornar o feijão gerenciado tardio é, na minha opinião, promovê-los fora da camada de visualização e entrar na lógica de negócios. Há uma razão pela qual todos esses tutoriais estão tão focados nos serviços: porque na maioria das vezes você deseja considerar o que seria necessário para o seu aplicativo correr "sem cabeça" e como seria fácil "esfolar" sua opinião se, para, para Por exemplo, você queria que ele fosse executado, com toda a sua funcionalidade, em um telefone Android.

Mas parece que muito do que você está trabalhando é a própria lógica de exibição - por exemplo, a necessidade de trocar em um modelo de exibição diferente. OSGI/Spring deve poder ajudar, mas você precisará de algo em seu aplicativo para escolher entre as implementações disponíveis: praticamente o que o Registro de Serviços da OSGI foi criado para fazer.

Isso deixa recursos estáticos. Você pode modularizá -los, mas lembre -se de que precisará definir uma interface para recuperar esses recursos e precisará fornecer uma implementação padrão para que seu aplicativo não engasgue se estiver ausente. Se o I18N for uma consideração, esse pode ser um bom caminho a percorrer. Se você queria ser verdade Aventureiro, então você pode empurrar seus recursos estáticos para o JNDI. Isso os tornaria completamente quente e economizaria a dor de tentar resolver qual implementação usar programaticamente, mas há algumas desvantagens: qualquer pesquisa com falha fará com que seu aplicativo jogue uma NamingException. E é um exagero. O JNDI é normalmente usado em aplicativos da Web para configuração de aplicativos.

Quanto às suas perguntas restantes:

Estou inventando uma bicicleta aqui? Existem soluções padrão para isso?

Você é, um pouco. Eu já vi aplicativos que fazem isso Gentil de coisa, mas você parece ter tropeçado em um conjunto de requisitos bastante único.

Você acha que Osgi é a tecnologia certa para a tarefa descrita?

Se você precisar que os módulos sejam de mudança quente, suas opções são OSGI e a interface ServiceLocator mais leve.

Meu esboço do aplicativo OSGI está mais ou menos correto?

Não sei dizer sem saber mais sobre onde estão seus limites de componentes. No momento, parece que você pode estar pressionando a OSGI a fazer mais do que é capaz de fazer.

Mas não aceite minha palavra para isso. EU encontrado outro material de leitura nesses lugares.

E desde que você pergunta sobre fatias de primavera, Isso deve ser suficiente para você começar. Você precisará de um cliente Git e parece que você estará treinando o aplicativo olhando através do código -fonte. E é um código de protótipo muito precoce.

Outras dicas

Estou enfrentando os mesmos problemas no meu projeto atual. Na minha opinião, o OSGI é a melhor e mais limpa solução em termos de padrões e suporte futuro, mas atualmente você pode atingir alguns problemas se tentar usá -lo em um aplicativo da Web:

  1. Ainda não existe uma solução bem integrada entre um contêiner da Web e a plataforma OSGI.
  2. O OSGI pode ser demais para um aplicativo Web de construção personalizado que está apenas procurando uma arquitetura modularizada simples. Eu consideraria a OSGI se meu projeto precisar oferecer suporte a extensões de terceiros que não estão 100% sob nosso controle, se o projeto precisar de reimplementação a quente, regras de acesso rigoroso entre plugins etc.

Uma solução personalizada baseada em carregadores de classe e filtros de recursos parece muito apropriada para mim. Como exemplo, você pode estudar o Código fonte de Hudson ou Java Plug-in Framework (JPF) (http://jpf.sourceforge.net/).

Como estendendo o web.xml, podemos ter sorte com a especificação Servlet 3.0 (http://today.java.net/pub/a/today/2008/10/14/introduction-to-servlet-3.html# Probatibilidade e extensibilidade).

O "Fragmento do Descritor de Implantação do Módulo da Web" (também conhecido Especificação do servlet 3.0 Seria bom aqui. A especificação define como:

Um fragmento da Web é uma particionamento lógico do aplicativo da Web de forma que as estruturas usadas no aplicativo da Web possam definir todos os artefatos sem pedir ao Devlopers que edite ou adicione informações no web.xml.

Java EE 6 talvez não seja uma opção para você agora. Ainda assim, seria a solução padronizada.

O Enterprise OSGI é um domínio bastante novo, então não pense que você obterá uma solução que satisfaz diretamente sua necessidade. Dito isto, uma das coisas que encontrei faltando no Equinox (o OSGI Engine por trás do Eclipse e, portanto, uma com a maior base de usuários!) É um serviço de configuração / DI consistente. No meu projeto, recentemente, tínhamos algumas necessidades semelhantes e terminamos a criação de um serviço OSGI de configuração simples.

Um dos problemas que serão inerentes a aplicações modulares seria em torno de DI, pois a visibilidade do módulo poderia impedir o acesso a classe em alguns casos. Contornamos isso usando uma política de budia registrada, que não é muito ideal, mas funciona.

Além da configuração, você pode dar uma olhada no livro Equinox lançado recentemente para obter orientações sobre o uso do OSGI como base para criar aplicativos modulares. Os exemplos podem ser específicos para o Equinox, mas os princípios funcionariam com qualquer estrutura do OSGI. Link - http://equinoxosgi.org/

Você deve procurar no Spring DM Server (ele está sendo transferido para o Eclipse Virgo, mas isso ainda não foi lançado). Há muitas coisas boas nas recentes especificações da OSGI Enterprise, que também foram lançadas.

Alguns dos tutoriais da Spring DM ajudarão, eu imagino. Mas sim, é possível ter recursos e classes carregados de fora do pacote da web usando modularidade padrão. Nisso, é um bom ajuste.

Quanto ao contexto da sessão - ele é tratado como você esperaria em uma sessão. No entanto, você pode ter problemas em compartilhar essa sessão entre os pacotes na Web, na medida em que não tenha certeza se é possível.

Você também pode procurar um único pacote da Web e, em seguida, usar o Registro de Extensão do Eclipse para estender os recursos do seu aplicativo da Web.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top