Parametrização dinâmica Jenkins + git

Precisando deixar a execução de um job do jenkins parametrizado para utilizar uma determinada branch do git. Pesquisei alguns alguns plugins e o mais perto que encontrei foi o “Git Parameter Plugin”, porém ele só faz utilizando as tags e revisions mas a branch teria que ser fixa.
Uma outra opção é utilizar uma listagem padrão do jenkins e a cada branch nova seria necessário editar o job e acrescentar o nome da nova branch.

E como deixar a listagem das branches dinâmicas? acabei criando o seguinte script (listbranch.sh):

#!/bin/bash
#  Script responsavel por  retornar todas as branches remotas de um determinado workspace
# O script consiste em criar um diretório [workspacename] contendo arquivos que representam as branches desse workspace.
# Com os arquivos criados acima pode-se utilizar do plugin "Extensible Choice Parameter plugin" para ler os arquivos gerados e utiliza-los como parametros no build
# A opcao do plugin é a  "File Choice Parameter" (no caso do script os arquivos serao gerados a partir de /jenkins/) configurando o Base Directory como  /jenkins/[workspacename] e o File Name Pattern *como *

if [ "$#" -ne 2 ];then
    echo "Illegal number of parameters $# of 2"
    echo "Use: listbranch.sh [workspacepath] [workspacename]"
    echo "Example: listbranch.sh /jenkins/jobs/NomeDoJob/workspace/  NomeDoRepositorio"
    exit 1
fi

cd $1

# os arquivos serão gerados sempre a partir do diretório /jenkins/
[ -d /jenkins/$2 ] && echo "[$2] Diretorio de $2 existente...Nao precisa ser criado" || mkdir /jenkins/$2

rm -rf /jenkins/$2/*

for branchName in $(git branch -r | cut -d'/' -f 2)
do
 echo  $branchName > /jenkins/$2/$branchName
done

Notem que o script possuem alguns parâmetros… um da workspace ( portanto antes desse cara funcionar preciso do git clone) e o workspacename, pois no nosso caso temos mais de um repositório git no cliente e esse parâmetro servirá para identifica-los.

No jenkins criei dois novos jobs:

  • refresh_branch_list

refresh_branch_list Config  Jenkins

Apenos executo o listbranch.sh que cria/atualiza uma estrura que representará as branches existentes naquele workspace.
O resultado ficaria +- assim
/jenkins/NomeDoRepositorio/
/jenkins/NomeDoRepositorio/branch1
/jenkins/NomeDoRepositorio/branch2
/jenkins/NomeDoRepositorio/branch3
/jenkins/NomeDoRepositorio/master

deixei esse job rodando a cada 2 minutos, assim se criarmos mais uma branch aparecerá como opção de build em até 2 minutos.
Outra abordagem seria criar um cron onde a cada x minutos o listbranch.sh seria executado.

  • build_project

Agora precisamos instalar o plugin capaz de ler esse estrutura criada “Extensible Choice Parameter plugin”

auto_build Config  Jenkins

– no item “File Choice Parameter”: /jenkins/NomeDoRepositorio/
– no item “File Name Pattern”: *
– tem um botão(List Files Now) que você consegue testar o resultado

Com o plugin de parâmetro devidamente configurado é só utilizarmos na configuração do repositório git, conforme abaixo

auto_build_pass_parameter

E no momento de executarmos o job de build temos o seguinte resultado :

build

 

Aplicação EJB 3.1 + JSF2 + PrimeFaces 3.0 + maven, parte 2

Continuando o post anterior link, vou ilustrar parcialmente a implemetação do backingbean / Controller e o serviço que será utilizado.

Inicialmente vamos para a implementação do nosso serviço EJB que será responsável por retornar, neste caso, uma lista de produtos. Importante saber que estarei omitindo a classe que mapeia a entidade Produto (VOProduto) e seus respectivos mapeamentos, ok ?

@Stateless
public class ProdutoBean {


    /**
     * Default constructor.
     */
    public ProdutoBean() {
    }

	@Override
	// a implementação do "dao" esta omitida, use a sua! ou acesse diretamente pelo entity manager! fell free! 
	public List<VOProduto> findAllProduto() {
		return dao.findAll();
	}

}

Lembrando que a estrutura do projeto WEB é a seguinte:

Segue o Web.xml utilizado no projeto.

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">  
    
  <display-name>Projeto</display-name>

    <context-param>
        <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
        <param-value>server</param-value>
    </context-param>
    
    <context-param>
        <param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
        <param-value>true</param-value>
    </context-param>
    
    	
    <context-param>
        <param-name>primefaces.THEME</param-name>
        <param-value>aristo</param-value>
    </context-param>


    <filter>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>PrimeFaces FileUpload Filter</filter-name>
        <servlet-name>Faces Servlet</servlet-name>
    </filter-mapping>

    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.jsf</url-pattern>
    </servlet-mapping>
    

    <welcome-file-list>
    	<welcome-file>index.jsf</welcome-file>
    </welcome-file-list>
