#monkeypatch kludge to get Parser to suppress "ignored element" warnings
#generated when mumboe-soap4r consumes wsdl that asp.net serves
#TODO: find a cleaner way to do this
require 'stringio'
class WSDL::Parser
private
old_decode_tag = instance_method(:decode_tag)
ignored_string = StringIO.new
define_method(:decode_tag) do |*args, &block|
old_stderr, $stderr = $stderr, ignored_string
result = old_decode_tag.bind(self).call(*args, &block)
$stderr = old_stderr
result
end
end
situation
recently i've been dealing with soap. T_T. but i'm getting paid. ^_^. i'm writing the client in ruby 1.9 using mumboe-soap4r lib (
gem1.9 install -r mumboe-soap4r). asp.net serves up the web services. the wsdl that asp.net serves has elements that the ruby lib ignores. mumboe-soap4r generates warnings printed to stderr.the warnings (modified to be more generic):
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}binding : #<WSDL::Binding:0xd2c490 {http://example.com/ExampleServices}ExampleSoap12>
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}operation : #<WSDL::OperationBinding:0xd21a54 CheckLogOnCredentials>
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}body : #<WSDL::Param:0xd20a78 >
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}header : #<WSDL::Param:0xd20a78 >
ignored element: {http://schemas.xmlsoap.org/wsdl/soap12/}address : #<WSDL::Port:0x1083bfc {http://example.com/ExampleServices}ExampleSoap12>
motivation
this was printed out to stderr every time the client grabbed the wsdl and parsed it. reading unit test results was quite annoying. and running the client was annoying. i could just redirect stderr to
/dev/null, but then i wouldn't get any errors at all. this code diagnoses problems and uses stderr to report those problems. so i need something more precise.solution
so instead i redirect stderr but only for the duration of the method that actually generates warnings. the file
/var/lib/gems/1.9.0/gems/mumboe-soap4r-1.5.8.3/lib/wsdl/xmlSchema/parser.rb (on ubuntu 9.10) defines the decode_tag method. i found it like this:
% gem1.9 environment|grep INSTALLATION
- INSTALLATION DIRECTORY: /var/lib/gems/1.9.0
% cd /var/lib/gems/1.9.0/
% ls
% cd mumboe-soap4r-1.5.8.3/lib
% grep -r "ignored element" *
wsdl/parser.rb
wsdl/xmlSchema/parser.rb
then i went back to a blog post i read earlier: jay fields alias method alternative. i also noticed there a link to another post by martin on method replacing. then i did a bit of trial and error to get it working for me in this case, where the class is defined in a module. once i was able to replace the method with my code, written in my file, i just needed to write code that would suppress stderr, call the original method, then resurrect stderr. temporarily redirecting stdout (or stderr) is common enough that someone had written nearly exactly what i needed. i didn't need to search for long.
You can set $VERBOSE = nil in your script to prevent it from logging to STDERR.
ReplyDeleteIf you look at mumboe-soap4r-1.5.8.3/lib/soap/soap.rb at line 145 you'll see that it defines a method Kernel.warn(). All of the messages you are monkey-patching away are logged by calls to Kernel.warn. Inside the method it writes to STDERR unless $VERBOSE.nil?. If you want to log those messages to a file you can redefine Kernel.warn. Just remember Kernel is a module.