Atualizando o estado do Managed Server no Weblogic

Olá pessoal, essa é uma dica rápida mas que pode ser muito útil.

Quem utiliza o Weblogic como servidor de aplicação pode se deparar com uma situação inusitada ao acessar a console de administração.

O Managed Server que está associado ao Gerenciador de Nós possui o estado ATIVO ou RUNNING na console, porém, o servidor não responde. O primeiro passo é conferir se o servidor está de fato no ar, para isso execute em um terminal Linux:

   ps -aux |grep java

Esse comando retorna todos os processos Java que estão sendo executados. Se o servidor não está na lista, como ele está ATIVO?

A resposta para essa pergunta está no arquivo “nomeServidor.state”. Exemplo: ManagedServer_2.state.

Esse arquivo fica no diretório nodemanager dentro da pasta do servidor. Exemplo: <ORACLE_HOME>/user_projects/domains/x_domain/servers/ManagedServer_2/data/nodemanager

O gerenciador de nós controla o estado do managed server usando esse arquivo como referência. Essa divergência pode surgir quando o Weblogic não é encerrado adequadamente, um kill no processo por exemplo.

Apesar da documentação enfatizar que esse arquivo não pode ser modificado diretamente, esse é um caso onde se faz necessário modificar o arquivo com o seguinte conteúdo:

 SHUTDOWN:N:N 

Restaurando o Managed Server para o estado “Parado” ou “SHUTDOWN” já será possível iniciar o servidor normalmente.

PLUS

Dentro do mesmo diretório, existem outros arquivos que são utilizados para controlar o estado do servidor.

nomeServidor.pid: Que possui o pid (número) do processo Java que está sendo executado.

nomeServidor.lck: Arquivo de lock que possui o id da transação interna do Weblogic. Utilizado quando o lock da console é solicitado para realizar alguma modificação.

Era isso!

Publicado em Uncategorized, Weblogic | Marcado com , , | Deixe um comentário

Web service JAX-RS com código mais limpo e a mágica do @BeanParam

É muito comum usar as anotações do JAX-RS nos métodos que são expostos como web service para recuperar os parâmetros. Algo como:

@POST
@Consumes("application/x-www-form-urlencoded")
public void postWS(@FormParam("nomeParametro") String valorParametro)
// alguma lógica para tratar o parâmetro

}

Ainda é possível substituir a anotação @FormParam por outras como @Context, @PathParam, @QueryParam, @MatrixParam, @HeaderParam e @CookieParam. Dependendo do cenário o código pode ficar mais complexo ainda, quando é necessário usar a anotação @DefaultValue ou @Encoded.

Mas como não há nada tão ruim que não possa piorar… Imaginem todas essas anotações em um método que recebe uns 10 parâmetros. Acaba que o código fica terrível de ler e com muitas variáveis que devem ser tratadas dentro do método.

A mágica do @BeanParam

Para resolver esse problema de misturar muitas anotações e variáveis a API do JAX-RS disponibiliza a anotação @BeanParam. Para usar a anotação @BeanParam vamos utilizar como exemplo o código do @POST que coloquei acima, vamos criar uma classe Java simples ou um pojo, como você quiser chamar…


package br.com.ws;

import javax.ws.rs.FormParam;

/**
 *
 * @author maicon
 */
public class BeanParamWs {

    @FormParam("nomeParametro")
    private String valorParametro;
   
    // get set do atributo valorParametro
}

E agora vamos substituir o código do @POST original por um novo que utiliza a anotação mágica @BeanParam

@POST
@Consumes("application/x-www-form-urlencoded")
public void postWS(@BeanParam BeanParamWs beanParamWs) {
    // alguma lógica para tratar o parâmetro
}

A mágica está justamente no fato da anotação @BeanParam fazer automaticamente o binding dos parâmetros como definimos na classe BeanParamWs. Se tivéssemos 10 parâmetros bastaria declarar os parâmetros como atributos na classe BeanParamWs,  realizar a devida anotação e Voilá.

O mais interessante é que no BeanParamWs todas as anotações de injection do JAX-RS funcionam (@FormParam, @Context, @PathParam, @QueryParam, @MatrixParam, @HeaderParam, @CookieParam além de @DefaultValue e @Encoded) e ainda podem ser combinadas.

Atenção

