Итак, мы приступаем к написанию нашего приложения в виде интернет-решения.

В предыдущих частях Вы уже посмотрели основы взаимодействия броузера с сервером. Мы выяснили, что запросы пользователя посылаются на сервер, где их обрабатывает сервлет. Сервлет может сам создать необходимый HTML, но это достаточно неудобно и поэтому в подавляющем большинстве случаев все данные сервлет может передать JSP, которая покажет все эти данные в виде HTML-страницы.

JNDI — первое знакомство
Для начала мы с вами немножко изменим наше ядро — ManagementSystem. Во-первых, посмотрим на новую технологию, во-вторых — сделаем наше приложение более профессиональным.
оспользуемся системой JNDI — Java Naming Directory Interface — специальная система имен, которая позволяет делать следующее: хранить в некотором репозитории нужные нам классы и возвращать их по требованию приложений по имени. Что очень удобно — мы можем задавать параметры для нужного нам ресурса во внешнем конфигурационном файл, а не прописывать жестко в коде — что в общем-то всегда является не очень хорошим стилем.
Заметьте, что даже класс драйвера мы можем теперь менять независимо от кода нашего приложения — можем позже использовать другую базу данных — Oracle, Sybase, DB2 и другие.

Рекомендуем: Для более полного ознакомления с технологией JNDI я вам советую посмотреть следующие ссылки:

http://java.sun.com/products/jndi/tutorial/TOC.html — это подробное описание системы JNDI

http://tomcat.apache.org/tomcat-4.1-doc/jndi-resources-howto.html — описание использования JNDI для сервера Tomcat

Как и в прошлый раз мы создадим необходимые нам файлы в обычном редакторе. Сейчас мы с вами сделаем приложение, которое будет очень похоже на то, что было сделано в «Части 7 — Первые шаги в Интернет». У нас будет один сервлет, который покажет нам таблицу групп.

Итак, давайте создадим наши файлы.

web.xml

Как видите, мы описали всего один сервлет, для которого сделали маппинг (связку, отображение — русского термина так и не придумали), т.е. связали URL и сервлет. Это мы уже видели раньше. Но вот дальше у нас с вами новинка — мы описали ресурс. У него есть описание — DB Connection. Далее мы указали имя, по которому мы будем его запрашивать через JNDI — jdbc/StudentsDS. Также мы описали тип/класс возвращаемого ресурса — javax.sql.DataSource. И в конце мы указали кто отвечает за авторизацию — будет ли приложение само подставлять логин и пароль или этим будет заниматься контейнер — в нашем случае этим будет заниматься Tomcat.

Отметим, что при таком описании контейнер берет на себя все заботы по поддержанию коннекта к базе. Причем не одного, а целого пула — несколько штук коннектов. Это удобно тем, что создание коннекта — дело сложное, долгое и ресурсоемкое. Если мы имеем некоторый запас свободных коннектов — это ускоряет работу.

Для того, чтобы Tomcat знал какие параметры он должен подставить нам необходим еще один файл — context.xml.

Я думаю. что многие параметры для вас очевидны. Но все же опишем их.
name — имя ресурса — оно должно совпадать с тем, кторое указано в файле web.xml
type — опять же должно совпадать с тэгом >res-type> из web.xml
username — логин к базе данных
password — пароль
driverClassName — класс драйвера JDBC (мы его можем получить из описанного ранее файла mysql-connector-java-3.1.13-bin.jar). К нему мы чуть позже еще раз вернемся.
maxIdle — максимальное количество незадействованных коннектов — свободных.
maxWait — время (в миллисекундах), в течении которого пул коннектов будет пытаться отдать коннект по запросу прежде чем «выбросит» исключение о недоступности ресурса.
validationQuery — запрос который будет выполнятся для проверки валидности (правильности) коннекта перед отдачей его приложению.
url — URL для соединения — его мы уже использовали
maxActive — максимальное количество акивных коннектов. Если надо будет больше, то остальным придется подождать. (см. параметр maxWait)

Теперь давайте посмотрим на изменения, которые мы сделали в файле ManagementSuystem.java. Сначала я приведу код, а после этого мы рассмотрим наши изменения.

ManagementSystem.java

