Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ void testAngularRunParagraph() throws Exception {

// Click on 1 paragraph to trigger z.runParagraph() function

ZeppelinITUtils.sleep(1000, false);
clickAndWait(By.xpath(getParagraphXPath(1) + "//div[@id=\"angularRunParagraph\"]"));

waitForParagraph(2, "FINISHED");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import org.apache.zeppelin.service.AuthenticationService;

/** Configurations Rest API Endpoint. */
@Path("/configurations")
Copy link
Contributor

@Reamer Reamer Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have changed the path of the API class here. Probably so that the call is /api/wsMaxMessageSize. However, I also think /api/configurations/wsMaxMessageSize is very good and would prefer this API endpoint.

Copy link
Contributor Author

@seung-00 seung-00 Oct 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Reamer
I also think the path you mentioned looks good. However, since the authentication referenced in shiro.ini appears to be set up based on the /configuration path, I excluded /configurations from the path. The wsMaxMessageSize API is intended to be a non-authenticated API.

Please feel free to let me know if you have any other suggestions. 🤔

@Path("/")
@Produces("application/json")
@Singleton
public class ConfigurationsRestApi extends AbstractRestApi {
Expand All @@ -47,7 +47,19 @@ public ConfigurationsRestApi(
}

@GET
@Path("all")
@Path("wsMaxMessageSize")
@ZeppelinApi
public Response getWsMaxMessageSize() {
try {
int maxMessageSize = configurationService.getWsMaxMessageSize();
return new JsonResponse<>(Status.OK, "", maxMessageSize).build();
} catch (Exception e) {
return new JsonResponse<>(Status.INTERNAL_SERVER_ERROR, "Fail to get max message size", e).build();
}
}

@GET
@Path("configurations/all")
@ZeppelinApi
public Response getAll() {
try {
Expand All @@ -60,7 +72,7 @@ public Response getAll() {
}

@GET
@Path("prefix/{prefix}")
@Path("configurations/prefix/{prefix}")
@ZeppelinApi
public Response getByPrefix(@PathParam("prefix") final String prefix) {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ public Map<String, String> getAllProperties(ServiceContext context,
return properties;
}

public int getWsMaxMessageSize() {
return Integer.parseInt(zConf.getWebsocketMaxTextMessageSize());
}

public Map<String, String> getPropertiesWithPrefix(String prefix,
ServiceContext context,
ServiceCallback<Map<String, String>> callback)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,14 @@ import { NzModalService } from 'ng-zorro-antd/modal';
import { MessageListener, MessageListenersManager } from '@zeppelin/core';
import { TRASH_FOLDER_ID_TOKEN } from '@zeppelin/interfaces';
import { MessageReceiveDataTypeMap, Note, OP, RevisionListItem } from '@zeppelin/sdk';
import { MessageService, NotebookService, NoteStatusService, SaveAsService, TicketService } from '@zeppelin/services';
import {
ConfigurationService,
MessageService,
NotebookService,
NoteStatusService,
SaveAsService,
TicketService
} from '@zeppelin/services';
import { NoteCreateComponent, ShortcutComponent } from '@zeppelin/share';

@Component({
Expand Down Expand Up @@ -191,11 +198,12 @@ export class NotebookActionBarComponent extends MessageListenersManager implemen
});
}

exportNote() {
async exportNote() {
if (!this.ticketService.configuration) {
throw new Error('Configuration is not loaded');
}
const sizeLimit = +this.ticketService.configuration['zeppelin.websocket.max.text.message.size'];

const sizeLimit = await this.configurationService.fetchWsMaxMessageSize();
const jsonContent = JSON.stringify(this.note);
if (jsonContent.length > sizeLimit) {
this.nzModalService.confirm({
Expand Down Expand Up @@ -326,6 +334,7 @@ export class NotebookActionBarComponent extends MessageListenersManager implemen
@Inject(TRASH_FOLDER_ID_TOKEN) public TRASH_FOLDER_ID: string,
private nzModalService: NzModalService,
private ticketService: TicketService,
private configurationService: ConfigurationService,
private nzMessageService: NzMessageService,
private router: Router,
private cdr: ChangeDetectorRef,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

import { Observable } from 'rxjs';
import { BaseRest } from './base-rest';
import { BaseUrlService } from './base-url.service';

Expand All @@ -24,7 +25,11 @@ export class ConfigurationService extends BaseRest {
super(baseUrlService);
}

getAll() {
fetchWsMaxMessageSize(): Promise<number> {
return this.http.get<number>(this.restUrl`/wsMaxMessageSize`).toPromise();
}

getAll(): Observable<{ [p: string]: string }> {
return this.http.get<{ [key: string]: string }>(this.restUrl`/configurations/all`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
<p class="ant-upload-text">Click or drag JSON file to this area to upload</p>
<p class="ant-upload-hint">
JSON file size cannot exceed
<strong class="tips warning">{{ maxLimit | humanizeBytes }}</strong>
<strong class="tips warning">{{ wsMaxLimit | humanizeBytes }}</strong>
</p>
</nz-upload>
</nz-tab>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@

import { HttpClient } from '@angular/common/http';
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { MessageService, TicketService } from '@zeppelin/services';
import { ConfigurationService, MessageService, TicketService } from '@zeppelin/services';

import { get } from 'lodash';
import { NzModalRef } from 'ng-zorro-antd/modal';
import { NzUploadFile } from 'ng-zorro-antd/upload';

Expand All @@ -32,7 +31,7 @@ export class NoteImportComponent extends MessageListenersManager implements OnIn
importUrl?: string;
errorText?: string;
importLoading = false;
maxLimit = get(this.ticketService.configuration, ['zeppelin.websocket.max.text.message.size'], null);
wsMaxLimit?: number;

@MessageListener(OP.IMPORT_NOTE)
noteImported(_: MessageReceiveDataTypeMap[OP.IMPORT_NOTE]) {
Expand All @@ -59,7 +58,7 @@ export class NoteImportComponent extends MessageListenersManager implements OnIn

beforeUpload = (file: NzUploadFile): boolean => {
this.errorText = '';
if (file.size !== undefined && this.maxLimit && file.size > Number.parseInt(this.maxLimit, 10)) {
if (file.size !== undefined && this.wsMaxLimit && file.size > this.wsMaxLimit) {
this.errorText = 'File size limit Exceeded!';
} else {
const reader = new FileReader();
Expand Down Expand Up @@ -102,12 +101,15 @@ export class NoteImportComponent extends MessageListenersManager implements OnIn
constructor(
public messageService: MessageService,
private ticketService: TicketService,
private configurationService: ConfigurationService,
private cdr: ChangeDetectorRef,
private nzModalRef: NzModalRef,
private httpClient: HttpClient
) {
super(messageService);
}

ngOnInit() {}
async ngOnInit() {
this.wsMaxLimit = await this.configurationService.fetchWsMaxMessageSize();
}
}
43 changes: 21 additions & 22 deletions zeppelin-web/src/app/notebook/notebook.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -267,30 +267,29 @@ function NotebookCtrl($scope, $route, $routeParams, $location, $rootScope,
return note && note.path ? note.path.split('/')[1] === TRASH_FOLDER_ID : false;
};

// Export notebook
let limit = 0;
$scope.exportNote = function() {
$http.get(baseUrlSrv.getRestApiBase() + '/wsMaxMessageSize').then(function(response) {
const limit = response.data.body;

websocketMsgSrv.listConfigurations();
$scope.$on('configurationsInfo', function(scope, event) {
limit = event.configurations['zeppelin.websocket.max.text.message.size'];
});
let jsonContent = JSON.stringify($scope.note, null, 2);

$scope.exportNote = function() {
let jsonContent = JSON.stringify($scope.note, null, 2);
if (jsonContent.length > limit) {
BootstrapDialog.confirm({
closable: true,
title: 'Note size exceeds importable limit (' + limit + ')',
message: 'Do you still want to export this note?',
callback: function(result) {
if (result) {
saveAsService.saveAs(jsonContent, $scope.note.name + '_' + $scope.note.id, 'zpln');
}
},
});
} else {
saveAsService.saveAs(jsonContent, $scope.note.name + '_' + $scope.note.id, 'zpln');
}
if (jsonContent.length > limit) {
BootstrapDialog.confirm({
closable: true,
title: 'Note size exceeds importable limit (' + limit + ')',
message: 'Do you still want to export this note?',
callback: function(result) {
if (result) {
saveAsService.saveAs(jsonContent, $scope.note.name + '_' + $scope.note.id, 'zpln');
}
},
});
} else {
saveAsService.saveAs(jsonContent, $scope.note.name + '_' + $scope.note.id, 'zpln');
}
}).catch(function(err) {
console.error('Error while fetching max message size', err);
});
};

// Export nbformat
Expand Down
43 changes: 23 additions & 20 deletions zeppelin-web/src/components/note-import/note-import.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,14 @@ import './note-import.css';

angular.module('zeppelinWebApp').controller('NoteImportCtrl', NoteImportCtrl);

function NoteImportCtrl($scope, $timeout, websocketMsgSrv) {
function NoteImportCtrl($scope, $timeout, websocketMsgSrv, $http, baseUrlSrv) {
'ngInject';

let vm = this;
$scope.note = {};
$scope.note.step1 = true;
$scope.note.step2 = false;
$scope.maxLimit = '';
let limit = 0;

websocketMsgSrv.listConfigurations();
$scope.$on('configurationsInfo', function(scope, event) {
limit = event.configurations['zeppelin.websocket.max.text.message.size'];
$scope.maxLimit = Math.round(limit / 1048576);
});

vm.resetFlags = function() {
$scope.note = {};
Expand All @@ -53,19 +46,29 @@ function NoteImportCtrl($scope, $timeout, websocketMsgSrv) {
let file = $scope.note.importFile;
let reader = new FileReader();

if (file.size > limit) {
$scope.note.errorText = 'File size limit Exceeded!';
$scope.$apply();
return;
}

reader.onloadend = function() {
vm.processImportJson(reader.result);
};
$http.get(baseUrlSrv.getRestApiBase() + '/wsMaxMessageSize')
.then(function(response) {
const limit = response.data.body;

if (file) {
reader.readAsText(file);
}
if (file.size > limit) {
$scope.note.errorText = 'File size limit Exceeded!';
$scope.$apply();
return;
}

reader.onloadend = function() {
vm.processImportJson(reader.result);
};

if (file) {
reader.readAsText(file);
}
})
.catch(function(err) {
console.error('Error while fetching max message size', err);
$scope.note.errorText = 'Unable to get upload limit.';
$scope.$apply();
});
};

$scope.uploadURL = function() {
Expand Down
Loading