Saiku链接地址

官网:https://community.meteorite.bi/
GitHub:https://github.com/OSBI/saiku
文档:https://saiku-documentation.readthedocs.io/en/latest/#open-source

本文中所使用的saiku版本为 3.x 版本

安装教程

一 使用git下载项目

git clone git://github.com/OSBI/saiku.git

【如果下载速度太感人,可以查看 git clone下载速度慢解决办法

二 修改maven依赖【重】

saiku自带的maven仓库下载地址可能会出现各种问题,比如503等
以下是我修改后的maven仓库地址【方便起见只贴了修改的地方】

  1. saiku/pom.xml
	<distributionManagement>
    <!--
    <repository>
  		<id>utility</id>
 			<name>utility-releases</name>
 			<url>http://repo.meteorite.bi/repository/alabs-release-local/</url>
 		</repository>
 		<snapshotRepository>
 			<id>utility</id>
 			<name>utility-snapshots</name>
 			<url>http://repo.meteorite.bi/repository/alabs-snapshot-local/</url>
 		</snapshotRepository>
    -->
	  <repository>
			<id>gitlab-maven</id>
			<url>https://gitlab.com/api/v4/projects/14840263/packages/maven</url>
	  </repository>
	  <snapshotRepository>
      <id>gitlab-maven</id>
			<url>https://gitlab.com/api/v4/projects/14840263/packages/maven</url>
	  </snapshotRepository>
	</distributionManagement>

	<pluginRepositories>
    <!--
  	<pluginRepository>
			<id>Analytical Labs Plugin Repo</id>
			<name>Analytical Labs Repo-releases</name>
			<url>http://repo.meteorite.bi/repository/alabs-release-local/</url>
		</pluginRepository>
    -->
    <pluginRepository>
      <id>pentaho-third-party</id>
      <url>http://nexus.pentaho.org/content/repositories/proxy-public-3rd-party-release/</url>
    </pluginRepository>
  </pluginRepositories>

<repositories>
  <!--
	<repository>
		<id>Analytical Labs Repo</id>
		<name>Analytical Labs Repo-releases</name>
		<url>http://repo.meteorite.bi/repository/alabs-release-local/</url>
	</repository>
	<repository>
		<id>Analytical Labs snapshots</id>
		<name>Analytical Labs Repo-releases</name>
		<url>http://repo.meteorite.bi/repository/alabs-snapshot-local/</url>
	</repository>
	-->
  <!-- 这里找到了四个有效的地址 -->
	<repository>
		<id>gitlab-maven</id>
		<url>https://gitlab.com/api/v4/projects/14840263/packages/maven</url>
	</repository>
	<repository>
		<id>saiku-group</id>
		<url>https://nexus.nuiton.org/nexus/content/repositories/saiku-group/</url>
	</repository>
	<repository>
 		<id>pentaho-pentaho-third-party</id>
		<url>http://nexus.pentaho.org/content/repositories/proxy-pentaho-public-release-group/</url>
	</repository>
	<repository>
		<id>pentaho-public-third-party</id>
		<url>http://nexus.pentaho.org/content/repositories/proxy-public-3rd-party-release/</url>
	</repository>
  <!-- 下面接省下的.... -->
 </repositories>

<plugins>
 	<!-- 建议注释掉检查(我这边是注释掉了)
 <plugin>
		<groupId>org.owasp</groupId>
		<artifactId>dependency-check-maven</artifactId>
		<version>3.3.2</version>
		<executions>
			<execution>
   			<goals>
					<goal>check</goal>
				</goals>
			</execution>
		</executions>
	</plugin> -->
  <!-- 下面接省下的.... -->
</plugins>
  1. saiku\saiku-ui\pom.xml
<repositories>
  <!--
	<repository>
		<id>jsdoctk1</id>
		<url>http://jsdoctk-plugin.googlecode.com/svn/repo</url>
	</repository>
	-->
  <repository>
		<id>saiku-group</id>
		<url>https://nexus.nuiton.org/nexus/content/repositories/saiku-group/</url>
	</repository>
