quarta-feira, 4 de setembro de 2013

NameNotFoundException from a ServletContextListener implementation

When I've started migrating some applications from JBoss AS 4.2 to EAP 6.1 I got a really tough behavior making me review all settings and implementations more than once for a while to figure out what was happening.

Basically, there was a ServletContextListener implementation which performs a look up to a Stateless Session Bean in its contextInitialized method. Nothing new, nothing different from what you've already seen...


public void contextInitialized(ServletContextEvent arg0) {

   try {

      Context ctx = new InitialContext();

      Object o = ctx.lookup("java:app/my-ejb/MyBean!com.blogspot.brmachado.service.MyBeanLocal");

      System.out.println(o);

   } catch(Exception e) {

   }

}


I saw all application EJBs being deployed successfully in the log, as well as it's JNDI bindings but even so there were a javax.naming.NameNotFoundException in the contextInitialized method. In AS 4.x and 5.x the application was deployed fine, but why NameNotFoundException was being thrown in EAP 6?

Next step in the troubleshooting process was to verify in the console if the JNDI bind was really there, and it was. Then I create a simple jsp with exaclty the same code and it was able to lookup successfully.

JBoss AS 7 and JBoss EAP 6, differently from the older versions, start all services in parallel and for some reason the Stateless Session Bean hasn't have it's JNDI bind in time. Note that the application.xml was ok, with the ejb jar coming first, even so it seemed that the order wasn't being making a difference:
  <module>
    <ejb>my-ejb.jar</ejb>
  </module>
  <module>
    <web>
      <web-uri>my-web.war</web-uri>
    </web>
  </module>
Then I saw a "light in the end of the tunnel" with the "initialize-in-order" attribute added to application.xml, it forces JBoss to keep the application.xml ordering.

 <initialize-in-order>true</initialize-in-order>

By setting initialize-in-order attribute, ejb.jar was deployed before the .war and the ServletContextListener implementation with the Stateles Session Bean worked just fine.

More about this in the EAP 6 Migration Guide.

Hope it helps you guys to save some time.

terça-feira, 16 de julho de 2013

Using the Knowledge Agent with a ChangeSet.xml file with JBoss BRMS

This is a really simple example of how to use the Knowledge Agent api (aka kagent) to retrieve a compiled package from BRMS (Guvnor) repository.
First of all you need to create your process, in my sample it just has a script task which prints "Hello" in the console by using System.out.println("Hello").
After it, you can built the package:


And then, download the ChangeSet.xml file descriptor containing the repository access info to authenticate and retrieve the package built. In this example, I'm getting the LATEST version of it, as following:


Copy the ChangeSet.xml to your classpath, usually in the src/main/resources of your JBoss Developer Studio project.

Now, you just have to use the KnowledgeAgent to read the ChangeSet.xml, get your KnowledgeBase instance and start the process. See a example below:

public static final void main(String[] args) throws Exception {
    // load up the knowledge base
    KnowledgeBase kbase = readKnowledgeBase();
    StatefulKnowledgeSession ksession = kbase.newStatefulKnowledgeSession();
    // start a new process instance
    ksession.startProcess("brm.process");
}
private static KnowledgeBase readKnowledgeBase() throws Exception {
    final KnowledgeAgent kagent = KnowledgeAgentFactory.newKnowledgeAgent("kagent");    
    ResourceFactory.getResourceChangeNotifierService().start();
    ResourceFactory.getResourceChangeScannerService().start();      
    kagent.applyChangeSet(ResourceFactory.newClassPathResource("ChangeSet.xml"));
    KnowledgeBase kbase = kagent.getKnowledgeBase();
    return kbase;
}

I'm going to upload it to a git as soon as I create one, but in the meanwhile download the MyProject.zip from this post.

Some things you should remember
Add the correct authentication to the ChangeSet.xml. The ChangeSet.xml created by BRMS doesn't come with the  basicAuthentication, username and password attributes. Add them to avoid issues.
  
basicAuthentication="enabled" username="admin" password="admin"
Something that is really common to happen is to thrown a NPE in the client:

Exception in thread "main" java.lang.NullPointerException
 at java.util.AbstractCollection.addAll(AbstractCollection.java:333)
 at org.drools.agent.impl.KnowledgeAgentImpl.addResourcesToKnowledgeBase(KnowledgeAgentImpl.java:1075)
 at org.drools.agent.impl.KnowledgeAgentImpl.rebuildResources(KnowledgeAgentImpl.java:822)
 at org.drools.agent.impl.KnowledgeAgentImpl.buildKnowledgeBase(KnowledgeAgentImpl.java:671)
 at org.drools.agent.impl.KnowledgeAgentImpl.applyChangeSet(KnowledgeAgentImpl.java:201)
 at org.drools.agent.impl.KnowledgeAgentImpl.applyChangeSet(KnowledgeAgentImpl.java:180)
 at com.sample.ProcessMain.readKnowledgeBase(ProcessMain.java:26)
 at com.sample.ProcessMain.main(ProcessMain.java:16)

