• Nenhum resultado encontrado

Tratamento de Eventos Orientado à Composição de Serviços Web Documento Técnico para Configuração e Validações Práticas (data: 27/02/2012)

N/A
N/A
Protected

Academic year: 2021

Share "Tratamento de Eventos Orientado à Composição de Serviços Web Documento Técnico para Configuração e Validações Práticas (data: 27/02/2012)"

Copied!
12
0
0

Texto

(1)

Tratamento de Eventos Orientado

à Composição de Serviços Web

Documento Técnico para

Configuração e Validações Práticas

(data: 27/02/2012)

Mauricio Chui Rodrigues (chui@usp.br)

(2)

Índice

1. Introdução...3

2. Módulo de Extensão...4

2.1. Artefatos e Configuração...4

2.2. Serviços Web para Composição...5

2.2.1. Declaração de Operações de Serviços Web...5

2.2.2. Requisitos...6

2.3. Definição de Tipos de Parâmetros...6

2.3.1. Serviços SOAP...7

2.3.2. Serviços REST...7

2.4. Recebimento de Chamadas de Retorno...8

2.5. Atividades Módulo x Núcleo...8

2.6. Pendências de Integração...9

3. Realização de Testes com o Módulo...10

3.1. Artefatos e Configuração...10

3.2. Aspectos Técnicos...11

(3)

1. Introdução

Este documento é um complemento à dissertação de mestrado “Tratamento de Eventos Orientado à Composição de Serviços Web” e apresenta detalhes técnicos referentes à implementação do trabalho. O embasamento teórico e outros resultados obtidos devem ser consultados no texto da dissertação, disponível em http://www.ime.usp.br/~chui/wedflow/.

A dissertação propõe uma forma de composição de serviços Web em que o fluxo de execução não é um requisito, como identificado junto às mais diversas implementações de coreografias e orquestrações; por meio da constante avaliação do estado dos dados, definem-se os momentos em que determinadas atividades devem ser realizadas, o que torna o fluxo de execução uma consequência. A forma proposta de composição tem como base a abordagem WED-flow de gerenciamento de processos de negócio.

Para que haja a aplicação prática dos conceitos apresentados, é necessária a implementação de dois principais módulos:

(1) o núcleo WED-flow, responsável pelo mecanismo geral de monitoração de eventos e por identificar quais são as atividades a serem realizadas, bem como os dados que devem ser transmitidos e que tipo de resultado deve ser esperado, entre diversas outras funções;

(2) o módulo de extensão para comunicação com serviços Web, que provê ao núcleo a capacidade de operar serviços como atividades disponíveis para composição: o cadastro de serviços Web (SOAP ou REST), a interação direta com os serviços e o tratamento dos dados enviados e recebidos na comunicação são alguns dos papéis que exerce.

Tanto este documento quanto a dissertação relacionada remetem ao segundo item, enquanto o núcleo é parte de outra dissertação. Portanto, apenas propriedades do núcleo que sejam relevantes para a compreensão da extensão proposta são abordadas. Mais informações sobre o núcleo WED-flow em breve serão publicadas.

(4)

2. Módulo de Extensão

Devido à escolha de Ruby como linguagem para a implementação do núcleo WED-flow, esta também foi a linguagem adotada para o módulo que habilita a comunicação com serviços Web. O desenvolvimento e os testes se deram com o Ruby 1.8.7 e o RubyGems 1.3.5, além das seguintes gems:

• actionpack (2.2.2, 1.13.6) • activerecord (2.2.2, 1.15.6) • activeresource (2.2.2) • activesupport (2.2.2, 1.4.4) • json (1.6.3) • postgres (0.7.9.2008.01.28) • rails (2.2.2) • rake (0.8.7)

Nota-se que o banco de dados escolhido para o armazenamento de informações é o PostgreSQL, mais especificamente o PostgreSQL 8.4.8 para Ubuntu. A escolha do banco de dados também foi influenciada pela implementação do núcleo WED-flow.

2.1. Artefatos e Configuração

Todos os artefatos produzidos como resultado prático da dissertação podem ser encontrados para download em http://www.ime.usp.br/~chui/wedflow/. Ao descompactar o arquivo disponível, deve surgir um diretório chamado ws_module com todo o código-fonte. Espera-se que o ambiente esteja apto à execução dos componentes desenvolvidos, portanto devem ser instalados o Ruby, o RubyGems e o PostgreSQL.