</repositories>
<pluginRepositories>
  <!--
	<pluginRepository>
		<id>jsdoctk2</id>
		<url>http://jsdoctk-plugin.googlecode.com/svn/repo</url>
	</pluginRepository>
	<pluginRepository>
		<name>oss.sonatype.org</name>
		<id>oss.sonatype.org</id>
		<url>http://oss.sonatype.org/content/groups/public</url>
	</pluginRepository>
	-->
  <pluginRepository>
		<id>saiku-group2</id>
		<url>https://nexus.nuiton.org/nexus/content/repositories/saiku-group/</url>
	</pluginRepository>
</pluginRepositories>
  1. saiku\saiku-bi-platform-plugin-p7\pom.xml
<repositories>
	<!--
	<repository>
		<id>Analytical Labs Repo</id>
		<name>Analytical Labs Repo-releases</name>
		<url>http://repo.meteorite.bi/repository/alabs-release-local/</url>
	</repository>
	<repository>
		<id>Analytical Labs snapshots</id>
		<name>Analytical Labs Repo-releases</name>
		<url>http://repo.meteorite.bi/repository/alabs-snapshot-local</url>
	</repository>
		-->
	<repository>
		<id>gitlab-maven</id>
		<url>https://gitlab.com/api/v4/projects/14840263/packages/maven</url>
	</repository>
	<repository>
		<id>saiku-group</id>
		<url>https://nexus.nuiton.org/nexus/content/repositories/saiku-group/</url>
	</repository>
	<repository>
		<id>pentaho-pentaho-third-party</id>
		<url>http://nexus.pentaho.org/content/repositories/proxy-pentaho-public-release-group/</url>
	</repository>
	<repository>
		<id>pentaho-public-third-party</id>
		<url>http://nexus.pentaho.org/content/repositories/proxy-public-3rd-party-release/</url>
	</repository>
  	<!-- 下面接省下的.... -->
  </repositories>
  1. saiku\saiku-core\saiku-olap-util\src\main\java\mondrian\olap4j\SaikuMondrianHelper.java
 public static String getMeasureGroup(Measure measure){
	if(isMondrian(measure)){
	  MondrianOlap4jMeasure	m = (MondrianOlap4jMeasure) measure;
/** 注释掉这里 */
/**	  try {
		return ((RolapBaseCubeMeasure) m.member).getMeasureGroup().getName();
	  }
	  catch(Exception e){
		return "";
	  }
	  catch(Error e2){
		return "";
	  }
	  */
	}
	return null;
  }
  1. saiku\saiku-core\saiku-olap-util\src\main\java\mondrian\rolap\DimensionLookup.java
  public static boolean getHanger(RolapCubeDimension dim){
    /** 这里改成true即可 */
    return true;
  }

三 下载maven依赖

// 在根目录下执行
mvn clean install -DskipTests

静静等待即可。
【如果提示mvn命令不存在,则需要先配置maven环境变量】
【如果改完上面的maven还报错,可以留言给我】

四 去除License验证信息【可选】

去除License验证信息需要修改以下几处源码

  1. saiku\saiku-core\saiku-web\src\main\java\org\saiku\web\rest\resources\License.java
  /**
   * Get the saiku
   * @summary Get the Saiku License installed on the current server
   * @return A response containing a license object.
   */
  @GET
  @Produces({ "application/json" })
  public Response getLicense() {
 // 直接返回正确结果
//   try {
//     return Response.ok().entity(licenseUtils.getLicense()).build();
//   } catch (IOException | RepositoryException | ClassNotFoundException e) {
//     e.printStackTrace();
//   }
    return Response.serverError().build();
  }

  1. saiku\saiku-core\saiku-web\src\main\java\org\saiku\web\service\SessionService.java