Followed by 404 in the server:

22:27:41,591 INFO  [TransformerServlet] check connection response code: 404
22:27:46,242 WARN  [ValueConstraint] validation of reference constraint is not yet implemented
22:27:46,500 INFO  [TransformerServlet] create connection response code: 200
22:28:29,448 INFO  [DocNumberCache] size=10/1024, #accesses=1001, #hits=1001, #misses=0, cacheRatio=100%
22:36:59,644 WARN  [RepositoryServlet] Unable to authenticate for rest api: null
If you've already added the correct authentication but you are still seeing the NPE, but without the 404 code, ensure you have the same BRMS jar files in both client and server sides.

Refer to the Knowledge Agent  official documentation for further details.

quarta-feira, 20 de fevereiro de 2013

De volta ao bom e velho Java, mas...

Voltei a ministrar um curso de Java básico, mas desta vez para administradores de servidores de aplicações com conhecimento em JBoss AS e Linux. Meu foco no curso não é formar excelentes programadores, porém trazer uma visão abrangente de Java e Java EE fazendo analogias com os cenários mais comuns de erros de programação utilizando Java em ambientes corporativos. Dentre estes erros, podemos citar OutOfMemory: Heap e Perm, influências de programação, NPE, StackOverFlow, Too Many Open Files, limites de Pools de Threads, erros comuns com JDBC, etc, etc, etc. Hoje vimos Strings x StringBuffers x StringBuilders e suas influências na memória heap, além de condições e laços. Satisfação enorme em ve-los imaginando possíveis formas de travamento súbito da aplicação ou alto consumo de CPU... já comparando com os ambientes que eles possuem.

terça-feira, 15 de janeiro de 2013

Lendo arquivos de propriedades de um .war ou .ear usando módulos no JBoss AS 7

Uma outra possibilidade para ler arquivos .properties no JBoss AS 7 é utilizar módulos. Desta forma, será possível obter o arquivo .properties utilizando um simples Thread.currentThread().getContextClassLoader().getResource("...") ou getResourceAsStream("...").

Os passos estão abaixo:

1. Crie um módulo com a seguinte estrutura de diretórios:

{jboss.home}/modules/propriedades/conf/main

2. Crie o arquivo module.xml em {jboss.home}/modules/propriedades/conf/main com o seguinte conteúdo

<module xmlns="urn:jboss:module:1.1" name="propriedades.conf">
    <resources>
        <resource-root path="arquivos"/>
    </resources>
</module>

3. Crie o diretório arquivos na estrutura do módulo:

{jboss.home}/modules/propriedades/conf/main/arquivos

4. Adicionar o arquivo de propriedades na nova estrutura de diretórios, exemplo:

{jboss.home}/modules/propriedades/conf/main/arquivos/meuarquivo.properties

5. Adicionar o arquivo jboss-deployment-structure.xml no diretório WEB-INF da aplicação .war ([arquivo].war/WEB-INF/jboss-deployment-structure.xml) com o seguinte conteúdo:

<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure>
  <deployment>
    <dependencies>
        <module name="propriedades.conf" />
    </dependencies>
  </deployment>
</jboss-deployment-structure>

Note que propriedades.conf é o nome do módulo criado no passo 2.

Caso esteja utilizando um .ear, adicione o arquivo jboss-deployment-structure.xml no diretório META-INF

6. No código java, você poderá ler os atributos do arquivo .properties conforme abaixo:

Properties properties = new Properties();
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("meuarquivo.properties"))
properties.get("nome-da-propriedade")

sexta-feira, 11 de janeiro de 2013

JBUG Brasil de volta!!!

Clique na imagem abaixo para acessar!

Como ler propriedades java no JBoss AS 7

Voltando ao blog depois de alguns anos sem novos posts. Creio que estou em dívida com ele :). Meu foco nos novos posts será adicionar conteúdo relacionado ao JBoss AS 7.x e novas versões que poderão vir deste servidor de aplicações.

Neste post específico, irei descrever formas de substituir o antigo properties-service.xml dos JBoss AS 4.x e 5.x para o JBoss AS 7.

A princípio, não encontrei nenhum serviço semelhante ao properties-service.xml, porém há diversas formas de contornar isto. Uma delas é passar diversos arquivos .properties em linha de comando durante a inicialização do JBoss.

  ./standalone.sh --properties=arquivo1.properties --properties=arquivo2.properties

Estas propriedades poderão ser lidas como System.getProperty("nome-da-sua-propriedade");

Poderia também ser passado via property no startup ou até mesmo na própria instância via Console Web.

  ./standalone.sh -Dproperty1=value1 -Dproperty2=value2

No próximo post, irei exemplificar outras formas de utilizar arquivos .properties no JBoss AS 7

Esta solução pode ser encontrada no fórum do jboss.org: https://community.jboss.org/message/750465