Недокументированная возможность в WebSphere Portal 5.1 (общая сессия для портлета и сервлета)

    Была следующая задача:

    написать портлет, который отображает график отчета, хранящегося в Когносе. Отчет Когноса может строиться очень и очень долго, от нескольких секунд до 20.
    Заставлять ждать пользователя столько времени — ужасное решение.

    Я решил положить в портлетное приложение сервлет. При загрузке портлет посылает xmlHttpRequest с путем до отчета, а в ответ ему приходит относительная ссылка на картинку отчета, которую сервлет получил от Когноса и сохранил на сервере.
    Казалось бы, все очень и очень просто, но проблема заключается в том, что при рефреше страницы или обращению к любому портлету на странице, Когнос-портлет отправит новый запрос к сервлету. Этого делать не надо, т.к. картинка уже загружена и обновлять её каждые пять минут не надо.
    Не секрет, что у посетителя портала (любого другого контейнера) есть сессия. В сессию обычно кладут так называемый StateBean, бин, в котором хранится всякий хлам, который может понадобиться пользователю во время работы с порталом. Сделаем в бине поле
    String pathToImage;
    и два метода:
    public String getPathToCognosImage(){ return pathToImage}
    public void setPathToCognosImage(String path){ pathToImage = path;}


    Проблема заключается в том, что при приёме ответа сервлета, JavaScript не сможет вызвать метод бина. Думаю, вы понимаете почему.
    Есть только один выход — писать в бин на Сервлете. Но разве это возможно? Как говорят, на портале 5.0 таких штук вытворять было нельзя. К сожалению, портал 5.0 я не застал и не имею возможности проверить этот слух.

    Способ обращения к бину сессии выглядит следующим образом:
    public class GetPathToChartImageServlet extends javax.servlet.http.HttpServlet implements javax.servlet.Servlet {
    //bla-bla-bla
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    //getting aditional parameters for Cognos.
    //Try to get it from StateBean
    Enumeration en = request.getSession().getAttributeNames();
    while(en.hasMoreElements()){
    attrName = (String)en.nextElement();
    Object o = request.getSession().getAttribute(attrName);
    System.out.println("attr name " + attrName + " = " + o.toString());
    if(o instanceof ru.habr.bean.ChartDataStateBean){
    System.out.println("attr name = " + attrName + ". Is my StateBean");
    statebean = (ru.habr.bean.ChartDataStateBean)o;
    break;
    }
    }
    }//doPost
    }//class


    В консоли можно обнаружить следующие строки:
    [04.06.08 11:04:25:495 MSD] 5a9899ea SystemOut O attr name PC_PRIVATE_5_0_CSI_PortletSessionData = { caiid = 5_0_CSI [PORTLET_ENTITY:13202], creationTime = 1212562835246, lastAccessedTime = 1212563065417 }

    [04.06.08 11:04:25:495 MSD] 5a9899ea SystemOut O attr name PC_5_0_CSI_ru.habr.bean.ChartDataStateBean = ru.habr.bean.ChartDataStateBean@7dc1d9b7

    [04.06.08 11:04:25:495 MSD] 5a9899ea SystemOut O attr name = PC_5_0_CSI_ru.habr.bean.ChartDataStateBean. Is my StateBean


    Ура, бин доступен!

    Перед тем, как тело метода закончится, нужно не забыть записать изменения:
    String newRelativePathToImageFromCognos = CognosFacadeAdapter.getInstance().runReport(reportStringForCognos);
    statebean.setPathToImage(newRelativePathToImageFromCognos);
    request.getSession().setAttribute(attrName, statebean);


    Такая возможность легко объяснятся тем, что:

    Внешне, это выглядит так:


    P.S.
    habracut text=«Что же делать?» выводится не один раз, а несколько. Это глюк или такой прикол?

    Комментарии 5

      0
      передайте знания ребятам из IBS ^_^
        0
        А уже все знают.
        Не пали контору :)
        0
        Вобщем не очень понятно чему вы удивляетесь, сервлет же развернут в контексте портлета. Я схожим образом писал ajax'овый портлет. Про "Что же делать?" почитайте жизненный цикл портлета, сам постоянно на грабли встаю связанные с ЖЦ. Интересный пример из личного опыта )) Писал дерево на struts'е портлетном, так вот это дерево(по сути аррай лист листов...) лежало в реквесте. Запускаешь портлет все прекрасно отривывается. Но по клику на дерево оно проподало из реквеста. Вобщем дело было в том что первая отрисовка использовала ActionRequest, а вторая RenderRequest. Нужно было расшарить между портлетными реквестами эту переменную.
          0
          struts портлетный, это xwork что ли?
          Не очень понял смысл задачи: у вас есть плоское дерево (представление данных) в виде листа листов, затем на jsp вы его JS'ом визуализируете, например используя dtree (http://www.destroydrop.com/javascripts/t…), а затем что? Не понимаю причем здесь AJAX и RenderRequest.
          Если вы, например на onclick по узлу дерева поставили action, то должно быть actionPerformed сработать.
          Если вас не затруднит, объясните, пожалуйста, подробнее. Я не умею расшаривать переменные. А почему бы не класть дерево в сессию?
            0
            ок, AJAX я реализовывал схожим с вами образом, т.е. все запросы принимал сервлет и исходя из логики, параметров запроса возвращал html.

            про "struts портлетный.."
            нет, просто переписанный стратс для портлетов. На IBM много информации.

            А RenderRequest и AJAX здесь непричем, это я уже про другой проект. Немного опишу почему я решил так писать. Ну вопервых, все дерево отрисовывать сразу было нельзя, слишком много данных и они достаточно долго собирались (через свой протокол обращения к железяке). Как вы наверно знаете дерево обычно строится рекурсией. На jsp рекурсию сложно прикрутить, я сделал так. Кладу в реквест корень, на jsp разруливается есть ли дочки у корня и далее jsp:include на эту же jsp. Таким нехитрым образом я построил дерево. По клику на ветвь дерева скриптом я сеттил значения формы, координаты клика и служебную информацию. В экшне обрабатывал, делал запрос на железяку и отрисовывал дополненное дерево.

        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

        Самое читаемое