修改login,去掉验证代码

	/* (non-Javadoc)
	 * @see org.saiku.web.service.ISessionService#login(javax.servlet.http.HttpServletRequest, java.lang.String, java.lang.String)
	 */
	public Map<String, Object> login(HttpServletRequest req, String username, String password ) throws LicenseException {
	//	Object sl = null;
	//	String notice = null;
		HttpSession session = ((HttpServletRequest)req).getSession(true);
		session.getId();
		sessionRepo.setSession(session);
	//	try {
	//		sl = l.getLicense();
	//	} catch (Exception e) {
	//		log.debug("Could not process license", e);
	//		throw new LicenseException("Error fetching license. Get a free license from http://licensing.meteorite.bi. You can upload it at /upload.html");
	//	}

	//	if (sl != null) {

	//		try {
	//			l.validateLicense();
	//		} catch (RepositoryException | IOException | ClassNotFoundException e) {
	//			log.debug("Repository Exception, couldn't get license", e);
	//			throw new LicenseException("Error fetching license. Please check your logs.");
	//		}

        if (authenticationManager != null) {
            authenticate(req, username, password);
        }
        if (SecurityContextHolder.getContext() != null
            && SecurityContextHolder.getContext().getAuthentication() != null) {
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();

            if (authorisationPredicate.isAuthorised(auth)) {
                Object p = auth.getPrincipal();
                createSession(auth, username, password);
                return sessionHolder.get(p);
            } else {
                log.info(username + " failed authorisation. Rejecting login");
                throw new RuntimeException("Authorisation failed for: " + username);
            }
        }
        return new HashMap<>();
	}
  1. saiku\saiku-ui\js\saiku\models\Session.js

需要更改process_session和check_session方法

check_session: function() {
		// This authentication cookie is used only by Orbis authentication strategy
		var authCookie = this.getCookie(Settings.ORBIS_AUTH.cookieName);

		if (Settings.ORBIS_AUTH.hazelcast_enabled && authCookie && !this.atemptedToLoginByCookie) {
            this.sessionid               = 1;
            this.username                = authCookie;
            this.password                = authCookie;
            this.atemptedToLoginByCookie = true;

            // In this case we inject the proper license attributes
            var ONE_YEAR = 31556952000;
			/**
            Settings.LICENSE = {
              licenseType: 'Orbis',
              expiration: Date.now() + ONE_YEAR
            }
            */
            this.login(authCookie, authCookie);
		} else {
			if (this.sessionid === null || this.username === null || this.password === null) {
				var that = this;
				this.clear();
				this.fetch({ success: this.process_session, error: this.brute_force });
			} else {
                if (!this.atemptedToLoginByCookie) {
                    this.username = encodeURIComponent(options.username);
                }

				this.load_session();
			}
		}
    },

	process_session: function(model, response) {
        if ((response === null || response.sessionid == null)) {
            // Open form and retrieve credentials
            Saiku.ui.unblock();
            if (Settings.DEMO) {
                this.form = new DemoLoginForm({ session: this });
            } else {
                this.form = new LoginForm({ session: this });
            }
            this.form.render().open();
        } else {
            this.sessionid = response.sessionid;
            this.roles = response.roles;
            this.isAdmin = Settings.ORBIS_AUTH.hazelcast_enabled || response.isadmin;
            this.username = encodeURIComponent(response.username);
            this.language = response.language;
            if (typeof this.language != "undefined" && this.language != Saiku.i18n.locale) {
                Saiku.i18n.locale = this.language;
                Saiku.i18n.automatic_i18n();
            }
			/**
                var license =new License();

                license.fetch_license('api/license/', function(opt) {
                    if (opt.status === 'success') {
                        Settings.LICENSE = opt.data.toJSON();
                    }
                    if(Saiku.session.isAdmin) {

                        var quota = new LicenseQuota();

                        quota.fetch_quota('api/license/quota', function (opt) {
                            if (opt.status === 'success') {
                                Settings.LICENSEQUOTA = opt.data.toJSON();
                            }
                        });
                    }

                });

			*/
            this.load_session();
        }

        return this;
    },
  1. saiku\saiku-ui\js\saiku\views\Upgrade.js

去除升级提示,注释掉所有render的内容