</web-app>

Nosso Controller:

@ManagedBean(name="ProdutoController")
@RequestScoped
public class TesteBean {

    @EJB ProdutoBean produtoBean;
	
    List<VOProduto> produtos;

    @PostConstruct
    public void init() {
	produtos = produtoBean.findAllProduto();
    }
}

Agora para finalizar apenas o um trecho da nossa pagina consulta.xhtml utilizando como exemplo o p:dataTable para exibir a lista de Produtos

<p:dataTable value="#{ProdutoController.produtos}"
	var="obj">
	<p:column>
		<f:facet name="header">
			<h:outputText value="Nome do produto" />
		</f:facet>
		<h:outputText value="#{obj.nomeExibicao}" />
	</p:column>
</p:dataTable>

Acabo por aqui este post! Muito Obrigado!

Aplicação EJB 3.1 + JSF2 + PrimeFaces 3.0 + maven, parte 1

A idéia do post é criar um projeto EAR com módulo EJB e WEB. E para este projeto utilizarei o EJ3.1 e JSF2 e PrimeFaces 3.0 sendo gerado pelo maven. A intenção não é mostrar como configurar o maven e suas configurações de ambiente necessárias.

O primeiro passo então é começar as configurações do maven vamos então vamos la para a estrutura do projeto:

Projeto
|____EAR
|____EJB
|____WAR

Por padrão de estrutura de projetos do maven é necessário ter o projeto pai que terá o pom.xml responsável por gerar suas dependencias.

Outro ponto importante é que o projeto WAR deve seguir a seguinte estrutura conforme a especificação do maven-war-plugin estrutura maven-war-plugin.

Projeto : pom.xml

<project>
	<name>Projeto WEB</name>
	<modelVersion>4.0.0</modelVersion>
	<groupId>Projeto</groupId>
	<version>1.0</version>
	<artifactId>projetoPai</artifactId>
	<packaging>pom</packaging>

	<modules>
		<module>EAR</module>
		<module>EJB</module>
		<module>WEB</module>
	</modules>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-ejb-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<ejbVersion>3.1</ejbVersion>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<repositories>
		<repository>
			<id>maven2-repository.dev.java.net</id>
			<name>Java.net Repository for Maven</name>
			<url>http://download.java.net/maven/2</url>
		</repository>

		<repository>
			<id>prime-repo</id>
			<name>Prime Technology Maven Repository</name>
			<url>http://repository.prime.com.tr</url>
			<layout>default</layout>
		</repository>
	</repositories>
</project>

EAR : pom.xml

<project>
	<name>EAR</name>
	<modelVersion>4.0.0</modelVersion>
	<groupId>EAR</groupId>
	<artifactId>EAR</artifactId>
	<packaging>ear</packaging>
	<version>1.0</version>


	<build>
		<plugins>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>2.3.2</version>
				<configuration>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-ejb-plugin</artifactId>
				<version>2.3</version>
				<configuration>
					<ejbVersion>3.1</ejbVersion>
				</configuration>
			</plugin>

			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-ear-plugin</artifactId>
				<version>2.5</version>
				<configuration>
					<displayName>EAR</displayName>
					<modules>
						<webModule>
							<groupId>EAR</groupId>
							<artifactId>WEB</artifactId>
							<contextRoot>/WEB</contextRoot>
						</webModule>
					</modules>
				</configuration>
			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>EAR</groupId>
			<artifactId>EJB</artifactId>
			<version>1.0</version>
			<type>ejb</type>
		</dependency>
		
		<dependency>
			<groupId>EAR</groupId>
			<artifactId>WEB</artifactId>
			<version>1.0</version>
			<type>war</type>
		</dependency>		
	</dependencies>

</project>

EJB : pom.xml

<project>
	<name>EJB</name>
	<modelVersion>4.0.0</modelVersion>
	<groupId>EAR</groupId>
	<artifactId>EJB</artifactId>
	<packaging>ejb</packaging>
	<version>1.0</version>

 	<parent>
		<groupId>Projeto</groupId>
		<artifactId>projetoPai</artifactId>
		<version>1.0</version>
	</parent>
	
	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-ejb-plugin</artifactId>

				<configuration>
					<archive>
						<manifest>
							<addClasspath>true</addClasspath>
						</manifest>
					</archive>
				</configuration>

			</plugin>
		</plugins>
	</build>
	<dependencies>
		<dependency>
			<groupId>javax</groupId>
			<artifactId>javaee-api</artifactId>
			<version>6.0</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>3.6.4.Final</version>
		</dependency>
		<dependency>
			<groupId>javassist</groupId>
			<artifactId>javassist</artifactId>
			<version>3.1</version>
		</dependency>
		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.2</version>
		</dependency>

		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.8.2</version>
			<scope>test</scope>
		</dependency>

	</dependencies>
