3.2.11. Alterações EJB 2.x

3.2.11.1. Atualização dos Aplicativos que usam o EJB 2.x

O JBoss EAP 6 foi construído nos padrões aberto e é compatível com a especificação do Java Enterprise Edition 6. Embora o servidor do aplicativo fornece suporte para o EJB 2.x, isto não suporta os recursos que vão além da especificação. Lembre-se de que a especificação Java EE 7 foi marcada EJB 2.x opcionalmente, portanto é altamente recomendável que você regrave o seu código de aplicativo à especificação EJB 3.x.
Caso não deseje migrar o seu código EJB 2.x, na maioria das vezes será necessário realizar modificações para executar no JBoss EAP 6. Este tópico descreve algumas alterações que possam ser necessárias para executar o EJB 2.x no JBoss EAP 6.
Alterações de configuração requeridas para executar o EJB 2.x no JBoss EAP 6

Inicie o servidor com o perfil completo
O EJB 2.x Container Managed Persistence (CMP) beans requer o Java Enterprise Edition 6 Full Profile. Este perfil contém elementos de configuração que são necessários para executar o CMP EJBs.
Este perfil de configuração contém o módulo de extensão org.jboss.as.cmp:
<extensions>
    ...
    <extension module="org.jboss.as.cmp"/>
    ...
</extensions>
Isto contém o subsistema cmp:
<profiles>
    ...
    <subsystem xmlns="urn:jboss:domain:cmp:1.1"/>
    ...
</profiles>
.
Para iniciar o servidor autônomo JBoss EAP 6 com o perfil completo, passe o argumento -c standalone-full.xml ou -c standalone-full-ha.xml na linha de comando antes de iniciar o servidor.
A configuração do contêiner não é mais suportada
Nas versões anteriores do JBoss EAP, era possível configurar um contêiner para a entidade CMP e outros beans e usá-lo pela configuração de referências dentro do arquivo do descritor de implantação do aplicativo jboss.xml. Por exemplo, haviam configurações diferentes para os beans de sessão no geral.
No JBoss EAP 6.x, é possível usar os beans de Entidade EJB 2 com o contêiner padrão. No entanto, as configurações de contêiner diferentes não são mais suportadas. A abordagem recomendada é migrar o EJB2 Stateful Session Beans (SFSB), Stateless Session Beans (SLSB), Message Driven Beans (MDB) para o EJB 3, e para o Container-Managed Persistence (CMP) e Bean-Managed Persistence (BMP) Entity Beans para uso do Java Persistence API (JPA) de acordo com a especificação EJB 3.
A configuração do contêiner default no JBoss EAP 6 contém as alterações para os beans EJB 2 CMP:
  • O bloqueamento pessimista é ativo por default. Isto pode resultar em bloqueios.
  • O código de detecção de bloqueio que estava na camada CMP no JBoss EAP 5.x não faz parte do JBoss EAP 6.
No JBoss EAP 5.x, era possível personalizar o caching, pooling, commit-options e a pilha do interceptor. No JBoss EAP 6, isto não é mais possível. Existe apenas uma implementação, que é parecida à política Instância por transação com commit-option C. Caso você migrar um aplicativo que usa a configuração de contêiner de bean de entidade cmp2.x jdbc2 pm, que usa o CMP2.x compatível JDBC baseado no gerenciador persistente, haverá um impacto no desempenho. Este contêiner foi optimizado para o desempenho. Recomenda-se a migração destas entidades ao EJB 3 antes de migrar o aplicativo.
Configuração do Interceptor ao lado do Servidor
O JBoss EAP 6 suporta o Java EE Interceptor padrão usando as anotações @Interceptors e @AroundInvoke. No entanto, isto não permite a manipulação fora da Segurança ou Transação.
Nas versões anteriores do JBoss EAP, era impossível modificar a pilha do interceptor para possuir interceptores personalizados para cada invocação EJB. Isto era normalmente usado para implementar a segurança personalizada ou mecanismos de reentrada, antes das checagens de segurança ou checagem de transação ou criação. O JBoss EAP 6.1 introduziu os interceptores do contêiner para fornecer funcionalidade similar. Para maiores informações sobre os interceptores do contêiner, consulte o capítulo Interceptores do Contêiner no Guia de Desenvolvimento do JBoss EAP.
Outra abordagem para fornecer mais controle do que anteriormente, durante ou após a fase de confirmação de uma transação enquanto mantendo a especificação do Java EE, é o uso do Registro de Sincronização da Transação para adição de um ouvinte.
O recurso pode ser restaurado usando um dos seguintes métodos:
  • O uso do InitialContext
    TransactionSynchronizationRegistry tsr = (TransactionSynchronizationRegistry) 
    		new InitialContext().lookup("java:jboss/TransactionSynchronizationRegistry");
    tsr.registerInterposedSynchronization(new MyTxCallback());
    
  • O uso da injeção
    @Resource(mappedName = "java:comp/TransactionSynchronizationRegistry")
    TransactionSynchronizationRegistry tsr;
    ...
    tsr.registerInterposedSynchronization(new MyTxCallback());
    
