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

sexta-feira, 23 de abril de 2010

sexta-feira, 20 de março de 2009

"Injetando" funcionalidades nas páginas do JBoss Portal

Este é meu segundo Post sobre JBoss Portal neste ano, e irá abordar uma forma diferenciada de "injetar" determinada funcionalidade a uma área do layout do seu site usando AOP com uma implementação de JBossInterceptor.

O JBoss Portal disponibiliza uma API de Injeção de Dependências onde é possível criar interceptadores a partir da classe abstrata JBossInterceptor. A classe ControllerInterceptor (q extends JBossInterceptor), é utilizada como base para adicionar segurança em commands, navegação, menus, header, dashboard, etc...
É possível criar seu Aspecto para o JBoss Portal herdando ControllerInterceptor e criando seu método invoke.

Para exemplificar, iremos adicionar um título ao layout do Portal utilizando o nome de cada página criado via interface administrativa em uma área pré-definida no layout utilizando o Interceptador PageCustomizerInterceptor, o qual já está sendo utilizado para outros fins. Resumindo, iremos alterar o PageCustomizerInterceptor para que a partir dele os títulos sejam incluídos dinamicamente.

O Código 1 define o MBean PageCustomizer com o atributo Title, onde é passado o Path da página que irá exibir o Título da página.

Código 1
   <mbean code="org.jboss.portal.core.aspects.controller.PageCustomizerInterceptor"
name="portal:service=Interceptor,type=Command,name=PageCustomizer" xmbean-dd=""
xmbean-code="org.jboss.portal.jems.as.system.JBossServiceModelMBean">
<xmbean/>
<attribute name="TargetContextPath">/portal-core</attribute>
<attribute name="HeaderPath">/WEB-INF/jsp/header/header.jsp</attribute>
<attribute name="TabsPath">/WEB-INF/jsp/header/tabs.jsp</attribute>
<attribute name="Breadcrumbs">/WEB-INF/jsp/header/breadcrumbs.jsp</attribute>
<attribute name="Title">/WEB-INF/jsp/header/title.jsp</attribute>
<!-- Overrides the value of core.login.namespace in config.xml --><!-- attribute name="LoginNamespace">dashboard</attribute -->
<depends optional-attribute-name="Config" proxy-type="attribute">portal:service=ServerConfig</depends>
<depends optional-attribute-name="PortalAuthorizationManagerFactory" proxy-type="attribute">
portal:service=PortalAuthorizationManagerFactory
</depends>
<depends optional-attribute-name="PortalObjectContainer" proxy-type="attribute">portal:container=PortalObject
</depends>
</mbean>

O Código 2 mostra a customização da classe PageCustomizerInterceptor onde foi criado o atributo de classe privado chamado title e seus métodos get e set. Este atributo está associado ao Title definido no MBean e será utilizado pelo método injectTitle para fazer o redirecionamento para o jsp de exibição do título. Além disso, o método injectTitle também adiciona dois atributos a requisição: org.jboss.portal.api.PORTAL_NODE e org.jboss.portal.api.PORTAL_RUNTIME_CONTEXT, com valor do Nó corrente e do contexto respectivamente. O método invoke é utilizado para montar a página com suas respectivas propriedades.