</project>

WEB:pom.xml

<project>
	<modelVersion>4.0.0</modelVersion>
	<groupId>EAR</groupId>
	<artifactId>WEB</artifactId>
	<packaging>war</packaging>
	<version>1.0</version>
	<name>WEB</name>


	<parent>
		<groupId>Projeto</groupId>
		<artifactId>projetoPai</artifactId>
		<version>1.0</version>
	</parent>

	<dependencies>

		<dependency>
			<groupId>EAR</groupId>
			<artifactId>EJB</artifactId>
			<version>1.0</version>
			<type>jar</type>
		</dependency>
		<dependency>
			<groupId>javax</groupId>
			<artifactId>javaee-api</artifactId>
			<version>6.0</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>2.0.4-b09</version>
		</dependency>

		<dependency>
			<groupId>com.sun.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<version>2.0.4-b09</version>
		</dependency>

		<dependency>
			<groupId>org.primefaces</groupId>
			<artifactId>primefaces</artifactId>
			<version>3.0.M1</version>
		</dependency>


		<dependency>
			<groupId>commons-lang</groupId>
			<artifactId>commons-lang</artifactId>
			<version>2.2</version>
		</dependency>

		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.2.2</version>
		</dependency>

		<dependency>
			<groupId>org.primefaces.themes</groupId>
			<artifactId>aristo</artifactId>
			<version>1.0.1</version>
		</dependency>

	</dependencies>


	<build>
    <plugins>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-war-plugin</artifactId>
        <version>2.1.1</version>
        <configuration>
          <archive>
            <manifest>
              <addClasspath>true</addClasspath>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
		<finalName>WEB</finalName>
	</build>
</project>

Agora é só acessar o diretório Projeto e executar “mvn install” e ver o resultado final.

Inicializando EJB bean no WebSphere Application Server Enterprise 6.1

No projeto que trabalho atualmente existe várias tarefas/funcionalidades que necessitam ser agendada de acordo com as necessidades propostas. No entanto tínhamos uma dúvida… Como e quando agendar essas tarefas assim que a aplicação fosse inicializada? No inicio do desenvolvimento optamos por utilizar ServletContextListener, porém encontramos uma maneira mais prática de chamar um Bean assim que a aplicação fossse inicializada, que é o uso do startup beans que é fornecido pelo WebSphere Application Server Enterprise.

A aplicação é relativamente fácil:
-O bean deve ser um session bean EJB 2.0 com uma interface remota. Onde a interface home deve ser com.ibm.websphere.startupservice.AppStartUpHome.
-A interface do bean remoto deve ser ou extender com.ibm.websphere.startupservice.AppStartUp.
-Os métodos start() e stop() na interface AppStartUp podem ter qualquer atributo de transação exceto TX_MANDATORY.

Um exemplo de como ficaria a configuração do bean de inicialização no ejb-jar.xml do projeto:

<session id="Session_WASStartupBeanPos"></pre>
  <description><![CDATA[]]></description>
  <display-name>WASStartupBeanPos</display-name>
  <ejb-name>WASStartupBeanPos</ejb-name>

    <home>com.ibm.websphere.startupservice.AppStartUpHome</home>
    <remote>com.ibm.websphere.startupservice.AppStartUp</remote>
    <local-home>StartupBeanPosLocalHome</local-home>
    <local>WASStartupBeanPosLocal</local>
    <ejb-class>WASStartupBeanPos</ejb-class>

  <session-type>Stateless</session-type>
  <transaction-type>Container</transaction-type>
</session>

agora suas interfaces e implementações :

public interface WASStartupBeanPosLocal extends javax.ejb.EJBLocalObject {

}
public interface WASStartupBeanPosLocalHome extends javax.ejb.EJBLocalHome
{
   public static final String COMP_NAME="java:comp/env/ejb/WASStartupBeanPosLocal";
   public static final String JNDI_NAME="app/LocalWASStartupBeanPos";