A routina da chamada de retorno deve implementar a Interface javax.transaction.Synchronization. Use o método beforeCompletion{} para executar quaisquer verificações antes da transção ser confirmada ou revertida. Caso um RuntimeException for lançado a partir deste método, a transação será revertida e o cliente é notificado com um EJBTransactionRolledbackException. No caso de um XA-Transaction, todos os recursos serão revertidos de acordo com o contrato XA. É possível também habilitar cada lógica comercial dependendo do estado da transação usando o método afterCompletion(int txStatus). Caso um RuntimeException seja lançado a partir deste método, a transação permanecerá no estado original, tanto confirmada ou revertida e o cliente não é informado. Apenas o gerente da transação apresenta um aviso nos arquivos de log do servidor.
Configuração ao lado do Servidor para Interceptores ao lado do Cliente
Nas versões anteriores do JBoss EAP, era possível configurar os interceptores do cliente com a configuração do servidor e fornecer apenas as classes com o cliente API.
No JBoss EAP 6, isto não é mais possível uma vez que o Proxy do cliente não é mais criado ao lado do servidor e transmitido ao cliente após a pesquisa. O proxy é agora gerado ao lado do cliente. Esta otimização evita a invocação do servidor para a pesquisa e atualizações da classe.
Configuração do Pool Bean de Entidade
A configuração do pool bean de entidade não é recomendada no JBoss EAP 6. Isto deve-se a ela ser limitada à configuração do elemento <strict-max-pool>, bloqueios e outros problemas que podem ocorrer caso o pool for muito pequeno para carregar todas as entidades no resultado determinado. Os beans de entidade não possuem métodos grandes de ciclo de vida durante a inicialização, portanto a criação da instância e em volta do contêiner não é mais lenta do que quando usando uma instância de bean de entidade com pool.
Substituição do Arquivo do Descritor de Implementação jboss.xml
O descritor da implementação jboss-ejb3.xml substitui o arquivo do descritor de implantação jboss.xml. Este arquivo é usado para substituir e adicionar os recursos fornecidos pelo Java Enterprise Edition (EE), definido no descritor de implantação ejb-jar.xml. O novo arquivo é incompatível com o jboss.xml e o jboss.xml é agora ignorado nas implantações.
Por exemplo, nos lançamentos anteriores do JBoss EAP, caso fosse definido um <resource-ref> no arquivo ejb-jar.xml, você necessitaria de uma definição de recurso correspondente para o nome JNDI no arquivo jboss.xml. O XDoclet gerou automaticamente ambos arquivos do descritor de implantação. No JBoss EAP 6, a informação de mapeamento JNDI é agora definida no arquivo jboss-ejb3.xml. Presuma que a fonte de dados está definida no código de fonte de dados conforme abaixo.
DataSource ds1 = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/Resource1");
DataSource ds2 = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/Resource2");
O ejb-jar.xml define as seguintes referências de recurso.
<resource-ref >
    <res-ref-name>jdbc/Resource1</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
<resource-ref >
    <res-ref-name>java:comp/env/jdbc/Resource2</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
O arquivo jboss-ejb3.jxml mapeia os nomes JNDI aos recursos usando a seguinte sintaxe XML.
<resource-ref>
    <res-ref-name>jdbc/Resource1</res-ref-name>
    <jndi-name>java:jboss/datasources/ExampleDS</jndi-name>
</resource-ref>
<resource-ref>
    <res-ref-name>java:comp/env/jdbc/Resource2</res-ref-name>
    <jndi-name>java:jboss/datasources/ExampleDS</jndi-name>
</resource-ref>
Algumas das opções de configurações disponíveis no JBoss EAP 5.x do arquvivo jboss.xml não foram implementadas no JBoss EAP 6. A seguinte lista descreve alguns dos atributos usados comumente no arquivo jboss.xml e se há uma maneira alternativa para arquivá-los no JBoss EAP 6.
  • O elemento method-attribute foi usado para configurar uma entidade individual e métodos de beans de sessão.
    • As opções de configuração read-only e idempotent não estão disponíveis no JBoss EAP 6.
    • A opção transaction-timeout está agora configurada no arquivo jboss-ejb3.xml.
  • O atributo missing-method-permission-exclude-mode alterou o comportamento dos métodos sem implementação do metadado de segurança explícito num bean com segurança. No JBoss EAP 6, a ausência de uma anotação @RolesAllowed é normalmente tratada de forma similar ao @PermitAll