Duas observações importantes para não estragar a brincadeira:

  • Evite misturar muitas anotações diferentes na mesma classe para evitar confusão
  • Não crie uma classe gigante com 500 atributos só por que você está com preguiça e pretende reusar a mesma classe em todos os web services do sistema

Utilize o bom senso sem moderação 😀

Abraço

Publicado em Desenvolvimento | Marcado com | Deixe um comentário

Por que o Hibernate 4 não mostra os logs no Log4j2

Depois de configurar o Log4j2 como descrevi aqui estava tudo funcionando da forma como queria, só tinha um porém, os logs do Hibernate 4 não apareciam, na console aparecia a query e nada mais.

Depois de fazer uma longa pesquisa no oráculo nosso de cada dia (leia-se google) encontrei diversas pessoas com o mesmo problema, só que não existe uma solução que atenda a todos, por isso vou contar um pouco de história e explicar como eu consegui resolver esse problema, let’s go.

Um pouco de história…

Vou começar explicando por que considero essa parte importante,  o contexto e o background do problema podem ajudar a outras pessoas que possuem um cenário diferente do meu e dessa forma adaptar ao seu cenário.

Pra começo de conversa desde a versão 4 o Hibernate utiliza o Jboss Logging como fachada para implementação de logs, anteriormente era utilizada o Slf4j,  é esse o nosso ponto de partida. Até a última versão do Hibernate (4.3.9.Final no momento em que escrevo esse texto) a dependência do JBoss Logging é a 3.1.3.GA e a mesma não possui suporte para Log4j2.

Buscando ser compatível com o Log4j2 o time do Jboss Logging resolveu  implementar essa compatibilidade na versão 3.2.0.Beta1 que foi baseada, adivinhem em qual versão do Log4j2?!? em uma versão também beta do Log4j2. Só que o time do Log4j2 mudou a API e quebrou a compatibilidade da versão 3.2.0.Beta1, somente a partir da versão 3.2.1.Beta2 do Jboss Logging é que de fato a integração com o Log4j2 funciona a contento.

Solução

A solução para usar o Hibernate 4 com o Log4j2 é sobrescrever a dependência do Jboss Logging, substituindo a versão 3.1.3.GA com a versão 3.2.1.Beta2 ou superior. No momento que escrevo esse post a última versão é 3.2.1.Final e foi ela que usei. Para quem usa maven basta adicionar a dependência no pom.xml da seguinte forma:


<dependency>
    <groupId>org.jboss.logging</groupId>
    <artifactId>jboss-logging</artifactId>
    <version>3.2.1.Final</version>
</dependency>

Feito isso o nosso Hibernate 4 vai funcionar corretamente. Mas dependendo do cenário pode ser que seja necessário realizar outros ajustes, como no meu caso…

Meu cenário

Uma aplicação web rodando no Glassfish 4.1, neste caso o Glassfish utiliza uma implementação do Jboss Logging que é 3.1.3.GA que fica dentro do diretório modules do Glassfish. Dessa forma ao fazer o deploy ele carrega a versão 3.1.3.GA antes de carregar os jar que estão dentro do WEB-INF/lib da minha aplicação, dentre esses jars esta a versão atualizada do Jboss Logging 😦

Moral da história a versão atualizada não é utilizada, atualizar a versão que está dentro do diretório modules seria uma saída, eu disse seria, ao atualizar a versão o Glassfish apresenta um erro. Me parece que esse erro acontece por que existe alguma implementação tentando fazer um import que não existe no jar novo.

A minha solução foi adicionar um atributo no glassfish-web.xml que faz com que ele carregue primeiro as classes que estão dentro do WAR, dessa forma:

<class-loader delegate="false"/>

Ai sim tudo funciona normalmente!!!

O único ponto de atenção que se deve ter é quando esse WAR acessa outros módulos de fora do WAR, por exemplo, módulos de um projeto EAR. Nessa caso a aplicação web não vai funcionar e a única solução é: trocar de servidor ou utilizar a versão antiga do Log4j, a versão 1.2.

Referências:

http://wiki.apache.org/logging/Log4j2AndHibernate4

http://docs.jboss.org/hibernate/orm/4.3/topical/html/logging/Logging.html

https://issues.jboss.org/browse/JBLOGGING-94

Fui.

Publicado em Desenvolvimento | Marcado com , , | Deixe um comentário

Configuração e utilização do Log4j2

O Log4j é um dos frameworks de log mais utilizados, se não for o mais utilizado – no mundo Java.