   public WASStartupBeanPosLocal create() throws javax.ejb.CreateException;
}
public class WASStartupBeanPos extends BaseSessionBean implements SessionBean {

private static final Logger logger = Logger.getLogger(WASStartupBeanPos.class.getName());

public void ejbCreate() throws EJBException, RemoteException {
}

public boolean start() {
   logger.logp(Level.FINER, this.getClass().getName(), "start", "starting...");

   // aqui vai o código de inicialização

   logger.logp(Level.FINER, this.getClass().getName(), "start", "started.");
   return true;
}

public void stop() {
   logger.logp(Level.FINER, this.getClass().getName(), "stop", "stoping...");

   logger.logp(Level.FINER, this.getClass().getName(), "stop", "stoped.");
}

}

Após estes passos acima devemos apenas configurar o WebSphere para que ele aceite um o nosso bean de inicialização. Por default essa opção vem desebilitada, mas podemos abilita-la em: Application servers > server1 > Container Services  >Startup beans service ,veja a imagem abaixo:

Desenvolvendo aplicações de alto desempenho em JAVA.

No término do desenvolvimento de uma aplicação, sempre fica aquela dúvida se a aplicação ficou “rápida” ou se suportaria um grande volume de transações e até mesmo se seria “rápida” contendo uma carga intensa de transações.

Não existe uma fórmula mágica para medir o desempenho da aplicação, porém podemos desde o início do desenvolvimento nos preocupar com alguns pontos importantes no desenvolvimento da aplicação.

O que temos que levar em consideração para determinar a performance da aplicação? Uma sugestão simples e na minha opinião, trivial, é sempre analisar métricas de utilização de CPU, throughput (requisições por segundo), tempo de resposta e uso de memória.


Arquitetura

Muitos fatores podem afetar a performance e escalabilidade de uma aplicação, que são: camadas lógicas e físicas, granularidade dos componentes da aplicação, segurança e network (delay de rede), podem porque não também adicionar nessa lista, complexidade na lógica de negócio.

Devemos sempre nos preocupar em não transitar objetos complexos pela aplicação, pois pode impactar no tempo de resposta, principalmente quando a aplicação possui alta granularidade dos componentes resultando em possíveis grandes quantidades de chamadas e/ou acessos remotos. Muitos fatores como acessos latência de rede faz com que chamadas locais sejam mais eficientes. Por outro lado é importante ressaltar que utilizando componentes distribuídos, considerandos até mesmo chamados remotas, podem ter vantagens até mesmo de performance quanto escalabilidade.

O requisito de escalabilidade deve ser visto com muita cautela, pois a performance pode depender de fatores como ambiente operacional e que algumas das vezes caso a escalabilidade seja um requisito muito forte, podemos ter impactos na performance, porém isso não é regra!

Pode sempre existir requisições sendo bloqueada por causa de contenção de recursos ou até mesmo dependência de outro processo. É importante verificar alocações de recursos como tamanho máximo de pool de conexões entre outros sistemas, como banco de dados e outros legados.

Programação e acesso a dados

O acesso a dados e/ou até mesmo acesso a dados de sistemas externos pode aparentar uma tarefa muito simples e que não necessita muita importância. Porém é sempre bom lembrar de alguns pontos para que nossa aplicação não seja comprometida.

Acesso à dados

É indispensável o uso de connection pool para acesso aos dados, o acesso aos bancos de dados deve sempre ser realizando utilizando um pool de conexão e ajustado de acordo com a necessidade ou limitação do ambiente.

A estratégia do uso de connection pool é muito bem vista para que não haja perda de tempo para criação de novas conexões e para controlar a quantidade de acesso ao destino desejado, de maneira que podemos prevenir sobrecarga a aplicações externas.

Sempre otimizar consultas SQL, lembrando que um SQL é sempre melhor que dois, ou seja, analise e aprimore sempre as consultas SQL.

No caso de utilizar frameworks de persistência como hibernate, se atentar ao uso de consultas e analisar muito bem o uso de caches desses frameworks, por exemplo, o uso de query cache é legal, mas qual é freqüência de atualização desses dados que estão na query cache? Lembre-se de que a query cache é síncrona e que toda vez que existir uma atualização, ela é invalidada e recarregada novamente. Ou seja, sempre que passar uma transação que atualize o objeto que esta na query cache você com certeza irá impactar a performance do sistema e o uso de recursos do ambiente computacional, pois a cache sempre será invalidada e carregada novamente e de forma síncrona. Por isso, antes de utilizar qualquer estratégia de cache estude como é o funcionamento e valide!

Uma ótima saída para caches de dados seria utilizar como estratégia alguma ferramenta NoSQL ou de soluções de GRIDs. Hoje existe várias ferramentas que pode auxiliar no desenvolvimento de caches NoSQL onde algumas podem ser vistas em http://nosql-database.org/. Podem auxiliar apenas para montar caches de dados e até mesmo como um repositório de dados distribuídos, onde aumentaria , sem dúvida, a escalabilidade da aplicação.

Lembrando que é sempre bom considerar o uso de caches de dados. São soluções rápidas por diminuir a necessidade de acesso aos dispositivos de armazenamentos, onde aumentaria a performance da aplicação e não sobrecarrega as soluções de armazenamentos de dados.

geração automática de códigos

A analise da real necessidade de utilizar códigos gerados por ferramentas é sempre importante, pois tais ferramentas podem sempre conter trechos de código com alta utilização de memória o que impactaria negativamente nosso aplicativo.

integração de sistemas

Para integrações com sistemas legados podemos utilizar Web Services, JMS, RMI, JCA entre outros mecanismos de integração que o Java fornece. Mas Acessos a sistemas legados desenvolvidos em arquiteturas heterogêneas (possivelmente fora da plataforma Java, incluindo bases de dados), deve ser utilizado JCA(Java EE Connector Architecture). Com JCA podemos garantir a gestão de conexões, transações e segurança, podendo assim viabilizar o requisito de disponibilidade do sistema e controlar cargas de transações para os legados e não os sobrecarregando.

Conclusão

Como sabemos se a aplicação esta performática sem saber como que ela se comportava antes? A boa prática de se ter uma aplicação performática é sempre medir, e após medir é medir novamente para sempre sabermos o ponto de partida e termos comparativos entre alterações e melhorias.

Utilizando scripts Jython para gerenciar recursos no WebSphere Application Server

Uma maneira simples para automatizar tarefas de administração e também monitoramento para WebSphere Application Server é utilizando scripts Jython. Lembrando que a partir da versão 6.1 o uso de jacl é depreciado.
Devemos saber:
Jython:
Jython é uma implementação de Python escrita em Java. Possue uma sintaxe muito limpa e clara, onde os usuários mais experiêntes podem implantar rapidamente novos scripts.

MBeans:
MBeans são os objetos Java que representam os recursos que podem ser gerenciados. A especificação JMX define as APIs e serviços disponíveis para a gestão de aplicação e acompanhamento em Java. Mais informações sobre JMX pode ser encontrada no artigo Sun Microsystems Java Management Extensions (JMX) Visão Geral da Tecnologia (consulte Recursos).
Com os MBeans podemos manipular/monitorar componentes do WebSphere que expõem eventos específicos. São usadas para criar e configurar clusters dinâmicos e para configurar as propriedades de tempo de execução.

Executando os scripts:
Quando você se conecta a uma célula WebSphere, você deve executar wsadmin  conectado a um “deployment manager” em execução. O comando wsadmin pode ser executado com o “deployment manager” não executando? Existe sim como se conectar sem que o “deployment manager” esteja executando, porém deve-se utilizar os parametros “-conntype none”, com isso poderá ser manipulados apenas arquivos de configuração. E obviamente voce não irá conseguir executar remotamente.

Para executar nosso script vamos assumir que os comandos serão executados a partir do diretório <WAS_HOME>/bin onde <WAS_HOME> é o diretório de instalação do WebSphere.

– Executar comandos de scripts contidos em um arquivo com a opção -f. Onde receberá o nome de arquivo como uma entrada e executa os comandos no arquivo. A opção -lang Jython especifica que você está usando Jython.

wsadmin.sh -lang jython -hostname <hostname> -port 8879 -username user -password pass -f profundidadeFila.jython

Este script abaixo é utilizado para ler a profundidade da fila “queue1”.
profundidadeFila.jython:

import  java
def getQueuesDepth():
        lQueues = AdminControl.queryNames('WebSphere:name=queue1,type=SIBQueuePoint,*')
        print AdminControl.getAttribute(lQueues,'depth') // leitura do atributo depth

getQueuesDepth(op)

Na linha 3 estamos instanciando o MBean SIBQueuePoint onde existe expostos os atributos depth e state, ja na linha 4 é impresso o valor do atributo depth.

Para o exemplo acima utilizamos o objeto AdminControl do wasadmin. Porém no wsadmin temos 4 objetos que podem ser utilizados, que são:

  1. AdminApp – manipula aplicações
    Utilizado para manipular aplicações, comandos válidos: install, uninstall, edit e list.
  2. AdminControl – manipular “objetos” (ex, servers)
    Utilizado para criar, remover ou modificar virtual hosts, servers, etc.
  3. AdminConfig – manipular “configurações de objetos”
    Utilizado para criar, remover ou modificar virtual hosts, servers, etc.
  4. Help – self-explanatory

Lembrando que  somente é possivel manipular ou ler informações de MBeans públicos, no link “https://publib.boulder.ibm.com/infocenter/wasinfo/v6r1/topic/com.ibm.websphere.javadoc.doc/public_html/mbeandocs/index.html” podemos viasualizar todas as interfaces dos MBeans públicos existentes no WebSphere Application Server Release 6.1.

Agora é só procurar o MBean que deseja gerenciar e mão na massa!!!!

fontes:
http://www.ibm.com/developerworks/websphere/library/techarticles/0707_lepech/0707_lepech.html
http://www.vm.ibm.com/events/2005-W25.PDF

Hibernate persistindo valores S/N ao invés de Y/N

Estes dias nos deparamos com um problema, já existia um banco de dados sendo usado por outras aplicações, onde todas as tabelas que havia colunas do tipo True/False não poderia ser persistidos com valores  Y/N que o Hibernate utiliza, exigia-se que os valores Booleanos deveriam ser persistidos em português S/N.

Assim, tivemos que fazer algumas mudanças para esse novo comportamento, foi utilizada a anotação TypeDefs para definir o novo tipo a ser utilizado. Abaixo está o exemplo simples para você entender.

package  entity;

import org.hibernate.annotations.Type;
import  javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;

@org.hibernate.annotations.TypeDefs({
@org.hibernate.annotations.TypeDef(name = "sim_nao",
typeClass = SimNaoType.class)})

@Entity
@Table(name = "TBL_USUARIO")
public class  Usuario {
    private Boolean ativo;
    // outros atributos

    @Column(name = "ATIVO", nullable = false, length = 1)
    @Type(type = "sim_nao")
    public Boolean getAtivo(){
        return this.ativo;
    }

    public void setAtivo(Boolean  ativo){
        this.ativo = ativo;
    }

     //setters/getters
}
package entity;

import org.hibernate.type.CharBooleanType;

public class SimNaoType extends CharBooleanType {
    @Override
    protected String getTrueString() {
        return "S";
    }

    @Override
    protected String  getFalseString() {
        return "N";
    }

    @Override
    public String getName() {
        return  "sim_nao";
    }
}

Criando um componente de Popup com JSF e Facelets

É possível criar componentes facelets de forma rápida e simples.
O exemplo a seguir se refere a criação de um componente para ser utilizado em várias páginas do sistema para busca de rua,  o modalPanel do Richfaces é utilizado para apresentar os dados em formato de popup.

Para começar vamos criar o arquivo facelets.taglib.xml em WEB-INF/
Nele criaremos um namespace e daremos o nome para o componente a ser criado:


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE facelet-taglib PUBLIC
"-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
"http://java.sun.com/dtd/web-facesconfig_1_0.dtd">
<facelet-taglib>
<namespace>http://facelets.exemplo.com.br</namespace>
<tag>
<tag-name>popupRua</tag-name>
<source>../taglibs/pesquisaRua.xhtml</source>
</tag>
</facelet-taglib>

Feito isso, vamos adicionar ao web.xml o arquivo criado para que o componente fique disponível


<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>/WEB-INF/facelets.taglib.xml</param-value>
</context-param>

Agora iremos criar o componente propriamente dito criando o arquivo pesquisaRua.xhtml em WebContent/taglibs


<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:c="http://java.sun.com/jstl/core">

<rich:modalPanel id="popupRuaPanel" autosized="true" width="800" height="450" moveable="false" resizeable="false" keepVisualState="true"  >

<f:facet name="header">
<h:outputText value="Pesquisar" />
</f:facet>
<f:facet name="controls">
<h:panelGroup>
<a4j:commandLink action="#{bean.popupBack}" immediate="true">
<h:graphicImage value="/images/ico_close.jpg" id="popupRuaClose"
style="cursor:pointer" styleClass="noborder"
onclick="Richfaces.hideModalPanel('popupRuaPanel')"/>
</a4j:commandLink>
</h:panelGroup>
</f:facet>
<f:view>

 <a4j:form id="popupRuaForm">

 <h:panelGrid columns="1">
 <h:column>
 <h:outputText value="Pesquisar:" />
 <br />
 <h:inputText value="${bean.popupBusca}" size="30" />
 </h:column>
 <h:column>
 <a4j:commandButton value="Pesquisar" action="#{bean.pesquisarRua}" reRender="popupRuaList" />
 </h:column>
 </h:panelGrid>

<!-- mais código para busca e exibição dos dados -->
  </a4j:form>
 </f:view>


</rich:modalPanel>
</ui:composition>

Cuidado: O form do popup não pode estar dentro de outro form !

Pronto ! Feito ! Agora basta adicionar o namespace criado a página que se deseja utilizar o componente e fazer a chamada do popup:

Primeiro adiciona-se o namespace ao composition da página e dá-se uma tag para o mesmo


xmlns:exemploFace="http://facelets.exemplo.com.br"

