Eu tenho um sistema que deve levar arquivos grandes contendo documentos e processá-los para dividir os documentos individuais e criar objects de documento a serem persistidos com JPA (ou pelo menos é assumido nesta questão).
Os arquivos estão no intervalo de 1 documento para 100 000 em cada arquivo. Os arquivos vêm em vários tipos
Agora, a maior preocupação é que a especificação proíbe o access a arquivos locais. Pelo menos do jeito que estou acostumado.
Eu poderia salvar os arquivos em uma tabela de database, mas isso é realmente uma boa maneira de fazer isso? Os arquivos podem ter até 2 GB e acessar os arquivos do database exigiria que você baixasse o arquivo inteiro, na memory ou no disco.
Meu primeiro pensamento foi separar esse processo do servidor de aplicativos e usar uma abordagem mais tradicional, mas estive pensando em como mantê-lo no servidor de aplicativos para fins futuros, como clustering etc.
Minhas perguntas são basicamente
Eu esboço aqui mais algumas proposições e considero as seguintes preocupações:
Com JCA
Os conectores JCA pertencem à pilha Java EE e permitem conectividade inboud / outboud de / para o mundo EJB. JDBC e JMS são geralmente implementados como conector JCA. Um conector JCA de input pode usar encadeamento (por meio da abstração de trabalhador) e transactions. Em seguida, ele pode encaminhar qualquer processamento para um bean controlado por mensagem (MDB).
Com linhas simples
Podemos obter mais ou menos o mesmo que o modo JCA, usando encadeamentos que são iniciados a partir de um ouvinte de contexto de servlet da web (ou até mesmo de um EJB Timer).
Com JMS
Para evitar a necessidade de ter vários encadeamentos de pesquisa simultâneos e o problema de aquisição / bloqueio de tarefas, o processamento real pode ser realizado de forma assíncrona usando o JMS. O JMS também pode ser interessante para dividir o processamento em tarefas menores.
Com ESB
Muitos projetos surgiram no ano passado para lidar com a integração: JBI, ServiceMix, OpenESB, Mule, integração Spring, Java CAPS, BPEL. Algumas são tecnologias, outras são plataformas e há alguma sobreposição entre elas. Todos eles têm um conjunto de conectores para rotear, transformar e orquestrar o stream de mensagens. IMHO, a mensagem deve ser uma pequena informação, e pode ser difícil usar essas tecnologias para processar seu grande arquivo de dados. Os padrões de website da integração de aplicativos corporativos é um excelente site para mais informações.
IMO, a abordagem mais adequada à filosofia do Java EE é a JCA. Mas o esforço para investir é relativamente alto. No seu caso, o uso de thread simples que delega processamento adicional ao SLSB é talvez a solução mais fácil. A abordagem JMS (perto da proposição de P. Thivent) pode ser interessante se o pipeline de processamento ficar mais complicado. Usando um ESB parece um exagero para mim.
Existe uma maneira padrão ou uma maneira recomendada de lidar com isso no Java EE?
Eu usaria uma camada de integração real (como no EAI) para essa finalidade, executando como um processo externo. As ferramentas de integração (ETL, EAI, ESB) são projetadas especificamente para lidar com … integração e muitas delas fornecem tudo o que é necessário pronto para uso (versão simplificada: transporte, conectores, transformação, roteamento, segurança).
Basicamente, ao lidar com arquivos, um conector de arquivo é usado para monitorar um diretório de arquivos recebidos, que são então analisados / divididos em mensagens (aplicando opcionalmente algumas transformações) e enviados para um terminal para processamento de negócios.
Dê uma olhada no Mule ESB, por exemplo (tem um conector de arquivo, suporta muitos transportes, pode ser executado como um processo independente). Ou talvez o Spring Integration (acoplado ao Spring Batch?) Que também possui o File e o JMS Adapters. Mas eu não tenho muita experiência com isso, então não posso dizer nada sobre isso. Ou, se você é rico, você poderia olhar para Tibco EMS , WebMethods, etc. Ou construir sua própria solução usando alguma biblioteca de análise (por exemplo, jFFP ou Flatworm ).
Existe uma maneira específica de servidor de aplicativos em torno disso?
Eu não estou ciente de nada assim.
Você pode justificar a quebra deste processo fora do servidor de aplicativos? E como você projetaria o canal de comunicação entre esses dois sistemas separados?
Como eu disse, eu usaria um processo externo para o material de processamento de arquivos (melhor adequado) e enviaria o conteúdo do arquivo como mensagens através do JMS para o servidor de aplicativos para o processamento de negócios (e assim se beneficiaria de resources Java EE como load balanceamento e gerenciamento de transactions).
acessar os arquivos do database exigiria que você baixasse o arquivo inteiro, na memory ou no disco.
Isso não é inteiramente verdade. Você não é obrigado a colocar a coisa toda em um byte[]
indermetia byte[]
ou algo assim. Você pode continuar usando streams. Obter um InputStream
dele usando ResultSet#getBinaryStream()
e imediatamente manipulá-lo da maneira usual, por exemplo, escrevendo para HttpServletResponse#getOutputStream()
. O custo é apenas o tamanho do buffer que você mesmo pode definir.
Existe uma maneira padrão ou uma maneira recomendada de lidar com isso no Java EE?
O database ou um caminho de sistema de arquivos de disco fixo com access r / w para o servidor de aplicativos. Por exemplo, /var/webapp/files
no disco raiz.
Eu acho que a maneira mais saudável de fazer isso é sem um servidor de aplicativos Java.
Os servidores de aplicativos gostam de gerenciar resources (CPU, memory, threads) do seu próprio jeito. A execução de processamento em lote intensivo de E / S de longa execução tende a distorcer esse tipo de gerenciamento de resources.
Eu sugiro usar um processo externo para dividir os arquivos, com uma limpeza periódica para manter o uso do disco sob controle, e usando o AS para access de leitura via sistema de arquivos, como o BalusC sugeriu.
Eu suponho que os problemas de access simultâneo seriam tratados pela camada JPA – que eu reconhecidamente não sei muito sobre, mas acho que vem também no sabor do J2SE.
A especificação proíbe acessar arquivos usando java.io. Existem outras formas legais de acessar arquivos, por exemplo, por meio de um driver DataSource / JDBC ou por meio de um conector de resources.
Veja pp545 de “JSR 220: Enterprise JavaBeansTM, Contratos e Requisitos Principais do EJB Versão 3.0”
… usando o JDBC para access a arquivos. Você poderia por favor explicar um pouco mais em detalhes?
Um arquivo é um armazenamento de dados da mesma maneira que um database. É um armazenamento de dados muito bom para dados de caracteres acessados serialmente, não estruturados, e não tão grande quando você deseja segurança de transactions, access multiusuário, access random gravável ou dados binários estruturados. Em um sistema corporativo, você tende a ter pelo menos um desses últimos requisitos quase o tempo todo.
Embora não seja estritamente verdadeiro dizer “Em um sistema corporativo não há arquivos” (porque existem arquivos de log e quase todos os bancos de dados usam arquivos em um nível baixo) é uma boa regra prática de design, por causa de todos os problemas que os arquivos de dados causam em um sistema corporativo de alto desempenho, multiusuário, seguro para transactions, de leitura e gravação.
Infelizmente, o mundo dos negócios está cheio de dados de negócios armazenados em arquivos. Você tem que lidar com eles. Alguns arquivos (por exemplo, planilhas do Excel) têm bastante em comum com um database simples que podem valer a pena acessar por meio de um driver JDBC. Nunca ouvi falar de alguém acessando arquivos de texto sem formatação através de um driver JDBC, mas você poderia – ou poderia usar um adaptador de resources mais genérico (de acordo com a especificação EJB3, o JDBC é uma API do gerenciador de resources).