Using jMeter for functional e2e testing - jmeter

We're using JMeter for e2e testing of a GraphQL API and have some problems that only the GUI shows us the test results, when running from the console there is no useful "test summary" visible, and jMeter always exits with a "0" exit code indicating "success" to our CI.
I've reproduced a minimal example included below to indicate what I'm trying to do:
use an HTTP sampler to make a request to a JSON API
make a "JSON Assertion" on the result
Print results of failed samplers or assertions to a file or console with a bean shell listener
My goal is to print something like the "View Results Tree" as a passed/failed summary to the console where jMeter was run, or write it to a file.
Our tests make use of simple HTTP samplers with JSON Assertions, my goal was to try and use a Bean Shell Listener and check if any samplers or JSON assertions had errors, and write to a file in either case.
<?xml version="1.0" encoding="UTF-8"?>
<jmeterTestPlan version="1.2" properties="4.0" jmeter="4.0 r1823414">
<hashTree>
<TestPlan guiclass="TestPlanGui" testclass="TestPlan" testname="Test Plan" enabled="true">
<stringProp name="TestPlan.comments"></stringProp>
<boolProp name="TestPlan.functional_mode">false</boolProp>
<boolProp name="TestPlan.tearDown_on_shutdown">true</boolProp>
<boolProp name="TestPlan.serialize_threadgroups">false</boolProp>
<elementProp name="TestPlan.user_defined_variables" elementType="Arguments" guiclass="ArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="TestPlan.user_define_classpath"></stringProp>
</TestPlan>
<hashTree>
<ThreadGroup guiclass="ThreadGroupGui" testclass="ThreadGroup" testname="Thread Group" enabled="true">
<stringProp name="ThreadGroup.on_sample_error">continue</stringProp>
<elementProp name="ThreadGroup.main_controller" elementType="LoopController" guiclass="LoopControlPanel" testclass="LoopController" testname="Loop Controller" enabled="true">
<boolProp name="LoopController.continue_forever">false</boolProp>
<stringProp name="LoopController.loops">1</stringProp>
</elementProp>
<stringProp name="ThreadGroup.num_threads">1</stringProp>
<stringProp name="ThreadGroup.ramp_time">1</stringProp>
<boolProp name="ThreadGroup.scheduler">false</boolProp>
<stringProp name="ThreadGroup.duration"></stringProp>
<stringProp name="ThreadGroup.delay"></stringProp>
</ThreadGroup>
<hashTree>
<HTTPSamplerProxy guiclass="HttpTestSampleGui" testclass="HTTPSamplerProxy" testname="HTTP Request" enabled="true">
<elementProp name="HTTPsampler.Arguments" elementType="Arguments" guiclass="HTTPArgumentsPanel" testclass="Arguments" testname="User Defined Variables" enabled="true">
<collectionProp name="Arguments.arguments"/>
</elementProp>
<stringProp name="HTTPSampler.domain">jsonplaceholder.typicode.com</stringProp>
<stringProp name="HTTPSampler.port"></stringProp>
<stringProp name="HTTPSampler.protocol">https</stringProp>
<stringProp name="HTTPSampler.contentEncoding"></stringProp>
<stringProp name="HTTPSampler.path">/posts/1</stringProp>
<stringProp name="HTTPSampler.method">GET</stringProp>
<boolProp name="HTTPSampler.follow_redirects">true</boolProp>
<boolProp name="HTTPSampler.auto_redirects">false</boolProp>
<boolProp name="HTTPSampler.use_keepalive">true</boolProp>
<boolProp name="HTTPSampler.DO_MULTIPART_POST">false</boolProp>
<stringProp name="HTTPSampler.embedded_url_re"></stringProp>
<stringProp name="HTTPSampler.connect_timeout"></stringProp>
<stringProp name="HTTPSampler.response_timeout"></stringProp>
</HTTPSamplerProxy>
<hashTree/>
<JSONPathAssertion guiclass="JSONPathAssertionGui" testclass="JSONPathAssertion" testname="JSON Assertion" enabled="true">
<stringProp name="JSON_PATH">$.userID</stringProp>
<stringProp name="EXPECTED_VALUE"></stringProp>
<boolProp name="JSONVALIDATION">false</boolProp>
<boolProp name="EXPECT_NULL">false</boolProp>
<boolProp name="INVERT">false</boolProp>
<boolProp name="ISREGEX">true</boolProp>
</JSONPathAssertion>
<hashTree/>
</hashTree>
<BeanShellListener guiclass="TestBeanGUI" testclass="BeanShellListener" testname="BeanShell Listener" enabled="true">
<boolProp name="resetInterpreter">false</boolProp>
<stringProp name="parameters"></stringProp>
<stringProp name="filename"></stringProp>
<stringProp name="script"></stringProp>
</BeanShellListener>
<hashTree/>
</hashTree>
</hashTree>
</jmeterTestPlan>
I tried a Bean Shell Listener with the following contents, but I don't find the JSON Assertion results in the variables/context available to the Bean Shell Listener.
import org.apache.jmeter.services.FileServer;
// Open File(s)
f = new FileOutputStream(FileServer.getFileServer().getBaseDir()+"/results.txt", true);
p = new PrintStream(f);
// Write data to file
p.println( "sampleResult " + sampleResult.toString() + ": " + sampleResult.isSuccessful() );
p.println( "sampleEvent " + sampleEvent.toString());
p.println( "prev " + prev.toString());
p.println( "props " + props.toString());
p.println( "ctx " + ctx.toString());
p.println( "vars " + vars.toString());
// Close File(s)
p.close();f.close();
We are not a Java shop, we use GitLab/etc for our CI, and the ideal case would be to be able to run our jMeter tests in the console, and see a summary of output as one would see when doing unit testing of a scripting language or similar, with a red/green summary of passed and failed tests.