No post de hoje eu vou colocar um resumão com as configurações do Log4j2 e alguns detalhes que devem ser observados para que tudo funcione sem dor de cabeça.

Novidades do Log4j2

  • Agora é possível utilizar JSON ou YAML no arquivo de configuração além de XML
  • A configuração através de arquivo properties foi removida
  • O arquivo XML de configuração utilizado na versão 1.2 não é compatível com a versão 2
  • Muitas melhorias de performance foram implementadas na versão 2, principalmente para cenários de log assíncronos
  • Possibilidade de aplicar filtros nos logs, ou seja, antes de passar o log para Loggers ou Appenders o log propriamente dito pode ser encaminhado para um classe de filtro
  • Suporte para substituição de propriedades, algo parecido com o funcionamento do Maven onde é possível declarar propriedades e depois fazer referência as mesmas
  • Suporte a reconfiguração automática quando o arquivo de configuração é modificado
  • Agora o log4j está dividido entre vários jar e não em somente em um como na versão 1.2
  • Requer no mínimo Java 6

São muitas novidades legais, mas a que menos me agradou foi a retirada do arquivo de properties para fazer a configuração de log. Gostava do arquivo de propriedades por achar mais fácil de ler e entender. Destaco duas novidades que achei bem legal, o “reload” automático do arquivo de configuração e o suporte a substituição de propriedades, além da tradicional melhoria de performance.

Configuração

Para configurar o Log4j2 eu optei por utilizar o arquivo XML. Uma importante mudança é o nome do arquivo que o Log4j2 procura no classpath da aplicação, no caso de xml o nome deve ser log4j2.xml. A extensão poderia ser json ou jsn para JSON ou ainda yaml ou yml para YAML. Também vale lembrar que é possível adicionar um arquivo de configuração para ambientes de testes, neste caso é necessário adicionar “-test” ao nome do arquivo e manter a extensão, algo como lo4j2-test.xml. Os arquivos de configuração do tipo teste tem preferência sobre os arquivos de produção. Mais informações sobre a ordem de leitura dos arquivos de configuração podem ser obtidas aqui.

Exemplo de XML:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
    <Properties>
        <Property name="pattern">%d{dd/MM/yyyy HH:mm:ss,SSS EEEE} %p [%-20c{1}] %m%n</Property>
        <Property name="filePath">${sys:user.home}</Property>
    </Properties>
    <Appenders>
        <RollingFile name="RollingFile"
                     fileName="${filePath}/logs/meuLog.log"
                     filePattern="${filePath}/logs/meuLog-%d{dd-MM-yyyy-HH:mm:ss}-%i.log">
            <PatternLayout pattern="${pattern}"/>
            <Policies>
                <SizeBasedTriggeringPolicy size="10 MB" />
            </Policies>
            <DefaultRolloverStrategy max="20"/>
        </RollingFile>
        
        <Console name="Console">
            <PatternLayout pattern="${pattern}"/>
        </Console>
    </Appenders>
    
    <Loggers>
        <Root level="debug">
            <AppenderRef ref="RollingFile"/>
            <AppenderRef ref="Console"/>
        </Root>
        
          <Logger name="org.hibernate" level="debug" additivity="false">
            <AppenderRef ref="Console"/>
            <AppenderRef ref="RollingFile"/>
        </Logger>
    </Loggers>
    
</Configuration>

Troubleshooting

Acho importante destacar alguns pontos do arquivo de configuração.

  1. Não existe ainda nenhum XSD ou DTD (pelo menos no momento em que escrevo esse post) para validar o arquivo de configuração. O que na minha opinião é um grande erro, dai a importância do atributo status=”debug” na tag Configuration, pelo menos em ambiente de desenvolvimento e testes, dessa forma o Log4j2 ao parsear o arquivo mostra no log os erros caso existam. Como não existe nenhum autocomplete das IDE’s um exemplo comum de erro é errar o nome da tag, é preciso ficar atento pois esse parser vai ser executado somente na primeira execução do Log4j2.

  2. A documentação do Log4j2 diz que é possível declarar um property usando a seguinte sintaxe:
    <Property name="pattern" value="%d{dd/MM/yyyy HH:mm:ss,SSS EEEE} %p [%-20c{1}] %m%n"/>

    Mas não funcionou, pelo menos comigo, o Log4j2 mostra o seguinte erro ao realizar o parser: Property contains an invalid element or attribute “value”. Não sei se é um bug, dei uma olhada rápida na internet e não encontrei nada relacionado

  3. A property com o nome filePath possui o valor ${sys:user.home}. É dessa forma que o Log4j2 busca por variáveis de sistema, não é possível utilizar diretamente ${user.home} pois o Log4j2 vai procurar por uma propriedade com esse nome. Existe outras configurações que permitem ao Log4j2 ler as variáveis a partir de outras fontes, mais detalhes aqui

  4. Por fim, mas não menos importante, reparem no atributo additivity=”false” da tag Logger. Essa tag evita que o log seja duplicado, primeiro o Log4j passa o log para o Appender e depois para o Root que contém a referência para Appender e bingo! log duplicado

