O que é?
Uma das preocupações do REST tlppCore é manter uma flexibilidade de uso onde o usuário/cliente possa ter recursos suficientes para desenvolver seus serviços REST conforme suas necessidades.
Uma dessas flexibilidades é uma chave de configuração de uso exclusivo do desenvolvedor, onde pode informar a quantidade de conjuntos de {chave:valor} que quiser através de um JSON.
Como usar?
O nome da chave deverá ser userData, ela pode ser informada no INI do appserver [detalhes aqui] ou via JSON, caso opte por executar o REST via código-fonte [detalhes aqui].
O userData deve ao final ser um JSON, porém existem algumas formas de informá-lo ao server, vamos à elas:
JSON diretamente na chave
Exemplo:
userData={"exemplo":"direto na chave"}
Esse modo é o mais simples, pois a informação já estará diretamente na chave.
Porém, valores em chaves podem ter a limitação na quantidade de caracteres do conteúdo do valor dependendo da versão do appserver utilizada (consulte documentação e versão do server).
Caso necessite utilizar JSON extensos, sugerimos utilizar os modos seguintes:
JSON através de um arquivo
Nesse modo será informado na chave o nome de um arquivo, na qual seu conteúdo será o JSON desejado para a configuração, vejamos:
Exemplo: (somente nome do arquivo):
userData=userData.json
No exemplo acima, o arquivo deverá estar na mesma pasta do appserver.
Exemplo: (caminho absoluto + nome do arquivo)
userData=c:\configRest\userData.json
O uso de caminho absoluto facilita na manutenção de arquivos de configuração, pois podem estar localizados em local central.
Notas
1 - A extensão do arquivo não é obrigatória ser .json, pode-se utilizar .txt.
2 - O conteúdo do arquivo deve ser um JSON válido.
Onde usar?
Essa chave pode ser usada em diversos níveis da infraestrutura do REST server, tal flexibilidade serve para ser usada conforme sua necessidade.
Considerando essa informação, pode-se então informar um userData nos seguintes níveis:
Para todos
- Server
Para Thread de atendimento
- Thread Pool
- Slaves
1 - Podem haver configurações coexistentes entre Server e ( Thread Pool ou Slave ).
2 - Não podem haver configurações coexistentes entre Thread Pool e Slave.
3 - Se Thread Pool possuir Slave, a configuração do userData deve ser feito diretamente no Slave.
4 - A userData que estiver configurada no Thread Pool somente será considerada se não possuir Slave.
Devemos lembrar que, quando uma Thread Pool possuir Slaves, o atendimento à requisição de fato será feito pelo Slave e não pela Thread Pool, embora a requisição passe inicialmente pela Thread Pool, porém somente será usada para distribuição da requisição para um dos Slaves com base nas regras do [onSelect].
O atendimento será feito pela Thread Pool somente quando ele não possuir Slave configurado.
Configuração
Observem os exemplos de configuração, feitas no INI, abaixo :
Exemplo 1 (sem Slave)
[HTTPSERVER] Enable=1 Servers=HTTP_SRV [HTTP_SRV] locations=HTTP_ROOT userData={"config":"server"} [HTTP_ROOT] ThreadPool=THREAD_POOL [THREAD_POOL] userData={"config":"threadpool"}
Nesse caso, temos 2 (dois) userData configurados:
Um para o servidor todo, ou seja, de qualquer Thread teremos acesso a esse mesmo userData.
O outro para as Threads de atendimento, e todas pegarão o userData configurado na Thread Pool, no exemplo acima com o nome de [THREAD_POOL]
.
Exemplo 2 (com 2 Slaves)
[HTTPSERVER] Enable=1 Servers=HTTP_SRV [HTTP_SRV] locations=HTTP_ROOT userData={"config":"server"} [HTTP_ROOT] ThreadPool=THREAD_POOL [THREAD_POOL] Slaves=SLAVE_01,SLAVE_02 [SLAVE_01] userData={"config":"slave01"} [SLAVE_02] userData={"config":"slave02"}
Nesse caso, temos 3 (três) userData configurados:
Um para o servidor todo, ou seja, de qualquer Thread teremos acesso a esse mesmo userData.
Os outros 2 (dois) para as Threads de atendimento, porém, cada uma de seu respectivo Slave, ou seja, se a requisição for distribuída para qualquer thread do [SLAVE_01], o conteúdo de userData será {"config":"slave01"}
, caso seja distribuída para qualquer thread do [SLAVE_02], então o conteúdo de userDataserá {"config":"slave02"}
Como resgatar os valores de userData
Para obter os valores configurados em userData, temos disponível dois métodos em oRest, são eles:
oRest:getThreadPoolServerUserData()
Esse método retornará o JSON informado no userData da sessão Server, nos exemplos aqui utilizados, a sessão seria [HTTP_SRV] e seu conteúdo:
{"config":"server"}
Esse método quando requerido, sempre retornará o valor configurado no server, independentemente de qual Thread está a execução do serviço.
Acesse sua documentação aqui
oRest:getThreadPoolUserData()
Esse método retornará o JSON informado no userData do Thread Pool, ou do Slave.
Conforme dito anteriormente, essa variação ocorre devido à configuração (se existirão slaves) e de qual thread está atendendo a requisição.
Para ficar claro, vamos utilizar os exemplos acima.
- Se o cenário for do "Exemplo 1 (sem Slave)", então o método irá retornar o valor informado na sessão Thread Pool, de nome [THREAD_POOL] e seu conteúdo seria:
{"config":"threadpool"}
- Se o cenário for do "Exemplo 2 (com 2 Slaves)", então o método irá retornar o valor informado na sessão Slave da qual pertence a thread que de fato está atendendo a requisição, sendo assim, temos 2 possibilidades:
2 - a) Se a thread pertencer ao primeiro Slave, então a sessão será de nome [SLAVE_01] e seu conteúdo:
{"config":"slave01"}
2 - b) Se a thread pertencer ao segundo Slave, então a sessão será de nome [SLAVE_02] e seu conteúdo:
{"config":"slave02"}
Acesse sua documentação aqui
Nota
O retorno da ambos os métodos será sempre em formato JSON.
Exemplo
No exemplo abaixo, estamos utilizando os dois métodos.
Sugerimos que utiliza o exemplo e modifique a configuração do seu server para que fixe bem o conhecimento sobre o assunto.
@Get("sample/userData") function sampleUserData() local cReturn := '' local cTmp := '' local jUserData jUserData := oRest:getThreadPoolServerUserData() cTemp := jUserData["config"] if ( valtype(cTemp) <> 'C' ) cTemp := '' endif cReturn += '{"serverUserData":"' + cTemp + '"' jUserData := oRest:getThreadPoolUserData() cTemp := jUserData["config"] if ( valtype(cTemp) <> 'C' ) cTemp := '' endif cReturn += ',"threadpoolUserData":"' + cTemp + '"}' oRest:setResponse( cReturn ) return