Tutorial de Instalação do jBPM 6.2 + PostgreSQL + JBoss 7.1 Final + Eclipse

Fala galera! O objetivo deste tutorial é guiá-los na instalação do jBPM 6.2.0.Final utilizando como base de dados o PostgreSQL. Não abordarei a instalação do PostgreSQL e do Ant pois não é o foco do tutorial.

AMBIENTE

Para este tutorial, estou utilizando o sistema operacional Ubuntu 14.04 mas nada impede que você utilize Windows ou qualquer outra distro Linux ok?

INGREDIENTES

  • Instalador do jBPM-6.2.0.Final
  • PostgreSQL
  • Ant
  • Uma boa conexão
  • Paciência

INSTALAÇÃO

Baixe o instalador: http://sourceforge.net/projects/jbpm/files/jBPM%206/jbpm-6.2.0.Final/jbpm-6.2.0.Final-installer-full.zip/download

Descompacte o arquivo no diretório “/opt” (ou em outro diretório de sua preferência)

Abra o arquivo build.properties que está na raiz do diretório “/opt/jbpm-installer”. O trabalho aqui é comentar/descomentar linhas, exceto a configuração do PostgreSQL que vamos adicionar.

As 3 primeiras linhas do arquivo indicam o diretório home da instalação, a snapshot e a release. Não é necessário fazer nenhuma alteração aqui.

install.home=./
snapshot.version=6.2.0-SNAPSHOT
release.version=6.2.0.Final

O próximo bloco diz respeito a versão do jBPM que iremos utilizar, como vamos trabalhar com a release, descomente as linhas abaixo e comente as demais:

jBPM.version=${release.version}
jBPM.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/drools/droolsjbpm-bpms-distribution/${jBPM.version}/droolsjbpm-bpms-distribution-${jBPM.version}-bin.zip

A próxima configuração é a respeito do WAR do jBPM Console que iremos instalar, em nosso caso, para JBoss AS 7:

jBPM.console.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/kie/kie-wb-distribution-wars/${jBPM.version}/kie-wb-distribution-wars-${jBPM.version}-jboss-as7.war

Eclipse + plugin jBPM e Drools:

droolsjbpm.eclipse.version=${release.version}
droolsjbpm.eclipse.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/drools/org.drools.updatesite/${droolsjbpm.eclipse.version}/org.drools.updatesite-${droolsjbpm.eclipse.version}.zip

e

eclipse.home=./eclipse
eclipse.clean.workspace=true

JBoss AS 7.1.1.Final:

jboss.server.version=as-7.1.1.Final
jboss.home=./jboss-${jboss.server.version}
jboss.download.url=http://download.jboss.org/jbossas/7.1/jboss-${jboss.server.version}/jboss-${jboss.server.version}.zip
jboss.server.conf.dir=${jboss.home}/standalone/configuration
jboss.server.deploy.dir=${jboss.home}/standalone/deployments
jboss.server.data.dir=${jboss.home}/standalone/data
jboss.clean.repository=true
jboss.war.type=${jboss.server.version}

O próximo é Dashboard. Dashboard é uma ferramenta utilizada para medir indicadores dos processos.

dashboard.version=${release.version}
dashboard.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/jbpm/dashboard/jbpm-dashboard-distributions/${dashboard.version}/jbpm-dashboard-distributions-${dashboard.version}-jboss-as7.war

E finalmente, o banco de dados. Por padrão, o jBPM usa o H2 como backend. Nós iremos utilizar o PostgreSQL 9.3 e a partir dessa configuração, fica fácil utilizar qualquer outro banco de dados.

Quem já tiver alguma experiência com módulos do JBoss, não terá nenhuma dificuldade aqui.
As duas linhas abaixo são respectivamente: O caminho de origem para o driver (jar) e a pasta do módulo no JBoss.

db.driver.jar=${install.home}/db/driver/${db.driver.jar.name}
db.driver.module.dir=${jboss.home}/modules/${db.driver.module.prefix}/main/

Faça o download do driver postgresql-9.3-1103.jdbc4.jar e salve-o na pasta “/opt/jbpm-installer/db/driver”.
No build.properties, comente as linhas referente ao H2 e acrescente as linhas abaixo:

#postgresql
db.name=postgresql
db.driver.module.prefix=org/postgresql
db.driver.jar.name=postgresql-9.3-1103.jdbc4.jar
db.driver.download.url=https://repository.jboss.org/nexus/content/repositories/thirdparty-uploads/postgresql/postgresql/9.1-902.jdbc4/postgresql-9.1-902.jdbc4.jar

Pronto. Depois de realizar essas alterações, seu arquivo build.properties deve se parecer com esse:

# NOTES for doing a release
# - replace all *.url variables with the variables marked as <RELEASE>
# - make sure all *.version variables = ${release.version}
# - set ${release.version} to the current release version.

install.home=./
snapshot.version=6.2.0-SNAPSHOT
release.version=6.2.0.Final

# the version of jBPM you want to use
# and the associated URL you want to get the dependencies from
# for example:
#<RELEASE>
#   jBPM.version=${release.version}
#   jBPM.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/jbpm/jbpm-distribution/${jBPM.version}/jbpm-distribution-${jBPM.version}-bin.zip
# or:
#<SNAPSHOT>
#   jBPM.version=${snapshot.version}
#   jBPM.url=https://hudson.jboss.org/hudson/job/jBPM/lastSuccessfulBuild/artifact/jbpm-distribution/target/jbpm-${jBPM.version}-bin.zip
jBPM.version=${release.version}
jBPM.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/drools/droolsjbpm-bpms-distribution/${jBPM.version}/droolsjbpm-bpms-distribution-${jBPM.version}-bin.zip

# the version of jBPM Console you want to use
# and the associated URL you want to get it from
# for example:
#<RELEASE>
# for AS7:
jBPM.console.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/kie/kie-wb-distribution-wars/${jBPM.version}/kie-wb-distribution-wars-${jBPM.version}-jboss-as7.war
# for EAP 6.4:
#   jBPM.console.url=http://repository.jboss.org/nexus/content/groups/public-jboss/org/kie/kie-wb-distribution-wars/${jBPM.version}/kie-wb-distribution-wars-${jBPM.version}-eap6_4.war
# for WildFly8:
#   jBPM.console.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/kie/kie-wb-distribution-wars/${jBPM.version}/kie-wb-distribution-wars-${jBPM.version}-wildfly8.war
# or:
#<SNAPSHOT>
#   jBPM.console.url=https://hudson.jboss.org/hudson/job/kie-wb-distributions/lastSuccessfulBuild/artifact/kie-wb/kie-wb-distribution-wars/target/kie-wb-${jBPM.version}-wildfly8.war

# the version of jBPM and Drools Eclipse plugin you want to use
# and the associated URL you want to get the dependencies from
# for example:
#<RELEASE>
#   droolsjbpm.eclipse.version=${release.version}
#   droolsjbpm.eclipse.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/drools/org.drools.updatesite/${droolsjbpm.eclipse.version}/org.drools.updatesite-${droolsjbpm.eclipse.version}.zip
# or:
#<SNAPSHOT>
#   droolsjbpm.eclipse.version=${snapshot.version}
#   droolsjbpm.eclipse.url=https://hudson.jboss.org/hudson/job/droolsjbpm-tools/lastSuccessfulBuild/artifact/drools-eclipse/org.drools.updatesite/target/org.drools.updatesite-${droolsjbpm.eclipse.version}.zip
droolsjbpm.eclipse.version=${release.version}
droolsjbpm.eclipse.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/drools/org.drools.updatesite/${droolsjbpm.eclipse.version}/org.drools.updatesite-${droolsjbpm.eclipse.version}.zip

# the home of your eclipse installation
# will be used to deploy the Eclipse plugin to
eclipse.home=./eclipse
eclipse.clean.workspace=true

