Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java EE (J2EE) и Spring > GWT. Servlet с static классом. !! Опасно или нет?


Автор: unkis 20.1.2011, 19:14
Ребята есть GWT приложение, в етом преложении реализованно следующее.

Код

public class CommunicationServiceImpl<T> extends RemoteServiceServlet implements CommuncationService<T>
{
    public static AAPSession session;
    
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
        CommunicationServiceImpl.session = new AAPSession(request.getSession());
                
        super.service(request, response);
    }
    
    .....
}

public class AAPSession extends StandardSessionFacade
{

    public AAPSession(HttpSession session)
    {
        super(session);        
    }
    
    ......
}




и дальше в коде можно встретить следующее:


Код

 Long userId = (Long)CommunicationServiceImpl.session.getAttribute("userID");



Как такое может работать? если статическое поле "session" для всех пользователей должно быть одинаковое или я что-то не понимаю?

Автор: emmanuil 21.1.2011, 20:23
Потому что инициализируешь поле session для каждого запроса. Посмотри ЖЦ сервлетов. И получается, что толку нету, что это поле статическое.
И если нужно иметь HttpSession чтобы все работало, то обновляй там в методе не поле session, а поле класса AAPSession, которое хранит HttpSession.

Автор: SoulSeeker 22.1.2011, 17:10
Цитата(emmanuil @  21.1.2011,  20:23 Найти цитируемый пост)
И получается, что толку нету, что это поле статическое.

Как это толку нету? Это будет одна разделяемая сессия для всех клиентов.
 session всегда будет инициализироваться тем, кто последний раз проходил через метод service. 
Не знаю, как такое может работать.

Автор: emmanuil 26.1.2011, 07:29
Цитата(SoulSeeker @  22.1.2011,  15:10 Найти цитируемый пост)
Как это толку нету?

А так. Если нужно статическое поле sesion и чтобы она хранила одни данные для всех и при этом продолжало всё работать (из указанного примера), то нужно обновлять поле класса AAPSession, а не каждый раз создавать экземпляр. Смотрю по тому, что дано. Не знаю, что там в самом классе реализовано.
Статика тут только для удобства получения данных текущего запроса и кроме этого толку в ней нет, так как при следующем запросе, все обновится и ничего разделяемого не будет. Можно сделать в классе AAPSession поле currentRequest, например, и его обновлять в сервлете.
Цитата(SoulSeeker @  22.1.2011,  15:10 Найти цитируемый пост)
Это будет одна разделяемая сессия для всех клиентов.
 session всегда будет инициализироваться тем, кто последний раз проходил через метод service.

Во первых, сессия у каждого своя.
Во вторых, если она при каждом запросе обновляется, откуда она будет одна разделяемая для всех клиентов? Поле session обновится данными клиента отправившего запрос. И так будет при каждом запросе.
Цитата(SoulSeeker @  22.1.2011,  15:10 Найти цитируемый пост)
Не знаю, как такое может работать. 

Как это работает, я уже описал. Возможно, сервлет слушает все запросы и поэтому проблем не возникает.

Если это все работает, то неопасно, может кто-то другой считает иначе. Просто нужно помнить про статическое поле.

Автор: SoulSeeker 26.1.2011, 21:36
emmanuil, при двух и более параллельных запросах статическое поле session никак не будет разным у всех потоков. Поэтому, отвечая на вопрос
Цитата

Опасно или нет?
,
да, опасно. Потому что на поле session не стоит синхронизация. Допустим, один поток инициализирует, другой тут же меняет session на свое значение, потому что запрос пришел на доли секунды позже.

Автор: emmanuil 28.1.2011, 08:15
Цитата(SoulSeeker @  26.1.2011,  19:36 Найти цитируемый пост)
да, опасно. Потому что на поле session не стоит синхронизация. Допустим, один поток инициализирует, другой тут же меняет session на свое значение, потому что запрос пришел на доли секунды позже.

Это да. И я не просто так написал, что помнить нужно про статическое поле.
Если есть интенсивная работа клиентов, то блокировка в методе service может привести к задержкам. Скорее нужно пересмотреть определение текущего пользователя.

Автор: SoulSeeker 29.1.2011, 00:38
Короче говоря, данный код неверен с точки зрения доступа к разделяемому ресурсу. Решение - убрать модификатор static с поля session и не париться по поводу левого изменения от разных потоков. Такие ошибки очень трудно выявляются впоследствии и их появление трудно воспроизвести.

Автор: _sten_ 29.1.2011, 00:57
можно использовать http://download.oracle.com/javase/1.4.2/docs/api/java/lang/ThreadLocal.html тогда проблем с конкурентным изменением не будут, но вопрос наснолько это коректно использовать с точки зрения дизайна остаеться открытым(ThreadLocal привязывает обьект к текущему токотку, и если создатасть новые потоки то будут проблемы), но как квикфикс пойдет точно.


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)