A instalação do RubyGems habilita o comando “gem”. Para baixar e instalar cada uma das gems mencionadas, basta executar o comando abaixo. É possível que as versões sejam diferentes das citadas, dependendo da versão do RubyGems.

gem install <nome-da-gem>

Para as configurações de acesso aos dados, utilize algum cliente de sua preferência para o PostgreSQL; se não tiver um, recomenda-se o pgAdmin, cliente normalmente adotado pelos usuários. Então realize os seguintes passos:

• Estabeleça um servidor em localhost, porta 5432;

• Crie um usuário cujo nome e cuja senha sejam iguais a “wsmodule”; • Defina, no servidor criado, um banco de dados chamado “wsmodule”.

O módulo já está configurado para utilizar o banco e o usuário descritos para a leitura e escrita de dados. Caso opte por alterar alguma das informações, lembre de alterar também o arquivo de

(5)

configurações config/database.yml.

As tabelas do banco de dados, assim como dados úteis para testes, são criadas por meio da execução de dois comandos. Acesse o diretório ws_module e execute, nessa ordem:

rake db:migrate rake db:populate

Finalmente, para iniciar a execução do módulo, acesse o diretório ws_module/script/ e execute o script que inicia o servidor:

./server start

O servidor disponibiliza seus recursos, por padrão, na porta 3000 do localhost. Assim, uma vez iniciado o servidor, deve se tornar acessível o endereço em http://localhost:3000. Os arquivos de log resultantes do uso do módulo de extensão surgirão no mesmo diretório ws_module assim que houver a primeira execução.

2.2. Serviços Web para Composição

O módulo de extensão desenvolvido necessita da declaração dos serviços Web a serem

compostos, o que pode ser feito via uma interface Web bastante simples, desde que o servidor esteja em execução. Todos os serviços declarados devem estar de acordo com os requisitos impostos para a adaptação à WED-flow.

2.2.1. Declaração de Operações de Serviços Web

Operações de serviços REST podem ser gerenciadas em http://localhost:3000/rest_operations. Para definir uma nova operação, são necessárias as seguintes informações:

Descrição: apenas algo que facilite a posterior identificação;

Método HTTP: método ao qual está associada a operação (ex.: POST);

Tipo do conteúdo: duas possibilidades, JSON ou XML;

Máscara de URL: endereço para a chamada da operação, com eventuais parâmetros

substituídos por “%s” (ex.: http://localhost:1234/resources/%s).

Já o endereço http://localhost:3000/soap_operations permite gerenciar as operações SOAP. Dois tipos de operações SOAP são habilitadas, as síncronas (devolvem resultados como resposta da

chamada) e as assíncronas (operações cujas respostas não devem ser esperadas de imediato, mas sim ser recebidas posteriormente). Seguem as propriedades que devem ser informadas:

Descrição: apenas algo que facilite a posterior identificação;

Endereço do arquivo WSDL: endereço para o arquivo que descreve o serviço em questão;

Nome da operação: nome como descrito no arquivo WSDL;

(6)

E a declaração dos parâmetros de entrada e saída? O vínculo entre operações e dados é promovido pelo núcleo WED-flow, que se responsabiliza por informar isso ao módulo. Embora os valores e os tipos de parâmetros sejam transmitidos do núcleo para o módulo, os tipos necessários devem ser estabelecidos junto ao último, vide a Seção 2.3.

2.2.2. Requisitos

Espera-se que tanto as operações de serviços SOAP quanto de REST atendam a um requisito básico: a capacidade de leitura e escrita de dados. Isso significa que, caso a interação com dados se faça necessária, os próprios serviços devem satisfazê-la; somente dados devolvidos como respostas a operações devem ser tratados pelo módulo de extensão.

Os monitores WED-flow avaliam o estado dos dados como um todo, como se os dados necessários para a execução estivessem em um grande quadro negro; a cada estado consistente

atingido, as informações podem ser replicadas para seus domínios reais. Para o uso real do módulo de extensão, é necessário, assim, que todos os serviços Web para composição operem com os dados mantidos pelo WED-flow. No entanto, para validar somente o funcionamento do módulo, com um comportamento simulado do núcleo, é possível o uso de serviços que utilizam somente os dados reais.

Operações SOAP assíncronas consistem no único tipo de operação que deve satisfazer a requisitos específicos:

1. Assim que a atividade assíncrona for disparada, deve ser devolvida uma resposta intermediária ao módulo de extensão;

2. Quando a atividade terminar, uma chamada de retorno (popularmente conhecida como callback) deve ser feita para o módulo;

3. A resposta intermediária e a chamada de retorno devem possuir dados comuns que permitam

ao módulo a identificação de um vínculo único.

Serviços Web com operações assíncronas só devem, assim, ser alterados para compatibilidade com o módulo de extensão caso não atendam aos requisitos. O tratamento da resposta intermediária e o recebimento da chamada de retorno são implementados junto ao módulo e não requerem alteração do serviço.

2.3. Definição de Tipos de Parâmetros

O módulo de extensão precisa receber os parâmetros de acordo com estruturas pré-definidas, de modo que possam ser empregados nas interações com os serviços Web. Cada estrutura é uma classe implementada junto ao módulo e varia de acordo com o tipo da operação; exemplos podem ser

consultados junto aos artefatos de teste, descritos no Capítulo 3 deste texto. Com o intuito de manter a organização, todos os tipos de parâmetros devem ser salvos no diretório ws_module/app/

models/ws_param/.

Vale lembrar que o núcleo WED-flow é o responsável por preencher os atributos dessas classes antes de acionar o módulo.

(7)

2.3.1. Serviços SOAP

Há quatro classes básicas voltadas à implementação de parâmetros para operações de serviços SOAP. Supõe-se que todas as filhas dessas classes declarem seus respectivos atributos e possuam construtores próprios para o preenchimento dos mesmos. Informações sobre as classes se encontram abaixo:

WsParam::SoapInput: base para parâmetros de entrada, demanda a implementação do

método inputAttributes(), que prepara os valores preenchidos para os atributos de modo a viabilizar seu envio ao serviço Web;

WsParam::SoapOutput: base para parâmetros de saída de operações síncronas, só impõe que suas classes filhas apresentem um construtor que preencha os atributos com base na resposta de uma operação;

WsParam::AsyncSoapOutput: base para parâmetros de saída de operações assíncronas e cujas subclasses devem implementar o método asyncReference(), responsável por devolver uma referência para a execução de atividade iniciada;

WsParam::AsyncSoapRef: base para as referências que vinculam respostas intermediárias

de operações assíncronas às respectivas chamadas de retorno, solicita a implementação dos métodos key() e params() para viabilizar a identificação de atividades assíncronas.

Os parâmetros recebidos junto a chamadas de retorno, no caso de operações SOAP assíncronas, dependem da forma como o serviço Web em questão estabelece a comunicação: pode tanto ser uma extensão de WsParam::SoapOutput quanto um modelo criado à parte. Detalhes sobre o

recebimento de chamadas de retorno estão na Seção 2.4.

2.3.2. Serviços REST

Operações de serviços REST que demandam parâmetros para execução precisam recebê-los em forma de documento. Como previamente descrito, o módulo de extensão opera com os formatos JSON e XML para os documentos. Devido ao uso de Ruby e Rails na implementação do módulo, criar as estruturas para esses recursos é razoavelmente simples.

Na versão do Rails utilizada para desenvolvimento e testes, todas as classes de modelagem estendem ActiveRecord::Base e, por isso, oferecem uma série de funcionalidades.

Particularmente interessante para o trabalho desenvolvido é a capacidade de conversão nativa dos modelos de e para os formatos JSON e XML. O aspecto negativo, no entanto, é que todo modelo precisa de uma tabela associada no banco de dados, o que resulta em tabelas vazias como efeito colateral. Para definir um novo modelo, deve-se especificar a estrutura da tabela com as colunas necessárias e, por fim, criar a classe relacionada, contendo todos os eventuais relacionamentos.

Versões mais recentes do Rails, mais especificamente a partir do Rails 3, possuem a classe ActiveModel, capaz de prover todas as propriedades de um modelo sem que esteja ligado a uma tabela. Assim, basta criar uma classe que inclua o módulo ActiveModel::Serialization e

(8)

definir seus atributos.

Tanto em versões a partir do Rails 3 quanto em versões anteriores, o aspecto comum é que, caso as conversões padrões não tenham o efeito desejado, os métodos relacionados (ex.: to_json() e to_xml()) podem ser reimplementados nas novas classes. De forma geral, a reimplementação consiste em invocar o método original com algumas configurações a mais.

2.4. Recebimento de Chamadas de Retorno

Para que operações SOAP assíncronas possam ser concluídas, é necessário que chamadas de retorno sejam recebidas pelo módulo de extensão. Isso significa que o módulo deve expor serviços Web dedicados à espera de tais chamadas, porém a implementação de cada serviço depende da operação em questão e do serviço de origem.

Há bastante flexibilidade para se implementar um serviço de retorno, a única restrição é que permita extrair os dados de WsParam::AsyncSoapRef que vinculem uma chamada de retorno à respectiva resposta intermediária. Toda resposta intermediária implica na criação de um registro para a atividade iniciada, o qual deve ser marcado como finalizado quando a chamada de retorno

correspondente é recebida. O endereço http://localhost:3000/async_execution_references permite consultar a situação de todos esses registros.

Um serviço de retorno pode tanto ser REST quanto SOAP e, junto ao módulo de extensão, é oferecida uma estrutura genérica para a criação de serviços REST de retorno: a classe

Callback::GenericController, localizada em ws_module/app/controllers/callback. Um

exemplo de implementação dessa estrutura genérica foi criado para os testes e pode ser encontrado no mesmo diretório mencionado. Seu funcionamento é descrito no Capítulo 3 deste documento.

2.5. Atividades Módulo x Núcleo

O fluxo a seguir é realizado para que uma operação de serviço Web seja inteiramente realizada segundo a abordagem WED-flow. Mais informações devem ser consultadas no texto da dissertação:

1. O núcleo detecta, via monitoração do estado dos dados, que deve ser realizada uma atividade; 2. O núcleo identifica que a atividade está mapeada como operação de serviço Web;

3. O núcleo extrai os valores necessários para a execução e preenche as estruturas de dados; 4. O núcleo passa ao módulo os parâmetros e o identificador da operação de serviço Web; 5. O módulo consulta as propriedades da operação com base no identificador;

6. O módulo prepara a comunicação de acordo com as propriedades da operação; 7. O módulo prepara todos os dados para envio ao serviço Web;

8. O módulo invoca a operação na interface do serviço Web;

9. [Somente assíncronas] O módulo registra a execução em curso da funcionalidade; 10. O módulo registra o término da execução junto ao núcleo.

Quanto aos aspectos técnicos, é importante ressaltar a interface disponibilizada pelo módulo para as chamadas que partem do núcleo. Independente do tipo de operação e da classe de serviço Web a

(9)

ser acionada, a interface é sempre a mesma: executeWSOperation( wsOperationId, outputType, *params )

ID da operação de serviço Web cadastrada junto ao módulo Classe para o mapeamento da resposta (nulo, se não for relevante) Parâmetros de entrada necessários para a execução

O valor de outputType é o que determina se deve haver tratamento para uma eventual resposta da operação em questão. Se for nulo, nada deve ser feito; caso contrário, o módulo checará se o resultado devolvido é compatível com o tipo informado e, se confirmado, preparará a estrutura para envio ao núcleo. O valor de outputType é obrigatório para operações assíncronas, pois corresponde à resposta intermediária previamente descrita.

Quanto a params, deve equivaler a um só objeto no caso de operações SOAP, uma vez que instâncias de WsParam::SoapInput possuem todas as informações necessárias para contato com serviços Web. Por outro lado, a multiplicidade de valores faz sentido para operações REST. Como descrito na Seção 2.2.1, essas operações são associadas a máscaras de URL com lacunas para valores, então params deve ter tamanho N+1 e ser composto da seguinte forma: os primeiros N valores devem ser aplicados no preenchimento da máscara de URL, enquanto o último deve ser a classe com os parâmetros do corpo (documento) da requisição.

Uma informação técnica relevante sobre o funcionamento do módulo é a presença de

retentativas de chamada. Caso ocorra algum tipo de problema que inviabilize a conexão a um serviço Web, são realizadas até quatro tentativas adicionais. Todas as cinco tentativas adotam um limite de

tempo de 10 segundos. Para serviços REST, ainda há outra informação importante: caso uma operação

não devolva o status de sucesso como resposta, e sim o de redirecionamento, o próprio módulo se encarrega de consultar o resultado no endereço recebido.

2.6. Pendências de Integração

