3131  ;  ;  ;  ;  ;  ;  ;  ; NodeService是用来解决用户在DSS提交的任务在第三方系统生成相应的任务的问题。用户如果在DSS系统的工作流中新建了一个工作流节点并进行任务的编辑,第三方系统需要同步感知到
3232- 4.getNodeExecution
3333
34-   ;  ;  ;  ;  ;  ;  ;  ; NodeExecution接口是用来将任务提交到第三方系统进行执行的接口,NodeExecution接口有支持短时间任务的NodeExecution和支持长时间任务的LongTermNodeExecution。一般短时间任务,如邮件发送等,可以直接实现NodeExecution接口,并重写execute方法,DSS系统同步等待任务结束。另外的长时间任务,如数据质量检测等,可以实现LongTermNodeExecution接口,并重写submit方法,返回一个NodeExecutionAction,DSS系统通过这个NodeExecutionAction可以向第三方系统获取任务的日志、状态等。
34+   ;  ;  ;  ;  ;  ;  ;  ; NodeExecution接口是用来将任务提交到第三方系统进行执行的接口,NodeExecution
35+ 接口有支持短时间任务的NodeExecution和支持长时间任务的LongTermNodeExecution。一般短时间任务,如邮件发送等,可以直接实现NodeExecution接口,并重写execute方法,DSS系统同步等待任务结束。另外的长时间任务,如数据质量检测等,可以实现LongTermNodeExecution接口,并重写submit方法,返回一个NodeExecutionAction,DSS系统通过这个NodeExecutionAction可以向第三方系统获取任务的日志、状态等。
3536
3637#### 3.第三方系统接入DSS的实现(以Visualis为例)
3738
38-   ;  ;  ;  ;  ;  ;  ;  ; Visualis是微众银行WeDataSphere开源的一款商业BI工具,DSS集成Visualis系统之后可以获得数据可视化的能力。Visualis接入DSS系统的代码在DSS项目中已经同步开源,下面将以开源代码为例,对步骤进行罗列分析。
39+   ;  ;  ;  ;  ;  ;  ;  ; Visualis是微众银行WeDataSphere开源的一款商业BI工具,DSS集成Visualis系统之后可以获得数据可视化的能力。
40+ Visualis接入DSS系统的代码在DSS项目中已经同步开源,下面将以开源代码为例,对步骤进行罗列分析。
3941Visualis接入的DSS系统的步骤如下:
4042
4143** 3.1.Visualis实现AppJoint接口**
4244
43-   ;  ;  ;  ;  ;  ;  ;  ; Visualis实现的 AppJoint接口的实现类是VisualisAppjoint。查看VisualisAppjoint的代码可知,它在init方法时候,初始化了自己实现的SecurityService、 NodeService以及NodeExecution。
45+   ;  ;  ;  ;  ;  ;  ;  ; Visualis实现的 AppJoint接口的实现类是VisualisAppjoint。查看VisualisAppjoint的代码可知,它在init方法时候,
46+ 初始化了自己实现的SecurityService、 NodeService以及NodeExecution。
47+ ``` java
48+ public void init(String baseUrl, Map<String , Object > params) {
49+ securityService = new VisualisSecurityService ();
50+ securityService. setBaseUrl(baseUrl);
51+ nodeExecution = new VisualisNodeExecution ();
52+ nodeExecution. setBaseUrl(baseUrl);
53+ nodeService = new VisualisNodeService ();
54+ nodeService. setBaseUrl(baseUrl);
55+ }
56+ ```
4457
4558** 3.2.Visualis实现SecurtyService接口**
4659
47-   ;  ;  ;  ;  ;  ;  ;  ; Visualis实现的SecurityService接口的类名是VisualisSecurityService,并重写了login方法,为了能够进行授权登陆,Visualis采用了提供token的方式,DSS的网关对该token进行授权,这样就能够做到用户鉴权。
60+   ;  ;  ;  ;  ;  ;  ;  ; Visualis实现的SecurityService接口的类名是VisualisSecurityService,
61+ 并重写了login方法,为了能够进行授权登陆,Visualis采用了提供token的方式,DSS的网关对该token进行授权,这样就能够做到用户鉴权。
62+
63+ ``` java
64+ public class VisualisSecurityService extends AppJointUrlImpl implements SecurityService {
65+ @Override
66+ public Session login (String user ) throws AppJointErrorException {
67+ VisualisSession visualisSession = new VisualisSession ();
68+ visualisSession. setUser(user);
69+ visualisSession. getParameters(). put(" Token-User" ,user);
70+ visualisSession. getParameters(). put(" Token-Code" ," 172.0.0.1" );
71+ return visualisSession;
72+ }
73+
74+ @Override
75+ public void logout (String user ) {
76+
77+ }
78+ }
79+ ```
4880
4981** 3.3.Visualis实现的NodeService接口**
5082
51-   ;  ;  ;  ;  ;  ;  ;  ; Visualis实现的NodeService接口的类是VisualisNodeService,并重写了createNode,deleteNode和updateNode三个方法,这三个方法是进行在第三方系统同步生成任务元数据。例如createNode方法是通过调用visualis的HTTP接口在Visualis系统生成同一工程下面的Visualis任务。
83+   ;  ;  ;  ;  ;  ;  ;  ; Visualis实现的NodeService接口的类是VisualisNodeService,并重写了createNode,
84+ deleteNode和updateNode三个方法,这三个方法是进行在第三方系统同步生成任务元数据。例如createNode方法是通过调用visualis的HTTP接口在Visualis系统生成同一工程下面的Visualis任务。
85+
86+ ``` java
87+ @Override
88+ public Map<String , Object > createNode(Session session, AppJointNode node,
89+ Map<String , Object > requestBody) throws AppJointErrorException {
90+ if (DisplayNodeService . getNodeType(). equals(node. getNodeType())) {
91+ return DisplayNodeService . createNode(session, getBaseUrl(), String . valueOf(node. getProjectId()), node. getNodeType(), requestBody);
92+ } else if (DashboardNodeService . getNodeType(). equals(node. getNodeType())) {
93+ return DashboardNodeService . createNode(session, getBaseUrl(), String . valueOf(node. getProjectId()), node. getNodeType(), requestBody);
94+ } else {
95+ throw new AppJointErrorException (42002 , " cannot recognize the nodeType " + node. getNodeType());
96+ }
97+ }
98+
99+ @Override
100+ public void deleteNode(Session session, AppJointNode node) throws AppJointErrorException {
101+ if (DisplayNodeService . getNodeType(). equals(node. getNodeType())) {
102+ DisplayNodeService . deleteNode(session, getBaseUrl(), String . valueOf(node. getProjectId()), node. getNodeType(), node. getJobContent());
103+ } else if (DashboardNodeService . getNodeType(). equals(node. getNodeType())) {
104+ DashboardNodeService . deleteNode(session, getBaseUrl(), String . valueOf(node. getProjectId()), node. getNodeType(), node. getJobContent());
105+ } else {
106+ throw new AppJointErrorException (42002 , " cannot recognize the nodeType " + node. getNodeType());
107+ }
108+ }
109+
110+ @Override
111+ public Map<String , Object > updateNode(Session session, AppJointNode node,
112+ Map<String , Object > requestBody) throws AppJointErrorException {
113+ if (DisplayNodeService . getNodeType(). equals(node. getNodeType())) {
114+ return DisplayNodeService . updateNode(session, getBaseUrl(), node. getProjectId(), node. getNodeType(), requestBody);
115+ } else if (DashboardNodeService . getNodeType(). equals(node. getNodeType())) {
116+ return DashboardNodeService . updateNode(session, getBaseUrl(), node. getProjectId(), node. getNodeType(), requestBody);
117+ } else {
118+ throw new AppJointErrorException (42002 , " cannot recognize the nodeType " + node. getNodeType());
119+ }
120+ }
121+ ```
52122
53123** 3.4.Visualis实现NodeExecution接口**
54124
55-   ;  ;  ;  ;  ;  ;  ;  ; Visualis实现的NodeExecution接口的类是VisualisNodeExecution,并重写了execute方法,该方法传入的两个参数为Node和NodeContext,从NodeContext中我们可以拿到用户、DSS的网关地址,还有网关验证的Token。通过这些,我们可以封装成一个HTTP的请求发送到第三方系统Visualis并从Visualis获取响应结果,NodeContext提供写入结果集的方法,如Visualis的结果集一般是以图片的形式展示,在execute方法的最后,Visualis通过nodeContext获取到一个支持图片写入的PictureResultSetWriter方法,并将结果集进行写入。
125+   ;  ;  ;  ;  ;  ;  ;  ; Visualis实现的NodeExecution接口的类是VisualisNodeExecution,并重写了execute方法,
126+ 该方法传入的两个参数为Node和NodeContext,从NodeContext中我们可以拿到用户、DSS的网关地址,还有网关验证的Token。
127+ 通过这些,我们可以封装成一个HTTP的请求发送到第三方系统Visualis并从Visualis获取响应结果,NodeContext提供写入结果集的方法,
128+ 如Visualis的结果集一般是以图片的形式展示,在execute方法的最后,Visualis通过nodeContext获取到一个支持图片写入的PictureResultSetWriter方法,并将结果集进行写入。
129+ ``` scala
130+ override def execute (node : AppJointNode , nodeContext : NodeContext , session : Session ): NodeExecutionResponse = node match {
131+ case commonAppJointNode : CommonAppJointNode =>
132+ val appJointResponse = new CompletedNodeExecutionResponse ()
133+ val idMap = commonAppJointNode.getJobContent
134+ val id = idMap.values().iterator().next().toString
135+ val url = if (commonAppJointNode.getNodeType.toLowerCase.contains(DISPLAY )) getDisplayPreviewUrl(nodeContext.getGatewayUrl, id)
136+ else if (commonAppJointNode.getNodeType.toLowerCase.contains(DASHBOARD )) getDashboardPreviewUrl(nodeContext.getGatewayUrl, id)
137+ else {
138+ appJointResponse.setIsSucceed(false )
139+ appJointResponse.setErrorMsg(" 不支持的appJoint类型:" + node.getNodeType)
140+ return appJointResponse
141+ }
142+ var response = " "
143+ val headers = nodeContext.getTokenHeader(nodeContext.getUser)
144+ nodeContext.appendLog(LogUtils .generateInfo(s " Ready to download preview picture from $url. " ))
145+ Utils .tryCatch(download(url, null , headers.toMap,
146+ input => Utils .tryFinally{
147+ val os = new ByteArrayOutputStream ()
148+ IOUtils .copy(input, os)
149+ response = new String (Base64 .getEncoder.encode(os.toByteArray))
150+ // response = IOUtils.toString(input, ServerConfiguration.BDP_SERVER_ENCODING.getValue)
151+ }(IOUtils .closeQuietly(input)))){ t =>
152+ val errException = new ErrorException (70063 , " failed to do visualis request" )
153+ errException.initCause(t)
154+ appJointResponse.setException(errException)
155+ appJointResponse.setIsSucceed(false )
156+ appJointResponse.setErrorMsg(s " 用户 ${nodeContext.getUser}请求Visualis失败!URL为: " + url)
157+ return appJointResponse
158+ }
159+ nodeContext.appendLog(LogUtils .generateInfo(" Preview picture downloaded, now ready to write results." ))
160+ val imagesBytes = response
161+ val resultSetWriter = nodeContext.createPictureResultSetWriter()
162+ Utils .tryFinally{
163+ resultSetWriter.addMetaData(new LineMetaData ())
164+ resultSetWriter.addRecord(new LineRecord (imagesBytes))
165+ }(IOUtils .closeQuietly(resultSetWriter))
166+ appJointResponse.setIsSucceed(true )
167+ appJointResponse
168+ }
169+ ```
56170
57171** 3.5.数据库内容的更新(dss-application模块)**
58172
@@ -66,7 +180,7 @@ Visualis接入的DSS系统的步骤如下:
66180| url | 10 | 如 http://127.0.0.1:8080 |
67181| is_user_need_init | 是否需要用户初始化 | 默认否 |
68182| user_init_url | 用户初始化url | 默认空 |
69- | exists_project_service | 是否存在自己的projectService服务, 存在的话要自己写appjoint实现projectService0 | |
183+ | exists_project_service | 是否存在自己的projectService服务, 存在的话要自己写appjoint实现projectService | |
70184| enhance_json | 加强json,在appjoint初始化的时候会作为map进行传入 | |
71185| homepage_url | 接入的系统主页url | |
72186| direct_url | 接入的系统重定向url | |
@@ -97,19 +211,25 @@ Visualis接入的DSS系统的步骤如下:
97211** 3.6.前端的修改**
98212
99213- 3.6.1 增加节点类型
100- 修改src/js/service/nodeType.js文件,增加Qualitis节点类型
214+ 修改src/js/service/nodeType.js文件,增加Visualis节点类型
101215- 3.6.2 增加节点图标
102216将节点图标复制到src/js/module/process/images/路径下,目前只支持SVG格式。
103217- 3.6.3 新增节点配置
104- 修改src/js/module/process/shape.js文件,增加Qualitis的节点配置信息 。
218+ 修改src/js/module/process/shape.js文件,增加Visualis的节点配置信息 。
105219- 3.6.4 修改首页单击节点事件
106220修改src/js/module/process/index.vue文件,增加节点单击事件以及单击事件的处理逻辑。
107221- 3.6.5 修改工作流节点双击事件
108222修改src/js/view/process/index.vue以及src/js/module/process/index.vue,增加节点双击事件以及双击事件的处理逻辑。
109223
110224** 3.7.编译打包成jar包放置到指定位置**
111225
112-   ;  ;  ;  ;  ;  ;  ;  ; 实现了上述的接口之后,一个AppJoint就已经实现了。打包之后,需要放置到指定的位置。jar包需要放置到dss-server和linkis-appjoint-entrance两个微服务中,以linkis-appjoint-entrance 为例(dss-server与linkis-appjoint-entrance一致),在linkis-appjont-entrance下面的lib的同级目录有一个appjoints目录,目录下面层次如图3-3所示。
226+   ;  ;  ;  ;  ;  ;  ;  ; 实现了上述的接口之后,一个AppJoint就已经实现了。打包之后,需要放置到指定的位置。
227+ jar包需要放置到dss-server和linkis-appjoint-entrance两个微服务中,以linkis-appjoint-entrance 为例(dss-server与linkis-appjoint-entrance一致),
228+ 在linkis-appjont-entrance下面的lib的同级目录有一个appjoints目录,目录下面层次如图3-3所示。
113229![ appjoints目录示例] ( /images/zh_CN/chapter4/appjoints.png ) <br >
114230图3-3 appjoints目录示例
115-   ;  ;  ;  ;  ;  ;  ;  ; 在appjoints目录下面新建一个visualis目录。visualis目录下面要求有lib目录,lib目录存放的是visualis在实现VisualisAppJoint的编译的jar包,当然如果有引入dss系统没有带入的jar包,也需要放置到lib目录中,如sendemail Appjoint需要发送邮件功能的依赖包,所以需要将这些依赖包和已经实现的jar包统一放置到lib目录中。另外可以将本AppJoint所需要的一些配置参数放置到appjoints.properties,DSS系统提供的AppJointLoader会将这些配置的参数读取,放置到一个Map中,在AppJoint调用init方法的时候传入。
231+   ;  ;  ;  ;  ;  ;  ;  ; 在appjoints目录下面新建一个visualis目录。
232+ visualis目录下面要求有lib目录,lib目录存放的是visualis在实现VisualisAppJoint的编译的jar包,
233+ 当然如果有引入dss系统没有带入的jar包,也需要放置到lib目录中,如sendemail Appjoint需要发送邮件功能的依赖包,
234+ 所以需要将这些依赖包和已经实现的jar包统一放置到lib目录中。
235+ 另外可以将本AppJoint所需要的一些配置参数放置到appjoints.properties,DSS系统提供的AppJointLoader会将这些配置的参数读取,放置到一个Map中,在AppJoint调用init方法的时候传入。
0 commit comments