Integrando Adobe Flex + BlazeDS + SpringFramework + Hibernate – Uma Solução OpenSource para Sistemas Web. (Parte 1)

Olá Pessoal,

Hoje vou começar algo que estou prometendo há um bom tempo! A integração dos seguintes frameworks:

Adobe Flex;

Adobe BlazeDS;

Spring Framework;

Hibernate;

Introdução

No mundo de desenvolvimento WEB principalmente com Java, temos problemas quanto ao desenvolvimento de interfaces, como incompatibilidade entre browsers, desenvolviemento lento, e outros detalhes que muitos vivenciam diariamente.

Existem soluções que prometem como o JSF por exemplo, mas como dizem “A primeira experiência em Flex o programador Java nunca esquece.” logo quero convidar você que vem do mundo do Java, para conhecer uma solução de desenvolvimento de interfaces com o AdobeFlex.

Apresentando Adobe Flex e Adobe BlazeDS

Adobe Flex

Do Flex não vou falar muito, também por que neste blog você pode encontrar muito conteúdo explicativo como por exemplo este link: http://23.20.48.222/?p=32 algumas abordagens ali já estão desatualizadas, porém a essência é a mesma como por exemplo algumas vantagens de se usar Flex:

O Flex é executado a partir de uma máquina virtual, logo o programador apenas se preocupa em desenvolver a interface não em programar compatibilidade entre browsers.

Você programa sua interface totalmente orientada a objetos, isso visa reuso de componentes, desenvolvimento de módulos e afins.

Há várias maneiras de comunicar o Java com o Flex, mas em destaque é que você pode trocar objetos Java/Flex por um protocolo que provê compactação e tranferência binária, este é o AMF.

Adobe BlazeDS

O BlazeDS é um produto OpenSource (Licença LGPL v3) que corresponde à tecnologia JAVA server-side que dá suporte tanto para o Remoting assim como ao Messaging de objetos trocados entre o Java e o Flex/Flash.

Com o BlazeDS você pode gerar vários tipos de canais de conexão, um destaque muito importante para toda a comunidade Flex/Flash mundial, é que o serviço de data-push também foi disponibilizado de graça!, para quem não conhece, é algo semelhante ao Pattern Observer.

Integrando o Adobe Flex com o BlazeDS

Requerimentos:

Eclipse 3.3;

Adobe Flex Builder 3 Plugin;
*No título apresento como solução OpenSource, e o FlexBuilder 3 é pago, mas irei fazer uso apenas para facilitar o entendimento, caso seja estudante, baixe o FlexBuilder 2 é de graça para estudantes ou afins, caso não, baixe o Flex SDK e compile com Ant ou com o FlashDeveloper que é de graça.

Adobe BlazeDS;
*É recomendável que baixe a documentação do BlazeDS, para futuros estudos.

Tomcat 6.0;

Ok, Vamos começar!

Extraia o Eclipse 3.3 em algum lugar, por exemplo C:/Desenvolvimento/Eclipse 3.3/

Instale o Plugin do Flex no Eclipse, quando pedir o local aonde instalar o flex sdk, você pode selecionar em C:/Desenvolvimento/Frameworks/Adobe/

Após baixado o BlazeDS, perceba que ele vem vários arquivos, o que importa agora são os seguintes:

blazeds-samples.war

blazeds.war

No blazeds-samples.war como o próprio nome diz, contém aplicações de exemplo, como implementação do data-push, um chat, e etc…

O blazeds.war contém tudo o que é necessário para podermos configurar nossa aplicação.

Você deve ter percebido que no arquivo que você baixou o BlazeDS, contém um Tomcat já com todas as libs necessárias e etc.. Algumas libs ali tem reelevância como a flex-tomcat-common.jar e flex-tomcat-server.jar mas vamos deixar isso para outro artigo =)

Apesar do BlazeDS já vir com um Tomcat, eu estarei usando meu próprio Tomcat 6.0.

Abra seu Eclipse, e faça como no screencast abaixo que mostra como criar seu projeto no Eclipse 3.3:

Link Externo

*Se na aba “Problems” estiver com o erro “Cannot create HTML wrapper. Right-click here to recreate folder html-template.” clique com o botão direito, e clique em Recreate HTML Templates. Considero isso um bug do FlexBuilder.


