Arquivo para a categoria 'Diversos'

Curso on-line de Flex + Vídeos

Só repassando, daqui algumas semanas ocorrerá mais uma boa oportunidade para o desenvolvimento Flex, A e-Genial ta promovendo um curso on-line. O curso terá 18 aulas/horas e irá iniciar em Agosto, vamos fazer a matrícula:

Curso On-Line de Flex e Vídeos (streaming)

Você já pode baixar a grade, e ao termino será feito uma aplicação exemplo.

Comunicação entre componentes distribuídos por mensagens assíncronas com MDB

Após um tempo estudando Enterprise JavaBeans (EJB’s) para um projeto em que estava participando, percebi que estava confuso em relação ao conceito do tipo de ambiente(arquitetura) que o Beans de Sessão(Sessions Beans) são utilizados, pois cheguei a seguinte situação; queria que meu cliente acessasse por JNDI serviços registrados em outro servidor remoto e esses me devolviam informações(objetos) de um sistema heterogêneo , sendo que o mesmo estava em uma outra rede de uma filial da empresa, interligadas por uma WAN, ou seja, queria uma interação direta e síncrona entre meus componentes. Mas essa solução não é adequada por uma serie de condições adversas tais como: Link esta fora, servidor remoto parar no meio de uma transação, pico de luz e etc. A não ser que meu cliente espere longos 30min para receber apenas um timeout como resposta de uma conexão falha, nem mesmo quando pode voltar a estabelecer uma nova conexão com esse servidor. Então, como sair dessa situação? Depois de muito queimar a ‘cuca‘, encontramos a resposta na seguinte solução:

Invocar serviços através mensagens assíncronas, monitoradas por um tipo de especial de EJB denominado Message Driven Bean (MDB). Antes de começar explicar, vou explanar alguns conceitos importantes da solução apresentada:

  • MDB: São beans consumidores de JMS dentro do container JEE.
  • Queue: Filas de mensagens onde só vai ser consumida por um único MDB.
  • Producer: Produtor de mensagens para um Provider JMS.
  • Consumer: Recebe as mensagens de uma Queue que esta ‘escutando’.
  • Provider: Ambiente responsável pela organização e entrega de JMS.

O Conceito do funcionamento de uma JMS Application pode ser muito bem ilustrada na figura abaixo:

Isso nos trouxe mais confiança à comunicação entre nossos componentes distribuídos, pois não temos que nos preocupar em “busca coisas” em serviços de um servidor remoto, pois ele se encarrega de enviá-los através de um Producer construído somente para empilhar mensagens em uma Queue, escutada pelo nosso Consumer em um servidor local. O processando das mensagens é forma ordenada e durável, ou seja, somente sai da fila quando for realmente processada na ordem de chegada. Então a disposição de comunicação de nossos componentes ficou da seguinte forma:

A grande sacada foi como um MDB acessa uma Queue remota e fazer com que minhas mensagens sejam consistentes o bastante para garantirem a entrega no meu Consumer. Para isso foi feito algumas configurações no JBoss(no meu caso v.405), primeiramente foi adicionado mais um mbean(Managed Bean) em <$JBOSS_HOME/server/<your-configuration>/deploy/jms/jms-ds.xml, que defini um Provider remoto (que pode ser gerenciado via jmx-console). Lembrando esta alteração é no container em que o MDB esta rodando. Por padrão todos os MDBs acessam o DefaultJMSProvider também declarado no arquivo como Provider.

<mbean code=“org.jboss.jms.jndi.JMSProviderLoader”

name=“jboss.mq:service=JMSProviderLoader,name=RemoteJMSProvider,server=remotehost”>

<attribute name=“ProviderName”>RemoteJMSProvider</attribute>

<attribute name=“ProviderAdapterClass”>org.jboss.jms.jndi.JNDIProviderAdapter</attribute>

<!– The connection factory –>

<attribute name=“FactoryRef”>UIL2XAConnectionFactory</attribute>

<!– The queue connection factory –>

<attribute name=“QueueFactoryRef”>UIL2XAConnectionFactory</attribute>

<!– The topic factory –>

<attribute name=“TopicFactoryRef”>UIL2XAConnectionFactory</attribute>