Código 2
public class PageCustomizerInterceptor extends ControllerInterceptor {
...

/** title */
private String title;

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

...

public ControllerResponse invoke(ControllerCommand cmd) throws Exception {
ControllerResponse resp = (ControllerResponse)cmd.invokeNext();

// Insert navigation portlet in the page
if (resp instanceof PageRendition) {
PageRendition rendition = (PageRendition)resp;

if (cmd instanceof PageCommand) {
PageCommand rpc = (PageCommand)cmd;

String tabbedTitle = injectTitle(rpc);
if (tabbedTitle != null) {
Map windowProps = new HashMap();
windowProps.put(ThemeConstants.PORTAL_PROP_WINDOW_RENDERER, "emptyRenderer");
windowProps.put(ThemeConstants.PORTAL_PROP_DECORATION_RENDERER, "emptyRenderer");
windowProps.put(ThemeConstants.PORTAL_PROP_PORTLET_RENDERER, "emptyRenderer");
WindowResult res = new WindowResult("", tabbedTitle, Collections.EMPTY_MAP, windowProps, null, WindowState.NORMAL, Mode.VIEW);
WindowContext blah = new WindowContext("BLAH", "tituloPrincipal", "0", res);
rendition.getPageResult().addWindowContext(blah);

//
Region region = rendition.getPageResult().getRegion2("tituloPrincipal");
DynaRenderOptions.NO_AJAX.setOptions(region.getProperties());
}
}
}

return resp;
}

...

public String injectTitle(PageCommand rpc) {
ControllerContext controllerCtx = rpc.getControllerContext();
ControllerRequestDispatcher rd = controllerCtx.getRequestDispatcher(targetContextPath, title);

if (rd != null) {
Page page = rpc.getPage();
PortalAuthorizationManager pam = portalAuthorizationManagerFactory.getManager();
PortalNodeImpl node = new PortalNodeImpl(pam, page);

rd.setAttribute("org.jboss.portal.api.PORTAL_NODE", node);
rd.setAttribute("org.jboss.portal.api.PORTAL_RUNTIME_CONTEXT", Navigation.getPortalRuntimeContext());

rd.include();
return rd.getMarkup();
}

return null;
}

...

}

O Código 3 mostra o JSP que exibe o título da página.

Código 3
<%@ page import="org.jboss.portal.api.node.PortalNode" %>
<%@ page import="java.util.Locale" %>
<%
PortalNode node = (PortalNode)request.getAttribute("org.jboss.portal.api.PORTAL_NODE");

// Get a locale
Locale locale = request.getLocale();
if (locale == null)
{
locale = Locale.getDefault();
}
%>
<%= node.getDisplayName(locale) %>

O Código 4 mostra a chamada a taglib para encaixar o título no layout desejado.

Código 4
<p:region regionName='tituloPrincipal' regionID='tituloPrincipal'/>


Considerações finais
Este post tratou uma forma flexível de inclusão de funcionalidades ao layout do JBoss Portal. Atualmente já é utilizada para outras áreas, mas, além da inclusão de títulos dinâmicos, pode ser totalmente adaptada para inclusão de breadcrumbs, por exemplo, principalmente para evitar ter que incluir seu respectivo Portlet em todas as páginas necessárias manualmente, economizando tempo precioso de desenvolvimento.

sexta-feira, 23 de janeiro de 2009

Lançamento JBossBrasil.ORG!


Na última quarta-feira, 21 de janeiro de 2009, aconteceu o lançamento da comunidade JBossBrasil.ORG. O evento foi apresentado no auditório da GlobalCode. É um grande incentivo ao aprendizado, troca de idéias e boas práticas das ferramentas JBoss.
É uma iniciativa muito importante para nós Brasileiros para que possamos contribuir cada vez mais a ferramentas Open Source.

Durante a primeira apresentação, Leandro Lima - um dos embaixadores da comunidade - mostrou os principais objetivos da comunidade e esclareceu dúvidas sobre o que é e o que não é a comunidade.

A noite também contou com a participação especial de Chris Morgan que é Senior Marketing Manager da plataforma JON, apresentando as ferramentas JON, Jopr e Embedded Jopr e suas diferenças.

Foi uma noite importante para a comunidade JBoss e principalmente para todos que puderam participar.

Veja as fotos em:
http://www.flickr.com/photos/alessandrolazarotti/3217148963/in/set-72157612860854836/

Notícias sobre o lançamento:

http://jbossbrasil.ning.com/forum/topics/lancamento-do-jbossbrasilorg

http://edgarsilva.com.br/2009/01/15/lancamento-dia-21-da-comunidade-jbossbrasil-em-sao-paulo/

http://www.leandrolima.eti.br/

http://br-linux.org/2009/red-hat-patrocina-lancamento-da-comunidade-jbossbrasilorg/

quarta-feira, 21 de janeiro de 2009

Breadcrumbs no JBoss Portal

Estive recentemente em um cliente que precisava adicionar Breadcrumbs em seu site criado em JBoss Portal para facilitar a navegação do usuário. Apenas para esclarecer um pouco antes de começar a parte técnica, Breadcrumb é um esquema de navegação o qual tem por objetivo mostrar o rastro, ou o caminho, percorrido em uma árvore de navegação de um site até chegar em sua página atual.