Com o projeto criado, vamos adicionar as libs necessárias para a execução do BlazeDS, para isso abra o blazeds.war (Com um Winrar da vida) e copie todos os Jars contidos na pasta WEB-INFlib para o nosso projeto na pasta WebContentWEB-INFlib.

Com as Libs adicionadas, vamos criar um serviço no java que servirá como exemplo de como o Flex pode acessar uma classe java através do BlazeDS.

Para isso na pasta src_java, crie uma estrutura de pacotes, por exemplo:

com/digows/artigos/JavaFlex/model/service/
com/digows/artigos/JavaFlex/model/entity/

Dentro do package entity crie uma classe java com o nome de Cargo com o seguinte conteúdo:

Cargo.java
[java]

package com.digows.artigos.JavaFlex.model.entity;

public class Cargo {

private long idCargo;
private String dsCargo;

public long getIdCargo() {
return idCargo;
}
public void setIdCargo(long idCargo) {
this.idCargo = idCargo;
}
public String getDsCargo() {
return dsCargo;
}
public void setDsCargo(String dsCargo) {
this.dsCargo = dsCargo;
}
}

[/java]

Entities (ou Entidades, nenhuma relação com Entity Beans) são objetos que possuem uma identidade única.

Um carrinho de compras numa loja virtual web não é igual a outro, não importa que possuam os mesmos produtos, o carrinho A é o carrinho do usuário A, o carrinho B é do usuário B. Mesmo que contenham os mesmos produtos você não pode exibir o carrinho B ao usuário A, eles são diferentes! O carrinho neste exemplo segue o Padrão Entity, ele é uma entidade de negócios única.

Dentro do package services crie uma classe java com o nome de CargoService com o seguinte conteúdo:

CargoService.java
[java]

package com.digows.artigos.JavaFlex.model.service;

import java.util.ArrayList;
import java.util.List;

import com.digows.artigos.JavaFlex.model.entity.Cargo;

public class CargoService {

public Cargo save(Cargo p_cargo) {
System.out.println(“Salvou o Cargo: “+p_cargo.getDsCargo());
return p_cargo;
}

public void remove(Cargo p_cargo) {
System.out.println(“Excluiu o Cargo: “+p_cargo.getDsCargo());
}

public List getList() {
return new ArrayList();
}

public Cargo findByPrimaryKey() {
return new Cargo();
}
}

[/java]

Services são classes que não implementam diretamente as regras de negócio da aplicação, apenas coordenam a interação entre os componentes, elas são quase sempre beans gerenciados pelo Spring. É muito importante que as classes do tipo Services não implementem as regras de negócio, elas apenas atuam como Façades coordenando as interações.

O CargoService claro não proverá persistência a um banco de dados, os sysouts ali são apenas para abstração da intragração.

Com as classes javas feitas, vamos a configuração dos channels do BlazeDS, para isso no web.xml contido dentro da pasta WebContentWEB-INFweb.xml, deixe como mostrado abaixo:

web.xml

[xml]

ArquiteturaJavaFlex

MessageBrokerServlet
MessageBrokerServlet

flex.messaging.MessageBrokerServlet

services.configuration.file
/WEB-INF/flex/services-config.xml

flex.write.path
/WEB-INF/flex

1