# the home of your JBoss AS installation
# for example, for AS7:
jboss.server.version=as-7.1.1.Final
jboss.home=./jboss-${jboss.server.version}
jboss.download.url=http://download.jboss.org/jbossas/7.1/jboss-${jboss.server.version}/jboss-${jboss.server.version}.zip
jboss.server.conf.dir=${jboss.home}/standalone/configuration
jboss.server.deploy.dir=${jboss.home}/standalone/deployments
jboss.server.data.dir=${jboss.home}/standalone/data
jboss.clean.repository=true
#   IMPORTANT: make sure to also set the H2.version property (below) to 1.3.161
# or for EAP 6.4
#   jboss.server.version=eap-6.4.0
#   jboss.home=./jboss-eap-6.4
#   jboss.download.url=### you need to manually download the eap 6.4.0 zip and put it in the lib folder ###
#   jboss.server.conf.dir=${jboss.home}/standalone/configuration
#   jboss.server.deploy.dir=${jboss.home}/standalone/deployments
#   jboss.server.data.dir=${jboss.home}/standalone/data
#   jboss.clean.repository=true
# or for Wildfly8
#   jboss.server.wildfly.version=8.1.0.Final
#   jboss.server.version=wildfly-${jboss.server.wildfly.version}
#   jboss.home=./${jboss.server.version}
#   jboss.download.url=http://download.jboss.org/wildfly/${jboss.server.wildfly.version}/${jboss.server.version}.zip
#   jboss.server.conf.dir=${jboss.home}/standalone/configuration
#   jboss.server.deploy.dir=${jboss.home}/standalone/deployments
#   jboss.server.data.dir=${jboss.home}/standalone/data
#   jboss.clean.repository=true
jboss.war.type=${jboss.server.version}

# jboss.port.offset=0
# org.uberfire.nio.git.daemon.port=9418
# org.uberfire.nio.git.ssh.port=8001

# the version of Dashboard Builder you want to use
# and the associated URL you want to get it from
# for example:
#<RELEASE>
# for AS7:
dashboard.version=${release.version}
dashboard.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/jbpm/dashboard/jbpm-dashboard-distributions/${dashboard.version}/jbpm-dashboard-distributions-${dashboard.version}-jboss-as7.war
# for EAP 6.4:
#   dashboard.version=${release.version}
#   dashboard.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/jbpm/dashboard/jbpm-dashboard-distributions/${dashboard.version}/jbpm-dashboard-distributions-${dashboard.version}-eap6_4.war
# for Wildfly8:
#   dashboard.version=${release.version}
#   dashboard.url=https://repository.jboss.org/nexus/content/groups/public-jboss/org/jbpm/dashboard/jbpm-dashboard-distributions/${dashboard.version}/jbpm-dashboard-distributions-${dashboard.version}-wildfly8.war
# or:
#<SNAPSHOT>
#   dashboard.version=${snapshot.version}
#   dashboard.url=https://hudson.jboss.org/hudson/job/jbpm-dashboard/lastSuccessfulBuild/artifact/jbpm-dashboard-distributions/target/jbpm-dashbuilder-${dashboard.version}-wildfly8.war

# data base related properties
db.driver.jar=${install.home}/db/driver/${db.driver.jar.name}
db.driver.module.dir=${jboss.home}/modules/${db.driver.module.prefix}/main/
# default is H2
# H2.version=1.3.168
# db.name=h2
# db.driver.jar.name=h2-${H2.version}.jar
# db.driver.download.url=http://repo1.maven.org/maven2/com/h2database/h2/${H2.version}/h2-${H2.version}.jar
#other options are:
#mysql
#  db.name=mysql
#  db.driver.module.prefix=com/mysql
#  db.driver.jar.name=mysql-connector-java-5.1.18.jar
#  db.driver.download.url=https://repository.jboss.org/nexus/service/local/repositories/central/content/mysql/mysql-connector-java/5.1.18/mysql-connector-java-5.1.18.jar
#postgresql
db.name=postgresql
db.driver.module.prefix=org/postgresql
db.driver.jar.name=postgresql-9.3-1103.jdbc4.jar

Agora, vamos executar o instalador e esperar (bastante):

ant install.demo

Enquanto você espera a instalação finalizar, vamos configurar o BD:

  • Crie um novo banco de dados chamado jbpm
  • Vá até a pasta “/opt/jbpm-installer/db/ddl-scripts/postgres/”
  • Execute o script postgresql-jbpm-schema.sql e na sequência quartz_tables_postgres.sql

Quando a instalação finalizar, abra o arquivo “/opt/jbpm-installer/jboss-as-7.1.1.Final/bin/standalone.conf”, na linha 50, e altere as configurações como na linha abaixo:

-Xmx1024m -XX:MaxPermSize=512m

e na linha 52:

JAVA_OPTS="$JAVA_OPTS -Djboss.server.default.config=standalone-full.xml"

Abra o arquivo “/opt/jbpm-installer/jboss-as-7.1.1.Final/standalone/configuration/standalone-full.xml”, localize a seção datasource e adicione:

<datasource jta="true" jndi-name="java:jboss/datasources/jbpmDS" pool-name="jbpmDS" enabled="true" use-java-context="true" use-ccm="true">
    <connection-url>jdbc:postgresql://localhost:5432/jbpm</connection-url>
    <driver-class>org.postgresql.Driver</driver-class>
    <driver>postgresql</driver>
    <pool>
        <min-pool-size>2</min-pool-size>
        <max-pool-size>100</max-pool-size>
    </pool>
    <security>
        <user-name>postgres</user-name>
        <password>postgres</password>
    </security>
    <validation>
        <validate-on-match>false</validate-on-match>
        <background-validation>false</background-validation>
        <background-validation-millis>1</background-validation-millis>
    </validation>
    <statement>
        <prepared-statement-cache-size>64</prepared-statement-cache-size>
        <share-prepared-statements>true</share-prepared-statements>
    </statement>
</datasource>

E na seção drivers, acrescente:

<driver name="postgresql" module="org.postgresql">
    <xa-datasource-class>org.postgresql.xa.PGXADataSource</xa-datasource-class>
</driver>

Se tudo estiver correto, você já pode iniciar o JBoss:

$ cd /opt/jbpm-installer/jboss-as-7.1.1.Final/bin/
$ ./standalone.sh -b 0.0.0.0

Se apareceu “Deployed” no terminal, você já pode acessar o jbpm-console: http://localhost:8080/jbpm-console

Espero que tudo tenha dado certo!

Um abraço e até o próximo post!

Postgres (Large Objects) + CodeIgniter (Image_Lib)

Estou no início do meu aprendizado com CodeIgniter e PostgreSQL e nesse pouco tempo não vi nenhuma referência à manipulação de blobs na documentação ou mesmo no código do framework. Para contornar o problema criei um helper para me auxiliar nessa tarefa. Utilizando as funções nativas do PHP em conjunto com o CodeIgniter, você pode manipular facilmente seus large objects. O único problema que tive foi com a image_lib usando gd2 e imagens geradas com pg_lo_read_all, sendo totalmente on the fly, isso ficará para um outro post.

Ok, vamos ao que interessa:

  • Exportando o large object – método 1
if ( ! function_exists('pgsql_lo_export')) {

	function pgsql_lo_export($id_object, $caminho_arquivo)
	{
		$CI =& get_instance();

		// Inicia a transação
		$CI->db->trans_start();

		// Exporta o arquivo
		$retorno = pg_lo_export($id_object, $caminho_arquivo);

		// Encerra a transação
		$CI->db->trans_complete();

		return $retorno;
	}
}

linha 5: Recupera a instância do CodeIgniter, sem isso não é possível usar as bibliotecas.

linha 8 e 14: Todas as funções de manipulação dos large objects devem estar dentro de uma transação e também precisam de um resource para a conexão. Essas linhas resolvem os dois problemas, engloba a chamada da função em uma transação e também cria uma conexão padrão. Não entendeu? clique aqui.

linha 11: Faz a mágica da exportação

  • Exibir a imagem – método 1
// Método do controller
public function thumbnail($oid)
{
	// define os diretórios
	$diretorio_saida = str_replace(SELF,'',APPPATH)."uploads/";
	$arquivo_saida = tempnam($diretorio_saida,'fa_');

	// Exporta o large object
	pgsql_lo_export($oid, $arquivo_saida);

	$config['image_library'] = 'gd2';
	$config['source_image'] = $arquivo_saida;
	$config['dynamic_output'] = TRUE;
	$config['create_thumb'] = TRUE;
	$config['maintain_ratio'] = TRUE;
	$config['width'] = 160;
	$config['height'] = 120;

	// Carrega a image_lib
	$this->load->library('image_lib', $config);

	// Tenta redimensionar a imagem
	if ( ! $this->image_lib->resize())
	{
		echo $this->image_lib->display_errors();
	}

	// Apaga o arquivo temporário
	unlink($arquivo_saida);
}

linha 5 e 6: Define onde gerar os arquivos temporários. Atenção para a linha 6 que usa a função tempnam, essa função cria um arquivo temporário com nome único. Vai ser útil para evitar problemas com nomes de arquivos