Самое важное изменение находится в методе getInstance().
Раньше наш класс загружал драйвер и устанавливал соединение. Теперь мы видим, что соединения класс не делает — он только запрашивает ресурс по имени (отметим. что именно по тому имени, которое указано в файла web.xml и context.xml). А уже Tomcat берет на себя все необходимые действия — открывает соединение (несколько штук сразу), проверяет правильность и т.д.

Возможно, что в нашем случае в таком подходе нет необходимости, но это удобно при большом количестве баз данных, коннектов и прочего.

Также надо отметить новый метод – getStudentById(..). Он достаточно очевидный – получаем данные конкретного студента по его ID. Он нам пригодится.

Приведем код нашего сервлета — SimpleList.java

Ну и по традиции добавим код для двух классов — Group.java и Student.java

Group.java

Student.java

Для компиляции наших классов иерархия файлов должна выглядеть так:

Я скопировал файл servlet-api.jar из директории <TOMCAT_HOME>\lib. Так удобнее собирать. Об этом мы говорили в раньше.
Для того, чтобы скомпилировать классы набираем команду (текущая директория та, в которой находится каталог students):

Теперь скопируем все наши файлы в директорию <TOMCAT_HOME>\webapps\studentsApp. Структура файлов в каталоге должна выглядеть так:

Что касается файла 
mysql-connector-java-3.1.13-bin.jar — теперь он должен находится в каталоге <TOMCAT_HOME>\lib.
Если все нормально собралось и скопировалось, то запускаем Tomcat и после старта открываем броузер и набираем строку

По идее мы должны получить список групп из нашей базы. И теперь мы перейдем непосредственно к написанию нашего приложения.

Студенческий отдел кадров — WEB-приложение
В данном приложении автор не собирается делать какие-то супер красивые и удобные HTML-странички. Посему будет все очень просто — во-первыхЮ чтобы было понятнее. Во-вторых — цель проекта познакомиться, а не вдаваться в тонкости GUI.
Давайте перечислим еще раз те формы, котоыре нам потребуются:
1. Главная форма, которая показывает список групп, поле для ввода года и список студентов, соответсвующий выбранной группе и году. В этой же форме можно выполнять удаление студента и удаление всех студентов из выделенной группы.
2. Форма для ввода данных о студенте — мы можем использовать одну форму для добавления и для редактирования.

Давайте немного подробнее опишем эти формы.

Итак — главная форма.

Для ввода года будем использовать обычное текстовое поле — можно с помощью JavaScript проверку корректности, но мы не будем этого делать — упростим все до предела.

Список групп будет обычным выпадающим списком.

Список студентов оформим в виде таблицы где удаление и редактирование мы сделаем просто — каждый студент в списке может быть выделен с помощью радиокнопки (RadioButton). После этого достаточно нажать кнопку — Редактировать, Удалить — и можно посылать команду на сервер.

Форма для редактирования/добавления студента — мы просто перечислим поля. Для поля «Пол» используем радиокнопки, для поля «Группа» — список. Дату будем вводить просто строкой — не будем усложнять.

Разобравшись с формами попробуем набросать список команд. В общем-то он и определит, какие сервлеты нам потребуются. Мы постараемся не делать список слишком длинным, тем более, что те же команды редактирования/добавления студента в общем-то можно свести к одной — если мы передаем ID студента =0, то можно сказать, что надо добавить. Иначе — редактировать.

Итак наш список выглядит следующим образом:
— Показать список студентов для определенного года и определенной группы.
— Удалить студента
— Редактировать/добавить студента

Замечение: Умение правильно проектировать набор нужных сервлетов — дело опыта. Так что проектируйте, делайте, ломайте и заново стройте — после нескольких попыток вы научитесь этому занимательному делу.

Я не буду утверждать, что сделал оптимальный набор — возможно кому-то захочется сделать его более полным, кому-то покажется, что кое-какие команды можно реализовать одним сервлетом. но как сделано — так сделано. Мне важно показать технологию в действии.

Мы будем использовать сервлеты для получения данных, преобразования и потом вызывать JSP для отображения.