MessageBrokerServlet
/messagebroker/*

index.html
index.htm
index.jsp

[/xml]

Perceba que ao gerar a Servlet Java, é passado por parâmetro um arquivo dentro da pasta WebContentWEB-INFflex, crie um arquivo chamado services-config.xml como referênciado, este arquivo é o que contém Factorys, Channels, LogConfigs. Nós vamos usar apenas um tipo de serviço que o BlazeDS implementa, que o canal de AMF3 simples, para isso adicione o seguinte conteúdo:

services-config.xml

[xml]

false

[BlazeDS]
false
false
true
false

<!–Endpoint.*–>
<!–Service.*–>
Message.*
DataService.*
Configuration

true
20
{context.root}/WEB-INF/flex/services-config.xml
{context.root}/WEB-INF/flex/remoting-config.xml
{context.root}/WEB-INF/web.xml

[/xml]

Perceba que é feito um include em um arquivo chamado: remoting-config.xml, então crie um arquivo com este nome na pasta WebContentWEB-INFflex. Este arquivo contém alguns adapters, e nossos destinations, que nada mais é que o mapeamento das nossas classes de serviços no java. Para isso adicione o seguinte conteúdo:

remoting-config.xml

[xml]

com.digows.artigos.JavaFlex.model.service.CargoService

[/xml]

A estrutura deverá ficar igual apresentado abaixo:

image

Para testar se tudo está ok, de um botão direito sobre o Projeto JavaFlex, e clique em Run As -> Run on Server. Na proxima janela aberta, em server runtime deixe seleciona o “Apache Tomcat v6.0 e clique em finish, o Servidor irá iniciar, observer a aba Console para verificar possíveis erros. Se alguma Exception tiver ocorrida, verifique os passos e faça novamente.

Acessando o serviço Java através do remoting do BlazeDS

Como nosso serviço já foi levantado, basta gerarmos um form simples para testar nosso serviço, para isso na pasta src_flex, crie a seguinte estrutura de pastas:

com/digows/artigos/JavaFlex/view/entity/
com/digows/artigos/JavaFlex/view/screen/

Dentro do package Entity crie uma Classe ActionScript com o nome de Cargo com o seguinte conteúdo:

Cargo.as
[as]

package com.digows.artigos.JavaFlex.view.entity
{
[RemoteClass(alias=”com.digows.artigos.JavaFlex.model.entity.Cargo”)]
[Bindable]
public class Cargo
{
public var idCargo:Number;
public var dsCargo:String;
}
}

[/as]

A Classe Cargo do Flex, é nada mais nada menos do que o espelho do Entity do java, nesta classe não realizei get’s set’s. Para fazer o espelho dos objetos usei a metatag [RemoteClass] mapeando a localização exata (Com package e nome da Classe) da mesma classe no java. A metatag Bindable é uma annotation muito importante, mais agora vamos apenas abstrair ela.

E dentro do package Screen, crie um arquivo MXML com o nome de CargoForm com o seguinte conteúdo:

CargoForm.mxml

[xml]

[/xml]

Perceba que acoplei muito código neste arquivo, isto não é uma boa prática, nos próximos artigos irei desaclopar as responsabilidades em camadas.

Para testar se tudo está ok, no arquivo JavaFlex.mxml que está na raiz da pasta src_flex renomeie para index.mxml, de um botão direito e clique em Set as Default Application, e deixe ele com o seguinte conteúdo:

index.mxml

[xml]

[/xml]

E para finalizar vamos dizer ao compilador do Flex que existe um servidor de AMF levantado, para isso de um botão direito no projeto JavaFlex -> Properties -> Selecione Flex Compiler -> em Additional compiler arguments adicione a linha e ok:

-services “../WebContent/WEB-INF/flex/services-config.xml”

Para Executar, de um botão direito sobre o projeto JavaFlex, e clique em Run As -> Run on Server e Finish.

Se tudo correr bem, você verá a descrição que você digitou no flex aparecerá no console do Tomcat.

Bom finalizo aqui a primeira parte desta poderosa integração, logo logo posto o resto.

Link do Source do Projeto:
Download

Abraço Pessoal!!

o/

Te Amuh Liz!! =******

93 thoughts on “Integrando Adobe Flex + BlazeDS + SpringFramework + Hibernate – Uma Solução OpenSource para Sistemas Web. (Parte 1)

  1. Eberton

    Rodrigo Parabéns cara…
    Com atitudes assim que nossa comunidade vai crescer cada vez mais, espero que esse artigo venha a incentivar todos aqueles que usam o Flex com outras tecnologias de back-end.

    Parabéns…

    Like

    Reply
  2. Rodrigo Pereira Fraga

    Olá,

    Na documentação, está assim:

    Application Servers
    Tomcat 6.0.14
    JBoss 4.2.2
    WebLogic 10 MP1
    WebSphere 6.1.0.13

    Perceba que ele fala somente em Tomcat 6,
    não testei por que não tenho o tomcat 5.x aqui mas…
    acredito que pegando as libs que vem com o tomcat que vem junto ao blaze, também irá funcionar.

    Like

    Reply
  3. Daniel Souza

    galera, seguindo o screncast, fiz como ele, mais me da esse error, alguem da uma força ?

    unable to open ‘C:eclipsepluginscom.adobe.flexbuilder.project_2.0.155577resourcesframeworks/flex-config.xml’

    Like

    Reply
  4. Rodrigo Pereira Fraga

    Provavelmente o plugin do FlexBuilder não foi devidamente instalado, lembrando também que o exemplo faz uso do flex builder 3.

    Like

    Reply
  5. Liz

    é!…bom…o FLex…ele…bem,ele…=X! não …vou começar falando do Java! é melhor!…bom o Java…oQ é isto mesmO??…o.O! ah! não seii…e nem kero saber!!
    na verdade só entendi uma frase! a parte que me toca: “Te amuh Liz =***”, e essa na minha opinião é a melhor linguagem de todas…não tem pra Java,não tem pra ninguém!! HIUihihiahh…:P! e o melHOr…tOdO mundo sabe!;)!
    Te amoo minHa vidah!
    mtooooo!;***
    de tdOo meu coraçãoO!(L)
    vocÊ é o melhoor!

    Like

    Reply
  6. Janderson Fernandes Cardoso

    Parabéns mais uma vez rodrigo, através do seu blog tenho aprendido muito coisa do adobe flex, mais posso te pedir um favor 🙄 , considero o Flex a grande aposta para o novo modelo de web (3.0), mais não sai da minha cabeça que o adobe Air é também o futuro do dekstop (2.0), será que tem como demostrar no seu blog como faria este mesmo exemplo que está bem sugestivo usando o adobe Air, eu preciso muito de um exemplo do adobe air com backend java, já procurei mais não consigo achar, desde de já obrigado.

    Like

    Reply
  7. George Tavares

    Muito interessante o exemplo.
    Estudo a algum tempo Flex, e sempre usei Java , com EJB3 e Hibernate.
    Uma duvida que sempre tive integrando essas tecnologias é como funciona a esse mapeamento de objetos java para flex, quando o objeto java possui instrumentacao, mais especificamente, as colecoes lazy do hibernate. O BlazeDS tem a inteligencia de voltar ao java, abrir uma sessao do hibernate e puxar a colecao lazy? Como resolver essa situacao?

    Like

    Reply
  8. Rodrigo Pereira Fraga

    Olá George, isso realmente é um problema na verdade não só com o flex mas de aplicações WEB em geral.
    Com html, (Request, Response) o pessoal usa o Pattern “OpenSessionInView” com o hibernate então consegue um workaround (contorno do problema).
    Com o LCDS, é possível fazer tais manipulações com o banco de dados, pois ele tem um módulo excluisivo para trabalhar com os Dados (Data Manager se não me engano.)
    Já com o BlazeDS, esse módulo não foi disponibilizado, logo trabalhar com coleções usando o Lazy do hibernate é um pouco complicado. Existem workarounds para isso, aqui nesse link já abri uma discussão sobre isso -> http://tech.groups.yahoo.com/group/flexcoders/message/98655
    Ali há algumas idéias de como você pode resolver isso. Eu na verdade ainda não defini um jeito bacana de usar Lazy.
    Mas acredito que ainda assim, dá para implementar uma espécie de “OpenSessionInViewFlex” heehehee
    Se achar outra solução, me avise.
    Obrigado.

    Like

    Reply
  9. George Tavares

    Obrigado Rodrigo ,

    Na verdade o OpenSessionInView ate seria facil de implementar com o Spring, mas o problema eh outro, eh questao que com Flex eh feito uma requisicao e vem os objetos. Numa segunda requisicao eh que iriamos andar nas relacoes, ai nem o OpenSessionInVIew resolve, porque o objeto que tinhamos, esta em outra conexao do banco de dados. Teriamos que ressussitar o objeto na nova conexao do banco/hibernate. Vou estudar o assunto. Obrigado

    Like

    Reply
  10. Pingback: Integrando Adobe Flex + BlazeDS + SpringFramework + Hibernate - Uma Solução OpenSource para Sistemas Web. (Parte 2 - Final) - Rodrigo Fraga - RIA Evangelist

  11. Pingback: FlexDev » Blog Archive » Artigo Flex+BlazeDS+Spring+Hibernate

  12. Rodrigo Pereira Fraga

    Mas qual a dificuldade?

    O Flex Builder é somente uma IDE, o BlazeDS é apenas um Framework que roda no back-end, resumindo… não tem muito a ver..

    =)

    Like

    Reply
  13. Ricardo

    Parabens pela atitute!
    Mas estou tentando seguir a risca mas não consigo, que plugin vc usa no eclipse para criar um projeto web dinamico?

    Estou usando eclipse 3.3.1.1.

    Like

    Reply
  14. Janderson

    Vlw Rodrigo, parabéns mais uma vez pelo artigo, muito bom. Fiz o exemplo como o artigo e funcionou legal, tentei adptar ao modelo que uso sem spring, usando hibernate annotation e o flex acessando minha classe controladora, aí no flex deu um erro que não acha o hibernate:
    “[BlazeDS] [ERROR] Root cause: java.lang.NoClassDefFoundError: org/hibernate/cfg/AnnotationConfiguration”
    será que alguém pod eme ajudar? vlw

    Like

    Reply
  15. Rodrigo Pereira Fraga

    Olá Janderson,

    Ao que parece vc está usando Annotations no hibernate,
    Então verifique se os jars:

    hibernate-annotations.jar;
    hibernate-commons-annotations.jar;
    ejb3-persistence.jar;

    Estão no classpath do projeto.

    Abraços
    o/

    Like

    Reply
  16. Janderson

    Rodrigo, se eu usar uma classe main(String[] args) para testar o hibernate ele grava normal no mysql, mais quando tento no flex parece que ele não acha o meu hibernate, estou 1 semana já tentando colocar o hibernate.cfg.xml em tudo que é lugar e nada. Já não sei mais o que pode ser, conseguir criar um modelo que não precisa do VO e está funcionado mais para minha infelicidade o hibernate não colabora agora. De qualquer forma Muito obrigado pela sua atenção!

    Like

    Reply
  17. Ricardo

    Rodrigo, sou iniciante e gostaria de saber que domumentação você usou para montar este projeto? Gostaria de saber o caminho das pedras, para que eu consiga montar meu raciocinío.
    Valeu..

    Like

    Reply
  18. Rodrigo Pereira Fraga

    @Ricardo,

    Amigo, depende do que! eheheh

    Pois na verdade quase tudo o que foi utilizado, também apresentei a documentação, tipo do Spring, Blaze, Hibernate…

    Só não falei do DomainDrivenDesing, este é muito complexo para ser abordado aqui.

    Abraços!
    o/

    Like

    Reply
  19. Araújo Jr.

    Olá Rodrigo, primeiro de tudo, gostaria de parabenizá-lo pelo tutorial que sem dúvida é top de linha. Bom, eu tentei seguir o tutorial mas por conta de ser bastante imaturo ainda na tecnologia Flex devo ter cometido algumas barbaridades…
    Aqui exibe a seguinte mensagem de erro:[faultCode:Client.Error.MessageSend faultString:’Send failed’ faultDetail:’Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Failed: url: ‘http://localhost:8080/JavaFlex/messagebroker/amf”]
    Alguma sugestão??
    Saudações Respeitosas.

    Like

    Reply
  20. Pingback: Manifesto Flex brasil - Rodrigo Fraga - RIA Evangelist

  21. Fábio

    Olá Rodrigo, parabéns pelo tutorial. Está muito legal.
    Bom tive a mesma mensagem de erro que o Araujo Jr.
    “http://localhost:8080/JavaFlex/messagebroker/amf”. No console do Eclipse exibe a mensagem que o MessageBroker não está acessível. Sou iniciante no eclipse, já configurei o tomcat um monte de vezes. Tem alguma idéia do que pode ser??
    Obrigado,

    Abraços…

    Like

    Reply
  22. Cristiano

    Olá,

    estou iniciando com Flex e Java e estou tendo dificuldade em fazer funcionar o exemplo deste tutorial. quando executo o seguinte erro aparece no tomcat:

    The processing instruction target matching “[xX][mM][lL]” is not allowed.

    Like

    Reply
  23. George Queiroz

    Olá Rodrigo…

    Então a integração funciona uma beleza, mais me diga o seguinte. Sendo que o hibernate para identificar uma entidade para save ou update ele se baseia no id da mesma nulo ou não, como funciona ao enviar um valor do flex+blazeds para uma entidade do hibernate, visto que quando é int ou Number ele envia zero?

    George

    Like

    Reply
  24. Rodrigo Pereira Fraga

    Você chegou a testar?

    Aqui no projeto apresentado, a ID quando nula sempre vai zero, e a configuração default do hibernate para chaves-primárias onde a ID é do tipo int ou derivado, quando o valor é 0, o hibernate trata como um novo registro.

    Abraços

    Like

    Reply
  25. Daniel

    Olá Rodrigo..

    Tenho uma dúvida, mas que ainda não consegui resolver (falta de tempo). O BlazeDS, como vc colocou, pode fazer um data-push. Isso inclui a parte de DataManagement ou só a parte de mensageria?

    Obrigado!

    Like

    Reply
  26. Rodrigo Pereira Fraga

    Olá Daniel,
    O BlazeDS é composto apenas pela mensageria, mas o que realmente você quer do modulo Datamanagement?

    Fique de olho, já existe algumas soluções que servem como add-on ao BlazeDS. LazyLoad mesmo eu já conheço 2 projetos.

    Abraços.

    Like

    Reply
  27. Daniel

    Rodrigo,

    Como DataManagement eu quero dizer o DataService. Eu vi que RPC e MessageService o BlazeDS tem, então fiquei com dúvida no DataService. Vc poderia me dizer algum add-on que supra essa necessidade?

    Muito Obrigado!

    Like

    Reply
  28. Adriano

    Olá Rodrigo, antes de tudo PARABÉNS!!
    Excelente artigo para nós iniciantes termos uma referência!!

    Quando faço Run on Server me dá o seguinte erro:
    type Status report
    message /JavaFlex/
    description The requested resource (/JavaFlex/) is not available.

    Alguém me ajuda?

    Like

    Reply
  29. Rodrigo Pereira Fraga

    Olá Adriano,

    Muito obrigado pelo feed-back,

    Quanto ao seu erro, este é muito evasivo.

    Para ter mais detalhes, por favor verifique seu stacktrace no console do tomcat.

    Dúvidas posteriores, use o Forum: http://forum.flexbrasil.com.br/
    Para tirar mais dúvidas, a comunidade poderá te ajudar.

    Abraços.
    o

    Like

    Reply
  30. David

    Oii Rodrigo!
    Agradeço muito voce pelos posts desta integraçao! (Parte 1 y 2) Estão sendo de grande valor pra mim, andei muito pra facer rolar esta integraçao, y con sua ajuda estou conseguindo. Amanha vou pela parte 2.
    Muchas gracias!!!
    Un grande abrazo desde paraguay!

    Like

    Reply
  31. Rodrigo Pereira Fraga

    Olá David,

    Fico muito feliz em saber que estou ajudando pessoas outros paises.

    Paraguay?, eu moro em Foz do Iguaçu, fronteira com Ciudad del leste. =)

    Bons estudos amigo.

    Like

    Reply
  32. Bruno Queiroz Mendes

    Olá Rodrigo, já postei aqui algum tempo atrás…e queria saber de você sobre o Lazy Loading que acontece quando preciso de obter um pojo que possui uma Collection. Já sei que o flex sempre carrega todo pojo e porisso acontece o erro, e sei isso é resolvivel com o OpenSessionInView do Spring. Tem como mostrar isso pra gente? faz um upgrade ae neste tutorial..abraço

    Like

    Reply
  33. Christian

    Parabéns, Rodrigo!!!!
    Artigo muito bem escrito!!!!

    Dica: Como eu tinha projeto separados (Java e Flex) ao inves de usar a diretiva de compilação (-services), no remoteObject usei o endpoint.:

    Like

    Reply
  34. Lindberg

    Rodrigo fiz tudo como vc falow, mas quando vou executar aparece a seguinte msg -> INFO: Servlet MessageBrokerServlet is currently unavailable

    Gostaria que me ajudasse, pois to precisando muito aprender como fazer a integração do Flex com o Java e nao consegui ainda. Se possível se alguem souber onde tem uma video aula por favor manda ai! Agradeço!

    Like

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s