Imaginem que para entrar na página de seguros de um carro o caminho seja:

Home > Produtos > Seguros > Automóvel > Valor de Veículos

O caminho acima é um Breadcrumb!!! Na verdade, estamos apenas colocando um nome a uma coisa que todo mundo utiliza em sites e é vastamente conhecido. As pessoas que dedicam seu tempo em arquitetura de informação não teriam problemas com o termo "Breadcrumbs", porém, para nós meros mortais desenvolvedores de software especialmente em Java (JEE) acaba sendo um termo novo.

Recomendo fortemente a leitura de alguns artigos no site do Guilhermo Reis http://www.guilhermo.com para mais informações sobre arquitetura de informações.

Após esta breve introdução, iremos a focar na criação de Breadcrumbs para o JBoss Portal, o qual infelizmente ainda não conta com uma solução "bate-e-pronto".

Basicamente toda e qualquer página no seu portal é uma instância de PortalNode. Você pode verificar como exemplo a página
jboss-portal.sar/portal-core.war/WEB-INF/jsp/header/tabs.jsp
que é responsável em criar o menu superior original do JBoss Portal.

Veja abaixo um trecho de código retirado da tabs.jsp:

PortalNode root = (PortalNode)request.getAttribute("org.jboss.portal.api.PORTAL_NODE");
PortalNode portal = root;
PortalNode mainPage = portal;

while (portal.getType() != PortalNode.TYPE_PORTAL)
{
mainPage = portal;
portal = portal.getParent();
}

O código acima obtém o PORTAL_NODE (página) corrente e faz um loop obtendo seu "nó pai" ou "parent" até chegar em um PortalNode do tipo Portal.

Um PortalNode pode ser qualquer instância de Página, Portal, Contexto e Janela. A diferenciação de cada um deles é realizada com as constantes PortalNode.TYPE_PAGE, PortalNode.TYPE_CONTEXT, PortalNode.TYPE_PORTAL e PortalNode.TYPE_WINDOW.

Um dos grandes problemas que senti ao criar os Breadcrumbs foi a obtenção da página corrente em um .jsp ou em um Portlet. Infelizmente, não descobri uma forma fácil de obter isso diretamente no .jsp.

Uma das sacadas para inclusão do breadcrumb seria reaproveitar a tag p:region adicionando um nome para a região e um regionID, assim como é realizado atualmente para o dashboardnav e o navigation sendo incluída diretamente em seu layout, e utilizar Aspectos para inclui-lo dinamicamente em todas as ocorrências de p:region breadcrumb, por exemplo.

Outra forma de criar breadcrumb é desenvolver um Portlet e adiciona-lo manualmente nas páginas que deseja inclui-lo. Neste primeiro post irei mostrar apenas como criar um Portlet para o breadcrumb.

Abordagem com Portlet

O código fonte abaixo mostra o Portlet BreadCrumbsPortlet o qual herda de JBossPortlet, disponibilizando o request e o response no formato de JBossRenderRequest e JBossRenderResponse, o que irá facilitar a obtençao de PortalNodes.

public class BreadCrumbsPortlet extends JBossPortlet {

private static final String VIEW = "/WEB-INF/jsp/breadcrumb/view.jsp";

@Override
public void processAction(JBossActionRequest request, JBossActionResponse response) throws PortletException, IOException {

response.setPortletMode(PortletMode.VIEW);
return;
}

@Override
protected void doView(JBossRenderRequest request, JBossRenderResponse response) throws PortletException, IOException, UnavailableException {

response.setContentType("text/html");

//portlet utilizado
PortalNode node = request.getPortalNode();

List l = new ArrayList();

//portal node
while (node.getType() != PortalNode.TYPE_PORTAL) {
if (node.getType() == PortalNode.TYPE_PAGE) {
l.add(node);
}

node = node.getParent();
}

Object[] array = l.toArray();
List nodes = new ArrayList();
for (int i = array.length - 1; i >= 0 ; i--) {
nodes.add((PortalNode)array[i]);
}

request.setAttribute("org.jboss.portal.api.PORTAL_RUNTIME_CONTEXT", Navigation.getPortalRuntimeContext());
request.setAttribute("list", nodes);

PortletRequestDispatcher prd = getPortletContext().getRequestDispatcher(VIEW);
prd.include(request, response);
}
}