Dependências

Como falei no começo do post, agora é preciso utilizar mais de uma arquivo jar. Como utilizo Maven, a minha configuração dessa maneira:

 
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.2</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.2</version>
        </dependency>
        
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-web</artifactId>
            <version>2.2</version>
        </dependency>

Além da API e core adicionei o módulo web, dessa forma ao realizar o deploy o Log4j2 já procura o arquivo de configuração e faz o parser. Se algo de errado acontecer, ele já informa na hora. Sem esse módulo o parser é realizado na primeira chamada ao Log4j2, o que pode demorar um pouco para acontecer e ainda custar mais tempo na realização de outro deploy.

Como no meu caso eu utilizo o Slf4j que é uma fachada para outras implementações de log tal como java.util.logging, logback, log4j, etc é necessário adicionar mais duas dependências:

         <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-slf4j-impl</artifactId>
            <version>2.2</version>
        </dependency>
        
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.10</version>
        </dependency>

Usando o Log4j2

Para usar basta declarar o seguinte atributo de classe:

private static final Logger logger = LogManager.getLogger(NomeDaClasse.class);

E usar da seguinte forma:

logger.debug("Teste");

Os imports para esse esse exemplo são:

import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;

O Log4j2 possui os seguinte níveis de log: trace, debug, info, warn, error e fatal. Sendo trace o nível mais baixo e fatal o nível mais alto, esse um conceito importante, pois ao definir no arquivo de configuração o level de debug no Logger todo o log que estiver abaixo desse nível será ignorado. Exemplo level=”warn” faz com que os logs com logger.debug não sejam logados.

Para quem utiliza Slf4j o código é quase o mesmo e não muda nada em função de ser o Log4j2.

Até a próxima.

Publicado em Desenvolvimento | Marcado com | 1 Comentário

Log4j 1.2 no Glassfish 4

Recentemente migrei uma aplicação que estava no Glassfish 3.1.x para o Glassfish 4.x e com alguns ajustes a aplicação voltou a funcionar normalmente, exceto os logs… Não aparecia nenhuma mensagem no arquivo de log.

Observando os arquivos de log do Glassfish quando a aplicação era disponibilizada foi possível ver a algumas mensagens de erro do Log4j como por exemplo:

SEVERE: 
  log4j:ERROR A "org.apache.log4j.<wbr />RollingFileAppender" object is not assignable to a "org.apache.log4j.Appender" variable.
SEVERE: 
  log4j:ERROR The class "org.apache.log4j.Appender" was loaded by
SEVERE: 
  log4j:ERROR [WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)<wbr />] whereas object of type
SEVERE: 
  log4j:ERROR "org.apache.log4j.<wbr />RollingFileAppender" was loaded by [WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)<wbr />].
SEVERE: 
  log4j:ERROR Could not instantiate appender named "FILE".
SEVERE: 
  log4j:ERROR A "org.apache.log4j.<wbr />ConsoleAppender" object is not assignable to a "org.apache.log4j.Appender" variable.
SEVERE: 
  log4j:ERROR The class "org.apache.log4j.Appender" was loaded by
SEVERE: 
  log4j:ERROR [WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)<wbr />] whereas object of type
SEVERE: 
  log4j:ERROR "org.apache.log4j.<wbr />ConsoleAppender" was loaded by [WebappClassLoader (delegate=true; repositories=WEB-INF/classes/)<wbr />].
2015-04-01T15:01:18.349-0300 
SEVERE: 
  log4j:ERROR Could not instantiate appender named "STDOUT".
  log4j: Parsing for [org.hibernate.type] with value=[ERROR].

Ficou claro que estava ocorrendo um erro de classloader mas por quê?

A resposta é relativamente simples porém complexa.