<!– Connect to JNDI on the host “the-remote-host-name” port 1099–>

<attribute name=“Properties”>

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory

java.naming.factory.url.pkgs=org.jnp.interfaces

java.naming.provider.url=the-remote-host-name:1099

</attribute>

</mbean>

Troque “the-remote-host-name” para o IP do servidor que a Queue se encontra. E para fazer com que o MDB consuma de um provider remoto é mais fácil ainda:

@MessageDriven(activateConfig =
{
@ActivationConfigProperty(propertyName=”destinationType”, propertyValue=”javax.jms.Queue”),
@ActivationConfigProperty(propertyName=”destination”, propertyValue=”queue/testQueue”),
@ActivationConfigProperty(propertyName=”providerAdapterJNDI”, propertyValue=”java:/RemoteJMSProvider”)
})
public class MDB implements MessageListener
{

}

Agora para garantir com que as mensagens fossem persistentes. Definimos o envio do nosso Producer maneira persistente:


QueueSender sender = session.createSender(myQueue);
Message message = session.createTextMessage(”hello”);
int priority = 4;
sender.send(message, DeliveryMode.PERSISTENT, priority, 0);

Fazendo isto, garantimos a entrega da mensagem para o MDB pelo menos uma vez após uma exceção, se tornar a persistir, a mensagem é levada para o DLQ (ou mais conhecida como “lixão”), mas para que isso não ocorra você pode indicar que não quer tratamento de DLQ utilizando useDQL, desta forma, sempre ira tentar entregar a mensagem sem retirar da Queue enquanto houver exceção. Outra configuração que pode fazer também é numero de vezes que ele vai tentar entregar antes de mandar para DLQ o DLQMaxResent. A configuração do MDB pode ficar da seguinte forma:


@MessageDriven(activateConfig =
{
@ActivationConfigProperty(propertyName=”destinationType”, propertyValue=”javax.jms.Queue”),
@ActivationConfigProperty(propertyName=”destination”, propertyValue=”queue/testQueue”),
@ActivationConfigProperty(propertyName=”useDLQ”, propertyValue=”true”),
@ActivationConfigProperty(propertyName=”DLQMaxResent”, propertyValue=”100″),
@ActivationConfigProperty(propertyName=”providerAdapterJNDI”, propertyValue=”java:/RemoteJMSProvider”)
})
public class MDB implements MessageListener
{

}

Fiquei muito satisfeito com a facilidade de criação de aplicações desse tipo e ainda existe uma serie de configurações que podem ser feitas customizando a utilização de um MDB aumentando ainda mais a escalabilidade de sistemas, pois de uma solução JMS não se resume apenas apresentação unilateral de comunicação entre componentes, mais de uma interação substancial de processos definidos em uma margem de requisitos do funcionamento do sistema como um todo, tornando-o como uma ferramenta essencial na aplicação de grandes projetos.

Bom, vou ficando por aqui espero ter colaborado da alguma forma para o entendimento de aplicações JMS com MDB boa sorte e ate à próxima.

Injeção de Dependência e o Google GUICE

Segundo Martin Fowler todo e qualquer conteiner leve deve por si só implementar Inversão de Controle (Inversion of Control, ou IoC), definidos por três possíveis formas de Injeção de Dependência (DI), constructor Injection (Injeção por Construtores), Setter Injection (Injeção por Métodos Set) e Interface Injection (Injeção por Interfaces), a DI está relacionada ao baixo acoplamento de diferentes componentes de seu sistema e como acessar o mesmos não por uma chamada direta e sim por uma “injeção” do conteiner, hoje existem vários conteiner leves que fazem essas implementações como PicoContainer, Spring, Avalon. O Guice criado pelos “GooglersBob Lee e Kevin Bourrillion traz como principal característica um conteiner puramente DI, suportando injeção via constructor e setter e podendo funcionar somente com anotações ou se preferir, construir módulos para definir os bind entre objetos.

DI, Guice Style

Diferentemente do clássico pattern Factory que traz a instância de uma implementação, quando se trata de DI ocorre a inversão desse controle e o Guice simplifica com uma simples anotação @Inject dizendo onde o conteiner vai injetar.

Code 1.