linha 9: Exporta o blob para o arquivo temporário usando a função criada anteriormente

linha 13 e 14: A opção dynamic_output indica que a imagem não será salva no disco (on the fly) e create_thumb que o arquivo original não será modificado

linha 23: Redimensiona nossa imagem

linha 29: Apaga nosso arquivo temporário

  • Exibir a imagem – método 2 (sem churumelas)
if ( ! function_exists('pgsql_lo_read_all')) {

	function pgsql_lo_read_all($id_objeto)
	{

		$CI =& get_instance();

		// Inicia a transação
		$CI->db->trans_start();

		// Abre o OID para leitura e envia para o browser
		$hnd = pg_lo_open($id_objeto, "r");
		pg_lo_read_all($hnd);
		pg_lo_close($hnd);

		// Encerra a transação
		$CI->db->trans_complete();

	}
}

Essa função é bem parecida com a primeira função, a diferença é que ela não exporta o binário para um arquivo no disco, o conteúdo é enviado diretamente para o browser usando pg_lo_read_all.

É isso ai, chega de programar … agora é a vez da cremosa gelada. Boas festas e até o próximo post.

Dica Rápida: Postgres – Exceção Genérica

Para “pegar” um exceção genérica no postgres, basta usar a constant OTHERS na cláusula EXCEPTION. Algo mais ou menos assim:

BEGIN

  PERFORM lo_export($1, $2);
  RETURN TRUE;

EXCEPTION
WHEN OTHERS THEN
  RETURN FALSE;
END;

Para saber mais sobre exceptions no postgres veja aqui http://www.postgresql.org/docs/8.1/static/errcodes-appendix.html e aqui http://www.postgresql.org/docs/8.0/static/plpgsql-control-structures.html#PLPGSQL-ERROR-TRAPPING

Abrasss

Postgres PLPGSQL Functions + Tabelas Temporárias

A alguns dias atrás precisei criar uma função no postgres que fazia inserções e consultas em uma tabela temporária que deveria ser criada dentro da função. Acontece que só funcionava na primeira execução, depois disso sempre me retornava algum erro na tentativa de criar a tabela novamente. Eu precisava de uma instrução que tem no SQL Server e que me parece não ter no postgres – “Exists” e “ObjectExists”. Bom, na falta .. dar-se um jeito. A solução que encontrei é usar o controle de exceções para dinâmicamente criar a tabela temporária caso ela ainda não exista na sessão.

— TESTA SE A TABELA JÁ FOI CRIADA NA SESSÃO

EXECUTE ‘SELECT * FROM tabela_tmp OFFSET 1’;

— SE NÃO EXISTIR, A EXCEÇÃO É DISPARADA E ENTÃO CRIA-SE A TABELA TEMPORÁRIA

EXCEPTION
WHEN undefined_table THEN
CREATE TEMPORARY TABLE tabela_tmp (
campo_1 INTEGER,
campo_2 VARCHAR(30)
) ON COMMIT DROP;
END;

Problema resolvido 🙂

Abraços

PostgreSQL + JasperServer / Transaction Read Only

Em breve devo fazer um post dedicado ao iReport e ao JasperServer. Um excelente solução para desenvolver relatórios para web com ferramentas open sources … masssss, pra quem já usa e teve ou está tendo dor de cabeça com o driver jdbc para postgresql e transações, vai ai minha dica :).

Meu Cenário

Tenho uma view que recebe os dados vindo de uma função que faz inserts em lote numa tabela (temporária) e no final da transação esses dados são excluídos.

Problema

Como a transação está definida como somente leitura (em algum lugar das profundezas dos milhares de arquivos de configuração do Java) a operação de insert/delete não é permitida e você ganha uma exception 🙂

Nas configurações do JasperServer, num dos inumeros arquivos de configuração e pastas do Java, deve existir um lugar onde você pode definir que a transação não é somente leitura. Bom, eu não “falo” java fluente e tive muita dificuldade em resolver o problema. Cansei de tentar achar a tal propriedade na sopa de letrinhas (JNDI, JDBC, BEAN, JSF, J2EE, etc) e resolver procurar a solução do outro lado … no banco. E não é que funcionou????

Basta na sua função/procedure colocar:
SET TRANSACTION READ WRITE;

Mais infos: http://www.postgresql.org/docs/8.1/interactive/sql-set-transaction.html