paulc Posted October 2, 2006 Share Posted October 2, 2006 Hi all, can anyone show me how to integrate jasperintelligence with ruby on rails application. Mainly is 1) Authentication - let rails handle to the authentication 2) url to access reports stored on jasperintelligence Link to comment Share on other sites More sharing options...
rosisr Posted November 27, 2006 Share Posted November 27, 2006 Hi, I'm actually dealing with it. I just can tell you the url connection as I havent been able to get a "fully" authentication. Url: "http://localhost/jasperserver/services/repository/" I've tried to authenticate with this: conn = Net::HTTP.start('10.128.10.81') get = Net::HTTP::Get.new('/jasperserver/services/repository/') get.basic_auth 'jasperadmin', 'jasperadmin' conn.request(get) print conn but it answers ok, but when I try to use any other method, it says "SOAP::HTTPStreamError: 401: Full authentication is required to access this resource". Im still looking into it but I'd really appreciate any suggestion. Link to comment Share on other sites More sharing options...
swood Posted November 28, 2006 Share Posted November 28, 2006 Have you checked outhttp://community.jaspersoft.com/questions/514432/jasperintelligence-11-web-services-doc-posted Sherman JaspersoftPost Edited by Tim Cloonan at 08/25/08 14:12 Link to comment Share on other sites More sharing options...
rosisr Posted November 28, 2006 Share Posted November 28, 2006 Thanks but though I've been checking it my Java knowledge is very low. What I need to do is a web service client in Ruby on Rails and I can understand I dont need to rewrite the code, do I? I mean in Ruby is supposed to be just: JASPER_SERVER = "http://10.128.10.81/jasperserver/services/repository/" driver = SOAP::RPC::Driver.new(JASPER_SERVER)driver.add_method('login','username','password') Thanks in advance for any suggestion. Link to comment Share on other sites More sharing options...
aaronhelton Posted December 1, 2006 Share Posted December 1, 2006 I've been toying around with this concept for at least 3 weeks, and I haven't been able to make any meaningful progress. Part of the problem as I see it is the inability for the default JI web service to display its WSDL, where you get the following error message: <error><description>Unable to generate WSDL for this service</description><reason>Either user has not dropped the wsdl into META-INF or operations use message receivers other than RPC.</reason></error> Another forum post addresses this and recommends deploying the repository.aar file as an axis2 service, with the caveat that you have to have all the required jar files, whatever those are supposed to be. All I ever get there is a faulty axis2 service. But back to the rails problem specifically. Based on the methods I see as available in the web service (the WSDL is available on the aforementioned forum post), I should be able to use add_method for the RPC driver to create a login method that works. It's obvious that something is wrong with the authentication method that I am using, because I get: SOAP::HTTPStreamError: 401: Full authentication is required to access this resource The thing is, I really like JasperIntelligence, and I am evaluating ways to integrate it into other web applications that may or may not be java-based. If I can show a solid success story here, I might even be able to convince my company to abandon Crystal entirely. Is there any way we can get more meaningful answers to this kind of question? Has anyone implemented a ruby SOAP client that interfaces with the JI web service? I don't guess I have to point out that existing documentation is understandably java-specific, and since I don't have a strong grasp of java in the first place, I don't relish the idea of digging through the iReport plugin to figure out how this works. Any suggestions? Link to comment Share on other sites More sharing options...
rosisr Posted December 4, 2006 Share Posted December 4, 2006 Hi, I've got the same error as you and finally Ive got authentication but I cannot do anything more, with add_method I tried the list method and all I got was Errno::ECONNREFUSED: Connection refused - connect(2) (, #0) My class for a web service client: class WsJasperClient < SOAP::RPC::Driver JASPER_SERVER = "http://10.128.10.81/jasperserver/services/repository/" # Authentication works!!! def new(nameserver) # nameserver => JASPER_SERVER driver = SOAP::RPC::Driver.new(JASPER_SERVER) driver.options["protocol.http.basic_auth"] << [JASPER_SERVER, "jasperadmin", "jasperadmin"] end # Create driver and set up methods # It doesnt work yet :-( def add_methods # driver = SOAP::RPC::Driver.new("http://10.128.10.81/jasperserver/services/repository/" ) [ %w(login username password), %w(list uri), %w(get uri args), %w(runReport reportUri map)].each do |signature| self.add_method(*signature) end end end I hope this can help you though I havent been able to get it works.Post edited by: rosisr, at: 2006/12/04 10:27 Link to comment Share on other sites More sharing options...
aaronhelton Posted December 4, 2006 Share Posted December 4, 2006 I got the following (via irb) to generate both a successful authentication and an error: require 'soap/rpc/driver' server = "http://localhost:8080/jasperserver/services/repository/" driver = SOAP::RPC::Driver.new(server) driver.options["protocol.http.basic_auth"] << [server, "admin", "admin"] driver.add_method('login','username','password') driver.login('admin','admin') The error that is generated: SOAP::Parser::FormatDecodeError: Unbalanced tag in XML. from /usr/lib/ruby/1.8/soap/parser.rb:95:in `parse' from /usr/lib/ruby/1.8/soap/processor.rb:39:in `unmarshal' from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:232:in `unmarshal' from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:175:in `route' from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:141:in `call' from /usr/lib/ruby/1.8/soap/rpc/driver.rb:178:in `call' from /usr/lib/ruby/1.8/soap/rpc/driver.rb:232:in `login' from (irb):6 However, getting this to work in the first place required me to install http-access2, since net/http + soap4r does not support basic authentication ( NotImplementedError: basic_auth is not supported under soap4r + net/http.) Kudos, though, for figuring out the mechanism for authentication. Next up, adding the other methods. I tried: driver.add_method('list','uri') which is what your class method attempts to do. I don't get a connection refused, but I do get an error, and it seems that JasperServer is returning this one: 09:49:15,778 ERROR ManagementService,http-8080-Processor23:283 - caught exception: Parsing Error : Content is not allowed in prolog. Line : 1 Column : 1 Parsing Error : Content is not allowed in prolog. Line : 1 Column : 1 {file: [not available]; line: 1; column: 1} .... I suspect I will be able to track that one down, and it's likely just the way I have constructed my argument. Anyway, I will keep trying to figure that out... In the mean time, I would love to hear from anyone else who has tried this. Link to comment Share on other sites More sharing options...
rosisr Posted December 5, 2006 Share Posted December 5, 2006 If you try from a rails console you can get an authentication with: JASPER_SERVER = "http://10.128.10.81/jasperserver/services/repository/" driver = SOAP::RPC::Driver.new(JASPER_SERVER) driver.options["protocol.http.basic_auth"] << [JASPER_SERVER, "jasperadmin", "jasperadmin"] I've also had the same problems as you. I got the authentication with the code above in a rails console and then I got other error when I tried to use list method and what I get is: ws.list('')Wire dump: = Request POST /jasperserver/services/repository/ HTTP/1.1! CONNECTION CLOSEDErrno::EPIPE: Broken pipe from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2.rb:1135:in `write' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2.rb:1135:in `<<' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2/http.rb:185:in `dump' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2/http.rb:386:in `dump' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2.rb:1213:in `query' from /usr/lib/ruby/1.8/timeout.rb:56:in `timeout' from /usr/lib/ruby/1.8/timeout.rb:76:in `timeout' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2.rb:1211:in `query' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2.rb:892:in `query' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2.rb:434:in `do_get_block' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2.rb:370:in `conn_request' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2.rb:285:in `request' from /usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/http-access2.rb:264:in `post' from /usr/lib/ruby/1.8/soap/streamHandler.rb:199:in `send_post' from /usr/lib/ruby/1.8/soap/streamHandler.rb:137:in `send' from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:170:in `route' from /usr/lib/ruby/1.8/soap/rpc/proxy.rb:141:in `call' from /usr/lib/ruby/1.8/soap/rpc/driver.rb:178:in `call' Link to comment Share on other sites More sharing options...
aaronhelton Posted December 6, 2006 Share Posted December 6, 2006 I figured a couple of things out this morning with respect to the list operation and authentication. First, the approach we are taking is the correct approach for authentication. Second, the list operation requires an XML document as an argument, not simply a path, like /reports. I found the structure of the XML document that lists the resources in the repository by running Ethereal and digging through the HTTP POST packets generated by iReport with the web service plugin. From that, I was able to construct the following program, which works to get a list of available resources given a URI: #!/bin/env ruby require 'soap/rpc/driver' strUser = 'admin'strPWD = 'admin'strServer = 'http://localhost:8080/jasperserver/services/repository/'strURI = %q{<?xml version="1.0" encoding="UTF-8"?> <request> <operation-name>list</operation-name> <resource-descriptor read-only="false" control-type="0" is-reference="false" is-new="false" strict-max="false" data-type="0" mandatory="false" has-data="false" strict-min="false" main-report="false" version="0"> <uri-string>/reports</uri-string><ws-type>folder</ws-type> </resource-descriptor></request>} driver = SOAP::RPC::Driver.new(strServer)driver.wiredump_dev = STDERRdriver.options["protocol.http.basic_auth"] << [strServer, strUser, strPWD] driver.add_method('list','request') puts driver.list(strURI) From there, it should be trivial to parse the resulting XML into something that works in rails: <?xml version="1.0" encoding="UTF-8"?> <operation-result return-code="0"><resource-descriptors xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" read-only="false" control-type="0" is-reference="false" is-new="false" strict-max="false" data-type="0" mandatory="false" has-data="false" strict-min="false" main-report="false" version="0" xsi:type="java:com.jaspersoft.jasperserver.api.metadata.xml.domain.impl.ResourceDescriptor"><name>samples</name><description>Samples</description><resource-type>com.jaspersoft.jasperserver.api.metadata.common.domain.Folder</resource-type><parent-folder>/reports</parent-folder><creation-date>2006-11-15T12:27:13.000-06:00</creation-date><uri-string>/reports/samples</uri-string><ws-type>folder</ws-type><label>Samples</label></resource-descriptors><version>1.1.0</version></operation-result> I will hopefully be able to deconstruct a runReport request here in the next couple of hours. Note that it is not necessary to explicitly call the login function, since the headers here are constructed with the authentication present. I believe that was the source of the 500 Internal Server Error mentioned previously. Link to comment Share on other sites More sharing options...
aaronhelton Posted December 6, 2006 Share Posted December 6, 2006 As promised, here's a plain ruby example of how to use the runReport method. I am betting it is pretty easy from this point to integrate this into rails. That's my next step, anyway. #!/bin/env ruby require 'soap/rpc/driver' strUser = 'admin'strPWD = 'admin'strServer = 'http://localhost:8080/jasperserver/services/repository/'strOutputFormat = 'HTML' #JRPRINT, RTF, PDF, etc?strURI = '/reports/samples/Employees'strRequest = %Q|<?xml version="1.0" encoding="UTF-8"?><request><operation-name>runReport</operation-name><resource-descriptor read-only="false" control-type="0" is-reference="false" is-new="false" strict-max="false" data-type="0" mandatory="false" has-data="false" strict-min="false" main-report="false" version="0"><uri-string>#{strURI}</uri-string></resource-descriptor><arguments xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.jaspersoft.jasperserver.api.metadata.xml.domain.impl.Argument"><name>RUN_OUTPUT_FORMAT</name><value>#{strOutputFormat}</value></arguments></request> | driver = SOAP::RPC::Driver.new(strServer)driver.wiredump_dev = STDERRdriver.options["protocol.http.basic_auth"] << [strServer, strUser, strPWD] driver.add_method('runReport','request') puts driver.runReport(strRequest) Link to comment Share on other sites More sharing options...
rosisr Posted December 7, 2006 Share Posted December 7, 2006 Thanks a lot, you've been a great help!! But I still have some problems, when I try to run this: #!/bin/env ruby require 'soap/rpc/driver' strUser = 'jasperadmin'strPWD = 'jasperadmin'strServer = 'http://10.128.10.81/jasperserver/services/repository/' strOutputFormat = 'HTML' #JRPRINT, RTF, PDF, etc?strURI = '/reports/samples/Employees'strRequest = %Q{<?xml version="1.0" encoding="UTF-8"?><request> <operation-name>runReport</operation-name><resource-descriptorread-only="false" control-type="0" is-reference="false" is-new="false" strict-max="false" data-type="0" mandatory="false" has-data="false" strict-min="false" main-report="false" version="0"><uri-string>#{strURI}</uri-string></resource-descriptor><arguments xmlnssi="http://www.w3.org/2001/XMLSchema-instance"xsi:type="java:com.jaspersoft.jasperserver.api.metadata.xml.domain.impl.Argument"><name>RUN_OUTPUT_FORMAT</name><value>#{strOutputFormat}</value></arguments></request>} driver = SOAP::RPC::Driver.new(strServer)driver.wiredump_dev = STDERRdriver.options["protocol.http.basic_auth"] << [strServer, strUser, strPWD] driver.add_method('runReport','request') puts driver.runReport(strRequest) What I get is: <?xml version='1.0 'encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header /><soapenv:Body><ns1:result xmlns:ns1="http://jasperserver/ws2/namespace1" xmlns:tns="http://ws.apache.org/axis2"><?xml version="1.0" encoding="UTF-8"?><operation-result return-code="1"><version>1.1.0</version><message>unable to instantiate java.util.List; </message></operation-result></ns1:result></soapenv:Body></soapenv:Envelope> Any suggestion? Link to comment Share on other sites More sharing options...
aaronhelton Posted December 7, 2006 Share Posted December 7, 2006 That looks like an issue with JasperIntelligence, and not with ruby. Try tailing your catalina.out file and see if there is more information there, like a stack trace. As for my progress in general, I still have to do the following: 1. Figure out how to pass parameters in the request XML2. Figure out how to view an HTML-exported report inline (in rails)3. Figure out everything else rails needs to make this work right Of course I will still be working on it today, but if anyone else comes across this topic and has any suggestions, I would love to hear them. Item number 2 has its own forum thread, since I can't seem to get any meaningful object out of the SOAP::Attachment when I choose HTML as the output format. Link to comment Share on other sites More sharing options...
aaronhelton Posted January 8, 2007 Share Posted January 8, 2007 Ok, after some additional time dedicated to this task, I have managed the following: 1. Provide a rails front-end that lists the reports residing in a specific folder. 2. Create links to those reports that then return the report in an exportable format, such as PDF. PDF is the only format I have actually gotten to work with the sample reports, but I suspect that other formats should work just fine if the report is set up to handle it. To accomplish this, I needed a model, a controller, a helper, and a view. Here is the code that I am using. Note that I am storing my JI connection information in the local database, since I don't want the user to know anything about the JI credentials explicitly. My table name for this configuration info is site_configs, and I have a corresponding rails model called site_configs.rb ##### begin app/models/reports.rb #####require 'soap/rpc/driver'class Reports < ActiveRecord::Base class << self def get_list(strURL, strUser, strPass, strURI) strRequestBody = %Q|<?xml version="1.0" encoding="UTF-8"?> <request> <operation-name>list</operation-name> <resource-descriptor read-only="false" control-type="0" is-reference="false" is-new="false" strict-max="false" data-type="0" mandatory="false" has-data="false" strict-min="false" main-report="false" version="0"> <uri-string>#{strURI}</uri-string><ws-type>folder</ws-type> </resource-descriptor></request> | driver = SOAP::RPC::Driver.new(strURL) driver.options["protocol.http.basic_auth"] << [strURL, strUser, strPass] driver.add_method('list','request') @report_list = driver.list(strRequestBody) end def get_report(strURL, strUser, strPass, strURI, strOutputFmt) strRequestBody = %Q|<?xml version="1.0" encoding="UTF-8"?> <request><operation-name>runReport</operation-name><resource-descriptor read-only="false" control-type="0" is-reference="false" is-new="false" strict-max="false" data-type="0" mandatory="false" has-data="false" strict-min="false" main-report="false" version="0"> <uri-string>#{strURI}</uri-string></resource-descriptor> <arguments xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="java:com.jaspersoft.jasperserver.api.metadata.xml.domain.impl.Argument"> <name>RUN_OUTPUT_FORMAT</name><value>#{strOutputFmt}</value></arguments></request> | driver = SOAP::RPC::Driver.new(strURL) driver.options["protocol.http.basic_auth"] << [strURL, strUser, strPass] driver.add_method('runReport','request') report = driver.runReport(strRequestBody)["Include"].content report end end end##### end app/models/reports.rb ##### ##### begin app/helpers/send_doc.rb #####module SendDoc def send_doc(strURL, strUser, strPass, strReportName, strReportURI, strOutputFmt) case strOutputFmt when 'PDF' mime_type = 'application/pdf' extension = 'pdf' else #rtf mime_type = 'application/rtf' extension = 'rtf' end send_data Reports.get_report(strURL, strUser, strPass, strReportURI, strOutputFmt), :filename => "#{strReportName}.#{extension}", :type => mime_type, :disposition => 'inline' endend##### end app/helpers/send_doc.rb ##### ##### begin app/controllers/reports_controller.rb #####require 'rexml/document'class ReportsController < ApplicationController include SendDoc def index @jasperServer = SiteConfig.find(:first, :conditions => "name = 'JasperServer URL'")["value"] @jasperUser = SiteConfig.find(:first, :conditions => "name = 'JasperServer User'")["value"] @jasperPass = SiteConfig.find(:first, :conditions => "name = 'JasperServer Password'")["value"] @jasperURI = '/reports/samples' @reportsXML = Reports.get_list(@jasperServer, @jasperUser, @jasperPass, @jasperURI) doc = REXML::Document.new(@reportsXML) @report_names = [] @report_labels = [] @res_type = [] @parent_folder = [] doc.elements.each('operation-result/resource-descriptors/name') do |ele| @report_names << ele.text end doc.elements.each('operation-result/resource-descriptors/label') do |ele| @report_labels << ele.text end doc.elements.each('operation-result/resource-descriptors/resource-type') do |ele| @res_type << ele.text end doc.elements.each('operation-result/resource-descriptors/parent-folder') do |ele| @parent_folder << ele.text end end def run @jasperServer = SiteConfig.find(:first, :conditions => "name = 'JasperServer URL'")["value"] @jasperUser = SiteConfig.find(:first, :conditions => "name = 'JasperServer User'")["value"] @jasperPass = SiteConfig.find(:first, :conditions => "name = 'JasperServer Password'")["value"] @reportName = params[:reportURI].gsub(///, '_') @report = send_doc(@jasperServer, @jasperUser, @jasperPass, @reportName, params[:reportURI], params[:format]) endend##### end app/controllers/reports_controller.rb ##### ##### begin app/views/reports/index.rhtml #####<% @page_title = 'Reports' %>Folder: <%= @parent_folder[0] %><br/><br/><% @report_names.each_with_index do |name, idx| %><% if @res_type[idx] == 'com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.ReportUnit' %><li><%= @report_labels[idx] %><%= link_to(image_tag("/images/pdf.gif", :border => 0), :controller => "reports", :action => "run", :reportURI => "#{@jasperURI}/#{name}", :format => 'PDF') %><% end %><% end %>##### end app/views/reports/index.rhtml ##### If anyone knows how to accomplish this better, I am still interested in learning how. Also, I would like to have a couple other options as far as output goes, so if anyone knows how I can get a native (JRPRINT) report to output from a non-java client, I would be appreciative. My next real task will be to construct the XML document that contains parameters, since reports aren't always very useful unless you can change your parameters. Link to comment Share on other sites More sharing options...
edxerx Posted March 15, 2007 Share Posted March 15, 2007 I tried this and get the same error :pinch: rosisr wrote:Thanks a lot, you've been a great help!! But I still have some problems, when I try to run this:#!/bin/env rubyrequire 'soap/rpc/driver'strUser = 'jasperadmin'strPWD = 'jasperadmin'strServer = 'http://10.128.10.81/jasperserver/services/repository/'strOutputFormat = 'HTML' #JRPRINT, RTF, PDF, etc?strURI = '/reports/samples/Employees'strRequest = %Q{<?xml version="1.0" encoding="UTF-8"?><request> <operation-name>runReport</operation-name><resource-descriptorread-only="false" control-type="0" is-reference="false" is-new="false" strict-max="false" data-type="0" mandatory="false" has-data="false" strict-min="false" main-report="false" version="0"><uri-string>#{strURI}</uri-string></resource-descriptor><arguments xmlnssi="http://www.w3.org/2001/XMLSchema-instance"xsi:type="java:com.jaspersoft.jasperserver.api.metadata.xml.domain.impl.Argument"><name>RUN_OUTPUT_FORMAT</name><value>#{strOutputFormat}</value></arguments></request>}driver = SOAP::RPC::Driver.new(strServer)driver.wiredump_dev = STDERRdriver.options["protocol.http.basic_auth"] << [strServer, strUser, strPWD]driver.add_method('runReport','request')puts driver.runReport(strRequest)What I get is:<?xml version='1.0 'encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header /><soapenv:Body><ns1:result xmlns:ns1="http://jasperserver/ws2/namespace1" xmlns:tns="http://ws.apache.org/axis2"><?xml version="1.0" encoding="UTF-8"?><operation-result return-code="1"><version>1.1.0</version><message>unable to instantiate java.util.List; </message></operation-result></ns1:result></soapenv:Body></soapenv:Envelope>Any suggestion? :xPost edited by: edxerx, at: 2007/03/15 09:16 Link to comment Share on other sites More sharing options...
edxerx Posted March 15, 2007 Share Posted March 15, 2007 seems that in the end all I get is #: The AXIS engine could not find a target service to invoke! targetService is repository/ (SOAP::FaultError) btw my code is as below Code: I can connect but can't do anything :blink: , anyone got clues? Link to comment Share on other sites More sharing options...
aaronhelton Posted March 16, 2007 Share Posted March 16, 2007 I believe my original code is now deprecated with the release of JI 1.2, but the good news (so far in my testing) is that you won't need it. What you should probably do now that the WSDL is generated and exposed, is use the ruby utility wsdl2ruby. To get it to work correctly for me, since it doesn't have HTTP Basic Authentication out of the box, I saved the WSDL file in some location, then used the saved file as the input for the wsdl2ruby script: $ wsdl2ruby --wsdl jasperserver.wsdl --type client I didn't have to force anything. The files that are generated (in my case) are: defaltDriver.rbdefaultMappingRegistry.rbdefault.rbManagementServiceServiceClient.rb You need the first three files, but any script you want to write should: require 'defaultDriver.rb' ManagementServiceServiceClient.rb is a sample client you can use to test out the available methods. Before you give it a whirl, you should make sure to add the basic authentication method discussed earlier in this thread. Just to get it off the ground, I added the following line after the wiredump_dev line: obj.options["protocol.http.basic_auth"] << [endpoint_url,"admin_user","admin_password"] Run the file with ruby -d to get the full request and response for each of the methods. This will show you how you might construct your own requests. Hopefully, as I get some time, I will be able to rework the code I originally wrote to take advantage of the auto-magic that ruby is capable of. If anyone else manages to get something working, I would love to see it.Post edited by: MariusAgricola, at: 2007/03/15 22:05 Link to comment Share on other sites More sharing options...
edxerx Posted March 16, 2007 Share Posted March 16, 2007 thanks for the reply, I will try your solution a.s.a.p :) Link to comment Share on other sites More sharing options...
aaronhelton Posted March 17, 2007 Share Posted March 17, 2007 One other thing to note in the client file is that in all cases the requestXmlString is set to nil: requestXmlString = nil This means that you will still have to construct the request in a particular format. I am not certain if the format is still the same with this version of JI, but a look at the wiredump indicates that it might not be. You could, as an alternative, attempt to get the format from a network analysis tool such as ethereal, while running the same operation inside the updated iReport program. I haven't had a chance to 1) update iReport, and 2) break down the packets. Link to comment Share on other sites More sharing options...
lemonyaide Posted March 17, 2007 Share Posted March 17, 2007 First let me thank you for the work you have done on this project. I have Jasperserver 1.2 installed and have the LIST functionality working with your framework. I just had to modify the strRequestBody values in the reports.rb, and the doument elements in the controller. What really has me stumped is the line of code report = driver.call('runReport', strRequestBody)['Include'].content in the reports model. I get this error: Any help would be greatly appreciated... You have a nil object when you didn't expect it!The error occurred while evaluating nil.content of course if I remove the ['Include'].content... I only get the success response:<?xml version="1.0" encoding="UTF-8" ?> - <operationResult version="1.2.0"> - <returnCode> - <![CDATA[ 0]]> </returnCode> </operationResult> A wiredump indicates that the pdf is being delievered as "chunked" just cannot figure out how to caputure it.. I've tried everything I can think of to inspect the object / response to determine what is going on.. YAML::dump, inspect...Please forgive me! I'm just hacking away at this. I really don't have a clue about how this stuff really works... I've built a small ruby script to test the wsdl2ruby method, and I have the same problem while trying to retrieve the response from runReport. ##### begin test.rb ##### require 'defaultDriver'strRequestBody = %Q|<?xml version="1.0" encoding="UTF-8"?> <request operationName="runReport" locale="en"> <argument name="RUN_OUTPUT_FORMAT">PDF</argument> <resourceDescriptor name="" wsType="" uriString="/reports/samples/AllAccounts" isNew="false"> <label>null</label> </resourceDescriptor> </request> | strRequestBody = %Q|<?xml version="1.0" encoding="UTF-8"?> <request operationName="runReport" locale="en"> <argument name="RUN_OUTPUT_FORMAT">PDF</argument> <resourceDescriptor name="" wsType="" uriString="/reports/samples/AllAccounts" isNew="false"> <label>null</label> </resourceDescriptor> </request> |obj = ManagementService.new("http://ubuntu:8080/jasperserver/services/repository")obj.options["protocol.http.basic_auth"] << ["http://ubuntu:8080/jasperserver/services/repository","jasperadmin","jasperadmin"]puts obj.runReport(strRequestBody)##### end test.rb ##### My 1.2 almost compliant / almost working hack of the integrate jasperintelligence with ruby on rails stuff follows: ##### begin app/models/reports.rb #####require 'soap/rpc/driver'class Reports < ActiveRecord::Base class << self def get_list(strURL, strUser, strPass, strURI) strRequestBody = %Q|<?xml version="1.0" encoding="UTF-8"?> <request operationName="list" locale="en"> <resourceDescriptor name="" wsType="folder" uriString="#{strURI}" isNew="false"> <label>null</label> </resourceDescriptor> </request> | driver = SOAP::RPC::Driver.new(strURL) driver.options["protocol.http.basic_auth"] << [strURL, strUser, strPass] driver.add_method('list','request') @report_list = driver.list(strRequestBody) end def get_report(strURL, strUser, strPass, strURI, strOutputFmt) strRequestBody = %Q|<?xml version="1.0" encoding="UTF-8"?> <request operationName="runReport" locale="en"> <argument name="RUN_OUTPUT_FORMAT">#{strOutputFmt}</argument> <resourceDescriptor name="" wsType="" uriString="#{strURI}" isNew="false"> <label>null</label> </resourceDescriptor> </request> | driver = SOAP::RPC::Driver.new(strURL) driver.options["protocol.http.basic_auth"] << [strURL, strUser, strPass] driver.add_method('runReport','request') report = driver.call('runReport', strRequestBody)['Include'].content report end end end ##### end app/models/reports.rb ##### ##### begin app/helpers/send_doc.rb ##### module SendDoc def send_doc(strURL, strUser, strPass, strReportName, strReportURI, strOutputFmt) case strOutputFmt when 'PDF' mime_type = 'application/pdf' extension = 'pdf' else #rtf mime_type = 'application/rtf' extension = 'rtf' end send_data Reports.get_report(strURL, strUser, strPass, strReportURI, strOutputFmt), :filename => "#{strReportName}.#{extension}", :type => mime_type, :disposition => 'inline' endend ##### end app/helpers/send_doc.rb ##### ##### begin app/controllers/reports_controller.rb #####require 'rexml/document'class ReportsController < ApplicationController include SendDoc def index @jasperServer = SiteConfig.find(:first, :conditions => "name = 'JasperServer URL'")["value"] @jasperUser = SiteConfig.find(:first, :conditions => "name = 'JasperServer User'")["value"] @jasperPass = SiteConfig.find(:first, :conditions => "name = 'JasperServer Password'")["value"] @jasperURI = '/reports/samples' @reportsXML = Reports.get_list(@jasperServer, @jasperUser, @jasperPass, @jasperURI) doc = REXML::Document.new(@reportsXML) @report_names = [] @report_labels = [] @res_type = [] @parent_folder = [] doc.elements.each('operationResult/resourceDescriptor') do |ele| @report_names << ele.attributes["name"] end doc.elements.each('operationResult/resourceDescriptor/label') do |ele| @report_labels << ele.text end doc.elements.each("operationResult/resourceDescriptor/resourceProperty[@name=PROP_RESOURCE_TYPE]/value") do |ele| @res_type << ele.text end doc.elements.each("operationResult/resourceDescriptor/resourceProperty[@name=PROP_PARENT_FOLDER]/value") do |ele| @parent_folder << ele.text end end def run @jasperServer = SiteConfig.find(:first, :conditions => "name = 'JasperServer URL'")["value"] @jasperUser = SiteConfig.find(:first, :conditions => "name = 'JasperServer User'")["value"] @jasperPass = SiteConfig.find(:first, :conditions => "name = 'JasperServer Password'")["value"] @reportName = params[:reportURI].gsub(///, '_') @report = send_doc(@jasperServer, @jasperUser, @jasperPass, @reportName, params[:reportURI], params[:format]) endend##### end app/controllers/reports_controller.rb ##### ##### begin app/views/reports/index.rhtml #####<% @page_title = 'Reports' %>Folder: <%= @parent_folder[0] %><br/><br/><% @report_names.each_with_index do |name, idx| %><% if @res_type[idx] == 'com.jaspersoft.jasperserver.api.metadata.jasperreports.domain.ReportUnit' %><li><%= @report_labels[idx] %><%= link_to(image_tag("/images/pdf.gif", :border => 0), :controller => "reports", :action => "run", :reportURI => "#{@jasperURI}/#{name}", :format => 'PDF')%><% end %><% end %>##### end app/views/reports/index.rhtml ##### Link to comment Share on other sites More sharing options...
juantar Posted October 2, 2007 Share Posted October 2, 2007 Has anyone been able to solve the chunked problem? I have the same problem. The report PDF is being sent back as a SOAP multipart attachment. I don't know how to read the multipart attachment from the response. Link to comment Share on other sites More sharing options...
schmitzc Posted October 11, 2007 Share Posted October 11, 2007 I modified the SOAP::RPC:Proxy class to return the SOAP::SOAPEnvelope in addition to the response object. Code: The SOAP::SOAPEnvelope has an attribute called external_content and this is where the SOAP::Attachment objects are stored. The external_content attribute is a hash and to access the desired SOAP::Attachment, use the Content-Id from the multipart attachment. For JasperServer, the Content-Id for the report attachment is 'report'. Code: Link to comment Share on other sites More sharing options...
mzukowski Posted November 9, 2007 Share Posted November 9, 2007 I can't get the above code to work... in fact those modifications to SOAP::RPC::Proxy don't make sense for soap4r -- at least not the latest version (1.5.8). What version of Ruby's SOAP libraries is this supposed to work against? Link to comment Share on other sites More sharing options...
schmitzc Posted November 9, 2007 Share Posted November 9, 2007 I am not using soap4r. I am only using the SOAP classes included in the Ruby standard library. I included the modifications to the SOAP::RPC::Proxy only in the class that I was using to connect to the Jasper Server Web Service. Link to comment Share on other sites More sharing options...
mzukowski Posted November 9, 2007 Share Posted November 9, 2007 Okay nevermind... I should double-check before I post. Anyway here's a slightly different version of the above monkeypatch. This one should work against soap4r 1.5.8. Also, it adds the instance variable @env to the response object rather than returning an array with the env data. I think this might be a bit safer since it doesn't break the API. Code:module SOAP module RPC class Proxy include SOAP def call(name, *params) # name must be used only for lookup op_info = lookup_operation(name) mapping_opt = create_mapping_opt req_header = create_request_header req_body = SOAPBody.new( op_info.request_body(params, @mapping_registry, @literal_mapping_registry, mapping_opt) ) reqopt = create_encoding_opt( :«»soapaction => op_info.soapaction || @soapaction, :envelopenamespace => @options["soap.envelope.requestnamespace"], :default_encodingstyle => @default_encodingstyle || op_info.request_default_encodingstyle, :use_default_namespace => op_info.use_default_namespace || @use_default_namespace ) resopt = create_encoding_opt( :envelopenamespace => @options["soap.envelope.responsenamespace"], :default_encodingstyle => @default_encodingstyle || op_info.response_default_encodingstyle ) env = route(req_header, req_body, reqopt, resopt) if op_info.response_use.nil? return nil end raise EmptyResponseError unless env receive_headers(env.header) begin check_fault(env.body) rescue ::«»SOAP::FaultError => e op_info.raise_fault(e, @mapping_registry, @literal_mapping_registry) end if @return_response_as_xml return resopt[:response_as_xml] else response_obj = op_info.response_obj(env.body, @mapping_registry, @literal_mapping_registry, mapping_opt) response_obj.instance_variable_set(:@env, env) return response_obj end end end endend And to use it: Code:[code]@driver = SOAP::RPC::«»Driver.new(@url)@driver.options["protocol.http.basic_auth"] << [@url, @user, @pass]@driver.add_method('runReport','request')result = @driver.runReport(request.to_s)report = result.instance_variable_get(:@env).external_content['report'].data.content Link to comment Share on other sites More sharing options...
mzukowski Posted November 9, 2007 Share Posted November 9, 2007 Okay nevermind... I should double-check before I post. Anyway here's a slightly different version of the above monkeypatch. This one should work against soap4r 1.5.8. Also, it adds the instance variable @env to the response object rather than returning an array with the env data. I think this might be a bit safer since it doesn't break the API. Code:module SOAP module RPC class Proxy include SOAP def call(name, *params) # name must be used only for lookup op_info = lookup_operation(name) mapping_opt = create_mapping_opt req_header = create_request_header req_body = SOAPBody.new( op_info.request_body(params, @mapping_registry, @literal_mapping_registry, mapping_opt) ) reqopt = create_encoding_opt( :«»soapaction => op_info.soapaction || @soapaction, :envelopenamespace => @options["soap.envelope.requestnamespace"], :default_encodingstyle => @default_encodingstyle || op_info.request_default_encodingstyle, :use_default_namespace => op_info.use_default_namespace || @use_default_namespace ) resopt = create_encoding_opt( :envelopenamespace => @options["soap.envelope.responsenamespace"], :default_encodingstyle => @default_encodingstyle || op_info.response_default_encodingstyle ) env = route(req_header, req_body, reqopt, resopt) if op_info.response_use.nil? return nil end raise EmptyResponseError unless env receive_headers(env.header) begin check_fault(env.body) rescue ::«»SOAP::FaultError => e op_info.raise_fault(e, @mapping_registry, @literal_mapping_registry) end if @return_response_as_xml return resopt[:response_as_xml] else response_obj = op_info.response_obj(env.body, @mapping_registry, @literal_mapping_registry, mapping_opt) response_obj.instance_variable_set(:@env, env) return response_obj end end end endend And to use it: Code:[code]@driver = SOAP::RPC::«»Driver.new(@url)@driver.options["protocol.http.basic_auth"] << [@url, @user, @pass]@driver.add_method('runReport','request')result = @driver.runReport(request.to_s)report = result.instance_variable_get(:@env).external_content['report'].data.content Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now