Configuração de Mapeamento de Tipo de Fonte de Dados
Nas versões anteriores do JBoss EAP, era possível configurar o type-mapping da fonte de dados com o arquivo de configuração de implementação da fonte de dados *-ds.xml.
No JBoss EAP 6, isto deve ser realizado no arquivo do descritor de implementação jbosscmp-jdbc.xml.
<defaults>  
    <datasource-mapping>mySQL</datasource-mapping>  
    <create-table>true</create-table>  
    ....  
</defaults>
Nas versões anteriores do JBoss EAP, o mapeamento personalizado era feito no arquivo standardjbosscmp-jdbc.xml. Este arquivo não está mais disponível e o mapeamento é agora realizado no arquivo do descritor de implantação jbosscmp-jdbc.xml.
Alterações do Container-Managed Persistence (CMP) Adicional e Container-Managed Relationship (CMR)

Alterações de Coleção e do Interador Container Managed Relationship (CMR)
Nas versões anteriores do JBoss EAP, era possível para alguns contêiners, como por exemplo o contêiner cmp2.x jdbc2 pm, interar as coleções CMR, além de remover e adicionar relações. Isto não é mais possível no JBoss EAP 6, uma vez que a configuração do contêiner não é suportada. Consulte EJB2.1 Finder for CMP entities with relations (CMR) returns duplicates in EAP6 na seção de Soluções de Conhecimento de Suporte do Portal do Cliente, para maiores informações sobre como atingir esta mesma funcionalidade no código do aplicativo.
Entradas duplicadas do Container Managed Relationship (CMR) para Buscas
Nas versões anteriores do JBoss EAP, era possível selecionar contêineres CMP diferentes que usavam estratégias de persistência diferentes. O contêiner cmp2.x jdbc2 pm no JBoss EAP 5.x usava o SQL-92 otimizado para gerar a sintaxe LEFT OUTER JOIN de buscas. A implementação não contém essas otimizações, uma vez que o JBoss EAP 6.x apenas suporta o contêiner para CMP e CMR. A busca deve conter a palavra DISTINCT na declaração SELECT para evitar o produto cartesiano no conjunto de resultado. Consulte EJB2.1 Finder for CMP entities with relations (CMR) returns duplicates in EAP6 na seção de Soluções de Conhecimento de Suporte do Portal do Cliente para maiores informações sobre este assunto.
Alteração Default de Exclusão Cascade para os Beans de Entidade CMP
O valor default de exclusão cascade foi alterado para false. Isto pode resultar em falhas de exclusão no JBoss EAP 6. Caso as relações de entidades forem marcadas como cascade-delete, o batch-cascade-delete deve ser explicitamente determinado para true no arquivo jbosscmp-jdbc.xml. Consulte cascade delete fail for EJB2 CMP Entities after migration to EAP6 na seção de Soluções de Conhecimento de Suporte no Portal do Cliente para maiores informações.
Mappers Personalizados CMP para Campos Personalizados.
Caso tenha usado classes mapper tais como JDBCParameterSetter, JDBCResultSetReader e Mapper em seu aplicaitivo do JBoss EAP 5.x, o java.lang.ClassNotFoundException será visível na implantação de seu aplicativo ao JBoss EAP 6. Isto é devido aos nomes de pacotes das interfaces terem sido alterados do org.jboss.ejb.plugins.cmp.jdbc.Mapper ao org.jboss.as.cmp.jdbc.Mapper. Consulte Como usar o mapeamento de Campo para as classes personalizadas num aplicativo EJB2 CMP do EAP6 na seção de Soluções de Conhecimento de Suporte do Portal do Cliente para maiores informações.
Geração de Chaves Primárias usando entity-commands
Caso seu aplicativo usar o aplicativo do JBoss EAP 5 entity-commands para gerar chaves primárias, por exemplo: Sequence ou Auto-increment, o ClassNotFoundException será visível para a classe JDBCOracleSequenceCreateCommand quando a migração para o JBoss EAP 6 for realizada. Isto é devido ao pacote da classe ter sido alterado de org.jboss.ejb.plugins.cmp.jdbc para org.jboss.as.cmp.jdbc.keygen. Caso deseje usar esta classe no seu aplicativo do JBoss EAP 6, a dependência deve ser adicionada no módulo EAP_HOME/modules/system/layers/base/org/jboss/as/cmp.
Alterações ao Aplicativo

