none
WCF Erro de comunicação desconhecido RRS feed

  • Pergunta

  • Olha só, estou usando NHibernate e estou tendo dificuldades de enviar entidades para meus clientes. Abaixo eu descrevo meu cenário e reparem que tenho o metodo doLogin(string, string). Este metodo retornará o Funcionario se ele realmente existir, senão retornará nulo. Quando o cliente chama esta ação e ela retorna nula a operação ocorre sem erros mas quando  retorna uma entidade do contexto NHibernate acontece o erro citado mais abaixo. Alguem sabe o que pode ser isso?

    // CONTRATO DO SERVIÇO

        [ServiceContract]
        public interface IFuncionarioService
        {
            [HibernateTransaction]
            [OperationContract]
            IList<Funcionario> GetAll();

            [HibernateTransaction]
            [OperationContract]
            Funcionario doLogin(string usuario, string senha);
        }


       // CLIENTE CHAMANDO O SERVICO

                FuncionarioServiceClient cliente = new FuncionarioServiceClient();
                Funcionario f = null;

                try {
                    f = cliente.doLogin("usuario", "senha");
                } catch (Exception e){
                    Debug.Print(e.ToString());
                }


    // ESTE ERRO SOMENTE ACONTECE QUANDO doLogin() RETORNA O FUNCIONARIO.

    A first chance exception of type 'System.ServiceModel.CommunicationException'
    
    
     occurred in
    
    
     mscorlib.dll
    System.ServiceModel.CommunicationException: A conexão de soquete foi anulada. Isso pode ter sido causado por um erro de processamento de sua mensagem, por um tempo limite de recepção ultrapassado pelo host remoto ou por um problema de recurso de rede subjacente. O tempo limite de soquete local era de '00:59:59.9843750'
    
    
    . ---> System.IO.IOException: Falha na operação de leitura, consulte a exceção interna. ---> System.ServiceModel.CommunicationException: A conexão de soquete foi anulada. Isso pode ter sido causado por um erro de processamento de sua mensagem, por um tempo limite de recepção ultrapassado pelo host remoto ou por um problema de recurso de rede subjacente. O tempo limite de soquete local era de '00:59:59.9843750'
    
    
    . ---> System.Net.Sockets.SocketException: Foi forçado o cancelamento de uma conexão existente pelo host remoto
       em System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
       em System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing)
       --- Fim do
    
    
     rastreamento de pilha de exceções internas ---
       em System.ServiceModel.Channels.SocketConnection.ReadCore(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout, Boolean closing)
       em System.ServiceModel.Channels.SocketConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
       em System.ServiceModel.Channels.DelegatingConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
       em System.ServiceModel.Channels.ConnectionStream.Read(Byte[] buffer, Int32 offset, Int32 count, TimeSpan timeout)
       em System.ServiceModel.Channels.ConnectionStream.Read(Byte[] buffer, Int32 offset, Int32 count)
       em System.Net.FixedSizeReader.ReadPacket(Byte[] buffer, Int32 offset, Int32 count)
       em System.Net.Security.NegotiateStream.StartFrameHeader(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
       em System.Net.Security.NegotiateStream.StartReading(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
       em System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
       --- Fim do
    
    
     rastreamento de pilha de exceções internas ---
       em System.Net.Security.NegotiateStream.ProcessRead(Byte[] buffer, Int32 offset, Int32 count, AsyncProtocolRequest asyncRequest)
       em System.Net.Security.NegotiateStream.Read(Byte[] buffer, Int32 offset, Int32 count)
       em System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
       --- Fim do
    
    
     rastreamento de pilha de exceções internas ---
    
    Server stack trace: 
       em System.ServiceModel.Channels.StreamConnection.Read(Byte[] buffer, Int32 offset, Int32 size, TimeSpan timeout)
       em System.ServiceModel.Channels.SessionConnectionReader.Receive(TimeSpan timeout)
       em System.ServiceModel.Channels.SynchronizedMessageSource.Receive(TimeSpan timeout)
       em System.ServiceModel.Channels.FramingDuplexSessionChannel.Receive(TimeSpan timeout)
       em System.ServiceModel.Channels.FramingDuplexSessionChannel.TryReceive(TimeSpan timeout, Message& message)
       em System.ServiceModel.Dispatcher.DuplexChannelBinder.Request(Message message, TimeSpan timeout)
       em System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       em System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
       em System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       em System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
    
    Exception rethrown at [0]: 
       em System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       em System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       em Dolphin.Teste.Service.Funcionario.IFuncionarioService.doLogin(String usuario, String senha)
       em Dolphin.Teste.Service.Funcionario.FuncionarioServiceClient.doLogin(String usuario, String senha) na d:\eliezer\prj_sl\dolphin\dolphin.teste\service references\service.funcionario\reference.cs:linha 57
       em Dolphin.Teste.Program.Main(String[] args) na D:\Eliezer\prj_sl\Dolphin\Dolphin.Teste\Program.cs:linha 30
    
    

    quarta-feira, 4 de novembro de 2009 12:35

Respostas

Todas as Respostas

  • Boas Eliezer.

    Voce está decorando suas classes mapeadas pelo NHibernate com o atributo [DataContract()] e todos os seus membros com o atributo [DataMember()] ?

    Pois voce disse que retorna um objeto do tipo Funcionário, classe que deve ter sido criada por voce, correto? Assim voce deve informar ao Wcf como este objeto é formado, utilizando os atributo que citei acima:

    using System.Runtime.Serialization

    [DataContract()]
    public class Funcionario
    {

    [DataMember()]
    public String Nome
    {
        get{}
        set{}
    }
    }

    quarta-feira, 4 de novembro de 2009 13:00
  • Minha classe decorada está assim, será que tem algum erro nela?  

        [DataContract]
        [KnownType(typeof(Endereco))]
        public class Funcionario {

            [DataMember]
            private int id;
            [DataMember]
            private String sexo;
            [DataMember]
            private String nome;
            [DataMember]
            private String ultimoNome;
            [DataMember]
            private DateTime aniversario;
            [DataMember]
            private String email;
            [DataMember]
            private String usuario;
            [DataMember]
            private String senha;
            [DataMember]
            private Endereco endereco;

            public virtual int Id {
                get { return id; }
                set { id = value; }
            }

            public virtual String Sexo {
                get { return sexo; }
                set { sexo = value; }
            }

          (...)
    quarta-feira, 4 de novembro de 2009 13:07
  • Boas Eliezer,

    Defina a propriedade IncludeExceptionDetailInFaults para True. Isso fará com que a exceção seja propagada para o cliente, e assim poderá identificar o que realmente está ocorrendo.
    http://www.israelaece.com
    quarta-feira, 4 de novembro de 2009 13:15
    Moderador
  • Siga a dica do Israel, porque na sua classe não há erro e definindo a propriedade IncludeExceptionDetailInFaults para True voce conseguirá mais detalhes do erro.
    quarta-feira, 4 de novembro de 2009 13:18
  • Eu configurei essa propriedade mas continua chegando o mesmo erro para o cliente. Eu acho que CommunicationException é uma exceção nova e não é lança como Fault. Veja como ficou minhas configurações do serviço:

        <behaviors>
          <serviceBehaviors>
            <behavior name="Default">
              <serviceMetadata httpGetEnabled="false" />
              <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
          </serviceBehaviors>
        </behaviors>

    <services>
        <service behaviorConfiguration="Default" name="Dolphin.Service.Impl.FuncionarioService">
            <endpoint address="" binding="netTcpBinding" name="EndFuncionario"
              contract="Dolphin.Service.IFuncionarioService">
              <identity>
                <dns value="localhost" />
              </identity>
            </endpoint>
           
            <endpoint address="mex"
                      binding="mexTcpBinding"
                      bindingConfiguration=""
                      name="EndMex"
                      contract="IMetadataExchange" />

            <host>
              <baseAddresses>
                <add baseAddress="net.tcp://localhost:8523/Service/Funcionario" />
              </baseAddresses>
            </host>
          </service>
    <services>
    quarta-feira, 4 de novembro de 2009 15:48
  • Olha só que negocio inesplicável. Eu fiz um teste criando a mesma entidade manualmente (usando o operador new) sem usar o hibernate para recuperar a entidade do banco. Para minha surpresa criando a entidade identica a entidade recuperada pelo hibernate não gera erros porém quando envio a entidade gerada pelo hibernate gera aquela exceção acima! Olha o codigo:


        // IMPLEMENTAÇAO DO CONTRATO COM IFuncionarioService
        public Funcionario doLogin(string usuario, string senha)
            {
                // Saida:
                // [ Id:13 Sexo:M Nome:Eliezer UltimoNome:Reis de Oliveira Aniversario:13/02/1984 00:00:00 Email:eliezerreis@hotmail.com 
                // Usuario:eliezerreis Senha:eliezer Estado:DF ]
               
                // Gera a excessao quando esta entidade chega no cliente
                Funcionario funcionario = funcionarioDAO.FindByLogin(usuario,senha);


                // Essa entidade gera a mesma saida da linha acima porém chega sem erros no servidor.
                /*Funcionario funcionario = new Funcionario() {
                    Id = 13,
                    Sexo = "M",
                    Nome = "Eliezer",
                    UltimoNome = "Reis de Oliveira",
                    Aniversario = new DateTime(),
                    Email = "eliezerreis@hotmail.com",
                    Usuario = "eliezerreis",
                    Senha = "eliezer",
                    Endereco = new Endereco() {
                        FuncionarioId = 13,
                        Estado = "DF"
                    }
                };*/
     
                Debug.Print(funcionario.ToString());

                return funcionario;
            }


    quarta-feira, 4 de novembro de 2009 16:21
  • Ahhh, descobri.

    Somente para deixar registrado caso alguem venha a ter algum problema desse o que ocorreu foi que Funcionario tem relacionamento one-to-one para Endereco entao em Funcionario eu tinha uma referencia para Endereco que por sua vez tem referencia para Funcionario e como eu ja disse que Funcionario tem um Endereço causava essa referencia ciclica o que gerava o erro abaixo.
    Eu acho que o WCF já reconhece essa referencia ciclica e joga imediatamente um erro de tempo excedido.


    System.ServiceModel.CommunicationException: A conexão de soquete foi anulada. 
    Isso pode ter sido causado por um erro de processamento de sua mensagem,
    por um tempo limite de recepção ultrapassado pelo host remoto ou por um
    problema de recurso de rede subjacente.
    O tempo limite de soquete local era de '00:59:59.9843750'

    Repara que o proprio erro mostra que eu tenho um time out de quase 1hora, so que devido a referencia cliclica ele exibe o erro como sendo limite de recepção ultrapassado pelo Host .

    Está é uma diferença entre NHibernate e o Hibernate do Java uma vez que isso náo acontece no Java ja que é logico o Endereco saber quem mora nele (Funcioanrio).


    Vlw pessoal.
    quarta-feira, 4 de novembro de 2009 17:48
  • Boas Eliezer,

    E você marcou o Endereco como DataContract?
    http://www.israelaece.com
    quarta-feira, 4 de novembro de 2009 18:07
    Moderador
  • Marquei sim.

    Cara, agora eu to lascado. Eu resolvi  o problema acima deixando um lado do relacionamento como o dono do relacionamento e simplismente apaguei do outro lado a entidade referenciada. O problema é que tem uma entidade minha que eu tenho uma self-relacionamento (um classe relacionando consigo mesmo) dai obrigatoriamente existirá referencia nos dois lados do relacionamento. Dai fica dando o seguinte erro , veja se está relacionado.

    System.ServiceModel.CommunicationObjectFaultedException: O objeto de comunicação, System.ServiceModel.Channels.ServiceChannel, não pode ser usado para comunicação porque está no estado Com Falha.
    
    Server stack trace: 
       em System.ServiceModel.Channels.CommunicationObject.ThrowIfFaulted()
       em System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
       em System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
       em System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
       em System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
    
    Exception rethrown at [0]: 
       em System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
       em System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
       em Dolphin.Teste.Service.Apuracao.IApuracaoService.GetAll(DateTime data, String titulo, String conteudo, String editor, Relevancia relevancia, Editoria editoria)
       em Dolphin.Teste.Service.Apuracao.ApuracaoServiceClient.GetAll(DateTime data, String titulo, String conteudo, String editor, Relevancia relevancia, Editoria editoria) na d:\prj_sl\dolphin\dolphin.teste\service references\service.apuracao\Reference.cs:linha 122
       em Dolphin.Teste.Program.Main(String[] args) na D:\prj_sl\Dolphin\Dolphin.Teste\Program.cs:linha 19
    


    quarta-feira, 4 de novembro de 2009 20:10
  • Boas Eliezer,

    E não há algum problema na configuração do NHibernate, que está disparando o problema?
    http://www.israelaece.com
    quinta-feira, 5 de novembro de 2009 01:18
    Moderador
  • O seu problema está relacionado ao NHibernate. Você ja tentou usar o ActiveRecord para mapear suas classes ao invés se fazer todo serviço braçal de mapeamento para o NHibernate?
    • Sugerido como Resposta Marcos Latchuk quinta-feira, 5 de novembro de 2009 19:54
    • Marcado como Resposta Eliezer Reis sexta-feira, 6 de novembro de 2009 00:07
    quinta-feira, 5 de novembro de 2009 11:50
  • É verdade, depois de variassssss horas eu consegui descobrir o detalhe do erro. Acontecia realmente um erro de mapeamento. O foda foi que eu peguei o MyGeneration para gerar as classes e os arquivos de configuracao e para espanto estavam exatamente iguais aos meus.

    Depois de muito analizar percebi que faltava um atributo fetch="join" em um relacionamento one-to-one . Engraçado que seria obvio um relacionamento one-to-one ter esse tipo de caracteristica por padrao.

    O legal é que aprendi a usar o log4net para mostrar o que exatamente esta acontecendo com o hibernate. Assim fica mais facil identificar os erros.

    Em suma, quando acontece um CommunicationObjectFaultedException é bem provavel que seja alguma falha de configuração do hibernate.


    Alguem podem confirmar se no WCF 3.5 SP1 é realmente necessário colocar DataContract e DataMember?

    O que acontece se meu hibernate retornar um coleção do tipo ISet? Como faço para pegar esse tipo também no cliente? Pergunto isso porque toda ação chamada pelo meu proxy que retorna uma coleção o cliente consegue enchergar somente como List mesmo que eu retorne um ISET la no meu contrato.



    quinta-feira, 5 de novembro de 2009 18:51
  • Boas Eliezer,

    Não, os atributos DataMember e DataContract são desnecessários a partir do SP1, visando também objetos POCOs.

    Se você precisa de algum tipo do outro lado que não é suportado pela serialização, você tem que conhecer os tipos dos dois lados: http://www.israelaece.com/post/Compartilhando-tipos-entre-o-servico-e-o-cliente.aspx.
    http://www.israelaece.com
    • Marcado como Resposta Eliezer Reis sexta-feira, 6 de novembro de 2009 00:07
    quinta-feira, 5 de novembro de 2009 18:54
    Moderador