web service com Qt, Qxt e qtSoap

Como uma tarefa de uma disciplina era desenvolver um web service simples o professor disse ‘Façam em Php como está no artigo que voces leram’. Mas bem, eu teria que instalar um servidor, configurar apache, fazer XMLSchema… Eu ia demorar mais tempo executando o setup do sistema.

Pra variar eu tenho que tentar sempre fazer as coisas usando Qt. Com uma breve busca no google, encontrei essa entrada para o lado servidor e essa outra para o lado cliente, ambas no blog QtEffort, muito bons posts (e os temas do blog tambem).

Primeiro vou dizer o que meu web service deve executar:
-Verificar se um usuário já está cadastrado em um BD;
-Cadastrar um novo usuário.
Bem simples, mas pretendo usar ele como base para incrementar uma aplicação para S60 colocando records online.

Bom o que tive que alterar nos códigos disponibilizados no QtEffort:

-Implementar o parser para tratar os pedidos SOAP;
-conectar em BD para buscar/cadastrar um novo usuário;
-construir mais de uma mensagem no cliente (verificar existencia/inserir usuário).

Vamos aos códigos, para facilitar eles estão no github.

No lado cliente temos agora essas funções para verificar se o cliente já está connectado e outra para criar um novo usuário com senha. Basicamente o que é feito é criar uma mensagem SOAP (usando a libQtSOAP) uma com o metodo ExistLogin e outra com o metodo CreateUser. O objeto http é do tipo QtSoapHttpTransport que cuida de toda parte de envio dos dados. O sinal QtSoapHttpTransport::responseReady() é connectado ao slot Client::getResponse().

void Client::checkLogin(QString login){
   QtSoapMessage request;
   request.setMethod("ExistLogin");
   request.addMethodArgument("login", "", login);
   http.submitRequest(request, "/add/");
}
void Client::createUser(QString login, QString pass){
   QtSoapMessage request;
   request.setMethod("CreateUser");
   request.addMethodArgument("login", "", login);
   request.addMethodArgument("pass", "", pass);
   http.submitRequest(request, "/add/");
}
void Client::getResponse(){
   const QtSoapMessage &msg = http.getResponse();
   if (msg.isFault()) {
     qDebug("Error: %s", qPrintable(msg.faultString().toString()));
   }
   emit response(msg.returnValue().toString());
}

Como podem ver não tem nada de outro mundo (como a maioria das coisas em Qt). Para o lado do servidor temos:

QString WebService::createUser(QString user, QString pass){
  QSqlQuery q ;
  if (checkLogin(user) == "Exist"){
    return QString("User allready exist!");
  }
  q.prepare("insert into users values(:a, :b)");
  q.bindValue(":a",user);
  q.bindValue(":b",pass);
  if (q.exec()){
    return QString("Inserted!");
  }
  q.finish();
  return QString("Sorry, Database error: " + q.lastError().text());
}

A função que cria um usuário gerando uma QString com o resultado. Esse resultado é que será enviado como resposta para o cliente.

A outra função alterada é a que trata os dados recebidos. Ela que trata do recebimento das informações do cliente e decide qual processamento deve ser executado.

void WebService::indexRequested(QxtWebRequestEvent *event){
  qDebug() << "Request Headers: ";
  if (event->method.compare("POST")==0) {
    QxtWebContent *myContent = event->content;
    qDebug() << "Bytes to read: " << myContent->unreadBytes();
    myContent->waitForAllContent();
    QByteArray requestContent = myContent->readAll();

    //Parse SOAP XML
    SimpleSoapParser handler;
    QXmlSimpleReader reader;
    reader.setContentHandler(&handler);
    reader.setErrorHandler(&handler);
    QBuffer xml(&requestContent);
    QXmlInputSource xmlInputSource(&xml);
    if (!reader.parse(xmlInputSource)){
      postEvent(new QxtWebPageEvent(event->sessionID,
                             event->requestID,
                             DEFAULT_MESSAGE));
      return;
    }
    if (handler.method() == "ExistLogin"){
      QString bodyMessage = buildResponse(
                        this->checkLogin(handler.arg(0)),
                        "ExistLogin");
      postEvent(new QxtWebPageEvent(event->sessionID,
                            event->requestID,
                            bodyMessage.toUtf8()));
    }
    if (handler.method() == "CreateUser"){
      QString bodyMessage = buildResponse(
               this->createUser(handler.arg(0),
                                            handler.arg(1)),
               "CreateUser");
      postEvent(new QxtWebPageEvent(event->sessionID,
                                event->requestID,
                                bodyMessage.toUtf8()));
    }
  } else if (event->method.compare("GET")==0) {
    postEvent(new QxtWebPageEvent(event->sessionID,
                                event->requestID,
                                DEFAULT_MESSAGE));
   }
}

Após executar o parse no XML enviado pelo cliente, é selecionado o metodo invocado pelo cliente (ExistLogin ou CreateUser) e os parâmetros de cada um deles sendo chamada a função para executar a ação no servidor (acessar um banco de dados nesse caso) e é construida um mensagem (outro XML) contendo a resposta da ação (a função buildResponse() não foi alterada, ela já era poderosa suficiente!)

O restante da função é para impedir o metodo GET e que o XML contenha algum erro.

A facilidade em criar esse web service está no fato de bibliotecas como QtSOAP e QxT (Qt ExTended) permitir criar um cliente com meia duzia de linhas sem perder a força. Caso eu venha a utilizar esse web service para a aplicação do S60 eu faço um novo post.

Ah! os códigos para quem não pegou é http://github.com/wiglot/WebService e não deixem de visitar as outras páginas:

http://efforts.embedded.ufcg.edu.br/qt/

http://qt.nokia.com/products/appdev/add-on-products/catalog/4/Utilities/qtsoap

http://www.libqxt.org/

Abraços

Anúncios

5 Respostas

  1. […] citei em um post anterior, eu desenvolvi um pequeno web service usando libQxt e Qt Soap (além do próprio Qt :p) e […]

  2. Olá, sou estudante e gostaria de saber se existe uma forma de com este exemplo de client, poder consumir um webservices em .NET?

    • Olá

      Bom, o Web service é uma ferramenta para efetuar a comunicação entre 2 sistemas distintos. Eu fiz uso nesse caso do SOAP como ‘formato’ dessa comunicação.
      Eu não conheço o .NET, mas se a comunicação é executa por SOAP, então esse cliente funciona. Se ele utiliza algum outro formato de XML, ou mesmo um outro formato de dados, tu ainda assim pode escrever um código que leia/escreva tal formato.

      respondi?

  3. Olá,

    Tentei rodar seu exemplo e tive esse problema cannot find -lQxtWebd você tem alguma idéia do que seja.
    Atenciosamente, Vinícius.

    • Olá Vinicius,
      está faltando o Qxt, você conseguiu instalar ele?

      Não me recordo agora como eu fiz a instalação, mas acho que é bem intuitiva.

      se precisar de algo é só prender o grito

      Abraços

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s

%d blogueiros gostam disto: