Веб сервис не хочет принимать файлы больше 3мб, пишет ошибка java.lang.outOfMemoryError

Gandliar

Lotus Team
16.02.2004
564
26
BIT
110
Подскажите, как это преодолеть?

Веб сервис не хочет принимать файлы больше 3мб, пишет ошибка java.lang.outOfMemoryError
 

savl

Lotus Team
28.10.2011
2 624
314
BIT
539
Подскажите, как это преодолеть?

Веб сервис не хочет принимать файлы больше 3мб, пишет ошибка java.lang.outOfMemoryError
нужен стек ошибки, так как сам веб-сервис с вероятностью 0,99 - принимает файл, скорее всего падает его обработка.
 

Gandliar

Lotus Team
16.02.2004
564
26
BIT
110
Выяснилось что падает не принимающий сервис а отправляющий.
Сделал принимающий сервис на soapui

Ошибка выскакивает при отправке.

как посмотреть стек ошибки - непонятно.


файлы до 3 мб включительно отправляются нормально, в сервисе приемнике на soapUI отображаются нормально.
а если взять файл больше 9 и 12 мб - выскакивает ошибка

1690892810512.png

1690892902112.png
 

Gandliar

Lotus Team
16.02.2004
564
26
BIT
110
Проблема возникает на клиенте. серверный агент отправляет и 12 мб файл.
Однако это происходит довольно медленно секунд 40, внутри сети.
Подскажите пожалуйста, медленная скорость отправки обусловлена технологией или можно как то увеличить?
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
470
Проблема возникает на клиенте. серверный агент отправляет и 12 мб файл.
Однако это происходит довольно медленно секунд 40, внутри сети.
Подскажите пожалуйста, медленная скорость отправки обусловлена технологией или можно как то увеличить?
помимо домины что-то есть в цепочке от сервера к клиенту?
и что именно отправляется (бинарник или текст) ?
 

Gandliar

Lotus Team
16.02.2004
564
26
BIT
110
сервер отправляет и 12мб файлы, с клиента больше 3мб - пишет ошибку
между клиентом и сервером 1 узел, пинги идут 1мс.
если сохранять документ в базу на сервере - сохраняется моментом через интерфейс клиента.
а вот скорость отправки веб-сервисом оставляет ждать лучшего.
веб сервис - на лотусскрипте. Пока непонятно, поможет ли переписать вызовы на java или делать свою реализацию через java классы.

отправляется файл в base64, чем больше файл тем больше задержка (нелинейно)
настроил провайдера в soapui для теста, принимает вот такого типа

1690959242711.png
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
470
сервер отправляет и 12мб файлы, с клиента больше 3мб - пишет ошибку
между клиентом и сервером 1 узел, пинги идут 1мс.
если сохранять документ в базу на сервере - сохраняется моментом через интерфейс клиента.
а вот скорость отправки веб-сервисом оставляет ждать лучшего.
веб сервис - на лотусскрипте. Пока непонятно, поможет ли переписать вызовы на java или делать свою реализацию через java классы.

отправляется файл в base64, чем больше файл тем больше задержка (нелинейно)
настроил провайдера в soapui для теста, принимает вот такого типа

Посмотреть вложение 70752
ничего не понял, можно блоксхему?
по текущим объяснениям выглядит (для меня) так
1690992292756.png
 
Последнее редактирование:

aameno2

Lotus Team
27.01.2009
777
187
BIT
411
может банально память течет? что в коде отправки?
ну и что в
JavaEnableJIT=
JavaMaxHeapSize=
JavaDebugString=-XX:MaxPermSize
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
470
может банально память течет? что в коде отправки?
ну и что в
JavaEnableJIT=
JavaMaxHeapSize=
JavaDebugString=-XX:MaxPermSize
base64 в схеме плохо работает кмк
но память увеличить надо, но я так и не понял - где ;) и как бинарник оборачивают, кода нет...
base64 в ЛС всегда был лютым п@здецом, уже несколько либ пилили (на nsftool втч)
 
Последнее редактирование:

aameno2

Lotus Team
27.01.2009
777
187
BIT
411
base64 в схеме плохо работает кмк
но память увеличить надо, но я так и не понял - где ;) и как бинарник оборачивают - тоже не понял (кода нет)
base64 в ЛС всегда был лютым п@здецом уже несколько либ пилили (на nsftool втч)
да там гадание на кофейной, тыкать пальцем куда хочешь)
мож память не настроена, мож течет. может код такой....
а по base64 имхо лучше на сях обертку сделать.
но я б ткнул сначала в память)
 
Последнее редактирование:

garrick

Lotus Team
26.10.2009
1 367
152
BIT
363
Web-сервис это же SOAP, а SOAP это XML. Java с дефолтными настройками в Domino всегда падает в Out of memory при парсинге больших XML файлов, т.к. для этого обычно используется DOM модель. Зная IBM, скорее всего, для парсинга SOAP сообщения через LotusScript используется именно DOM из Java. Если я всё правильно понял у вас падает web-service consumer при формировании SOAP сообщения. Первое, самое простое - увеличить память для Java на клиенте. Есть такой параметр в notes.ini. Второе переписать клиентскую часть на Java не используя сгенерённый дизайнером код, в виде агента с использованием SAX/StAX, может быть JAXB.

Ещё вариант - если файлы загружают пользователи "ручками", нажимая какие-то кнопки в интерфейса, вообще убрать клиентскую часть. Сделать на сервере XPages страничку с интерфейсом загрузки файла. Грузить файлы через браузер.
 

savl

Lotus Team
28.10.2011
2 624
314
BIT
539
Зная IBM, скорее всего, для парсинга SOAP сообщения через LotusScript используется именно DOM из Java.

Немного оффтоп, вот это замечание верно. WebService на LotusScript в конечном итоге представляют собой java.jar, который запускается http задачей.
Это видно по полям в элементе дизайна.
Поэтому тут не важно что именно происходит, чтение xml, передача файлов или просто сбор данных - всё это делается через java.

Field Name: $FILE
File Name: %%webserviceresource%%.jar

1691398032408.png
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
470
Ещё вариант - если файлы загружают пользователи "ручками", нажимая какие-то кнопки в интерфейса, вообще убрать клиентскую часть. Сделать на сервере XPages страничку с интерфейсом загрузки файла. Грузить файлы через браузер.
вот, да, сразу уйдёт гимор с base64
НО, как недавно пробегало, хэпаговые сервлеты текут, как понял - нужен ФП2 для 12.0.2
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
470
пример (хоть и неоднозначный) хэпаги
XML:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
    xmlns:xe="http://www.ibm.com/xsp/coreex" rendered="false"
    viewState="nostate" disableTheme="true">
    <xp:this.afterRenderResponse><![CDATA[#{javascript:var exCon:javax.faces.context.ExternalContext = null;
try{
  importPackage( lmike.org);
  exCon = facesContext.getExternalContext();
  //var response:javax.servlet.http.HttpServletResponse = externalContext.getResponse();
  //var response = exCon.getResponse().getDelegate();
  var batch=paramValues.get("id");
  var batchChecker:BatchChecker=new BatchChecker
  var status=batchChecker.getBatch(batch==null?batch:batch.toString());//, response);
  exCon.getResponse().setStatus(status);
}catch(e){
  _dump(e);
  print("<<batchcheck.xsp>>"+e.toString());
  org.openntf.domino.xsp.XspOpenLogUtil.logError(e);
  if (exCon!=null)exCon.getResponse().setStatus(500)
}
}]]></xp:this.afterRenderResponse>
    <xe:restService id="BatchCheckService" pathInfo="BatchCheckService"
        rendered="false" preventDojoStore="true" disableTheme="true">
        <xe:this.service>
            <xe:customRestService
                serviceBean="com.setralubs.BatchCheckService"
                contentType="application/json">
            </xe:customRestService>
        </xe:this.service>
    </xe:restService>
</xp:view>
в чём суть:
- если запустить хэпагу без параметров - класс перехватывает вывод и по входному потоку (надо передать хухель/эксель) - выдаёт zip с файлами из базы (по списку из хухеля)
- если указать параметр id - выдаст один файл (из дока)
- если указать сервис - вызовет сервис (на выходе json)
в хухеле, в константах выглядит так
Visual Basic:
Const xsp = "/__432582C8005FD4C4.nsf/batchcheck.xsp"
Const XLSXtype = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
Const LinkBase = "https://" & dominoServer & xsp & "?id"
Const checkService = xsp & "/BatchCheckService?exists=true"
класс перехватывает вывод хэпаги так ((см. checking2ZIP))
Java:
import com.ibm.xsp.webapp.XspHttpServletResponse;
......
import org.apache.commons.io.IOUtils;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.io.*;
import java.net.HttpURLConnection;
import java.util.*;
import java.util.function.Supplier;
import java.util.logging.Level;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;

import org.openntf.domino.*;
import org.openntf.domino.utils.Factory;
......

public class BatchChecker {
    private final String classID="::"
            + new Throwable().getStackTrace()[0].getClassName() + "::";
    @ExcelCellName("Material")
    String fusion;

