Registrando DataSnap Server Class em tempo de execução no Delphi
Sempre que estamos construindo uma aplicação DataSnap temos que registrar as classes que serão disponbilizadas para o lado cliente, o natural é utilizar o componente DSServerClass pra isso, muitas vezes queremos fazer isso em tempo de execução, abaixo segue um código exemplo de como efetuar o registro destas classes em tempo de execução.
No código abaixo a classe TSimpleServerClass herda de TDSServerClass e estende o método Create onde passamos a classe a ser registrada, seu respectivo DataSnap Server e o LifeCycle.
type TSimpleServerClass = class(TDSServerClass) private FPersistentClass: TPersistentClass; protected function GetDSClass: TDSClass; override; public constructor Create(AOwner: TComponent; AServer: TDSCustomServer; AClass: TPersistentClass; ALifeCycle: String); reintroduce; overload; end; procedure RegisterServerClasses(AOwner: TComponent; AServer: TDSServer); implementation constructor TSimpleServerClass.Create(AOwner: TComponent; AServer: TDSCustomServer; AClass: TPersistentClass; ALifeCycle: String); begin inherited Create(AOwner); FPersistentClass := AClass; Self.Server := AServer; Self.LifeCycle := ALifeCycle; end; function TSimpleServerClass.GetDSClass: TDSClass; begin Result := TDSClass.Create(FPersistentClass, False); end;
Agora é criar uma instância de TSimpleServerClass para cada classe que contém os server methods.
Abaixo um exemplo onde são registradas 3 classes no mesmo server, com LifeCycles distintos:
procedure RegisterServerClasses(AOwner: TComponent; AServer: TDSServer); begin Assert(AServer.Started = false, 'Não é possível adicionar classes com o servidor ativo'); TSimpleServerClass.Create(AOwner, AServer, TGlobal, TDSLifeCycle.Server); TSimpleServerClass.Create(AOwner, AServer, TCustomer, TDSLifeCycle.Session); TSimpleServerClass.Create(AOwner, AServer, TObjectPool, TDSLifeCycle.Invocation); end;
Simples e muito prático, até o próximo artigo.
Andreano, vlw… era isso que estava precisando… fiz uma alteração e postei no meu blog.
http://www.wzmsoftware.com.br/blog/?p=193
A alteração que você fez não é recomendada, você assume que todas as classes são Session e além disso usa a string Session em vez do tipo TDSLifeCycle
No novo DataSnap, em uma conexão do tipo Session, eu sei que os objetos são criados apenas quando são usados (execução de algum de seus métodos), porém destruídos apenas quando a conexão é encerrada.
Existe alguma maneira de destruir os objetos criados sem ter que fechar a conexão?
Andreano,
Como fica a implementação disso, tem como você colocar isso num exemplo?
Rodrigo
Adriano, por favor !
O método Constructor da classe criada para poder ser registrada dessa forma não é executado.
Tem alguma forma de fazer ser executado ou alguma outra forma de instanciar alguns objetos adicionados nela quando ela for instanciada pelo DataSnap ?
O que acontece é que quero criar alguns objetos para serem utilizados pela classe servidora, porém esses não consigo instanciar por conta do método Constructor não ser chamado.
Tem alguma idéia ?
Muito obrigado !
Att. Tiago
Andreano,
Você poderia citar em que casos cada tipo TDSLifeCycle deve ser aplicado ?
Aldeson,
Por favor leia esse post http://www.andreanolanusse.com/pt/implementando-cache-de-dados-em-servidores-datasnap/
Olá Andreano, essa forma como implementou o server precisa estar parado. Eu preciso registrar as classes depois que o server foi iniciado.
Bom dia Andreano,
Estou efetuando o registro de minhas classes dessa forma, porem quando eu tento carregar o meu CDS ele retorna o erro.
Remote Error: TDSCidade.AS_GetRecords method not found in the server method list.
caso eu faça o registro utilizando o componente
DSServerClass ele funciona perfeitamente.
você saberia me informar o por que deste problema?
Agradecido desde já,
Atenciosamente,
Rodrigo Martim.
Oi Rodrigo,
Isso acontece porque você está tentando retornar um ClientDataSet em um dos métodos e isso não é possível, na seção DataSnap do meu blog eu explico os tipos que podem ser retornados e convertidos em JSON.
Boa tarde Andreano,
Desculpe – me pela ignorancia, porem, não consigo entender o seguinte.
Fazendo a publicação da classe para o lado cliente utilizando o componente TDSServerClass e seu metodo OnGetClass este problema se resolve.
O Problema apenas acontece quando a publicação para o lado cliente é realizada com a classe TSimpleServerClass,
notei que ao registrar por este metodo, vários metodos não são publicados.
Exemplos:
TDSCidade.AS_ApplyUpdates TDSCidade AS_ApplyUpdates
TDSCidade.AS_GetRecords TDSCidade AS_GetRecords
TDSCidade.AS_DataRequest TDSCidade AS_DataRequest
TDSCidade.AS_GetProviderNames TDSCidade AS_GetProviderNames
TDSCidade.AS_GetParams TDSCidade AS_GetParams
TDSCidade.AS_RowRequest TDSCidade AS_RowRequest
TDSCidade.AS_Execute TDSCidade AS_Execute
Aparecem apenas quando registrados pelo componente TDSServerClass
Desculpe – me se estiver falando besteira, e muito obrigado pela ajuda.
Atenciosamente,
Rodrigo Martim
Rodrigo, estes métodos que você menciona são métodos relacionados a interface do IAppServer, que é usado pelo provider e clientdataset.
Andreano so voce pode me salvar, estou gostando demais o datasnap, porem como meu sistema é todo dinamico em BPLs preciso fazer o mesmo para o metodos do servidor, para isso criei pacotes (BPL) para cada modulo, Compra.bpl, Estoque.bpl, Venda.bpl carregado em tempo de execução com LoadPackage() assim nao preciso recompilar meu executavel do servidor para adicionar novos metodos no servidor e quando eu mudar um metodo do pacote Estoque.bpl nao preciso atualizar todo o servidor, so parar o servico colocar a nova bpl e iniciar o servico novamente, porem ja tentei de varios jeitos vincular DSServerClass dentro de um bpl carregada em tempo de execução com LoadPackage() mas nao consegui ter sucesso, existe algum bug relacionado a isso? pode enviar um exemplo? ja com pacotes carregados automaticos ja funciona, to acredito ser um BUG do datasnap, estou utilizando DELPHI XE, socorre eu. Obrigado.
Eu fiz a mesma coisa utilizando DLLs com LoadLibrary e a classe TSimpleServerClass.
Eu percebi que essa classe cria os componentes TSimpleServerClass no Server Datamodule (através da constatação da existência do componente na lista de componentes do Datamodule), mas apesar disso a classe e nem os seus métodos são publicados. Ou seja, os TSimpleServerClass estão criados mas não publicam nada.
O que pode estar sendo feito de errado? Não é possível registrar e publicar métodos de classes contidas em DLLs ou BPLs ?
Esse seu exmplo não permite que seja publicados os Providers do Servidor DataSnap.
Apenas podemos publicar os metdos declarados no ServerModule.
Se você Andreano, tiver uma maneira de publicar os providers para serem ligados ao clientDataSet na App cliente, por favor disponibilize o exemplo.
Tenho urgencia em Resolver esse problema.
Obrigado
Achei a solução para publicar os provider nesse exemplo.
mude o codigo da função GetDSClass para o codigo a abaixo.
function TSimpleServerClass.GetDSClass: TDSClass;
begin
Result := TDSClass.Create(FPersistentClass, false);
Result := TDSClass.Create(TDSProviderDataModuleAdapter, Result)
end;
Abraço
Esse codigo não publica os providers de um servermodule, ae não ajuda muito.
Eu modifiquei uma função pra resolver o problema.
segue o códgio abaixo.
function TSimpleServerClass.GetDSClass: TDSClass;
begin
Result := TDSClass.Create(FPersistentClass, false);
Result := TDSClass.Create(TDSProviderDataModuleAdapter, Result)
end;
facinho.
Abraço
Bom dia Andreano.
Com relação ao registro de classes pelo servidor DataSnap, existe uma forma de permitir que uma classe com um método em overload possa ser registrada?
Tentei realizar um teste com um método chamado GetImage com as assinaturas abaixo:
GetImage( const id: Integer ): TStream; overload;
GetImage( const login: String ): TStream; overload;
Mas o DataSnap não aceita o registro da respectiva classe pois reclama que o método GETIMAGE já foi registrado.
Olá Andreano, excelente artigo, o seu blog é praticamente a única ou no mínimo a melhor fonte de informação sobre DataSnap.
Estou querendo utilizar sua classe TSimpleServerClass em um projeto de um servidor DataSnap genérico, que vai servir de base para outros servidores com poucas modificações. Ele está sendo escrito em XE7. O diferencial dele é que os Server Methods vão ser carregados dinamicamente por meio de classes contidas em DLLs, bastando adicionar a DLL para o diretório específico e o servidor carrega os métodos e os registra no servidor.
Já está tudo pronto, as DLLs são carregadas dinamicamente e as classes registradas utilizando TSimpleServerClass. Entretanto as classes registradas NÃO APARECEM na lista de classes do servidor, mas ao consultar a lista de componentes do TDatamodule usado como Server Container destas classes, todos os componentes TSimpleServerClass registrados pela DLL estão lá com as respectivas propriedades preenchidas corretamente.
Se eu utilizo o mesmo comando TSimpleServerClass diretamente no DataModule a classe é registrada e publicada normalmente, então a rotina está correta, o problema acontece quando a classe é registrada por dentro da DLL.
Existe alguma incompatibilidade conhecida do DataSnap com DLLs ? Você tem alguma idéia do que pode ser o problema?
Fico grato por qualquer dica que puder me fornecer pois já tentei de tudo e não consigo contornar o problema.
Obrigado.
Boa tarde.
Fiz o método no Delphi XE 7, e tive o seguinte erro:
{
“error”:”Unknown driver: DSServer1″
}