调用BIEE提供的web service

门户项目中准备用web service获取现有的制作好的报表进行展示。遂去研究了下,研究的过程也是满纠结的,总算根据多方资料,将demo跑通了。

本文参考了网上的一些资料,做一下总结而已。讲解下如何配置,成功的获取到相关报表。

 

biee的web service的介绍我就不说了了,官方文档如下:
http://download.oracle.com/docs/cd/E21764_01/bi.1111/e16364/soa_overview.htm

提供的服务如下:
http://download.oracle.com/docs/cd/E12096_01/books/AnyWebServ/AnyWebServTOC.html


使用axis生成WEB service的客户端代码:
步骤参考:
http://gerardnico.com/wiki/ide/eclipse/eclipse_how_to_consume_a_webservice_with_wtp
需要指定包名为:com.siebel.analytics.web.soap.v5

客户端代码生成后,在eclipse下由于下载了插件依赖包都是有的,所以可以直接写一个java程序去测试下是否调用web service成功。
如果用maven生成工程,或者最终发布的话,需要在pom。xml中增加如下的依赖配置:

        <dependency>
            <groupId>org.apache.axis</groupId>
            <artifactId>axis</artifactId>
            <version>1.4</version>
        </dependency>
        <dependency>
            <groupId>javax.xml</groupId>
            <artifactId>jaxrpc</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>commons-discovery</groupId>
            <artifactId>commons-discovery</artifactId>
            <version>0.2</version>
        </dependency>
        <dependency>
            <groupId>wsdl4j</groupId>
            <artifactId>wsdl4j</artifactId>
            <version>1.6.2</version>
        </dependency>
        <dependency>
            <groupId>org.apache.httpcomponents</groupId>
            <artifactId>httpclient</artifactId>
            <version>4.1-beta1</version>
        </dependency>

 

测试代码如下:

public class TestReadCatalog {
    public static void main(String[] args) {
        String sessionID = "";
        SAWSessionServiceSoapProxy myPort = new SAWSessionServiceSoapProxy();
        try {
            sessionID = myPort.logon("jianchen", "jianchen");
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        //测试获取目录结构
        WebCatalogServiceSoapProxy catalogService = new WebCatalogServiceSoapProxy();
        try {
            CatalogObject catalogItems = catalogService.readObject("/shared", false, sessionID);
            System.out.println(catalogItems.getItemInfo().getPath());
            ItemInfo[] items = catalogService.getSubItems("/shared", "*", false, null, sessionID);
            for (ItemInfo item : items) {
                System.out.println(item.getCaption());
            }
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

 

这里我用的登录账号是:rpd的账号。登录成功后会返回一个sessionID。跟服务器的交互必须要有sessionID作为参数。
执行后,的确能够获取到返回的catalog目录,输出目录名称。

最关键的来了,就是如何把biee中做好的报表展示到web页面上呢。biee提供了HtmlViewService,支持对biee report进行访问。
测试代码如下:

public class TestReadReport {

    /**
     * @param args
     */
    public static void main(String[] args) {
        String sessionID = "";
        SAWSessionParameters sessionparams = new SAWSessionParameters();
        SAWSessionServiceSoapProxy myPort = new SAWSessionServiceSoapProxy();
        try {
            sessionID = myPort.logon("jianchen", "jianchen");
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        HtmlViewServiceSoapProxy viewService = new HtmlViewServiceSoapProxy();
        ReportRef reportRef = new ReportRef();
        reportRef.setReportPath("/shared/");

        StartPageParams startPageParams = new StartPageParams();
        startPageParams.setIdsPrefix("beijixing"+Math.round(Math.random()*1000000));
        startPageParams.setDontUseHttpCookies(false);
        try {
            String pageID = viewService.startPage(startPageParams, sessionID);

            viewService.addReportToPage(pageID, "beijixing", reportRef, null, null, null, sessionID);

            StringBuffer reportHTML = new StringBuffer();
           /* reportHTML.append(viewService.getHeadersHtml(pageID, sessionID));
            reportHTML.append(viewService.getHtmlForReport(pageID, "beijixing", sessionID));*/
            reportHTML.append(viewService.getHtmlForPageWithOneReport("beijixing", reportRef, null, null, null, null, sessionID));
            System.out.println(reportHTML.toString());
        } catch (RemoteException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

 测试是能够获取到html代码的。但是在页面上展示这段代码时,只会出现一个“等待”,而没有真正的获取报表内容。
分析页面源代码:发现页面里的js以及css等资源的路径都是:“missing_xxx.css”之类的。说明获取的那些资源没有加载到。
还有一个很关键的点,在某篇老外的博客上提到:

写道
SAWLocale and SAWSessionParameters are quite important for the OBIEE report to be displayed. Many have tried and have seen only the rotating clock instead of the report. We too went through the same problem and realized that the OBIEE report javascript file paths are dependent on the Locale and the User-Agent.

 所以在登录服务器前,需要有如下代码段:

    SAWLocale sawlocale = new SAWLocale();
    sawlocale.setLanguage(request.getLocale().getLanguage());
    sawlocale.setCountry(request.getLocale().getCountry());

    SAWSessionParameters sessionparams = new SAWSessionParameters();
    sessionparams.setUserAgent(request.getHeader("User-Agent"));
    sessionparams.setLocale(sawlocale);
    sessionparams.setAsyncLogon(false);

 后仔细阅读文档,内容如下:

写道
To embed a report with active drilldown links, the HtmlViewService service allows the Web browser to issue callback requests from embedded reports to the Oracle BI Web Services server. Although it is possible to route requests directly to the Oracle BI Web Services server, in many cases it is preferable to route requests through the Presentation Services that originally serviced the third-party page. Also, in situations where Oracle BI Web Services and the third-party Web server do not belong to the same Domain Name Service (DNS) domain, users may get JavaScript errors related to browser security constraints for cross-domain scripting.

To avoid these issues, use the setBridge() method to modify callback URLs to point to the third-party Web server. Be aware that a Web component executed by the third-party Web server to re-route requests to Oracle BI Web Services is not provided. This function would need to be fulfilled by the third-party application. For more information about the setBridge() method, read setBridge() Method.

 就是说这些静态资源需要用桥接的方式向真正的服务器发起请求,返回给浏览器。

 桥接的实现,可以利用servlet,该servlet里要干的事情如下:

 
Read the RedirectURL argument of the request which will contain the absolute path to the OBIEE resources.
Make a URLConnection to the URL and read the content.
Write to the output stream.

当时为了立即看到效果,该bridge的代码我是借用了别人的(代码有点bug,比如连接未关闭,不能复用的bug),等正式开发用的时候可以考虑重新改写下,优化下性能。还是贴出来吧,方便下大众。

 

public class MyBridge extends HttpServlet {
	private static final long serialVersionUID = 1L;
	/**
	 * Default constructor.
	 */
	public MyBridge() {
		// TODO Auto-generated constructor stub
	}
	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	@SuppressWarnings("unchecked")
	protected void doGet(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		String relatedtUrl = request.getParameter("RedirectURL");
		relatedtUrl = relatedtUrl.replaceAll("NoAuthGo", "Go");
		StringBuffer url = new StringBuffer("").append(relatedtUrl);
		System.out.println("relatedtUrl>>>>>*****>>>>>>>>>>" + relatedtUrl);

		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		Map parameterMap = request.getParameterMap();
		for (Iterator iterator = parameterMap.keySet().iterator(); iterator
				.hasNext();) {
			String parameterName = (String) iterator.next();
			String[] parameterValues = (String[]) parameterMap
					.get(parameterName);
			if (parameterValues != null && parameterValues.length > 0) {
				if (parameterName.equals("RedirectURL")) {
					continue;
				}

				for (int i = 0; i < parameterValues.length; i++) {
					NameValuePair pair = new BasicNameValuePair(parameterName,
							parameterValues[i]);
					nvps.add(pair);
				}
			}
		}
		HttpClient client = new DefaultHttpClient();
		if (!url.toString().endsWith(".js") && !url.toString().endsWith(".css")
				&& !url.toString().endsWith(".png") && !url.toString().endsWith(".gif")) {
			List<NameValuePair> tmp = new ArrayList<NameValuePair>();
			NameValuePair pair = new BasicNameValuePair("NQUser", "jianchen");
			NameValuePair pair1 = new BasicNameValuePair("NQPassword", "jianchen");
			tmp.add(pair);
			tmp.add(pair1);
			HttpPost lpost = new HttpPost(url.toString());
			lpost.setEntity(new UrlEncodedFormEntity(tmp, "GBK"));
			HttpResponse lresp = client.execute(lpost);
			System.out.println("登陆结果:"+lresp.getStatusLine().getStatusCode());
            lpost.abort();
		}
		if(url.toString().indexOf("?Go")<0 || url.toString().indexOf("?DocPart")>0){
			HttpPost post = new HttpPost(url.toString());
			post.setEntity(new UrlEncodedFormEntity(nvps,"GBK"));
			post.addHeader("Content-Type", "binary/data");
			post.addHeader("User-Agent", request.getHeader("USER-AGENT"));
			HttpResponse resp = client.execute(post);
			HttpEntity entity = resp.getEntity();
			InputStream in = entity.getContent();
			if(url.toString().indexOf("?DocPart")>0){
				FileOutputStream fout=new FileOutputStream("e:\\aaa.jpg");
				byte buffer1[] = new byte[1024 * 128];
				int k = 0;
				while ((k = in.read(buffer1)) != -1) {
					fout.write(buffer1, 0, k);
				}
				fout.flush();
				fout.close();
			}
			ServletOutputStream out = response.getOutputStream();
			byte buffer1[] = new byte[1024 * 128];
			int k = 0;
			while ((k = in.read(buffer1)) != -1) {
				out.write(buffer1, 0, k);
			}
			in.close();
			out.close();
		} else {
			HttpPost post = new HttpPost(url.toString());
			post.setEntity(new UrlEncodedFormEntity(nvps,"GBK"));
			post.addHeader("Content-Type", "binary/data");
			post.addHeader("User-Agent", request.getHeader("USER-AGENT"));
			HttpResponse resp = client.execute(post);
			HttpEntity entity = resp.getEntity();
			InputStream in = entity.getContent();
			InputStreamReader isr = new InputStreamReader(in);
			BufferedReader br = new BufferedReader(isr);
			StringBuffer sb = new StringBuffer();
			String r = br.readLine();
			sb.append(r);
			while (r != null) {
				r = br.readLine();
				sb.append(r);
			}
			String html = sb.toString();//TODO 本地
			InputStream sin = new ByteArrayInputStream(html.getBytes());
			ServletOutputStream out = response.getOutputStream();
			byte buffer1[] = new byte[1024 * 128];
			int k = 0;
			while ((k = sin.read(buffer1)) != -1) {
				out.write(buffer1, 0, k);
			}
			sin.close();
			out.close();
            post.abort();
		}

       
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse
	 *      response)
	 */
	protected void doPost(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		doGet(request, response);
	}

}

 

 

web.xml中配置servlet如下:

         <servlet>
		<description>
		</description>
		<display-name>MyBridge</display-name>
		<servlet-name>MyBridge</servlet-name>
		<servlet-class>com.taobao.service.kunshuo.webservice.MyBridge</servlet-class>
	</servlet>
	<servlet>
		<display-name>Apache-Axis Servlet</display-name>
		<servlet-name>AxisServlet</servlet-name>
		<servlet-class>org.apache.axis.transport.http.AxisServlet</servlet-class>
	</servlet>
	<servlet>
		<display-name>Axis Admin Servlet</display-name>
		<servlet-name>AdminServlet</servlet-name>
		<servlet-class>org.apache.axis.transport.http.AdminServlet</servlet-class>
		<load-on-startup>100</load-on-startup>
	</servlet>

    <servlet-mapping>
		<servlet-name>MyBridge</servlet-name>
		<url-pattern>/MyBridge</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>AxisServlet</servlet-name>
		<url-pattern>/servlet/AxisServlet</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>AxisServlet</servlet-name>
		<url-pattern>*.jws</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>AxisServlet</servlet-name>
		<url-pattern>/services/*</url-pattern>
	</servlet-mapping>
	<servlet-mapping>
		<servlet-name>AdminServlet</servlet-name>
		<url-pattern>/servlet/AdminServlet</url-pattern>
	</servlet-mapping>

 

至此,将获取到的报表html增加到要展示的页面里,比如jsp,就可以直接展示报表了。

后面的获取xml结果,自己可以进行处理展示结果。还有待后续研究。

 

 

有几个开发同学跟我要源代码,都是通过邮箱发送的,这里我把我当时的demo发上来作为附件吧。

可以在附件中进行下载

你可能感兴趣的:(web Service)