Archive for the ‘Programação’ Category.

Maven, Hibernate, Spring, CXF e MySql rodando no Jboss 7

Este post demonstra como usar de maneira prática o Hibernate com Spring publicando um Web Services utilizando com o Apache CXF, no Jboss 7 AS.

O primeiro passo é configurar o Maven, que irá auxiliar na automação do projeto. Acredito que é a parte mais complicada deste tutorial, já que encontrar todas as bibliotecas e dependências necessárias não é uma tarefa fácil. O pom.xml (arquivo de configuração do Maven) abaixo funciona perfeitamente para a configuração feita no nosso application-context.xml que você irá ver a seguir, você poderá fazer download da versão completa deste projeto no fim deste post.

...

	<dependencies>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate</artifactId>
			<version>3.2.1.ga</version>
			<exclusions>
				<exclusion>
					<groupId>asm</groupId>
					<artifactId>asm</artifactId>
				</exclusion>
				<exclusion>
					<groupId>asm</groupId>
					<artifactId>asm-attrs</artifactId>
				</exclusion>
				<exclusion>
					<groupId>cglib</groupId>
					<artifactId>cglib</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.8</version>
		</dependency>
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib-nodep</artifactId>
			<version>2.1_3</version>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-annotations</artifactId>
			<version>3.2.0.ga</version>
		</dependency>
		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>persistence-api</artifactId>
			<version>1.0</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aop</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${spring.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-simple</artifactId>
			<version>1.5.2</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>${servlet.version}</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>${junit.version}</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.unitils</groupId>
			<artifactId>unitils</artifactId>
			<version>1.0</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-frontend-jaxws</artifactId>
			<version>${cxf.version}</version>
		</dependency>
		<dependency>
			<groupId>org.apache.cxf</groupId>
			<artifactId>cxf-rt-transports-http</artifactId>
			<version>${cxf.version}</version>
		</dependency>
	</dependencies>
...

Vamos começar a fazer nosso serviço que irá retornar informações sobre Clubes de Futebol. Vamos mapear o Bean referente a tabela TB_CLUBES.

package com.lucianosilva.lab.entity;

@Entity
@Table(name = "TB_CLUBES")
public class Clube implements BaseEntity<Long> {
	private static final long serialVersionUID = 5541457395540986982L;

	@Id
	@Column(name = "ID_CLUBE", nullable = false)
	private Long idClube;

	@Column(name = "NOME", nullable = true)
	private String nome;

	@Column(name = "NOME_POP", nullable = true)
	private String nomePopular;

	@Column(name = "FUNDACAO", nullable = true)
	private Date dataFundacao;

	/* (non-Javadoc)
	 * @see com.lucianosilva.lab.core.BaseEntity#getId()
	 */
	@Override
	public Long getId() {
		//
		return this.idClube;
	}

	/* (non-Javadoc)
	 * @see com.lucianosilva.lab.core.BaseEntity#setId(java.lang.Object)
	 */
	@Override
	public void setId(Long id) {
		//
		this.idClube = id;
	}

//... getters and setters
}

Agora podemos construir o acesso aos dados, que faz uso de Generic DAO ocultado neste post, não se preocupe é uma prática comum, no fim do post estão os arquivos para download.

Essa classe básicamente define o que vamos ter no serviço, duas operações de retorno filtrando pelo ID e Nome.

package com.lucianosilva.lab.dao;

public class ClubesDao extends HibernateGenericRepository<Clube, Long> {

	/* (non-Javadoc)
	 * @see com.lucianosilva.lab.repository.HibernateGenericRepository#findById(java.io.Serializable)
	 */
	@Override
	public Clube findById(Long id) {
		return super.findById(id);
	}

	public ClubesDao(){
		super(Clube.class);
	}

	/**
	 *
	 * @param name
	 * @return
	 */
	public List<Clube> findByName( String name ){
		return super.findByCriteria(Expression.like("nome", name, MatchMode.ANYWHERE));
	}
}

A definição deste serviço é tão simples quanto a construção do DAO acima, não foi feito o tratamento customizado das exceções já que o objetivo não é esse e, sim demonstrar a integração dos frameworks e como devem ser configurados, nada impede de você mesmo evoluir este código.

package com.lucianosilva.lab.webservices;

@WebService
public interface ClubeService {

	@WebMethod(operationName="ListAllClubes")
	@WebResult(name = "Clube")
	public List<Clube> listAll();

	@WebMethod(operationName="FindByClubeName")
	@WebResult(name = "Clube")
	public List<Clube> findByName(@WebParam(name = "clubeName") String name);

}

Implementação do serviço.

package com.lucianosilva.lab.webservices.impl;

import java.util.List;

import javax.jws.WebService;

import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.lucianosilva.lab.dao.ClubesDao;
import com.lucianosilva.lab.entity.Clube;
import com.lucianosilva.lab.webservices.ClubeService;

@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
@WebService(endpointInterface="com.lucianosilva.lab.webservices.ClubeService")
public class ClubeServiceImpl implements ClubeService {

	private ClubesDao clubesDao; // configuracao no application-context

	public List<Clube> findByName(String name) {
		return clubesDao.findByName(name);
	}

	public List<Clube> listAll() {
		//
		return clubesDao.listAll();
	}

	/**
	 * @return the clubesDao
	 */
	public ClubesDao getClubesDao() {
		return clubesDao;
	}

	/**
	 * @param clubesDao the clubesDao to set
	 */
	public void setClubesDao(ClubesDao clubesDao) {
		this.clubesDao = clubesDao;
	}

}

Bem, até aqui nada de novo, pelo contrário tudo muito trivial. A configuração desta aplicação (application-context.xml) é o “pulo-do-gato”.

Adicionei comentários no bloco abaixo, para explicar cada parte da configuração.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:jaxws="http://cxf.apache.org/jaxws"
	xmlns:tx="http://www.springframework.org/schema/tx" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:jaxrs="http://cxf.apache.org/jaxrs"
	xsi:schemaLocation="  

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd

http://www.springframework.org/schema/tx

http://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://cxf.apache.org/core

http://cxf.apache.org/schemas/core.xsd

http://cxf.apache.org/jaxws

http://cxf.apache.org/schemas/jaxws.xsd

http://cxf.apache.org/jaxrs

http://cxf.apache.org/schemas/jaxrs.xsd"

	default-dependency-check="none" default-lazy-init="false">

	<!-- arquivo separado para a configuração dos EndPoints (WebServices) CXF veja mais abaixo -->
	<import resource="cxf-beans.xml" />

	<!-- Bean abstrato para evitar repetição de código -->
	<bean id="baseSessionFactory" abstract="true">
		<property name="sessionFactory" ref="sessionFactory" />
	</bean>

	<!-- IoC - Implementação da interface ClubesDAO -->
	<bean id="clubesDao" class="com.lucianosilva.lab.dao.ClubesDao"
		parent="baseSessionFactory" />

        <!-- Configuração do DataSource para o Connection Pool - Este JNDI name está seguindo o padrão do JBoss -->
	<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="jndiName">
			<value>java:/Laboratorio</value>
		</property>
	</bean>

	<!-- Configurações de uma Session Factories -->
	<bean id="sessionFactory"
		class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
		<property name="dataSource">
			<ref local="dataSource" />
		</property>
		<property name="annotatedClasses">
			<list>
				<value>com.lucianosilva.lab.entity.Clube</value>
			</list>
		</property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">
					org.hibernate.dialect.MySQLInnoDBDialect
				</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">false</prop>
			</props>
		</property>
	</bean>
	<bean id="transactionManager"
		class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory">
			<ref local="sessionFactory" />
		</property>
	</bean>
	<tx:annotation-driven transaction-manager="transactionManager" />
</beans>

Bem, lá no começo do application-context.xml fizemos o import da configuração do CXF, segue a descrição do arquivo cxf-beans.xml.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:jaxws="http://cxf.apache.org/jaxws"
	xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd">

	<!-- Configurações do Apache CXF -->
	<import resource="classpath:META-INF/cxf/cxf.xml" />
	<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
	<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

	<!-- Configurações do endpoint WSDL -->
	<jaxws:endpoint id="clubeService" depends-on="clubeServiceImpl"
		implementor="#clubeServiceImpl" address="/ClubeService">
	</jaxws:endpoint>

	<!-- Bean que implementa o endpoint do nosso webservice -->
	<bean id="clubeServiceImpl" class="com.lucianosilva.lab.webservices.impl.ClubeServiceImpl">
		<property name="clubesDao" ref="clubesDao" />
	</bean>
</beans>

Compile, empacote e faça deploy no Jboss, agora vamos ver o serviço rodando no soapUI.

 

Por fim, você viu a configuração de um serviço simples, com acesso ao banco de dados utilizando DataSource, a qual considero importantíssimo como exemplo, já que NÍNGUEM utiliza a configuração do application-context informando os parâmetros do banco de dados (exceto para o uso do JUnit).

Você pode evoluir este código implementando o controle de erros com WebFault e também utilizando o Autowired no Spring, aumentando o controle da sua aplicação e diminuindo a configuração manual.

Download

 

Criando, Populando e Consumindo Advanced Queue com BPEL – Parte 3/3

E por fim, vamos fazer uso da AQ que foi criada e populada com dados fixos, veja Parte 1 e Parte 2.
O processo de consumo de uma fila chamado de Dequeue, quando executado remove o registro da tabela controladora (Queue Table).

Na camada Oracle Middleware o consumo desta AQ pode ser feito utilizando o Oracle JCA Adapter for Advanced Queue (AQ Adapter) do BPEL.

Nota: Não serão detalhados os procedimentos para a configuração do AQ Adapter no Weblogic, e também a construção básica de um Composite e BPEL, veja as referências deste post.

Consumindo Advanced Queue com BPEL

Crie um novo projeto SOA, e adicione um processo BPEL assíncrono, dê o nome de BPELProcessQueue.

Criando o BPEL Assincrono

Criando o BPEL Assíncrono

Configure o banco de dados em que foi criada a fila, utilizando o usuário proprietário da AQ.
Arreste o componente AQ Adapter para o processo BPEL, e faça a configuração informando o nome, nome da fila e tipo de uso (enqueue / dequeue) neste caso iremos fazer o Dequeue.

Alguns passos básicos foram ocultados, preencha apenas as configurações a seguir e utilize o next-next-finish.

AQ Adapter

Selecione a configuração Dequeue.

AQ Adapter - Dequeue

Selecione o nome da fila que estamos utilizando como exemplo – “XXAR_INVOICE_QTAB”.

AQ Adapter - Selecionando Queue

Pronto. A fila está preparada para fazer parte do fluxo BPEL, adicione um Receive e associe ao Adaptador, crie uma variável de output que irá conter o tipo de dados da fila.

Fluxo BPEL

Bem, com isso feito você já tem o controle total da fila e poderá fazer uso dos dados como quiser, veja abaixo um Assign simples, apenas demonstrando o resultado do nosso receive.

BPEL Assign

Conclusão
O uso do Oracle AQ pode ser aplicado a diversas situações, uma delas quando está trabalhando com sistemas limitados a tecnologia de Web Services, este recurso é muito útil também em casos que toda a programação está centralizada no banco de dados. Tendo em vista que a implementação e desenvolvimento são razoávelmente rápidos, utilizar a Oracle AQ fornece um ganho enorme para a plataforma de integração.

A seguir você poderá fazer download do projeto utilizado como exemplo e também os scripts para construção da fila.

Downloads

Referência

\o/

Criando, Populando e Consumindo Advanced Queue com BPEL – Parte 2/3

Com a estrutura da AQ criada, o próximo passo ainda utilizando o PLSQL é o envio das informações para a fila. O enqueue deve ser feito utilizado a API Core DBMS_AQ.

Populando (Enqueue)

O enfileiramento é um processo simples, uma vez que as variáveis foram declaradas, basta popular o type da mensagem que será enviada a fila, e fazer uso do dbms_aq.enqueue.

Este exemplo demonstra o enfileiramento de um único registro na fila, mas você pode evoluir o código fazendo o preenchimento com multiplos registros.

Veja como popular o objeto correspondente a mensagem com dados fixos.


    --
    -- Formatacao da Mensagem para o Enqueue com dados fake
    --
    MESSAGE := XXAR_KEY_INVOICE( INVOICE_NUM => 10001,
                                 SOURCE_NAME => 'core system',
                                 TOTAL_AMOUNT => 139.99,
                                 DESCRIPTION => 'White T-Short'
                               );
--

Uma vez que a mensagem foi preenchida, a próximo ação é o enfileiramento da mensagem, um procedimento tão simples quanto o anterior. O commit da transação é obrigatório.

    --
    -- Enqueue (enfileiramento)
    dbms_aq.enqueue(queue_name           => p_queue, -- nome da fila
                    payload              => MESSAGE, -- mensagem
                    enqueue_options      => enqueue_options,
                    message_properties   => message_properties,
                    msgid                => message_handle);

    commit; --
--

Pronto, feito isto já é possível consultar a Queue Table e verificar o novo registro que acabou de ser inserido.

SELECT * FROM XXAR_INVOICE WHERE 1 = 1 ORDER BY enq_time DESC;

A coluna State da Queue Table corresponde ao status do registro.

dbmsaq.READY     = 0
dbmsaq.WAITING   = 1
dbmsaq.PROCESSED = 2
dbmsaq.EXPIRED   = 3

O registro na fila está pronto para ser consumido, e vou demonstrar isto na próxima parte utilizando o BPEL.

Download

Criando, Populando e Consumindo Advanced Queue com BPEL – Parte 1/3

Este post irá mostrar como você pode fazer uso das filas do banco de dados Oracle – Oracle Advanced Queue.
No cenário apresentado, é sugerida a integração entre dois sistemas, sendo que o Sistema A irá enfileirar as informações para que o serviço da camada Middleware faça o consumo e dispare os dados para o Sistema B.

A seguir você poderá criar uma nova fila com um tipo de dado definido, em seguida ela será populada com dados fixos utilizando PLSQL e por fim, em um processo BPEL assíncrono fazer o dequeue (consumo).

Construindo

Os passos a seguir são para construção da fila e definição da mensagem que será entregue ao consumidor.
Conecte no banco de dados Oracle e execute os scripts na sequência, no final deste artigo você poderá fazer download dos scripts.

Tipo que define a estrutura da mensagem que será adicionada a fila.

--
CREATE TYPE XXAR_KEY_INVOICE AS OBJECT (
    INVOICE_NUM         NUMBER(10),
    SOURCE_NAME         VARCHAR2(200),
    TOTAL_AMOUNT        NUMBER(15,2),
    DESCRIPTION         VARCHAR2(500))
/

Criação da Queue Table, associada ao tipo (estrutura da mensagem).

--
Begin
 DBMS_AQADM.create_queue_table( queue_table => 'XXAR_INVOICE', -- nome da QTable
                                queue_payload_type => 'XXAR_KEY_INVOICE' -- tipo mensagem da QTable
                              );
End;
/

Criação da fila vinculada com a tabela controladora dos registros que serão adicionados a fila.

--
Begin
 DBMS_AQADM.create_queue(queue_name => 'XXAR_INVOICE_QTAB', -- nome da Queue
                         queue_table => 'XXAR_INVOICE' -- Tabela controladora da Queue
                         );
End;
/

Iniciando a fila.

--
Begin
  DBMS_AQADM.start_queue( queue_name => 'XXAR_INVOICE_QTAB' );
End;
/
CREATE OR REPLACE TYPE XXAR_KEY_INVOICE_T AS TABLE OF XXAR_KEY_INVOICE;
/

Pronto, agora conseguimos criar a AQ com um tipo de dado complexo definido.
Como você deve ter percebido toda a criação da fila faz uso da API core DBMS_AQADM. Para o nosso próximo passo que é o envio de mensagens para a fila (enqueue), será necessário a DBMS_AQ.

Downloads

[]‘s

Instalando Oracle Database 10.2 32bit no Windows 7 64bit

Este vídeo é muito util pra você que precisa instalar o Oracle Client (ou Enterprise) no Windows 7[bb] plataforma 64bit e utilizar como IDE o PLSQL Developer (versões 7 ou 8) e SQL Navigator 6.

Assista o vídeo até o final para entender que mesmo depois do banco de dados instalado é necessário configurar as IDEs.

 

 

Créditos ao senhor Alam.