No Glassfish 3.1.x ao realizar o deploy de uma aplicação ele cria um diretório temporário e utiliza esse diretório como classloader independente enquanto faz o deploy, ao final do deploy esse diretório é removido.

Já no Glassfish 4.x houve uma mudança interna que não utiliza mais o conceito de criar um classloader independente, dessa forma ele carrega algumas classes do Log4j antes de carregar e iniciar o Log4j que está no WEB-INF/lib da aplicação e por isso ocorre o erro.

Solução

Colocar o jar do Log4j no diretório lib do domínio onde se deseja realizar o deploy. Dessa forma o Glassfish 4 carrega todas as classes necessárias do Log4j e ele funciona normalmente.

É possível colocar o jar do Log4j para ser compartilhado no classpath do Glassfish entre vários domínios, mas é algo que particularmente eu evito fazer, prefiro fazer isso somente quando necessário.

Publicado em Glassfish | Marcado com , | Deixe um comentário

Error parsing file no Netbeans

Um dos erros mais comuns que acontecem com o Netbeans é o famigerado “Error parsing file”, bastante conhecido na internet e no bugzilla do Netbeans.

Apesar de ser um erro bastante comum e relativamente antigo parece que afeta até a última versão, a 8.0.1.

Na IDE alguns arquivos podem ficar sobrepostos com um ícone de exclamação e a mensagem: Error parsing file, ai você abre o arquivo e descobre que não tem nada de errado com ele.

Qual a solução para remover esses erros?

– Apagar o cache do Netbeans.

No Windows o local é: C:\Users\<usuário>\AppDataLocal\Cache

No Linux: /home/<usuário>/.cache/netbeans/

No Mac: /Users/<usuário>/Library/Caches/NetBeans

Até a próxima.

Publicado em IDE | Marcado com | 1 Comentário

Migrando do Hibernate 3 para Hibernate 4 no Glassfish 4

Além do guava que falei aqui, outro ponto da minha aplicação que não funcionou quando migrei do Glassfish 3.1.2.2 para o Glassfish 4 foi o Hibernate.

Ao fazer o deploy a mensagem abaixo era exibida:

Caused by: java.lang.AbstractMethodError: org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(Ljavax/persistence/SynchronizationType;Ljava/util/Map;)Ljavax/persistence/EntityManager;

Após algumas pesquisas cheguei a esse link: https://hibernate.atlassian.net/browse/HHH-8308

Como conclusão foi possível observar que o Hibernate possui suporte para JPA 2.0 até as versão 4.2 e o Glassfish provê suporte somente para a versão 2.1+, dessa forma seria necessário apenas atualizar o Hibernate para a versão 4.3.x.

Após atualizar para a versão 4.3.5.Final do Hibernate o deploy foi realizado com sucesso, mas agora ao acessar a aplicação ocorria outro erro no log do Glassfish:

java.lang.NullPointerException
     at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.getStatus(JtaStatusHelper.java:73)
     at org.hibernate.engine.transaction.internal.jta.JtaStatusHelper.isActive(JtaStatusHelper.java:115)
    at org.hibernate.engine.transaction.internal.jta.CMTTransaction.join(CMTTransaction.java:149)
    at org.hibernate.ejb.AbstractEntityManagerImpl.joinTransaction(AbstractEntityManagerImpl.java:1204)
     at org.hibernate.ejb.AbstractEntityManagerImpl.postInit(AbstractEntityManagerImpl.java:175)
     at org.hibernate.ejb.EntityManagerImpl.<init>(EntityManagerImpl.java:90)
     at org.hibernate.ejb.EntityManagerFactoryImpl.createEntityManager(EntityManagerFactoryImpl.java:111)

Encontrei esse link que falava da propriedade “hibernate.transaction.jta.platform“. Então eis que encontro a explicação na documentação do Hibernate, ou seja, a partir da versão 4 do Hibernate é necessário especificar a “plataforma” JTA que será utilizada. Cada servidor de aplicação possui uma plataforma diferente, o que na minha opinião tira um pouco da “portabilidade” do Hibernate já que eu eu preciso configurar um persistence.xml para cada plataforma específica, a lista das plataformas suportadas pode ser visualizada na documentação ou no javadoc da API.

No caso do Glassfish bastou adicionar o seguinte atributo ao persistence.xml da aplicação:

<property name="hibernate.transaction.jta.platform"
value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform"/>

Era isso por hoje.

Publicado em Desenvolvimento | Marcado com , | Deixe um comentário

guava no Glassfish 4

Recentemente tive que migrar uma aplicação que estava disponibilizada na versão 3.1.2.2 do Glassfish para a versão 4, ao fazer o deploy me deparei com a seguinte mensagem de erro no log do Glassfish:

CDI deployment failure:WELD-001408 Unsatisfied dependencies for type [Set<Service>] with qualifiers [@Default] at injection point [[BackedAnnotatedParameter] Parameter 1 of [BackedAnnotatedConstructor] @Inject com.google.common.util.concurrent.ServiceManager(Set<Service>)]

Pesquisando um pouco descobri que o problema estava relacionado com a biblioteca guava.jar que estava presente no WAR da aplicação que eu estava tentando fazer deploy. Acontece que na versão 4 do Glassfish esse jar foi adicionado aos módulos do servidor e por tanto já está disponível no classpath.

Para realizar o deploy basta remover o guava.jar do WAR da aplicação.

Utilizando o Maven descobri qual era a dependência que estava fazendo o uso do guava e bastou excluí-la da dependência com a seguinte configuração:


<exclusions>
    <exclusion>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
    </exclusion>
</exclusions>

Quem depende diretamente da dependência do guava pode alterar o valor da tag scope do Maven para provided ou test, dessa forma a dependência não será adicionada ao WAR.

Até a próxima!

Publicado em Glassfish | 1 Comentário

Lock de tabelas no banco de dados H2

O H2 é um banco de dados open source extremamente rápido e pequeno. Muito utilizado por aplicações Java que necessitam de um banco de dados embarcado, dispensando a configuração e uso de um banco de dados externo a aplicação. Muitas ferramentas utilizam o H2 de forma embarcada,  por ser mais simples e para permitir que o usuário utilize e teste a ferramenta sem se preocupar com a criação e gerenciamento de um banco de dados.

Como em muitos casos o H2 é utilizado para testes somente, é bastante comum realizar o encerramento da ferramenta de forma abrupta, ocasionando o encerramento inesperado por parte do H2. Dessa forma as tabelas podem ficar em lock e da próxima vez quando o banco de dados for iniciado pode ser que ocorra a seguinte mensagem:

org.h2.jdbc.JdbcSQLException: Timeout trying to lock table "USER";

O H2 permite o uso concorrente dos acessos ao banco de dados, porém, em alguns casos pode ocorrer timeout devido a duas ou mais transações estarem esperando um commit, ou seja a tabela está em lock esperando uma ação ser realizada, para permitir um nível maior de concorrência é possível configurar o H2 para tal, essa configuração precisa estar explícita na URL de conexão JDBC ao banco de dados, permitindo assim que o H2 controle o uso do acesso concorrente através de um nível de lock maior nas tabelas. No exemplo da mensagem a tabela “USER” está em lock e o banco de dados não inicia exatamente por esse motivo.

Para resolver isso basta adicionar na URL de conexão JDBC o seguinte: ;MVCC=TRUE

A URL final deve ficar parecida com isso: jdbc:h2:tcp://localhost:9000/nome_banco_de_dados;MVCC=TRUE

Era isso!

 

Publicado em Desenvolvimento | Marcado com , | Deixe um comentário

Erro no deploy com JMS e Glassfish

A utilização de JMS é um prática relativamente comum.

Mas para quem utiliza o Glassfish como servidor pode ser que tenha uma particularidade no meio do caminho, se ao realizar o deploy da aplicação você tiver um problema como o que está logo abaixo não se desespere, pode ser que o problema não esteja no seu código e sim no servidor.

Acontece que o broker do Glassfish gera um arquivo com o nome “lock”, se ocorrer um erro ele marca esse arquivo com um erro e com isso não disponibiliza o serviço de JMS.

Basta remover o arquivo de nome lock que fica dentro do domínio e reiniciá-lo, a sua localização fica em: <glassfish_home>/glassfish/domains/<nome_do_dominio>/imq/instances/imqbroker/

Quem utiliza a ferramenta utilitária imqbrokerd para administrar as filas pode utilizar o seguinte argumento: -reset takeover-then-exit

Fique atento não é porque esse arquivo está lá, que o broker está com um problema, após o reinício do servidor o arquivo será criado novamente pelo Glassfish e isso é normal. A diferença  de tamanho entre o arquivo novo e o arquivo com erro no meu caso foi mínima, o arquivo novo tinha 24 bytes e o arquivo com erro tinha 25 bytes.