O método doView basicamente obtém o PortalNode corrente e vai adicionando cada um dos seus "parents" em uma lista, até chegar em um PortalNode que seja TYPE_PORTAL. Em seguida faz uma nova iteração ordenando na forma inversa e adicionando em uma lista de PortalNodes que será enviada para a tela.

O view.jsp irá apenas exbir os PortalNodes que já estão ordenados na tela adicionando links.

<%@ taglib uri="http://java.sun.com/portlet" prefix="portlet" %>

<%@ page import="java.util.ArrayList" %>
<%@ page import="java.util.List" %>
<%@ page import="java.util.Locale" %>
<%@ page import="java.util.Iterator" %>
<%@ page import="org.jboss.portal.api.node.PortalNode" %>
<%@ page import="org.jboss.portal.api.PortalRuntimeContext" %>

<portlet:defineObjects/>

<% String contextPath = renderResponse.encodeURL(renderRequest.getContextPath()); %>

<%

PortalRuntimeContext context = (PortalRuntimeContext)request.getAttribute("org.jboss.portal.api.PORTAL_RUNTIME_CONTEXT");

// Get a locale
Locale locale = request.getLocale();
if (locale == null)
{
locale = Locale.getDefault();
}

List l = (List)request.getAttribute("list");
Iterator iterator = l.iterator();
while (iterator.hasNext())
{
PortalNode node = (PortalNode)iterator.next();
%>
<a href="<%= node.createURL(context) %>"><%= node.getDisplayName(locale) %></a> <% if (iterator.hasNext()) { %> / <% } %>
<%
}
%>


Para fazer com que este Portlet funcione no JBoss Portal 2.7 ou superior, é necessário criar um filtro, conforme o link http://docs.jboss.org/jbportal/v2.7.0.B1/referenceGuide/html/changelog.html. Um exemplo do portlet.xml está abaixo:

<portlet-app
xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd"
version="2.0">


<filter>
<filter-name>JBossPortletFilter</filter-name>
<filter-class>org.jboss.portlet.filter.JBossPortletFilter</filter-class>
<lifecycle>ACTION_PHASE</lifecycle>
<lifecycle>RENDER_PHASE</lifecycle>
</filter>

<filter-mapping>
<filter-name>JBossPortletFilter</filter-name>
<portlet-name>BreadCrumbsPortlet</portlet-name>
</filter-mapping>

<portlet>
<description>Simple portlet to create breadcrumbs</description>
<portlet-name>BreadCrumbsPortlet</portlet-name>
<portlet-class>com.jboss.breadcrumb.BreadCrumbsPortlet</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<supported-locale>en</supported-locale>
<supported-locale>pt_BR</supported-locale>
<resource-bundle>BreadCrumbsResource</resource-bundle>
<portlet-info>
<title>BreadCrumb</title>
<keywords>breadcrumb, breadcrumbs</keywords>
</portlet-info>
</portlet>
</portlet-app>


Feito isto, faça o deploy do Portlet em seu JBoss Portal e adicione-o nas páginas que deseja.

quarta-feira, 26 de novembro de 2008

Jopr!!! :)

O Jopr é uma ferramenta de gerenciamento e monitoração que permite "cuidar"de forma centralizada de diferentes servidores que fazem parte do seu ambiente. Resumindo, facilita a manutenção, testes, deployment e monitoração de JBoss AS, Apache, Postgres, Sistema Operacional, File System, etc... etc... etc... além de proporcionar gráficos de disponibilidade e alertas.

O nome Jopr (se pronuncia jopper) foi escolhido baseado no filme Jogos de Guerra (WarGames), onde havia um super computador chamado WOPR (Whopper) - War Operation Plan Response. :)

O Embedded Jopr também é uma ferramenta importante em toda essa história, pois tem foco em apenas 1 instância de JBoss disponibilizando ferramentas para monitorar e manter esta instância em forma gráfica (isso mesmo, gráfica).

Veja algumas referências sobre o Jopr abaixo.
Fórum:
http://www.jboss.com/index.html?module=bb&op=viewforum&f=292

Jopr:
http://www.jboss.org/jopr/

Embedded Jopr:
http://www.jboss.org/embjopr/

WarGames:
http://en.wikipedia.org/wiki/WarGames

Entrevista com Christian Morgan sobre o Jopr
http://www.redhatmagazine.com/2008/10/31/interview-chris-morgan-on-jopr/

Demo do Embedded Jopr:
http://www.jboss.org/embjopr/demo.html

terça-feira, 30 de setembro de 2008

Verificando código das Rules no Drools

Em muitos casos é necessário verificar o códifo fonte referente às Rules do Drools para entender algum erro gerado.
Para isso, utilize o parâmetro de start de VM:
-Ddrools.dump.dir=SEUDIRETORIO


Todos os fontes serão gerados no diretório informado.

Ex.:
package org.acme.fidelity;
import org.acme.fidelity.*;
public class Rule_CartaoBranco_0 {
private static final long serialVersionUID = 400L;
public static void consequence(org.drools.spi.KnowledgeHelper drools, org.acme.fidelity.SolicitacaoPassageiro sol, org.drools.FactHandle sol__Handle__ ) throws Exception {

sol.setCartao(Cartao.BRANCO)

}


}

terça-feira, 19 de agosto de 2008

JBoss Brasil!

Comunidade de usuários JBoss oficial do Brasil foi lançada recentemente pelo Edgar!Vale a pena conferir. http://jbossbrasil.ning.com/



Exibir minha página em JBoss Brasil

segunda-feira, 18 de agosto de 2008

Detectando Connection Leaks no JBoss - Parte 1

Quando o usuário te liga falando as famosas frases:
- "alguma coisa está acontecendo!" ou
- "hummm, a aplicação está estranha!" ou ainda
- "esse JBoss NÃO FUNCIONA! não fecha minhas conexões!" ... hummm "JBoss não fecha suas conexões"? Ok, o JBoss fecha conexões idle (timeout default de 15 minutos), mas até lá já estourou o pool, e olhando o log você verá as mensagens:

15:58:48,931 ERROR [STDERR] org.jboss.util.NestedSQLException: No ManagedConnections available within configured blocking timeout ( 30000 [ms] ); - nested throwable: (javax.resource.ResourceException: No ManagedConnections available within configured blocking timeout ( 30000 [ms] ))


E até que o JBoss é gente fina, ao fechar alguma conexão aberta avisa educadamente para você fazer isso:

16:03:19,135 INFO  [CachedConnectionManager] Closing a connection for you.  Please close them yourself: org.jboss.resource.adapter.jdbc.WrappedConnection@121dcac java.lang.Throwable: STACKTRACE


Mas afinal, em alguns casos a aplicação não loga em modo debug onde está abrindo/fechando as conexões, e em aplicações grandes, ou sem padronização, a tarefa de detectar um gargalo destes torna-se tarefa complicada. Então, como detectar onde está ocorrendo a leak?

Este post tem como objetivo mostrar algumas técnicas para isolar os pontos e atacá-los.

Para fazer esta prova de conceito, criei uma classe que tenta abrir 30 conexões em pool de no máximo 20, fazendo um loop e armazenando-as em um Map.