Depois adiciona-se o componente utilizando a tag criada, neste exemplo estou passando como parâmetro o bean da página para o popup.


<exemploFace:popupRua bean="#{exemploManagedBean}" />

Com o componente adicionado faremos a chamada ao popup desta forma:


<a4j:commandButton value="Buscar"
action="#{exemploManagedBean.prepareBuscaRuaPopup}"
immediate="true"
oncomplete="Richfaces.showModalPanel('popupRuaPanel');"
reRender="popupRuaPanel" />

O managed bean e algumas partes do código deste exemplo foram omitidas por não apresentar nenhuma novidade.  São códigos e  metódos simples para realizar as operações de busca.

Categorias:java2ee, web Tags:, , ,

Utilizando JSF 1.2 + Facelets + RichFaces + JBoss Seam + Apache MyFaces Trinidad.

A intenção do post não será de dar exemplos sobre como utilizar o frameworks, mas sim de configura-los de maneira correta. No projeto que estou trabalhando no momento já utilizamos JSF1.2, Facelets, RichFaces e JBoss Seam sem qualquer problema.

Agora surgiu a necessidade de utilizar componentes de gráficos e alguns recursos como drill-down, após algumas buscas chegamos ao Apache MyFaces Trinidad, porém tivemos alguns problemas de utilizarmos junto com o richfaces e após longas tentativas conseguimos e segue um resumo das configuração utilizadas nos arquivos web.xml, Trinidad-config.xml e faces-config.xml.

Começando pelo web.xml

Configurando o Faces Servlet:

  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.seam</url-pattern>
  </servlet-mapping>
  <context-param>
    <param-name>org.richfaces.SKIN</param-name>
    <param-value>blueSky</param-value>
  </context-param>

Agora são as configurações dos filters, notamos que a ordem dos filtros influenciaram no funcionamento e se alguém conseguir de outra forma não deixem de comentar o post…

  <filter>
    <filter-name>trinidad</filter-name>
    <filter-class>org.apache.myfaces.trinidad.webapp.TrinidadFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>trinidad</filter-name>
    <servlet-name>faces</servlet-name>
  </filter-mapping>

  <filter>
        <display-name>RichFaces Filter</display-name>
        <filter-name>richfaces</filter-name>
        <filter-class>org.ajax4jsf.Filter</filter-class>
  </filter>

  <filter-mapping>
       <filter-name>richfaces</filter-name>
       <servlet-name>Faces Servlet</servlet-name>
       <dispatcher>REQUEST</dispatcher>
       <dispatcher>FORWARD</dispatcher>
       <dispatcher>INCLUDE</dispatcher>
  </filter-mapping>

  <listener>
    <listener-class>org.jboss.seam.servlet.SeamListener</listener-class>
  </listener>

  <filter>
    <filter-name>Seam Filter</filter-name>
    <filter-class>org.jboss.seam.servlet.SeamFilter</filter-class>
  </filter>

  <filter-mapping>
    <filter-name>Seam Filter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>

Configurando os Servlets restantes, ja que a do JSF ja foi configurado anteriormente, não testamos se a ordem de declaração pode influenciar no funcionamento..

  <servlet>
    <servlet-name>Seam Resource Servlet</servlet-name>
    <servlet-class>org.jboss.seam.servlet.SeamResourceServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>Seam Resource Servlet</servlet-name>
    <url-pattern>/seam/resource/*</url-pattern>
  </servlet-mapping>

  <servlet>
    <servlet-name>resources</servlet-name>
    <servlet-class>org.apache.myfaces.trinidad.webapp.ResourceServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>resources</servlet-name>
    <url-pattern>/adf/*</url-pattern>
  </servlet-mapping>

E por incrível que pareça a grande dor de cabeça que tivemos foi com as configurações de DEBUG, é preciso informar que essa configuração abaixo teoricamente não precise, ok? Mas como true não funcionará.

    <context-param>
        <param-name>
            org.apache.myfaces.trinidad.resource.DEBUG
        </param-name>
        <param-value>false</param-value>
    </context-param>

    <context-param>
      <param-name>facelets.DEVELOPMENT</param-name>
      <param-value>true</param-value>
    </context-param>
   <context-param>
      <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
      <param-value>.xhtml</param-value>
   </context-param>

  <context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>server</param-value>
  </context-param>

  <context-param>
         <param-name>org.apache.myfaces.trinidad.CACHE_VIEW_ROOT</param-name>
         <param-value>false</param-value>
  </context-param>

Segue mais configurações que devem estas no web.xml. E como o guia de instalação do Trinidad já orienta, não esqueça de remover com.sun.facelets.FaceletViewHandler do arquivo faces-config.xml, pois o
Trinidad possui seu próprio ViewHandler.

  <context-param>
    <param-name>org.apache.myfaces.trinidad.ALTERNATE_VIEW_HANDLER</param-name>
    <param-value>org.apache.myfaces.trinidadinternal.facelets.TrinidadFaceletViewHandler</param-value>
  </context-param>

  <context-param>
    <param-name>org.apache.myfaces.trinidad.FACELETS_VIEW_MAPPINGS</param-name>
    <param-value>*.xhtml</param-value>
  </context-param>

  <security-constraint>
    <display-name>Restrict raw XHTML Documents</display-name>
    <web-resource-collection>
      <web-resource-name>XHTML</web-resource-name>
      <url-pattern>*.xhtml</url-pattern>
    </web-resource-collection>
    <auth-constraint/>
  </security-constraint>
</web-app>

Já no arquivo trinidad-config.xml a única configuração que fizemos foi alterar o debug para false.

<debug-output>false</debug-output>

Por fim e não menos importante o arquivo faces-config.xml onde temos que configurar o default-render-kit-id para usar o do Trinidad, lembre-se que anteriormente já dissemos que é necessário o com.sun.facelets.FaceletViewHandler por motivos já ditos.

    <default-render-kit-id>
      org.apache.myfaces.trinidad.core
    </default-render-kit-id>

Veja na imagem abaixo um exemplo do gráfico gerado:

Com essas configurações citadas tivemos uma integração perfeita do Trinidad e RichFaces, lembrando que com o debug ativado existe alguns comportamentos estranhos, bem como alguns componentes RichFaces não funcionando corretamente.

Agora com o Trinidad configurado só nos resta implementar os gráficos como drill-down!

maiores informações sobre o framework: http://myfaces.apache.org/trinidad/index.html

Liberar acesso externo, utilizando JBOSS

Por esses dias tivemos que liberar a aplicação para acesso externo, pois o ambiente teria que ser utilizado para demonstração da aplicação. A intenção era que ele fosse acessado a partir da url da empresa ex.:www.nomeempresa.com.br/aplicacao. Na primeira tentativa já encontramos um problema: toda vez que a aplicação era acessada o JBOSS redirecionava para “http://nomedamaquina.nomeempresa.com.br&#8221;. Como na visão limitada do JBoss com relação à requisição, o nome da interface de rede que recebia a requisição era “nomedamaquina”, o JBOSS fazia o redirecionamento para este nome, o que funcionava internamente já que o nome “nomedamaquina” é conhecido na rede mas interna mas não externamente. Dessa maneira ,uma saída seria criar um novo host no nosso servidor de nomes (dns) , o que levaria em nosso caso uns 2 dias (tempo de expiração configurado para nossas entradas), além de deixarmos a maquina inteira exposta na Internet.

Em suma tínhamos um cenário parecido com a figura abaixo:

Topologia - JBoss + Apache + Mod_rewrite

Topologia - JBoss + Apache + Mod_rewrite

Dando uma googlada encontramos que a solução seria realizar uma alteração no server.xml do jboss.

Veja abaixo as configurações…. Lembrando que a configuração foi realizada com conexão segura (ssl):

server.xml original:

      <!-- A AJP 1.3 Connector on port 8009 -->
      <connector protocol="AJP/1.3" port="8009" address="${jboss.bind.address}" redirectport="8443"></connector>

      <!-- SSL/TLS Connector configuration using the admin devl guide keystore-->
      <connector protocol="HTTP/1.1" sslenabled="true" port="8443" address="${jboss.bind.address}" scheme="https" secure="true" clientauth="false" keystorefile="${jboss.server.home.dir}/conf/chap8.keystore" keystorepass="rmi+ssl" sslprotocol="TLS"></connector>

server.xml alterado:

<!-- A AJP 1.3 Connector on port 8009 -->
      <connector protocol="AJP/1.3" port="8009" address="${jboss.bind.address}" redirectport="8443" proxyname="www.nomeempresa.com.br" proxyport="443"></connector>

      <!-- SSL/TLS Connector configuration using the admin devl guide keystore -->
      <connector protocol="HTTP/1.1" sslenabled="true" port="8443" address="${jboss.bind.address}" scheme="https" secure="true" clientauth="false" keystorefile="${jboss.server.home.dir}/conf/chap8.keystore" keystorepass="nomemaquina" sslprotocol="TLS" uriencoding="UTF-8" proxyname="www.nomeempresa.com.br" proxyport="443"></connector>

Com essa alteração, instruímos o JBoss para ignorar o que ele achava ser o host correto e assumir o que havíamos informado, que nada mais é que o IP/Nome do Proxy externo, ou seja, quem está realmente recebendo a requisição.

Categorias:network Tags:, ,