Пойдем по порядку — главная форма — MainFrameServlet.
Как уже говорилось в предыдущих частях JSP служит для того, чтобы показать данные которые ей передал сервлет. Профессионалы могут поспорить, но мне важно, чтобы вы поняли вот какой момент — сервлет собирает все данные по разным таблицам, по разным файла и т.д., кладет это все в некоторую структуру и передает JSP, которая занимается тем, что из этой структуры «вытаскивает» нужные данные и кладет их на соотвтествующее место на странице.

Как видите для реализации команды нам надо три компонента:
— сервлет, который выполняет какие-то действия, собирает необходимые нам данные и кладет их в
— структуру, которая содержит все необходимые данные для показа на
— JSP странице, которая «вынимает» из структуры данные и располагает их по странице

Начнем мы со второго пункта — состав структуры достаточно очевиден — год, список групп, ID конкретной группы, список студентов для конкретной группы и данного года. Для всех таких структур создадим новый пакет — students.web.forms.

Мы еще вернемся к этому вопросу, но все-таки предварительного упоминания этот момент заслуживает:

JSP 2.0 и выше используется так называемы «Язык выражений» (ЯВ) или Expression Language (EL) — основная его идея в том, чтобы не писать страшные конструкции типа

<%= request.getParameter(«parameter») %>

ЯВ имеет упрощенный синтаксис обращения к полям объектов, которые находятся в JSP (это как раз наша структура, которая содержит много данных). Писать постоянно формулы и get/set методы не очень интересно и поэтому был сделан ЯВ. В нем обращение к данным гораздо приятнее на вид.
Очень важно учесть, что ЯВ требует правильного именования полей и наличия методов set/get. Чуть ниже приведен код нашей структуры и там можно увидеть как именовать поля и методы доступа к ним.
Т.е. получим вот такой вот класс:

MainFrameForm.java

Код для сервлета нашей главной страницы:

MainFrameServlet.java

Теперь нам необходимо сделать страницу JSP, которая будет нам показывать наши результаты. Эту страницу мы положим в корень каталога для нашего WEB-приложения.

Вам необходимо обратить внимание на следующие моменты:

1.       <%@ taglib prefix=»c» uri=»http://java.sun.com/jsp/jstl/core» %> — команда, которая загружает библиотеку стандартных тэгов – тот самыйJSTL о котором мы говорили в предыдущей части.

2.       Фрагменты из JSP

c:forEach – специальный тэг, который позволяет перебрать элементы коллекции

c:choose – тэг для выбора из вариантов по условию c:when и то, что не подошло будет выполнятеся в теле тэгаc:otherwise

Стоит отметить, что JSTL является достаточно мощным инструментом и я советую Вам потратить время на изучение тэгов. Мне очень понравилась книга
Сью Шпильман.  «JSTL. Практическое руководство для JSP-программистов». Очень кратко, но  по делу

MainFrame.jsp

Теперь рассмотрим код, который необходим для редактирования данных о студенте.

Первый наш класс содержит информацию, которую мы будем показывать на странице – он аналогичен MainFrameForm.java, только данные теперь будут о конкретном студенте.

StudentForm.java

Теперь код для нашего сервлета, который будет обрабатывать полученные данные.

StudentFrameServlet.java

И наконец JSP для отображения данных.

StudentFrame.jsp

Наш файл web.xml тоже притерпел некоторые изменения – в нем теперь два сервлета.

web.xml

В процессе работы Tomcat не может загрузить библиотеку тэгов JSTL — ее у него нет. Советую найти и загрузить файлы из каталога примеров, который идет вместе с Tomcat — каталог «TOMCAT_HOME/webapps/examples/WEB-INF/lib» — jstl.jar и standard.jar и положить их в <TOMCAT_HOME>\lib (туда, куда мы поместили драйвер для MySQL). Тогда все должно работать хорошо. В принципе можно устанавливать библиотеку вместе с приложением в каталог WEB-INF\lib, но т.к. большинство приложений будет использовать JSTL, то имеет смысл положить библиотеки в общий доступ.

Вот и все, что мне хотелось рассказать о WEB-программировании. Конечно же, мы не смогли просмотреть очень многое, но надеюсь, что Вам стало проще ориентироваться в его многообразии. А пока мы перейдем к несколько иной стороне программирования – к тестированию. Встречайте – Часть 10 — Тестирование с точки зрения разработчика

Я внес исправления и добавил архив с исходным кодом в виде проекта под NetBeans: Исходный код