Atualmente, o que realmente falta para a integração com o núcleo WED-flow é: o próprio núcleo =) Os trabalhos, realizados em paralelo, culminaram no término do módulo de extensão antes de o núcleo ficar pronto. Assim que o núcleo for terminado, os passos 1, 2, 3, 4 e 10 apresentados na seção anterior serão concretizados.

Os testes realizados com o módulo permitiram avaliá-lo de forma independente do núcleo WED-flow. Tudo o que é preciso saber sobre os testes e os artefatos relacionados consta no próximo capítulo.

(10)

3. Realização de Testes com o Módulo

Para que o funcionamento do módulo pudesse ser testado e também fosse simulada uma composição de serviços Web por meio dele, aplicações e serviços de teste foram implementados com base no exemplo de uso apresentado na dissertação: a compra em um sistema de e-commerce, passando por um gateway de pagamento até a entrega do pedido por uma empresa especializada. A linguagem de programação adotada foi Java, evitando assim a adoção repetida de Ruby. Além da versão 1.6.0_17 de Java, uma série de outras tecnologias foram utilizadas no desenvolvimento:

• Spring 2.5.3 e Velocity 1.5 para a camada de apresentação;

• EJB3 para todo o backend, tanto para aplicações quanto serviços, e para expor serviços SOAP; • RestEasy 2.2, para expor serviços REST;

• Hibernate 3.2, para o mapeamento de entidades e a integração com banco de dados. O JBoss 4.2.2 foi escolhido como servidor de aplicações e toda a construção e geração de artefatos se deu com o uso do Apache Maven 2.2.1. Em comum com o módulo de extensão

implementado, somente o PostgreSQL foi adotado como o banco de dados, inclusive na mesma versão 8.4.8, e o Ubuntu se manteve como sistema operacional.

A automação dos fluxos propostos para o caso de uso na dissertação, visando a simulação do comportamento do núcleo WED-flow, foi feita com Selenium 1. Dois scripts de testes foram

manualmente gerados em sua versão HTML para que possam ser executados via Selenium IDE, um plugin para o navegador Firefox.

3.1. Artefatos e Configuração

Todos os artefatos de testes se encontram em http://www.ime.usp.br/~chui/wedflow/, inclusive o código-fonte das aplicações e serviços Web de teste. A seguir são descritos os procedimentos para a preparação de um ambiente local contendo os artefatos implementados, portanto espera-se que a infra-estrutura (Java, JBoss e PostgreSQL) esteja pronta. Caso outro banco de dados tenha sido adotado para o uso do módulo de extensão, o mesmo pode ser aproveitado para os testes, porém deve ser feita uma variação da configuração proposta. Quanto ao servidor de aplicações e ao Java, espera-se que as versões utilizadas sejam as mesmas do desenvolvimento.

Apesar de o caso de uso conter três aplicações em diferentes domínios, todas são executáveis em um mesmo servidor, para evitar a complexidade de configuração. Assim, tudo será encontrado no mesmo IP e sob a mesma porta.

1. Faça o download do arquivo compactado somente com os binários; 2. Descompacte o arquivo no diretório “server/default/deploy” do JBoss;

3. Copie o arquivo “docs/examples/jca/postgres-ds.xml” para “server/default/deploy”; 4. Define as credenciais para acesso ao banco de dados no novo arquivo XML;

(11)

6. Certifique-se de que há dois serviços disponíveis em http://localhost:8080/jbossws/services; 7. Verifique que http://localhost:8080/app-samples/index.html se encontra disponível.

O último endereço, aliás, é de suma importância para o acesso às aplicações Web de teste. Trata-se de uma página simples que permite acessar cada uma das aplicações, além de prover duas

funcionalidades essenciais para os fluxos automatizados (sucesso e falha por dados inválidos):

Criação de massa para testes: sempre que o servidor é iniciado, o banco de dados é (re)criado

com as tabelas necessárias, portanto é possível preencher algumas delas com dados padrões; • Chaveamento de fluxo: para respeitar os princípios da abordagem WED-flow, em que o estado

dos dados orienta o fluxo da execução, é possível definir qual cenário dos dados será adotado em uma simulação.

É nítido que as aplicações disponibilizadas possuem interfaces Web rudimentares e sofrem da falta de validação dos dados enviados, porém são suficientes para a realização de testes.

3.2. Aspectos Técnicos

Todo o funcionamento das aplicações e serviços Web implementados se baseia no uso de EJB. Inclusive a classe GenericWedBean é utilizada para encapsular funcionalidades comuns, como o cancelamento de tudo o que foi realizado em uma transação em caso de erro.

O aspecto técnico mais relevante se refere à operação SOAP assíncrona implementada com EJB e JMS. Embora o componente acionado pelo serviço Web seja um bean como os outros, seu comportamento é diferenciado: ele cria uma mensagem com os dados necessários para a execução assíncrona e então a agenda para recebimento em uma fila nativa do JBoss, dez segundos depois. Feito o agendamento, o serviço devolve imediatamente a resposta intermediária ao módulo de extensão, o que expõe a natureza assíncrona da operação.

Para estabelecer o vínculo entre resposta intermediária e a chamada de retorno, optou-se por usar como atributos um identificador e um timestamp gerado pelo serviço no momento da execução. Quando o serviço encerra sua execução, envia uma requisição do tipo POST para um serviço REST implementado junto ao módulo, informando ambos os atributos junto ao resultado da atividade assíncrona.

O código-fonte do serviço que recebe a chamada de retorno se encontra em ws_module/app/

controllers/callback. A classe, chamada Callback::PaymentsController, é mapeada para o

recebimento de requisições por meio do arquivo ws_module/config/routes.rb.

3.3. Simulação Automatizada

Com os dois servidores em execução, tanto o que contém o módulo de extensão quanto o com os artefatos de teste, é possível realizar a simulação dos cenários propostos. Espera-se que as tabelas de teste associadas ao exempo de uso ainda estejam vazias ou já tenham passado pelo processo de criação de massa, pois as credenciais de usuário nela presentes são utilizadas na simulação. Caso as tabelas

(12)

estejam vazias, os próprios testes garantirão que sejam devidamente preenchidas.

Abra uma instância do Firefox e instale o plugin Selenium IDE, ferramenta para criação e execução de testes automatizados, a partir de http://seleniumhq.org/download/. Faça o download também dos scripts de teste gerados, disponíveis em http://www.ime.usp.br/~chui/wedflow/. Cada script corresponde a um cenário: basta abrir o arquivo HTML pela Selenium IDE e iniciar a execução.

Você provavelmente verá uma tela bastante peculiar, repleta de formulários, aparecer seguidas vezes durante os testes. Trata-se da página situada em http://localhost:3000/tests, uma alternativa criada para suprir a ausência do núcleo WED-flow e que embarca junto com o módulo de extensão. Esta página foi especialmente gerada para os testes com os artefatos implementados, pois contém um formulário para cada possível atividade ao longo da execução do processo.

Os valores inseridos em cada formulário da página de testes permitem simular a extração de

informações do banco de dados , o que de fato acontece, porém indiretamente: cada valor inserido

pelos scripts de teste é obtido via interface Web, com base no que consta no banco. O envio dos formulários, por sua vez, resulta em chamadas ao módulo que o núcleo promoveria.

Referências

Documentos relacionados

Ficou com a impressão de estar na presença de um compositor ( Clique aqui para introduzir texto. ), de um guitarrista ( Clique aqui para introduzir texto. ), de um director

Depois da abordagem teórica e empírica à problemática da utilização das Novas Tecnologias de Informação e Comunicação em contexto de sala de aula, pelos professores do

da quem praticasse tais assaltos às igrejas e mosteiros ou outros bens da Igreja, 29 medida que foi igualmente ineficaz, como decorre das deliberações tomadas por D. João I, quan-

Quando conheci o museu, em 2003, momento em foi reaberto, ele já se encontrava em condições precárias quanto à conservação de documentos, administração e organização do acervo,

Em que pese ausência de perícia médica judicial, cabe frisar que o julgador não está adstrito apenas à prova técnica para formar a sua convicção, podendo

Não obstante todos os formulários, prazos e orientações estejam publicados no portal da universidade, o Departamento de Registro e Controle Acadêmico (DRCA) da UFTM

O Conselho Federal de Psicologia (CFP) apresenta à categoria e à sociedade em geral o documento de Referências Técnicas para a Prática de Psicólogas(os) em Programas de atenção

das políticas de saúde e saúde mental no Brasil, como subsídio para uma melhor compreensão dos aspectos históricos que influenciaram a constituição do Sistema Único