public class Cliente {

private Service service;

@Inject

public Cliente(Service service) {

this.service = service;

}

public void getMyService(){

service.getService();

}

}

No Code 1 acima usa-se uma injeção por construtor. O mais interessante é a configuração de dependência:

Code 2.

@ImplementedBy(ServiceImpl.class)

public interface Service {

void getService();

}

@Singleton

public class ServiceImpl implements Service {

public void getService() {

System.out.println(“Metodo getService foi chamado”);

}

}

Pronto, agora podemos testar o nosso exemplo a partir da classe Cliente do Code 1, as anotações @ImplementedBy define sua implementação de classe eliminando qualquer código, e a @Singleton define o escopo de implementação por padrão o Guice cria uma instância a cada chamada.

Code 3.

public class App {

public static void main(String[] args) {

Injector guiceInj = Guice.createInjector(new Module[0]);

Cliente c = guiceInj.getInstance(Cliente.class);

c.getMyService ();

}

}

Se tivermos sorte nosso Code 3 irá imprimir “Metodo getService foi chamado”, é claro podemos também definir nosso bind explicitamente por construção de módulos:

Code 4.

public class MyModule implements Module {

public void configure(Binder binder) {

binder.bind(Service.class).to(ServiceImpl.class).in(Scopes.SINGLETON);

}

}

…..

Injector guiceInj = Guice.createInjector(new MyModule());

Cliente c = guiceInj.getInstance(Cliente.class);

c.getMyService ();

……

O Code 4 mostra que um único metodo da interface é definido com um objeto Bind, podendo ser usado para definir sua especial sintaxe que pode ser lido da seguinte forma: “Amarra interface Service a implementação ServiceImpl no escopo Singleton”. Ate ai tudo bem, mais como sair da situação onde temos mais de uma implementação para nossa Service.class? Podemos também utilizar o AbstractModule para fazer nossa subclasse. A mesma implementa a interface Module e não define argumento no metodo configure, sigamos o exemplo com essa implementação:

Code 5.

public class MyModule extends AbstractModule {

public void configure() {

bind(Service.class).to(ServiceImpl.class);

bind(Service.class).to(ServiceImplNew.class);

}

}

Provavelmente quando for executar esse Code 5 irá ocorrer um erro de execução, pois o Guice não trabalha desta forma, então como sair dessa situação? Simples, basta fazer um bind com anotação da seguinte forma:

Code 6.

public class MyModule extends AbstractModule {

public void configure() {

bind(Service.class).to(ServiceImpl.class);

bind(Service.class).annotateWith(Marca.class).to(ServiceImplNew.class);

}

}

Isso mesmo, podemos definir um bind com uma marcação anotada em uma determinada requisição, vamos a sintaxe lendo da esquerda para direita: “Amarra todas as requisições para a interface Service anotado com @Marca para a implementação ServiceImpl”, porém a anotação @Marca deve ser criada programaticamente com a seguinte estrutura:

Code

Explanation

@Retention(RetentionPolicy.RUNTIME)

Anotação em tempo de execução

@Target({ElementType.FIELD,ElementType.PARAMETER})

Onde pode ser colocada

@BindingAnnotation

Informa que é uma anotaçao ‘binding’

Public @interface Marca{}

Como é declarada

Feito isso basta definir como marcação:

public class Cliente {

private Service service;

@Inject

public Cliente(@Marca Service service) {

this.service = service;

}

……

Bom, explorando mais a fundo o Guice podemos encontrar inúmeras funcionalidades como bindInterceptor, Aspect-Oriented Programming (AOP), Integrating Web(Struts 2, Wicket) entre outros, onde pode ou não trazer benefícios para sua arquitetura, isso vai depender muito do que você precisa e com que você esta trabalhando. Anteriormente em muitos fóruns já foi discutido isso, e muita gente não se sente muito confortável de como o Guice trabalha, porém, temos que concordar que não há muito que refazer com o que já foi feito só nos resta a escolha. Boa sorte a todos e espero que eu tenha ajudado de alguma forma com esse meu primeiro post.

Referencias:

http://martinfowler.com/bliki/InversionOfControl.html

http://www.javafree.org/content/view.jf?idContent=1

http://www.apress.com/book/view/9781590599976

http://code.google.com/p/google-guice/