    @ExcelCellName("Material Description")
    String prodName_Pack;

    @ExcelCellName("Batch")
    String batch;

    private Session ses;

    private Database db;

    private View view;
    private PrintWriter opw;
    private OutputStream os;
    private ZipOutputStream append;
 
    public BatchChecker() {
        ses = Factory.getSession();
        db = ses.getCurrentDatabase();
        view = db.getView("batches");
    }
.....
    /**
     * process input and write result as zip to output
     */
    public int checking2ZIP(){
        Throwable throwable = new Throwable();
        int status=HttpURLConnection.HTTP_INTERNAL_ERROR;
        InputStream is=null;
        FacesContext fc = FacesContext.getCurrentInstance();
        ExternalContext ex = fc.getExternalContext();
        HttpServletRequest request = (HttpServletRequest) ex.getRequest();
        try {
            is=request.getInputStream();
            status=HttpURLConnection.HTTP_NOT_FOUND;
            if( is!=null
                    && request.getContentType()!=null
                    && request.getContentType().contains(
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                    )
.......
        try {
            is=request.getInputStream();
            status=HttpURLConnection.HTTP_NOT_FOUND;
            if( is!=null
                    && request.getContentType()!=null
                    && request.getContentType().contains(
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
                    )
            {
                XspHttpServletResponse xspResponse = (XspHttpServletResponse) ex.getResponse();
                javax.servlet.http.HttpServletResponse response=xspResponse.getDelegate();
                String type=MIMEType.get("zip");
                response.setHeader("Content-Type",type);
                response.setHeader("Content-Disposition","attachment; filename=allFiles.zip");

                this.os =response.getOutputStream();
                append = new ZipOutputStream(os);
                //PoijiOptions options = PoijiOptionsBuilder.settings().sheetIndex(0).build();
                Poiji.fromExcel(is, PoijiExcelType.XLSX, BatchChecker.class, this::add2Zip);//, options, this::dbCheck);
                append.finish();
                status=HttpURLConnection.HTTP_OK;
а сервис так
Java:
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.logging.Level;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.openntf.domino.xsp.XspOpenLogUtil;

import com.ibm.domino.services.ServiceException;
import com.ibm.domino.services.rest.RestServiceEngine;
import com.ibm.xsp.extlib.component.rest.CustomService;
import com.ibm.xsp.extlib.component.rest.CustomServiceBean;
public class BatchCheckService extends CustomServiceBean {
    private final String classID="::"
            + new Throwable().getStackTrace()[0].getClassName() + "::";

    @Override
    public void renderService(CustomService service, RestServiceEngine engine) throws ServiceException {
        try {
            Throwable throwable = new Throwable();
            super.renderService(service, engine);
            HttpServletRequest request = engine.getHttpRequest();
            HttpServletResponse response = engine.getHttpResponse();
            PrintWriter writer = response.getWriter();
            //JsonJavaObject jo = new JsonJavaObject();
            boolean exists=request.getParameter("exists")!=null;
            //System.out.println("id length: "+id.length());
            BatchChecker obj=new BatchChecker();
            response.setHeader("Content-Type", "application/json; charset=UTF-8");
            writer.write("{\"body\": \"");
            if(request.getContentType()!=null && request.getContentType().contains(
                    "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                    )
                  ){
                //String ext=MIMEType.getKey(request.getContentType());
                InputStream bodyIs=request.getInputStream();
......
                obj.checking(bodyIs, writer, exists);
            }else //if(request.getContentType().contains("application/json"))
            {
                obj.testCheckingOut(writer);
            }
            writer.write("\"}");
            writer.close();
 
Последнее редактирование:

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
470
т.о. - чтобы не "жевать" SOAPли - можно на выбор: выдать жсон или бинарник, ну если очень надо - можно и в хмл, при этом сохранится контроль над происходящим и появится возможность выбирать библиотеки
в отличии от "штатных соплей" и мороки с либами в агентах
 

lmike

нет, пердело совершенство
Lotus Team
27.08.2008
7 985
611
BIT
470
ОФФ: в хухеле (экселе) я сделал макросы по кнопкам, суть:
- текущий файл сохраняется в темп и отправляется домине (POST)
- домина разгребает файл от способа вызова и выдаёт бинарник/жсон
- хухель парсит ответ: по жсон корректирует инфу на листе, по бинарнику- сохраняет в темп, вызывает его открытие в explorer.exe
 

Gandliar

Lotus Team
16.02.2004
564
26
BIT
110
По итогу отказались от встроенных веб сервисов.
Написали на httprequest и работает.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!