render: function() {
		/*
		var self = this;
		var license = new License();

		if(Settings.BIPLUGIN5){
				if(Saiku.session.get("notice") != undefined && Saiku.session.get("notice")!=null && Saiku.session.get("notice")!=""){
					$(this.el).append("<div><div id='uphead' class='upgradeheader'>Notice:"+Saiku.session.get("notice")+"</div>");

				}
				if (Settings.LICENSE.licenseType != undefined && (Settings.LICENSE.licenseType != "trial" && Settings.LICENSE.licenseType != "Open Source License")) {
					return this;
				}
				if (Settings.LICENSE != undefined && Settings.LICENSE.licenseType === "trial") {
					var yourEpoch = parseFloat(Settings.LICENSE.expiration);
					var yourDate = new Date(yourEpoch);
					self.remainingdays = self.daydiff(new Date(), yourDate);


					$(this.el).append("<div><div id='uphead' class='upgradeheader'>You are using a Saiku Enterprise" +
						" Trial license, you have "+ self.remainingdays+" days remaining. <a href='http://www.meteorite.bi/saiku-pricing'>Buy licenses online.</a></div>");
					return self;
				}
				else {
					$(this.el).append("<div><div id='uphead' class='upgradeheader'>You are using Saiku Community" +
						" Edition, please consider upgrading to <a target='_blank' href='http://meteorite.bi'>Saiku Enterprise</a>, or entering a <a href='http://meteorite.bi/products/saiku/sponsorship'>sponsorship agreement with us</a> to support development. " +
						"<a href='http://meteorite.bi/products/saiku/community'>Or contribute by joining our community and helping other users!</a></div></div>");

					return self;
				}
		}
		else {
				if(Saiku.session.get("notice") != undefined && Saiku.session.get("notice")!=null && Saiku.session.get("notice")!=""){
					$(this.el).append("<div><div id='uphead' class='upgradeheader'>Notice:"+Saiku.session.get("notice")+"</div>");

				}
				if (Settings.LICENSE.licenseType != undefined && (Settings.LICENSE.licenseType != "trial" &&
					Settings.LICENSE.licenseType != "Open Source License")) {
					return this;
				}
				if (Settings.LICENSE.licenseType === "trial") {
					var yourEpoch = parseFloat(Settings.LICENSE.expiration);
					var yourDate = new Date(yourEpoch);

					self.remainingdays = self.daydiff(new Date(), yourDate);

					$(this.el).append("<div><div id='uphead' class='upgradeheader'>You are using a Saiku Enterprise" +
						" Trial license, you have "+ self.remainingdays+" days remaining. <a href='http://www.meteorite.bi/saiku-pricing'>Buy licenses online.</a></div>");
					return self;
				}
				else {
					$(this.el).append("<div><div id='uphead' class='upgradeheader'>You are using Saiku Community" +
						" Edition, please consider upgrading to <a target='_blank' href='http://meteorite.bi'>Saiku Enterprise</a>, or entering a <a href='http://meteorite.bi/products/saiku/sponsorship'>sponsorship agreement with us</a> to support development. " +
						"<a href='http://meteorite.bi/products/saiku/community'>Or contribute by joining our community and helping other users!</a></div></div>");
					return self;
				}
		}
		*/
	},

去除之后重新打包即可

问题及解决方案

一、启动报错 Cannot set SAX feature because outdated XML parser in classpath: http://javax.xml.XMLConstants/feature/secure-processing

问题原因

Saiku 自带的xerces,与jdk8中的JAX-B不兼容

解决方式

  1. 降级,从jdk1.8 降级到 jdk1.7
  2. 为java添加系统变量。编辑 saiku\saiku-server\target\dist\saiku-server\start-saiku.bat,在CATALINA_OPTS 后面加上如下内容
-Dorg.xml.sax.parser="com.sun.org.apache.xerces.internal.parsers.SAXParser" -Djavax.xml.parsers.DocumentBuilderFactory="com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl" -Djavax.xml.parsers.SAXParserFactory="com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl"

如果不想打包就更改的话,可以直接设置

System.setProperty("org.xml.sax.driver", "com.sun.org.apache.xerces.internal.parsers.SAXParser");
System.setProperty("javax.xml.parsers.DocumentBuilderFactory","com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
System.setProperty("javax.xml.parsers.SAXParserFactory","com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");

或者在maven的tomcat插件里加上

<javax.xml.parsers.DocumentBuilderFactory>com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl</javax.xml.parsers.DocumentBuilderFactory>
<org.xml.sax.parser>com.sun.org.apache.xerces.internal.parsers.SAXParser</org.xml.sax.parser>
<javax.xml.parsers.SAXParserFactory>com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl</javax.xml.parsers.SAXParserFactory>

参考文献

Error unmarshalling xml in java-8 “secure-processing org.xml.sax.SAXNotRecognizedException causing java.lang.IllegalStateException”

Q.E.D.

知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

You got to put the past behind you before you can move on.