Be aware that as per JMeter 3.1 it is recommended to use JSR223 Test Elements for any form of scripting. So I would suggest switching to JSR223 Listener instead.
You can access AssertionResults as prev.getAssertionResults()
Groovy SDK allows working with files much easier, so you could use something like:
def results = new File('results.txt')
def newLine = System.getProperty('line.separator')
results << 'Sampler Name: ' + prev.getSampleLabel() + ' Successful: ' + prev.isSuccessful()
if (!prev.isSuccessful()) {
prev.getAssertionResults().each {assertionResult ->
results << ' Error message: ' << assertionResult.failureMessage << newLine
}
}
in order to get output in form of:
Sampler Name: HTTP Request Successful: false Error message: No results for path: $['userID']
See Apache Groovy - Why and How You Should Use It article for more information on Groovy scripting in JMeter.
You can also consider running your test using Taurus tool which provides real-time console reporting and powerful Pass/Fail Criteria subsystem where you can specify thresholds and actions to be taken when they are hit/exceeded. So you can configure Taurus to exit with non-zero code in case of failures which can be used for scripting or continuous integration.

Related

Running an existing JMeter Test with parametrization using csv file from Java code

I have recorded the jmeter script with CSVDataConfig. I mentioned the csv config file location as "search.csv" like
<CSVDataSet guiclass="TestBeanGUI" testclass="CSVDataSet" testname="CSV Data Set Config" enabled="true">
<stringProp name="delimiter">,</stringProp>
<stringProp name="fileEncoding"></stringProp>
<stringProp name="filename">search.csv</stringProp>
<boolProp name="quotedData">false</boolProp>
<boolProp name="recycle">true</boolProp>
<stringProp name="shareMode">shareMode.all</stringProp>
<boolProp name="stopThread">true</boolProp>
<stringProp name="variableNames">searchkeyword</stringProp></CSVDataSet>
Now I call the jmeter non gui using the following code in java as
public String sJMeterHome = "C:/Apache/apache-jmeter-2.13";
public String sJMeterProprtiesPath = "C:/Apache/apache-jmeter-2.13/bin/jmeter.properties";
String sUrlTestScriptFilePath = "C:/SourceFiles";
FileInputStream oFileTestCaseNameCSV = new FileInputStream(sUrlTestScriptCSVFilePath);
JMeterUtils.setJMeterHome(sJMeterHome);
JMeterUtils.loadJMeterProperties(sJMeterProprties.getPath());
JMeterUtils.initLogging();// you can comment this line out to see extra log messages of i.e. DEBUG level
JMeterUtils.initLocale();
StandardJMeterEngine jmeter = new StandardJMeterEngine();
HashTree testPlanTree = new HashTree();
SaveService.loadProperties();
testPlanTree = SaveService.loadTree(oFileTestCaseName);
jmeter.configure(testPlanTree);
jmeter.run();
Now the problem is csv file not found exception error thrown.
I store the jmx and csv file in same folder.
oFileTestCaseName - is read the jmx file and add in saveservice.
How can I resolve this issue
Did you mention the full CSV file name i.e C:/SourceFiles/filename.csv ?