37 comments to Простое WEB-приложение

  • samsim  says:

    Хороший пример использование данного скрипта. Надо будет как то попробовать самому написать что то подобное. Автору респект!

  • Aleksei  says:

    org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class » for connect URL ‘null’

    • admin  says:

      Я не очень понял вопрос, но есть подозрение, что не указан URL для коннекта. Хотя лучше все-таки боле подробно писать.

  • Aleksei  says:

    такая ошибка возникает при попытке зайти по адресу http://localhost:8080/studentsApp/simple
    Все классы и xml файлы — из примера. Я так понимаю, что Tomcat не может определить где находиться com.mysql.jdbc_5.1.5.jar… Пробовал копировать его в разные директории, но ошибка все время та же…

    • admin  says:

      Я проверял пример, который лежит в виде архива в статье — http://www.java-course.ru/students/Sources/part09.zip
      Лучше прислать просто архив Вашего проекта на почту — я постараюсь посмотреть. Потому что надо смотреть более подробно.

  • Aleksei  says:

    Спасибо! Разобрался! Файл context.xml находился не в каталоге META-INF.

  • AlexanderS  says:

    Добрый день!
    Скачал архив с проектом для NetBeans. Попробовал запустить — всё заработало. Однако возникла проблема с кодировкой: при попытке передать что-либо на русском переданные записи в базе данных и в броузере отображались как знаки вопроса(?). Проблему решил, вставив параметр characterEncoding=UTF-8 в URL к базе данных,т.е пишем:
    url=»jdbc:mysql://127.0.0.1:3306/students?characterEncoding=UTF-8»
    Уважаемый, admin, подскажите, почему без этого параметра текст на русском не отображается нормально, учитывая, что при создании базы данных кодировка utf8 уже была указана (базу создавал, используя код из раздела «База данных»)?

    • admin  says:

      Дело в том, что кроме базы данных, надо указать, что само соединение будет использовать при передаче кодировку UTF-8. По умолчанию используется кодировка cp-1251. Вот и получаются вопросы вместо символов.

  • Баклан Беларускі  says:

    Респект и уважуха автору статей, не смотря на опечатки в тексте и листингах. Пусть воздастся Вам и детям Вашим! 🙂

  • Anton  says:

    А почему конекшен не клозится?

    • admin  says:

      Потому что берем один коннекшен и используем только его. В принципе наверно можно переделать так, чтобы каждый раз брать из пула новый коннект. Но руки не доходят.

      • Alex  says:

        Прежде всего спасибо большое за статью!
        У меня тоже вопрос по коннекшину — действительно, у нас нет кода, который закрывал бы коннекшн, когда мы прекращаем работу с приложением. Скажите, есть ли смысл переопределить в классе ManagementSystem метод finalize и добавить туда con.close(), чтобы коннекшн наверняка закрывался при уничтожении объекта класса?
        А также интересно, сколько будет «жить» сам инстанс класса ManagementSystem?
        Обычно пишется, что объект живет до тех пор, пока на него есть ссылка.
        Но если мы, к примеру, мы зашли в аппликейшн, сделали какое-то действие, а потом ничего не делаем. Т.е. есть период простоя. Когда в таком случае начнут уничтожаться объекты? Или это зависит от сервера?
        Спасибо.

        • admin  says:

          Спасибо за добрые слова и замечание. Я с ним согласен — момент получился достаточно спорным и скорее всего надо переписать на более достойное решение с закрытием коннекта. Но очень не хотелось как-то сильно менять код на тот момент — грешен, поленился. Я очень хочу переписать «Отдел кадров» полностью. Сейчас работаю над разделом «Начала Java», в котором по сути собираюсь разобрать все, о чем говориться в первой книге «Отдела кадров», кроме EJB.
          Т.е. план сделать из «Отдела кадров» сразу профессиональное приложение со сборкой на Maven и сразу с вариантом Hibernate, Spring, EJB. Надеюсь, что до конца следующего года я смогу завершить работу над «Началами» и приступить к совершенно новой версии «Отдела кадров».

          • Alex  says:

            Спасибо за ответ.
            У меня есть еще вопросы по коннекшинам и могопоточности (заранее прошу простить, если скажу глупость или изложение будет сумбурным):
            1. Мы делаем объект класса ManagenetSystem только один (singleton), т.е. одновременно 2 и более пользователей не смогут делать операции в нашем приложении, им надо будет ждать своей очереди, пока объект не разлочится одним пользователем/потоком и не станет доступен другому. Я правильно понимаю?
            2. Если это так, то у нас одновременно будет использоваться только один коннект из пула, а остальные будут резервными, на случай обрыва первого. Так ли это?
            3. Правильно ли я понимаю, что для того, чтобы позволить нескольким юзерам работать с базой, как вариант, можно разбить ManagementSystem на 2 части/класса: 1я — операции чтения данных в БД, 2я — операции редактирования данных. Для первой можно позволить создание нескольких объектов класса, для 2й — синглтон, чтобы избежать коллизий? Это, конечно, все условно, уверен, что есть более валидный способ. Здесь просто хочется понять, насколько адекватна сама идея.
            4. Метод ManagementSystem().getInstance() имеет директиву synchronized. Что в данном случае является потоком? И как долго он живет?
            Т.е., как я понимаю, поток возникает, когда приходит get риквест на сервер (т.е. приходит юзер) и заканчивается после того, как на риквест отправляется ответ. Так ли это?
            Спасибо.

          • admin  says:

            Вы правы — пример сделан не очень хорошо. Так сложилось исторически — пока шли от обычного приложения в вебу.
            Мне уже об этой ситуации писали и я признаю, что просто поленился. Надо переделать, что я очень хочу сделать. Буду стараться.

            Корректно было бы при каждом запросе запрашивать коннект из пула, работать с ним и в конце честно закрывать/отдавать обратно в пул.

  • Esme  says:

    Добрый день, Антон.
    Большое спасибо за огромный труд, который вы проделали, и, надеюсь, вы продолжите эту работу! 🙂 Ваши статьи мне очень помогают в освоении java.
    Хочу сказать, что вплоть до этой статьи я не испытывала особых затруднений в освоении материала. Информация изложена четко, с примерами и комментариями 🙂
    А на этой статье я «застряла». Очень резкий переход от предыдущего материала к новому. Сразу так много новых вещей к изучению , и довольно скудные объяснения.
    Ваш пример у меня почти сразу заработал (единственное, что я изменила – это использование MS SQL вместо MySQL). А вот применение технологий к разработке своего приложения – вот тут пришлось сильно «попотеть» 🙂 И это при том, что предыдущие примеры я тоже «приводила» к своей задаче, то есть аналогичные модули уже были написаны. Если вы возьметесь переписывать статьи, о чем вы говорили выше, возможно, вы учтете мой отзыв.
    Некоторые вещи мне до конца не понятны: почему «вход» должен осуществляется через index.jsp, где прописана ссылка на «главный» сервлет. С главного сервлета можно осуществить переходы на другие страницы (сервлеты). Можно ли организовать несколько «сервлетов», которые работали бы на отдельных страницах?

    • admin  says:

      Спасибо за отклик. Я постараюсь учесть Ваши пожелания.
      По вопросам — в общем-то вход с index.jsp не обязателен, но эта страница может использоваться «по умолчанию», что удобно. И честно скажу — это не самое удачное решение. Я надеюсь, что смогу переписать «Студенческий отдел кадров» в другом виде.

  • Aloe  says:

    Добрый день!
    Спасибо за ваши материалы — очень помогают в освоении java.
    Не подскажите вкратце, как запустить готовое приложение? Его сначала надо собрать а потом положить в томкат?

    • admin  says:

      Спасибо за добрые слова. По поводу вопроса: готовое — это исходники или уже готовый WAR-файл ?

  • Aloe  says:

    Выложенный проект под NetBeans — что нужно сделать, чтобы его запустить?

    • admin  says:

      Если установлен NetBeans, то можно попробовать просто запустить проект — Tomcat сам стартует, установит приложение, стартует его и запустит браузер.
      Второй вариант — собрать WAR-файл, скопировать его в директорию /webapps, потом стартовать Tomcat, убедиться, что Tomcat распаковал WAR в этой же директории, самому запустить браузер и набрать
      http://localhost:8080/studentsApp/

      (studentsApp/ — nочнее надо посмотреть в какую папку распакуется WAR и ее написать в строке браузера)

      • Aloe  says:

        Попробовала запустить — проект успешно собрался, томкат подключен, показывает первую страницу, а при «переходе на главную страницу» выдает:
        java.lang.NullPointerException
        students.logic.ManagementSystem.getGroups(ManagementSystem.java:44)
        students.web.MainFrameServlet.processRequest(MainFrameServlet.java:104)
        students.web.MainFrameServlet.doGet(MainFrameServlet.java:148)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
        javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
        org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
        org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)

        не знаете, в чем может быть проблема?

        • Aloe  says:

          students.sql — запустила, на порту 3306, соединение есть
          не знаю что нетак

          • admin  says:

            Без кода и логов Томката я тоже не смогу ответить на этот вопрос.

        • admin  says:

          Как я понимаю упало на третьей строке из этого куска
          public List getGroups() throws SQLException {
          List groups = new ArrayList();
          Statement stmt = con.createStatement();

          Судя по всему само приложение не получило соединение с базой данных. Надо смотреть логи Томката, чтобы понять, что именно не получилось. Может драйвер не положили, может еще что.

        • Денис  says:

          У меня была аналогичная ошибка.
          Вылечилось изменением в context.xml: validationQuery=»SELECT 1 from dual»
          Правда я работаю с Ораклом.

  • serg1961  says:

    супер курс
    читал взахлеб
    все работает
    для запуска tomcat в последней версии
    исправте config tomcat
    спасибо cyberforum
    :noJuliConfig
    set «JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%»
    ..
    :noJuliManager
    set «JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%»
    to
    :noJuliConfig
    set JAVA_OPTS=%JAVA_OPTS% %LOGGING_CONFIG%
    ..
    :noJuliManager
    set JAVA_OPTS=%JAVA_OPTS% %LOGGING_MANAGER%

  • some8uddy  says:

    Для Tomcat 7 заработало после добавления файла jstl-1.2.jar в каталог WEB-INF\lib. Добавление в TOMCAT_HOME/webapps/examples/WEB-INF/lib не помогало.

  • Александр  says:

    Большое спасибо за статью, до прочтения страшно было лезть в дебри Java для web. Сейчас понимаю в каком направлении хочу развиваться.

    • admin  says:

      И Вам спасибо, что читаете. Удачи.

  • Yury  says:

    Спасибо большое за пример.
    1. Создал пустую базу MySQL students
    2. Изменил context.xml в части паролей и url
    url=»jdbc:mysql://127.0.0.1:3309/students»
    3. Пример запустился в NetBeans 7.2 Но при переходе на страницу main возникают исключения

    type Exception report

    message

    description The server encountered an internal error () that prevented it from fulfilling this request.

    exception

    java.lang.NullPointerException
    students.logic.ManagementSystem.getGroups(ManagementSystem.java:44)
    students.web.MainFrameServlet.processRequest(MainFrameServlet.java:104)
    students.web.MainFrameServlet.doGet(MainFrameServlet.java:148)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
    note The full stack trace of the root cause is available in the Apache Tomcat/7.0.27 logs.

    Лог Томката

    июн 15, 2017 10:14:19 AM org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Servlet.service() for servlet [MainFrameServlet] in context with path [/studentsApp] threw exception
    java.lang.NullPointerException
    at students.logic.ManagementSystem.getGroups(ManagementSystem.java:44)
    at students.web.MainFrameServlet.processRequest(MainFrameServlet.java:104)
    at students.web.MainFrameServlet.doGet(MainFrameServlet.java:148)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

    июн 15, 2017 10:19:27 AM org.apache.catalina.core.StandardWrapperValve invoke
    SEVERE: Servlet.service() for servlet [MainFrameServlet] in context with path [/studentsApp] threw exception
    java.lang.NullPointerException
    at students.logic.ManagementSystem.getGroups(ManagementSystem.java:44)
    at students.web.MainFrameServlet.processRequest(MainFrameServlet.java:104)
    at students.web.MainFrameServlet.doGet(MainFrameServlet.java:148)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:225)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:999)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:565)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:307)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:745)

    Прошу прощения за длинный лог.
    Подскажите пожалуйста в чем загвоздка.

    • admin  says:

      Лучше присылать вопросы такого плана на почту — здесь не очень удобно смотреть и отвечать. И присылайте сразу код — чтобы был материал для просмотра и ответа.

  • Yury  says:

    Спасибо. Если совсем не получится, попробую на почту.
    Мне не стоило весь лог выставлять. Достаточно только этого
    SEVERE: Servlet.service() for servlet [MainFrameServlet] in context with path [/studentsApp] threw exception
    java.lang.NullPointerException
    at students.logic.ManagementSystem.getGroups(ManagementSystem.java:44)
    at students.web.MainFrameServlet.processRequest(MainFrameServlet.java:104)
    at students.web.MainFrameServlet.doGet(MainFrameServlet.java:148)

    Тоесть первым делом возникает исключение в методе
    public List getGroups() throws SQLException {
    на строке
    Statement stmt = con.createStatement();
    класса ManagementSystem

    Думал может потому, что база пустая. Заполнил базу таблицами предложенными в http://java-course.ru/student/book1/database/
    Не помогло. Пока не получается разобраться…
    Версия NetBeans — 7.2 JDK 1.7 Версии 8.1 1.8 соответственно все то же.
    Думаю, по возможности, полезно обсудить данную проблему в комментах к данной статье с примером кода. Наверняка еще кто-то столкнется. Ваш пример web приложения очень хороший. С него можно делать неплохой старт в Java Web.

    • admin  says:

      NullPointerException — судя по всему коннект к базе не создался. Надо посмотреть, что делается в момент установки соединения — может там исключение не обрабатывается и сообщений нет ? Или есть, но вы не обратили внимания.

  • Yury  says:

    Да, похоже нет соединения с базой. Не пойму почему. В NetBeans Tomcat пишет:
    java.sql.SQLException: Cannot load JDBC driver class ‘com.mysql.jdbc.Driver’
    at org.apache.tomcat.dbcp.dbcp2.BasicDataSource.createConnectionFactory(BasicDataSource.java:2138)
    at org.apache.tomcat.dbcp.dbcp2.BasicDataSource.createDataSource(BasicDataSource.java:2032)
    at org.apache.tomcat.dbcp.dbcp2.BasicDataSource.getConnection(BasicDataSource.java:1532)
    at students.logic.ManagementSystem.getInstance(ManagementSystem.java:32)
    Хотя драйвер mysql-connector-java-5.1.40-bin.jar я положил в папку C:\Program Files\Apache Software Foundation\Apache Tomcat 8.0.27\lib\

    Переключил проект на GlassFish Вроде соединение проходит, но теперь другая проблема при том же переходе на http://localhost:8080/studentsApp/main:

    java.io.IOException: Table/View ‘GROUPS’ does not exist

    При этом GlassFish пишет:
    Warning: StandardWrapperValve[MainFrameServlet]: Servlet.service() for servlet MainFrameServlet threw exception
    java.io.IOException: Table/View ‘GROUPS’ does not exist.
    at students.web.MainFrameServlet.processRequest(MainFrameServlet.java:117)
    at students.web.MainFrameServlet.doGet(MainFrameServlet.java:148)

    Что-то с базой не то. Хотя создал базу как обычно, командой mysql -u root -p < students.sql

    • admin  says:

      В первом случае куда-то не туда положен JDBC драйвер для MySQL — проверить надо, где и что.
      Во втором случае нет таблицы — смотрите.

  • Yury  says:

    Переключился на WindowsXP MySQL Server 5.5
    NetBeans 7.2 Apache Tomcat 7.0.27.0
    Проект запустился.
    При переходе на GlassFish Server 3.1.2.1 возникает исключение
    Warning: StandardWrapperValve[MainFrameServlet]: PWC1406: Servlet.service() for servlet MainFrameServlet threw exception
    java.lang.NullPointerException
    at students.logic.ManagementSystem.getGroups(ManagementSystem.java:44)
    Это на строке Statement stmt = con.createStatement(); метода List getGroups() класса ManagementSystem
    — не хочет соединяться с базой.
    Пока не понял в чем хитрость.
    Думаю во время разбора примера прояснится…
    Спасибо.

Leave a reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code class="" title="" data-url=""> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <pre class="" title="" data-url=""> <span class="" title="" data-url="">

Лимит времени истёк. Пожалуйста, перезагрузите CAPTCHA.