Modificação do Código para Uso das Novas Regras di JNDI Namespace.
A partir do EJB 3.0, o uso do prefixo JNDI completo com o EJB 2.x deve ser realizado. Consulte a Seção 3.1.8.1, “Atualização dos Nomes JNDI Namespace do Aplicativo” para maiores informações sobre as novas regras JNDI namespace e amostras de código.
Amostras demonstrando como atualizar o JNDI namespace de lançamentos anteriores podem ser encontradas na: Seção 3.1.8.5, “Amostra do JNDI Namespaces nos Lançamentos Anteriores e como são especificados no JBoss EAP 6”.
Modificação do Descritor do Arquivo jboss-web.xml
Modifique o <jndi-name> para cada <ejb-ref> usar o novo formato de pesquisa inteiramente qualificado JNDI.
Use o XDoclet para Mapear o Nome JNDI de Interfaces Locais Internas
No EJB 2, era bastante comum o uso do Locator padrão para observar os Beans. Caso este padrão seja usado em seu aplicativo, o XDoclet pode ser usado para gerar um mapa aos nomes JNDI, ao invés de modificar o código do aplicativo.
Uma anotação XDoclet é parecida com o seguinte:
@ejb.bean name="UserAttribute" display-name="UserAttribute" local-jndi-name="ejb21/UserAttributeEntity" view-type="local" type="CMP" cmp-version="2.x" primkey-field="id"
O nome JNDI ejb21/UserAttributeEntity na amostra acima não é mais válido no JBoss EAP 6. Você pode mapear este nome a um nome JNDI usando o subsistema naming na configuração do servidor e um patch para o XDoclet.
Mappers personalizados podem ser criados conforme descrito no parágrafo acima titulado Mappers Personalizados do CMP para Campos Personalizados ou você pode modificar o código conforme descrito no seguinte procedimento.

Procedimento 3.24. Alteração do Código Gerado XDoclet e Uso do Subsistema de Nomeação

  1. Extraia o template XDoclet lookup.xdt localizado no ejb-module.jar e modifique o lookup() no lookupHome conforme abaixo:
    private static Object lookupHome(java.util.Hashtable environment, String jndiName, Class narrowTo) throws javax.naming.NamingException {  
        // Obtain initial context  
        javax.naming.InitialContext initialContext = new javax.naming.InitialContext(environment);  
        try { 
            // Replace the existing lookup      
            // Object objRef = initialContext.lookup(jndiName);  
            // This is the new mapped lookup
            Object objRef;  
            try {  
                // try JBoss EAP mapping  
                objRef = initialContext.lookup("global/"+jndiName);  
            } catch(java.lang.Exception e) {  
                objRef = initialContext.lookup(jndiName);  
            }  
            // only narrow if necessary  
            if (java.rmi.Remote.class.isAssignableFrom(narrowTo))  
                return javax.rmi.PortableRemoteObject.narrow(objRef, narrowTo); 
            else  
                return objRef;  
        } finally {  
            initialContext.close();  
        }  
    }
  2. Execute Ant, configurando o atributo do template para uso do lookup.xdt modificado para a tarefa ejbdoclet.
  3. Modifique o subsistema naming no arquivo da configuração do servidor para mapear o nome JNDI ao novo nome JNDI válido.
    <subsystem xmlns="urn:jboss:domain:naming:1.2">  
        <bindings>  
            <lookup name="java:global/ejb21/UserAttributeEntity" lookup="java:global/ejb2CMP/ejb/UserAttribute!de.wfink.ejb21.cmp.cmr.UserAttributeLocalHome"/>  
        </bindings>  
        <remote-naming/>  
    </subsystem>
    
Sumário dos Arquivos Obsoletos

Os seguintes arquivos não são mais suportados no JBoss EAP 6.

jboss.xml
O arquivo do descritor de implantação jboss.xml não está mais suportado e será ignorado caso incluído no arquivo implantado.
standardjbosscmp-jdbc.xml
O arquivo de configuração standardjbosscmp-jdbc.xml não é mais suportado. Esta informação de configuração é agora incluída no módulo org.jboss.as.cmp e não está mais personalizada.
standardjboss.xml
O arquivo de configuração standardjboss.xml não é mais suportado. A informação de configuração está incluída no arquivo standalone.xml quando executada num servidor autônomo ou arquivo domain.xml quando executando num managed domain.