Spring Integration: how to add custom HTTP headers to the HTTP outbound gateway?

I'm trying to pass some custom HTTP headers using <int-http:outbound-gateway> and <int:header-enricher> components of Spring Integration, but it doesn't work on my configuration.
I have tried two configurations. The first one with the "mapped-request-headers" attribute:
<int:chain input-channel="requestChannel" output-channel="replyChannel">
<int:header-enricher>
<int:header name="test" value="test"></int:header>
</int:header-enricher>
<int-http:outbound-gateway id="gateway"
encode-uri="true" url="http://localhost:8080/webapp/service/{request}"
http-method="GET" mapped-request-headers="test, HTTP_REQUEST_HEADERS">
<int-http:uri-variable name="request" expression="payload"/>
</int-http:outbound-gateway>
</int:chain>
The second one with the "header-mapper" attribute, with the relative DefaultHttpHeaderMapper configuration:
<int:chain input-channel="requestChannel" output-channel="replyChannel">
<int:header-enricher>
<int:header name="test" value="test"></int:header>
</int:header-enricher>
<int-http:outbound-gateway id="gateway"
encode-uri="true" url="http://localhost:8080/webapp/service/{request}"
http-method="GET" header-mapper="headerMapper">
<int-http:uri-variable name="request" expression="payload"/>
</int-http:outbound-gateway>
</int:chain>
<bean id="headerMapper" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<property name="outboundHeaderNames" value="HTTP_REQUEST_HEADERS, test" />
<property name="userDefinedHeaderPrefix" value="" />
</bean>
But in both cases, the message's headers loaded by the remote application are the following:
GenericMessage[
payload={},
headers={
http_requestMethod=GET,
replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#4c8b7a27,
errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#4c8b7a27,
host=localhost: 8080,
http_requestUrl=http://localhost:8080/webapp/service/hello,
connection=keep-alive,
id=3c2a21ba-b7f5-e5e9-c821-45251d406318,
cache-control=no-cache,
pragma=no-cache,
user-agent=Java/1.8.0_65,
accept=[
text/html,
image/gif,
image/jpeg,
*/*;q=.2,
*/*;q=.2],
timestamp=1469009855797
}
]
There is no trace of the "test" header that I'm trying to add to the request message.
What's the right way to add a custom header to the <int-http:outbound-gateway> ?
It's also good any other working solution.
UPDATE
As from Gary indication, I turned on the DEBUG mode.
This is a very interesting thing: the log says that the header [test] "will be mapped":
message sent: GenericMessage [payload=hello, headers={id=79f98422-418b-f00f-1e21-09461b1ff80c, timestamp=1469021452494}]
2016-07-20 15:53:57 DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper.fromHeaders:402 (executor-4) - outboundHeaderNames=[test, HTTP_REQUEST_HEADERS]
2016-07-20 15:53:57 DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper.shouldMapHeader:537 (executor-4) - headerName=[test] WILL be mapped, matched pattern=test
2016-07-20 15:53:57 DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper.fromHeaders:420 (executor-4) - setting headerName=[X-test], value=test
2016-07-20 15:53:57 DEBUG org.springframework.http.client.support.HttpAccessor.createRequest:79 (executor-4) - Created GET request for "http://localhost:8080/webapp/service/hello"
I have implemented a simple Filter on the server side that intercepts every HTTP request, and it prints on the log every header of that request.
This is the result:
x-test=test
cache-control=no-cache
pragma=no-cache
user-agent=Java/1.8.0_65
host=localhost:8080
accept=text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
connection=keep-alive
So, the header "x-test" is present on the HttpServletRequest instance.
But after that, in the log I can see this other message (I have reported only those significant for this context):
2016-07-20 15:53:57 DEBUG org.springframework.web.servlet.DispatcherServlet.doService:865 (http-nio-8080-exec-1) - DispatcherServlet with name 'dispatcherServer' processing GET request for [/webapp/service/hello]
2016-07-20 15:53:57 DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper.toHeaders:436 (http-nio-8080-exec-1) - inboundHeaderNames=[Accept, Accept-Charset, Accept-Encoding, Accept-Language, Accept-Ranges, Authorization, Cache-Control, Connection, Content-Length, Content-Type, Cookie, Date, Expect, From, Host, If-Match, If-Modified-Since, If-None-Match, If-Range, If-Unmodified-Since, Max-Forwards, Pragma, Proxy-Authorization, Range, Referer, TE, Upgrade, User-Agent, Via, Warning]
2016-07-20 15:53:57 DEBUG org.springframework.integration.http.support.DefaultHttpHeaderMapper.shouldMapHeader:561 (http-nio-8080-exec-1) - headerName=[x-test] WILL NOT be mapped
2016-07-20 15:53:57 DEBUG org.springframework.integration.handler.AbstractMessageHandler.handleMessage:115 (executor-4) - ServiceActivator for [org.springframework.integration.handler.MethodInvokingMessageProcessor#6ae60a] (channelServiceActivator) received message: GenericMessage [payload={}, headers={http_requestMethod=GET, replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#565fe0d8, errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#565fe0d8, host=localhost:8080, http_requestUrl=http://localhost:8080/webapp/service/hello, connection=keep-alive, id=9578f82d-7fc2-fe94-d8bf-3225ec955b22, cache-control=no-cache, pragma=no-cache, user-agent=Java/1.8.0_65, accept=[text/html, image/gif, image/jpeg, */*;q=.2, */*;q=.2], timestamp=1469022837172}]
Now the log says that the header "[x-test] WILL NOT be mapped". How is possibile? It's because it doesn't appear in the inboundHeaderNames ?
In fact, the header seems to be "disappeared" in the GenericMessage:
GenericMessage [
payload={},
headers={
http_requestMethod=GET,
replyChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#16b10fb6,
errorChannel=org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel#16b10fb6,
host=localhost:8080,
http_requestUrl=http://localhost:8080/webapp/service/hello,
connection=keep-alive,
id=ba2af515-9e29-4d84-d176-5b9d0d066cb0,
cache-control=no-cache,
pragma=no-cache,
user-agent=Java/1.8.0_65,
accept=[text/html,
image/gif,
image/jpeg,
*/*;q=.2,
*/*;q=.2],
timestamp=1469021452542
}
]
I don't understand why the header in present in the HTTP Request, but it's no present in the headers of the Message channel.
I have found the answer for this issue.
The <int-http:outbound-gateway> maps the headers that had to be inserted in the "exiting" HTTP requests.
The <int-http:inbound-gateway> maps the headers that are contained in the "entering" HTTP requests.
So, it has to be defined a "header-mapper" that:
maps the "inboundHeaderNames" for the <int-http:inbound-gateway>
maps the "outboundHeaderNames" for the <int-http:outbound-gateway>
In my example case, the solution for the "OUTBOUND SIDE" (the client application) was:
<int:chain input-channel="requestChannel" output-channel="replyChannel">
<int:header-enricher>
<int:header name="test" value="test"></int:header>
</int:header-enricher>
<int-http:outbound-gateway id="gateway"
encode-uri="true" url="http://localhost:8080/webapp/service/{request}"
http-method="GET" header-mapper="headerMapper">
<int-http:uri-variable name="request" expression="payload"/>
</int-http:outbound-gateway>
</int:chain>
<bean id="headerMapper" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<property name="outboundHeaderNames" value="HTTP_REQUEST_HEADERS, test" />
<property name="userDefinedHeaderPrefix" value="" />
</bean>
The "outboundHeaderNames" has to be setted with the header names that has to be mapped in the "outbound requests" ("test" in this case).
While the solution for the "INBOUND SIDE" (the receiver application) was:
<int-http:inbound-gateway id="gateway" request-channel="requestChannel"
path="/service/**" supported-methods="GET"
reply-channel="outputChannel" header-mapper="headerMapper">
</int-http:inbound-gateway>
<bean id="headerMapper" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<property name="inboundHeaderNames" value="*" />
</bean>
The "inboundHeaderNames" setted to "*" ensure that all the headers of the source request will be mapped in the Message headers.
With this approach, we can pass custom headers to any URL in HTTP requests, and we can recover them on the server side in the message channel context.
Turn on DEBUG logging; you should see messages about header mapping like this...
08:46:44.987 DEBUG [main] ... headerName=[id] WILL NOT be mapped
08:46:44.987 DEBUG [main] ... headerName=[test] WILL be mapped, matched pattern=test
08:46:44.987 DEBUG [main] ... setting headerName=[X-test], value=foo
(This is with your first example - custom headers currently get the X- prefix by default).

Why doesn't initialize appear as a method when I call on the instance methods of a class?

I'm writing a blog post on how almost everything is an object in Ruby, and I'm trying to show this through the following example:
class CoolBeans
attr_accessor :beans
def initialize
#bean = []
end
def count_beans
#beans.count
end
end
So from looking at the class we can tell it has 4 methods(unless of course, I'm wrong):
It can initialize a default empty array of beans when a new instance is created
It can count how many beans it has
It can read how many beans it had (through the attr_accessor)
It can write(or add) more beans to the empty array (also through the attr_accessor)
However, when I ask the class itself what instance methods it has, I don't see the default initialize method:
CoolBeans.new.class.instance_methods
# => [:beans, :beans=, :count_beans, :lm, :lim, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :itself, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :inspect, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :singleton_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
Does this mean that the initialize method is not an instance method? If not, why isn't it showing up as a method available to the class CoolBeans?
instance_methods returns an array of public and protected methods. However, initialize is automatically private ref.
CoolBeans.private_instance_methods
# => [:initialize, :default_src_encoding, :irb_binding, :initialize_copy, :initialize_dup, :initialize_clone, :sprintf, :format, :Integer, :Float, :String, :Array, :Hash, :warn, :raise, :fail, :global_variables, :__method__, :__callee__, :__dir__, :eval, :local_variables, :iterator?, :block_given?, :catch, :throw, :loop, :respond_to_missing?, :trace_var, :untrace_var, :at_exit, :syscall, :open, :printf, :print, :putc, :puts, :gets, :readline, :select, :readlines, :`, :p, :test, :srand, :rand, :trap, :load, :require, :require_relative, :autoload, :autoload?, :proc, :lambda, :binding, :caller, :caller_locations, :exec, :fork, :exit!, :system, :spawn, :sleep, :exit, :abort, :Rational, :Complex, :set_trace_func, :gem, :gem_original_require, :singleton_method_added, :singleton_method_removed, :singleton_method_undefined, :method_missing]
# ^^^^^^^^^^^

Watir inspecting json in firefox "network" tab - Parsing

I'm not 100% sure if Im asking the right question.
There's a website I go to that uses has a JSON string that I need to access. I can see the location of the JSON string in Firefox's "network tab" by clicking F12 and selecting the "Network" tab.
So I thought i could access the file by going into the temporary internet files, but no dice.
I also thought watir could access the temporary internet files through itself, but all i could find is this.
require 'watir-webdriver'
$browser = Watir::Browser.new
$browser.methods
=> [:driver, :wd, :inspect, :goto, :back, :forward, :url, :title, :close, :quit, :cookies, :name, :text, :html, :alert, :refresh, :wait, :ready_state, :status, :execute_script, :send_keys, :screenshot, :add_checker, :disable_checker, :run_checkers, :exist?, :exists?, :assert_exists, :reset!, :browser, :wait_until, :wait_while, :windows, :window, :element, :elements, :extract_selector, :a, :as, :abbr, :abbrs, :address, :addresses, :area, :areas, :article, :articles, :aside, :asides, :audio, :audios, :b, :bs, :base, :bases, :bdi, :bdis, :bdo, :bdos, :blockquote, :blockquotes, :body, :bodys, :br, :brs, :button, :buttons, :canvas, :canvases, :caption, :captions, :cite, :cites, :code, :codes, :col, :cols, :colgroup, :colgroups, :data, :datas, :datalist, :datalists, :dd, :dds, :del, :dels, :details, :detailses, :dfn, :dfns, :dialog, :dialogs, :div, :divs, :dl, :dls, :dt, :dts, :em, :ems, :embed, :embeds, :fieldset, :fieldsets, :figcaption, :figcaptions, :figure, :figures, :footer, :footers, :form, :forms, :frameset, :framesets, :h1, :h1s, :h2, :h2s, :h3, :h3s, :h4, :h4s, :h5, :h5s, :h6, :h6s, :head, :heads, :header, :headers, :hgroup, :hgroups, :hr, :hrs, :htmls, :i, :is, :iframe, :iframes, :img, :imgs, :input, :inputs, :ins, :inses, :kbd, :kbds, :keygen, :keygens, :label, :labels, :legend, :legends, :li, :lis, :main, :mains, :map, :maps, :mark, :marks, :menu, :menus, :menuitem, :menuitems, :meta, :metas, :meter, :meters, :nav, :navs, :noscript, :noscripts, :object, :objects, :ol, :ols, :optgroup, :optgroups, :option, :options, :output, :outputs, :p, :ps, :param, :params, :pre, :pres, :progress, :progresses, :q, :qs, :rp, :rps, :rt, :rts, :ruby, :rubies, :s, :ss, :samp, :samps, :script, :scripts, :section, :sections, :select, :selects, :small, :smalls, :source, :sources, :span, :spans, :strong, :strongs, :style, :styles, :sub, :subs, :summary, :summaries, :sup, :sups, :table, :tables, :tbody, :tbodys, :td, :tds, :template, :templates, :textarea, :textareas, :tfoot, :tfoots, :th, :ths, :thead, :theads, :time, :times, :titles, :tr, :trs, :track, :tracks, :u, :us, :ul, :uls, :var, :vars, :video, :videos, :wbr, :wbrs, :checkbox, :checkboxes, :file_field, :file_fields, :font, :fonts, :frame, :frames, :hidden, :hiddens, :image, :images, :link, :links, :radio, :radios, :select_list, :select_lists, :text_field, :text_fields, :field_set, :field_sets, :psych_to_yaml, :to_yaml, :to_yaml_properties, :dclone, :to_json, :nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, :singleton_class, :clone, :dup, :taint, :tainted?, :untaint, :untrust, :untrusted?, :trust, :freeze, :frozen?, :to_s, :methods, :singleton_methods, :protected_methods, :private_methods, :public_methods, :instance_variables, :instance_variable_get, :instance_variable_set, :instance_variable_defined?, :remove_instance_variable, :instance_of?, :kind_of?, :is_a?, :tap, :send, :public_send, :respond_to?, :extend, :display, :method, :public_method, :define_singleton_method, :object_id, :to_enum, :enum_for, :==, :equal?, :!, :!=, :instance_eval, :instance_exec, :__send__, :__id__]
There is a way to access everything else but the json temporary file i need to access.
I haven't seen any documentation on this, because I'm not sure I'm asking the correct questions.
Update:
The method is a 200 POST with the extension type json.

ruby-savon communicate with mono-wcf

i am new to mono wcf, and i came across some problems about my code.
recent, i use ruby-savon to get data from wcf host on mono.
and this is my ruby code:
client = Savon::Client.new do
wsdl.document="http://localhost:9000/MonoWcf/MonoSevice/wsdl"
end
puts client.wsdl.soap_actions
response = client.request :get_data
and this this puts :
ruby -KU -- '/home/charlot/Documents/Aptana Studio 3 Workspace/rubyfun/soap/savon.rb'
W, [2012-12-21T02:45:41.845966 #10527] WARN -- : HTTPI executes HTTP GET using the httpclient adapter
get_data
get_data_using_data_contract
D, [2012-12-21T02:45:41.856091 #10527] DEBUG -- : SOAP request: http://localhost:9000/MonoWcf/MonoSevice/soap
D, [2012-12-21T02:45:41.856294 #10527] DEBUG -- : SOAPAction: "http://localhost:9000/IMonoService/GetData", Content-Type: text/xml;charset=UTF-8, Content-Length: 293
D, [2012-12-21T02:45:41.856329 #10527] DEBUG -- : <?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="http://tempuri.org/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body><GetData>
</GetData>
</env:Body>
</env:Envelope>
W, [2012-12-21T02:45:41.856403 #10527] WARN -- : HTTPI executes HTTP POST using the httpclient adapter
D, [2012-12-21T02:45:41.873963 #10527] DEBUG -- : SOAP response (status 415):
D, [2012-12-21T02:45:41.874057 #10527] DEBUG -- :
/usr/local/lib/ruby/gems/1.9.1/gems/savon-1.2.0/lib/savon/soap/response.rb:108:in `raise_errors': Savon::HTTP::Error
from /usr/local/lib/ruby/gems/1.9.1/gems/savon-1.2.0/lib/savon/soap/response.rb:18:in `initialize'
from /usr/local/lib/ruby/gems/1.9.1/gems/savon-1.2.0/lib/savon/soap/request.rb:35:in `new'
from /usr/local/lib/ruby/gems/1.9.1/gems/savon-1.2.0/lib/savon/soap/request.rb:35:in `response'
from /usr/local/lib/ruby/gems/1.9.1/gems/savon-1.2.0/lib/savon/client.rb:86:in `request'
from /home/charlot/Documents/Aptana Studio 3 Workspace/rubyfun/soap/savon.rb:15:in `dosoap'
from /home/charlot/Documents/Aptana Studio 3 Workspace/rubyfun/soap/savon.rb:23:in `<main>'
**
and this is the mono-wcf wsdl :
**
`
<import location="http://localhost:9000/MonoWcf/MonoSevice/wsdl?wsdl=wsdl0" namespace="http://localhost:9000"/>
<types/>
<binding name="BasicHttpBinding_IMonoService" type="i0:IMonoService">
<soap:binding transport="http://schemas.xmlsoap.org/soap/http"/>
<operation name="GetData">
<soap:operation soapAction="http://localhost:9000/IMonoService/GetData" style="document"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
<operation name="GetDataUsingDataContract">
<soap:operation soapAction="http://localhost:9000/IMonoService/GetDataUsingDataContract" style="document"/>
<input>
<soap:body use="literal"/>
</input>
<output>
<soap:body use="literal"/>
</output>
</operation>
</binding>
<service name="service">
<port name="BasicHttpBinding_IMonoService" binding="tns:BasicHttpBinding_IMonoService">
<soap:address location="http://localhost:9000/MonoWcf/MonoSevice/soap"/>
</port>
</service>
`
**but when i host wcf in windows(7), it really get the data.
my os is: ubuntu 12
mono version:
Mono JIT compiler version 2.10.8.1 (Debian 2.10.8.1-1ubuntu2.2)
Copyright (C) 2002-2011 Novell, Inc, Xamarin, Inc and Contributors. www.mono-project.com
TLS: __thread
SIGSEGV: altstack
Notifications: epoll
Architecture: x86
Disabled: none
Misc: softdebug
LLVM: supported, not enabled.
GC: Included Boehm (with typed GC and Parallel Mark)
really thanks your help!
This is a bug in Mono's WCF code that I just fixed in mono/master commit ea2f2cd.
Ruby-savon sends Content-Type: text/xml;charset=UTF-8, but the server expected Content-Type: text/xml; charset=utf-8. This is incorrect, the check is supposed to be case-insensitive and ignore whitespace.
You need to either compile the latest mono from github or, as a temporary workaround, somehow make ruby-savon send Content-Type: text/xml; charset=utf-8.
Temporary Workaround
Edit lib/savon/request.rb (it's in /Library/Ruby/Gems/1.8/gems/savon-2.0.2 on my Mac), at the top, there's
CONTENT_TYPE = {
1 => "text/xml;charset=%s",
2 => "application/soap+xml;charset=%s"
}
Change that into
CONTENT_TYPE = {
1 => "text/xml; charset=%s",
2 => "application/soap+xml; charset=%s"
}
Then set the encoding to "utf-8", for instance:
require 'savon'
client = Savon.client(:wsdl => "http://localhost:9999/MyService?wsdl", :encoding => "utf-8")
puts client.operations
response = client.call(:hello)
Tested with Ruby 1.8.7 on my Mac.

Resources