Abaixo a stack trace completa do erro, no meu caso o nome da classe era MailSubscriber por isso ela aparece na primeira linha do erro.

INFO: JMS013: end point determine destionation name, Res name: javax.jms.Queue, JNDI name: MailSubscriber descriptor name : {3}
2014-05-06T14:18:02.569-0300 javax.enterprise.resource.resourceadapter.com.sun.enterprise.connectors.inbound
WARNING: RAR8501: Exception during endpoint activation for ra [ jmsra ], activationSpecClass [ com.sun.messaging.jms.ra.ActivationSpec ] : java.lang.NullPointerException
2014-05-06T14:18:02.569-0300 javax.enterprise.system.container.ejb.mdb.com.sun.ejb.containers
SEVERE: MDB00017: [MailSubscriber]: Exception in creating message-driven bean container: [java.lang.Exception]
2014-05-06T14:18:02.569-0300 javax.enterprise.system.container.ejb.mdb.com.sun.ejb.containers
SEVERE: java.lang.Exception
java.lang.Exception
    at com.sun.enterprise.connectors.inbound.ConnectorMessageBeanClient.setup(ConnectorMessageBeanClient.java:233)
    at com.sun.ejb.containers.MessageBeanContainer.<init>(MessageBeanContainer.java:205)
    at com.sun.ejb.containers.ContainerFactoryImpl.createContainer(ContainerFactoryImpl.java:121)
    at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:230)
    at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:305)
    at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:108)
    at org.glassfish.internal.data.ModuleInfo.load(ModuleInfo.java:186)
    at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:264)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:460)
    at com.sun.enterprise.v3.server.ApplicationLoaderService.processApplication(ApplicationLoaderService.java:375)
    at com.sun.enterprise.v3.server.ApplicationLoaderService.postConstruct(ApplicationLoaderService.java:219)
    at com.sun.hk2.component.AbstractCreatorImpl.inject(AbstractCreatorImpl.java:131)
    at com.sun.hk2.component.ConstructorCreator.initialize(ConstructorCreator.java:91)
    at com.sun.hk2.component.AbstractCreatorImpl.get(AbstractCreatorImpl.java:82)
    at com.sun.hk2.component.SingletonInhabitant.get(SingletonInhabitant.java:67)
    at com.sun.hk2.component.EventPublishingInhabitant.get(EventPublishingInhabitant.java:139)
    at com.sun.hk2.component.AbstractInhabitantImpl.get(AbstractInhabitantImpl.java:78)
    at com.sun.enterprise.v3.server.AppServerStartup.run(AppServerStartup.java:253)
    at com.sun.enterprise.v3.server.AppServerStartup.doStart(AppServerStartup.java:145)
    at com.sun.enterprise.v3.server.AppServerStartup.start(AppServerStartup.java:136)
    at com.sun.enterprise.glassfish.bootstrap.GlassFishImpl.start(GlassFishImpl.java:79)
    at com.sun.enterprise.glassfish.bootstrap.GlassFishDecorator.start(GlassFishDecorator.java:63)
    at com.sun.enterprise.glassfish.bootstrap.osgi.OSGiGlassFishImpl.start(OSGiGlassFishImpl.java:69)
    at com.sun.enterprise.glassfish.bootstrap.GlassFishMain$Launcher.launch(GlassFishMain.java:117)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.sun.enterprise.glassfish.bootstrap.GlassFishMain.main(GlassFishMain.java:97)
    at com.sun.enterprise.glassfish.bootstrap.ASMain.main(ASMain.java:55)
Caused by: java.lang.NullPointerException
    at com.sun.messaging.jms.ra.DirectConnectionFactory._createConnectionId(DirectConnectionFactory.java:424)
    at com.sun.messaging.jms.ra.DirectConnectionFactory._createConnection(DirectConnectionFactory.java:522)
    at com.sun.messaging.jms.ra.EndpointConsumer.createDirectMessageConsumer(EndpointConsumer.java:752)
    at com.sun.messaging.jms.ra.EndpointConsumer._init(EndpointConsumer.java:306)
    at com.sun.messaging.jms.ra.EndpointConsumer.<init>(EndpointConsumer.java:185)
    at com.sun.messaging.jms.ra.ResourceAdapter.endpointActivation(ResourceAdapter.java:478)
    at com.sun.enterprise.connectors.inbound.ConnectorMessageBeanClient.setup(ConnectorMessageBeanClient.java:225)
    ... 29 more