public class ConnectionLeak {

private static Logger log = Logger.getLogger(ConnectionLeak.class);

private static Map m = new HashMap();

public static void action() {
for (int i = 0; i < 30; i++) {
try {
Context ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup("java:DefaultDS");
Connection c = ds.getConnection();
log.info("Obtendo conexao: " + c + " loop: " + i);
m.put(i, c);
} catch (NamingException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}



Estou logando um toString de cada conexão após abri-la:

16:31:33,444 INFO  [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@41f871 loop: 0
16:31:33,445 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@11df416 loop: 1
16:31:33,446 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@183d60d loop: 2
16:31:33,447 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@5a1e6b loop: 3
16:31:33,447 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@83198c loop: 4
16:31:33,448 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@1025f9f loop: 5
16:31:33,449 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@d3e83f loop: 6
16:31:33,450 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@3492fc loop: 7
16:31:33,450 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@19e0994 loop: 8
16:31:33,451 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@86f847 loop: 9
16:31:33,452 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@1162ab9 loop: 10
16:31:33,453 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@4eda4a loop: 11
16:31:33,465 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@1eab16b loop: 12
16:31:33,466 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@126099c loop: 13
16:31:33,467 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@40eca3 loop: 14
16:31:33,468 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@6fe350 loop: 15
16:31:33,469 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@1b4b415 loop: 16
16:31:33,469 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@9addef loop: 17
16:31:33,470 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@1609812 loop: 18
16:31:33,471 INFO [ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@9fe953 loop: 19

1. Monitore as conexões ativas do seu Datasource
Existem boas ferramentas para realizar uma monitoração efetiva do seu pool de conexões, entre elas está o JON - JBoss Operations Network que além de guardar histórico podendo ser filtrado em horas, dias, meses também gera alertas com ações remediativas e envio de e-mails ou traps SNMP. Porém o JBoss AS disponibiliza o Web Console e o JMX Console que, apesar de não serem tão completos como o JON, podem ser utilizados para um diagnóstico inicial. Abaixo um Screenshot do meu Connection Leak simulado:




2. Habilite o log abaixo no jboss-log4j.xml:

<!-- Show the evolution of the DataSource pool in the logs [inUse/Available/Max]-->
<category name="org.jboss.resource.connectionmanager.JBossManagedConnectionPool">
<priority value="TRACE" class="org.jboss.logging.XLevel"/>
</category>


2008-08-18 16:58:04,460 INFO  [org.jboss.ConnectionLeak] Obtendo conexao: org.jboss.resource.adapter.jdbc.WrappedConnection@4f12c2 loop: 1
2008-08-18 16:58:04,461 TRACE [org.jboss.resource.connectionmanager.JBossManagedConnectionPool] supplying ManagedConnection from pool: org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener@15092c0[state=NORMAL mc=org.jboss.resource.adapter.jdbc.local.LocalManagedConnection@d2883b handles=0 lastUse=1219089352148 permit=false trackByTx=false mcp=org.jboss.resource.connectionmanager.JBossManagedConnectionPool$PoolBySubject@554189 context=org.jboss.resource.connectionmanager.InternalManagedConnectionPool@141a32f xaResource=org.jboss.resource.connectionmanager.TxConnectionManager$LocalXAResource@1ee1775 txSync=null]
2008-08-18 16:58:04,462 TRACE [org.jboss.resource.connectionmanager.JBossManagedConnectionPool] Got connection from pool org.jboss.resource.connectionmanager.TxConnectionManager$TxConnectionEventListener@15092c0[state=NORMAL mc=org.jboss.resource.adapter.jdbc.local.LocalManagedConnection@d2883b handles=0 lastUse=1219089352148 permit=true trackByTx=false mcp=org.jboss.resource.connectionmanager.JBossManagedConnectionPool$PoolBySubject@554189 context=org.jboss.resource.connectionmanager.InternalManagedConnectionPool@141a32f xaResource=org.jboss.resource.connectionmanager.TxConnectionManager$LocalXAResource@1ee1775 txSync=null] [InUse/Available/Max]: [3/17/20]


3. Verifique as conexões em cache
O MBean CachedConnectionManager possui o método listInUseConnections() que permite a verificação das conexões em uso. Pode te dar alguma pista:



to be continued...

terça-feira, 12 de agosto de 2008

JBoss 4.2.3.GA

Pouco antes de sair o tão esperado JBoss 5, foi lançado o JBoss 4.2.3.GA que tem como principal característica, além das correções de bugs referentes à versões anteriores, a possibilidade de ser compilado com Java 6 descrita na Feature Request JBAS-4501.

Vale lembrar que o suporte a JDBC 4 deve ser considerado como modo experimental.

Esta General Availability (GA) foi disponibilizada no dia 18 de julho de 2008 (demorei um pouco para postar...)

Release Notes:
https://sourceforge.net/project/shownotes.php?release_id=614346&group_id=22866

JPS - Process Status Tool

Após alguns longos meses estou voltando a postar nesta madrugada de quarta-feira (13/08/2008) enquanto aguardo a finalização de alguns testes.
Existe uma ferramenta muito útil e de fácil utilização chamada JPS, a qual lista os processos Java startados no seu Sistema Operacional.

Bem melhor que digitar ps aux | grep java! :)

Exemplos:

[bmachado@bmachado ~]$ jps
5343
30286 Jps
30271 Main

[bmachado@bmachado ~]$ jps -l
5343
30456 sun.tools.jps.Jps
30271 org.jboss.Main

[bmachado@bmachado ~]$ jps -m
5343
30529 Main -c node1
30664 Jps -m


Mais informações:
http://java.sun.com/j2se/1.5.0/docs/tooldocs/share/jps.html

terça-feira, 1 de julho de 2008

Open TDC - 2008

No dia 28/06 aconteceu o Open TDC da GlobalCode o qual contou com palestras muito legais sobre JavaSE, JavaEE, metodologias e tendências tecnológicas.

Apresentei a palestra Administração do JBoss Application Server que dava algumas dicas sobre ambiente de produção, performance, tuning, balanceamento de carga e monitoramento de um ambiente utilizando JON (JBoss Operations Network).

Foi uma experiência muito gratificante poder participar de um evento bacana ao lado de pessoas tão bem relacionadas no mercado Java.

Como disse na palestra, só tenho a agradecer a todas as pessoas que compareceram, pois era uma manhã fria de sábado, e mesmo assim estavam lá para assistir palestras sobre Java. :)

Aproveitei para rever alguns amigos das antigas como Dr. Spock que também palestrou no evento.

Valeu Edgar e David pelo apoio e confiança.

Veja algumas fotos abaixo:



Exemplo de balanceamento de carga 2 JBosses com Apache e mod_jk




Lançamento de camisetas


Pessoal pulando para pegar a camiseta :)
Eu, Edgar Silva (Solutions Architect JBoss) e David Barzilay (Gerente de Marketing da Red Hat BR)

Mais fotos aqui.

quarta-feira, 11 de junho de 2008

JBoss Resteasy JAXRS: REST in Peace

Estou aproveitando a noite para colocar alguns posts em dia... obs.: Sport 2x0 Corinthians - Sport bate Corinthians e leva Copa do Brasil pela 1ª vez...

Em um dos dias de consultoria, retornei ao escritório para conversar com o Edgar sobre um dos projetos. Ao chegar, o vi muito empolgado com REST - (JSR 311: JAX-RS: The JavaTM API for RESTful Web Services), que está se tornando cada vez mais popular como alternativa para arquiteturas baseadas em SOAP.

É uma spec que tem por objetivo disponibilizar uma API em Java para o rápido desenvolvimento de REST ful WebServices totalmente baseada em anotações (Java 5).

No fundo, a explicação mais básica para o objetivo da API é uma forma rápida de desenvolver um retorno (que pode ser um XML, Texto, etc) sem precisar saber de Servlets ou JAX-WS, por exemplo... :) ... de forma padronizada. O que torna o desenvolvimento muito produtivo.

Atualmente para implementar REST em Java acaba sendo um pouco sofrível, e esta JSR veio para facilitar e agilizar nossa vida.

Aproveitem para ver um mini-tutorial de fácil entendimento sobre JBoss Resteasy feito pelo Edgar.

JBoss Messaging 2.0 Alpha

Estou meio atrasado com o post sobre o JBoss Messaging 2.0 Alpha, mas vale a intenção :).

Dia 02/06 foi lançada a mais nova versão do JBoss Messaging, a qual tem foco em performance e o principal objetivo é ser a número 1 em providers de mensageria open-source.

Abaixo algumas das principais características:
- Arquitetura 100% baseada em POJOs
- Pode ser executado fora do JBoss AS, ou seja, independente do JBoss AS... não precisa ter o Application Server de pé.
- Alta performance utilizando Journal, podendo ser executado via Java NIO ou Linux Asynchronous IO
- Utilização de Apache MINA

Veja algumas comparações com outros providers, incluindo o JBossMQ e ActiveMQ:
http://www.jboss.org/file-access/default/members/jbossmessaging/freezone/docs/userguide-2.0.0.alpha1/html/performance.html#performance.results

Referências:
User Guide: http://www.jboss.org/file-access/default/members/jbossmessaging/freezone/docs/userguide-2.0.0.alpha1/html/index.html
Tim Fox's blog: http://jbossfox.blogspot.com/2008/03/high-performance-persistence-with-jboss.html
Clebert Suconic's Blog: http://clebertsuconic.blogspot.com/2008/05/speeding-up-io-on-files.html