Usuário com melhor resposta
WCF Erro de comunicação desconhecido

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
Respostas
-
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
-
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
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{}
}
} -
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; }
}
(...) -
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 -
-
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> -
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;
}
-
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. -
-
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
-
Boas Eliezer,
E não há algum problema na configuração do NHibernate, que está disparando o problema?
http://www.israelaece.com -
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
-
É 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.
-
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