2014-05-06T14:18:02.570-0300 javax.enterprise.system.core.com.sun.enterprise.v3.server
SEVERE: Exception while invoking class org.glassfish.ejb.startup.EjbDeployer load method
java.lang.RuntimeException: EJB Container initialization error
    at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:242)
    at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:305)
    at org.glassfish.ejb.startup.EjbDeployer.load(EjbDeployer.java:108)
    at org.glassfish.internal.data.ModuleInfo.load(ModuleInfo.java:186)
    at org.glassfish.internal.data.ApplicationInfo.load(ApplicationInfo.java:264)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:460)
    at com.sun.enterprise.v3.server.ApplicationLoaderService.processApplication(ApplicationLoaderService.java:375)
    at com.sun.enterprise.v3.server.ApplicationLoaderService.postConstruct(ApplicationLoaderService.java:219)
    at com.sun.hk2.component.AbstractCreatorImpl.inject(AbstractCreatorImpl.java:131)
    at com.sun.hk2.component.ConstructorCreator.initialize(ConstructorCreator.java:91)
    at com.sun.hk2.component.AbstractCreatorImpl.get(AbstractCreatorImpl.java:82)
    at com.sun.hk2.component.SingletonInhabitant.get(SingletonInhabitant.java:67)
    at com.sun.hk2.component.EventPublishingInhabitant.get(EventPublishingInhabitant.java:139)
    at com.sun.hk2.component.AbstractInhabitantImpl.get(AbstractInhabitantImpl.java:78)
    at com.sun.enterprise.v3.server.AppServerStartup.run(AppServerStartup.java:253)
    at com.sun.enterprise.v3.server.AppServerStartup.doStart(AppServerStartup.java:145)
    at com.sun.enterprise.v3.server.AppServerStartup.start(AppServerStartup.java:136)
    at com.sun.enterprise.glassfish.bootstrap.GlassFishImpl.start(GlassFishImpl.java:79)
    at com.sun.enterprise.glassfish.bootstrap.GlassFishDecorator.start(GlassFishDecorator.java:63)
    at com.sun.enterprise.glassfish.bootstrap.osgi.OSGiGlassFishImpl.start(OSGiGlassFishImpl.java:69)
    at com.sun.enterprise.glassfish.bootstrap.GlassFishMain$Launcher.launch(GlassFishMain.java:117)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at com.sun.enterprise.glassfish.bootstrap.GlassFishMain.main(GlassFishMain.java:97)
    at com.sun.enterprise.glassfish.bootstrap.ASMain.main(ASMain.java:55)
Caused by: java.lang.Exception
    at com.sun.enterprise.connectors.inbound.ConnectorMessageBeanClient.setup(ConnectorMessageBeanClient.java:233)
    at com.sun.ejb.containers.MessageBeanContainer.<init>(MessageBeanContainer.java:205)
    at com.sun.ejb.containers.ContainerFactoryImpl.createContainer(ContainerFactoryImpl.java:121)
    at org.glassfish.ejb.startup.EjbApplication.loadContainers(EjbApplication.java:230)
    ... 26 more
Caused by: java.lang.NullPointerException
    at com.sun.messaging.jms.ra.DirectConnectionFactory._createConnectionId(DirectConnectionFactory.java:424)
    at com.sun.messaging.jms.ra.DirectConnectionFactory._createConnection(DirectConnectionFactory.java:522)
    at com.sun.messaging.jms.ra.EndpointConsumer.createDirectMessageConsumer(EndpointConsumer.java:752)
    at com.sun.messaging.jms.ra.EndpointConsumer._init(EndpointConsumer.java:306)
    at com.sun.messaging.jms.ra.EndpointConsumer.<init>(EndpointConsumer.java:185)
    at com.sun.messaging.jms.ra.ResourceAdapter.endpointActivation(ResourceAdapter.java:478)
    at com.sun.enterprise.connectors.inbound.ConnectorMessageBeanClient.setup(ConnectorMessageBeanClient.java:225)
    ... 29 more
2014-05-06T14:18:02.571-0300 javax.enterprise.system.core.com.sun.enterprise.v3.server
SEVERE: Exception while loading the app

Era isso!

Publicado em Desenvolvimento | Marcado com , | Deixe um comentário