Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Friday, October 28, 2016

Курс Spring Framework - The Basics

Когда-то давно я создал и вёл курс по основам Spring Framework. Это было где-то одновренно с курсами по Advanced Java. Однако запись курса была в плохом качестве, и поэтому я его не выложил. Чуть позже с помощью компании, где я работаю, мы создали MOOC курс, записав его в студии. Также, я его нормально структурировал, добавил домашнее задания, проверочные тесты и т.п. В общем, всё, чтобы плодотворно учиться. К сожалению, по определенным причинам я не смог его тогда дооформить для youtube и выложить. И вот наконец, этот день настал :)

Данный курс знакомит с базовыми концепциями Spring Framework и его основными модулями: Core, AOP, JDBC. С помощью практических примеров объясняется внедрение зависимостей (dependency injection), определение объектов (beans), их связывание. Курс учит различным способам конфигурации Spring, а также показывает базовые приемы использования базы данных и аспектов (aspects), языка выражений (expression language) и аннотаций.

Курс состоит из 13 видео-уроков (хо-хо, 13!), темы которых такие:

  1. Spring Architecture
  2. Dependency Injection
  3. Bean Naming and Context Start-up
  4. Scopes and Inner Beans
  5. Initialize and Destroy
  6. Context Features
  7. Property Injection
  8. More Context Features
  9. Configuration with Annotations
  10. Expression Language
  11. Aspect-Oriented Programming
  12. Simple Aspects
  13. Simple DB Access

Повествование идет на русском языке, слайды на английском - в конце-концов без него никуда. В этот раз я также добавил субтитры в видео на двух языках. После каждого видео-урока я предлагаю пройти небольшой тест (5-6 вопросов), чтобы просто проверить, как Вы усвоили материал. Вопросы теста на английском :) Ссылка на тест есть в описании к каждому видео.

Как и с курсами Advanced Java, видео-уроки расчитаны на практику. Т.е. предлагается параллельно слушать и писать код. Также, в конце курса будет домашнее задание, где надо будет написать небольшое приложение, приближенное к реальному. На самом деле, домашних задания будет три: по темам 1-10, 11-12, и 13.

Внимательный читатель тут может сказать: "Аха! А ведь уже были лекции по Spring Framework!" Да, лекции были. Но то были только лекции :) В этот раз, информации больше, плюс практика и еще раз практика. И сразу отвечу на вопрос, почему нет еще больше информации. А как же web, security, и другие фишки? Нет, по двум причинам. Во-первых, по другим темам курс я не создавал. Во-вторых, для новичка сложнее всего понять базу. Если он её осилит, то дальше и самостоятельно сможет. :)


Как Вы уже, наверное, знаете, Spring Framework - это один из самых популярных фреймворков для разработки приложений на языке программирования Java. Он обеспечивает всестороннюю поддержку инфраструктуры при создании приложений, и используется миллионами разработчиков по всему миру. Знание Spring является полезным для понимания концепции внедрения зависимостей и способов управления объектами в любом приложении.

Read More...

Wednesday, February 5, 2014

Thursday, September 19, 2013

Многопоточные коллекции в Java

Начиная с версии Java 5 в пакете java.util.concurrent появились реализации коллекций для эффективной работы в многопоточных приложения. Эти коллекции используют различные неблокирующие алгоритмы для достижения высокой скорости чтения/записи значений. Синхронизированный доступ происходит крайне редко и в целом не влияет на производительность. Почти. В зависимости от реализации. :) Рассмотрению таких коллекций посвящен данный урок.

Со списками все просто: единственная существующая concurrent реализация - это CopyOnWriteArrayList. Из названия можно догадаться, как она работает - при изменении создается новая копия списка и, соответственно, происходит блокировка. При чтении блокировок нет. Следовательно, при частых операциях записи или удаления элементов работать будет медленнее, чем даже Collections.synchronizedList(), в котором блокируются все операции, но при этом нет копирования списка. На данном уроке Вы сможете на практике увидеть скороть и медлительность работы этой реализации. Вы напишите мультипоточное приложение, которое определит время чтения/записи значений в разные конкурентные списки.

Учитывая особенности работы CopyOnWriteArrayList, имеет смысл выбирать данную реализацию, только если Вам действительно необходим индексный доступ к элементам, либо в коллекции возможно хранение дубликатов. Данное утверждение справедливо не только к мультипоточным реализациям, а к любым спискам вообще. Если же элементы в коллекции уникальны, и Вам достаточно последовательного доступа, тогда вполне подойдет Set.

Concurrent реализаций интерфейса Set существует две. Первая - это CopyOnWriteArraySet. Свойства такие же, как и у аналогичного списка. Вторая реализация - это ConcurrentSkipListSet. Последняя основана на интересной структуре данных  - слоёный список (SkipList). Подробнее на русском языке Вы можете прочитать на algolist.ru и википедии. Я скажу лишь, что она представляет собой связный список, где вставка и удаление элементов происходит достаточно быстро. Такая структура данных также хорошо подходит для неблокирующего доступа несколькими потоками, ведь, например, для вставки достаточно заблокировать изменение двух соседних элементов в связном списке. В дополнении ко всему, набор ConcurrentSkipListSet хранит значения в отсортированном виде, реализуя интерфейс NavigableSet. При этом, конечно, не стоит забывать о Comparator-е, который будет сравнивать элементы, или интерфейсе Comparable, который они могут реализовывать.

Для использования Map в многопоточной среде существуют два класса - ConcurrentSkipListMap и ConcurrentHashMap. Первая реализация подобна аналогичной для Set. Вторая подобна HashMap, где все пространство значений разбито на независимые области, каждая из которых представляет собой хеш-таблицу. При вставке элемента блокируется только одна область, позволяя параллельные чтение/запись в другие области. Используя этот класс, необходимо помнить о занимаемой памяти, так как для эффектиной работы с несколькими потоками, количество и размеры этих областей быстро растут. Еще одним полезным свойством обоих этих Map есть то, что они реализуют интерфейс ConcurrentMap. В нем представлены методы на основе неблокирующих алгоритмов, позволяющие безопасным образом выполнять проверку и изменение значений в рамках одной атомарной операции. Подобным образом работают атомарные переменные, такие как AtomicInteger и др. Подробнее о них я рассказывал на втором уроке из курса Advanced Java Concurrency.

В качестве домашнего задания для данного урока предлагаю добавить немного “параллелизма” в приложение, написанное для предыдущих уроков:

  • Во-первых, добавьте параллельную загрузку всех праздников в отсортированный Set. Прочитав файл с помощью org.apache.commons.io.FileUtils.readLines(file, encoding), передайте различные области списка нескольким потокам, которые будут парсить праздники и добавлять их в Set.
  • Во-вторых, одновременно с загрузкой и парсингом праздников выполните подсчет количества праздников для каждого дня и каждого месяца. Для этого используйте отдельные Map для хранения того, сколько праздников будет в каждом дне и каждом месяце.
  • В результате выполнения программы выведите наиболее и наименее “праздничный” день, а также количество праздников в каждом месяце.

Ну и, конечно, видео данной урока:

Read More...

Saturday, July 20, 2013

Интересные реализации интерфейса Map в Java

У интерфейса Map из Java Collections Framework есть несколько реализаций, и у некоторых из них есть очень интересные свойства, знание которых поможет Вам эффективно решать определенные задачи. Отличия между двумя распространенными реализациями - HashMap и TreeMap - такие же, как между HashSet и TreeSet (тем более, что последние реализованы на основе первых), и про них я уже рассказывал. В этом видео, я остановился на не-concurrent классах, таких как LinkedHashMap, EnumMap, WeakHashMap.

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

С EnumMap все еще проще - обычный Map, где ключами есть значения enum. Не все это знают, но эффективность хранения элементов и скорость работы намного превышает другие реализации, при использовании перечислений для ключей.

Реализация WeakHashMap основана на использовании слабых ссылок (WeakReference) для ключей. Это позволяет эффективно использовать Map для временного хранения информации, где запись будет удалятся, когда сборщик мусора в Java удалит объект ключа. Для продуктивного и правильного использования этой реализации необходимо понимание механизма ссылок в Java и работы сборщика мусора. Об этом можно почитать, например, тут.

Небольшое домашнее задание для практики навыков работы с этими реализациями:
Необходимо доработать программу, созданную в результате выполнения задания из прошлого поста. Немного изменив shell-скрипт, я сделал так, чтобы теперь в файл holidays.txt дописылась информация о том, какой стране принадлежит праздник. Таким образом, каждая строка в этом файле теперь выглядит следующим образом:

<дата> <название праздника> (<страна праздника>)

Неоходимо дописать парсинг этого файла, чтобы теперь в объект класса Holiday также записывалась страна. Но, так как страны повторяются в файле, то необходимо сделать так, чтобы не создавались новые строки в памяти программы, хранящие одинаковые данные. Поясню дополнительно на примере.

Содержание файла holidays.txt:
2013/10/26 Всероссийский день гимнастики (Праздники России)
2013/6/29 День партизан и подпольщиков (Праздники России)
Прочитав этот файл, программа должна создать 2 объекта класса Holiday. Каждый из них будет хранить ссылки на следующие объекты:
  • разные объекты класса Date
  • разные объекты класса String, хранящие название празника
  • один и тот же объект класса String, в котором будет записано "Праздники России".
Кстати, так как в один и тот же день может быть несколько праздников, то можно сделать так, чтобы объект Date тоже был один для каждого для, в который есть хоть один праздник.

Для реализации это задания необходимо использовать WeakHashMap.
Видео, где я рассказываю про реализации интерфейса Map, их свойства и особенности:

Read More...

Tuesday, July 16, 2013

Использование HashSet и TreeSet

HashSet и TreeSet - две наиболее распространенные реализации интерфейса Set в Java Collections Framework. Первая основана на использовании функции hashCode и структуры данных “хеш-таблица”, вторая - на основе сравнения элементов и структуры данных “бинарное дерево” (точнее красно-черное дерево). Знание и понимание отличий этих структур данных необходимо для любого программиста. К сожалению, многие лишь поверхностно рассматривают их, что приводит к созданию неэффективного кода, а  иногда и к багам. Познакомиться с этими и другими классами коллекций Java можно, посмотрев урок 10 из курса Java для тестировщиков. Для детального изучения необходимо читать дополнительную литературу. В данном видео Вы познакомитесь с некоторыми особенностями этих классов, незнание которых может привести к возникновению ошибок или изобретению новых “велосипедов”.

Я думаю, что некоторым из Вас это видео может показаться неинтересным, не открывшим ничего нового. Это хорошо, что Вы знаете эти темы - подождите следующих видео :) А я буду рад за тех, кто почерпнет что-то полезное из этого материала. Потому что на самом деле, реальные баги в реальных проектах, которые мне пришлось отлавливать, возникли как раз из-за невнимательности (или незнания) при работе с этими реализациями
Set.

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

Написать программу, которая выводит 3 блока информации:
  • список праздников на сегодняшний день
  • список праздников на завтрашний день
  • список праздников на ближайшие 5 дней, не включая сегодняшний и завтрашний дни
Список праздников прочитать при старте программы из этого файла: holidays.txt.zip
Каждую строку в этом файле преобразовать в объект класса
Holiday, который implements Comparable<Date>, и который будет иметь два поля: Date date и String name.
Для хранения объектов
Holiday в памяти использовать TreeSet.
Результат работы программы должен быть приблизительно таким:


#>java package.name.ShowHoliday
Сегодня:
Праздник 1
Праздник 2

Завтра:
Праздник 3
Праздник 4

Скоро:
Ср, 17 июля - Праздник 5
            - Праздник 6
Чт, 18 июля - Праздник 7
            - Праздник 8


Реализовать в программе возможность передать заданный день и количество дней в командной строке. В этом случае вывести все праздники на этот день и на следующее количество дней, оформив вывод так, как сделано в блоке “Скоро” при обычном запуске программы.

P.S. Если вдруг кому интересно, то для формирования файла с праздниками я написал shell-скрипт на bash, который посылает запросы на сайт и парсит праздники с результирующей страницы. Вы можете скачать скрипт и поиграться с ним (нужен Linux): holiday_parse.sh


Ну и, собственно, видео:


Read More...

Monday, June 10, 2013

Курсы Advanced Java

Опыт общения с различного уровня программистами на языке Java - как на собеседованиях, так и просто в дружественной обстановке - показал наличие некоторых пробелов в знаниях особенностей языка, а также его инструментов. В целом, причины этого вполне объяснимы – ведь, если все время программируешь, например, web-интерфейсы, то не будешь особо задумываться над различными способами взаимодействия с базами данных или обеспечения эффективного чтения/записи файлов. Однако, никогда не знаешь, к чему может привести очередной виток в карьере. Поэтому хорошее владение выбранным языком программирования и знание его особенностей просто необходимо, чтобы не изобретать повторно велосипеды и не ощущать удары грабель по уже набитым шишкам. Выделив отдельные темы из области Java Core, в которых было замечено большего всего пробелов, а также которые, возможно, сложны для понимания из-за отсутствия практики, я создал курс Advanced Java, который и представляю Вашему вниманию.

Об основах языка Java я уже рассказал в курсе Java для тестировщиков. Конечно, были затронуты далеко не все темы и многие из них рассмотрены очень поверхностно. Во-первых, этого было достаточно для слушателей, а во-вторых, я считаю, что заинтересованный программист сможет и сам отыскать необходимую ему информацию, главное - показать направление. В курсе Java Практика я постарался рассказать, как писать программы, применяя имеющиеся знания, а также дал различные домашние задания для закрепления материала - ведь ничто не запоминается лучше, чем то, что напишешь сам.

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

Данный курс разбит на пять отдельных мини-курсов, которые охватывают такие темы, как многопоточность (concurrency), коллекции (collections), обобщения (generics), аннотации (annotations), рефлексию (reflection) и сериализацию (serialization). Эти мини-курсы можно изучать отдельно, по каждому из них будет выпущено несколько видео. Единственное, что стоит упомянуть – вторая часть мини-курса по коллекциям посвящена неблокирующим реализациям коллекций (concurrent collections), и ее стоит изучать после мини-курса по многопоточности.

Мини-курс "Advanced Java - Concurrency" знакомит со сложными концепциями многопоточности и параллелизма в языке Java на основе пакета java.util.concurrent. В нем кратко вспоминаются основные механизмы синхронизации в Java, одновременно представляются общие проблемы, связанные с использованием потоков (например, возникновение взаимной блокировки (deadlock)), и показываются эффективные способы их решения. Курс знакомит с высокоуровневыми методами синхронизации с использованием CountDownLatch, CyclicBarrier, ThreadLocal, а также различными Executors для запуска потоков.

Мини-курс “Advanced Java – Collections” посвящен детальному рассмотрению стандартных реализаций интерфейсов Java Collections Framework (hash maps, queues, sets), объясняет их особенности, способы применения и знакомит с некоторыми интересными свойствами, позволяющими повысить эффективность работы с коллекциями в программе, а также избежать возникновения скрытых багов. Вторая часть данного мини-курса знакомит с неблокирующими реализациями коллекций (non-blocking lists and sets, concurrent maps, blocking queues), объясняет разницу между ними, а также на практике показывает их плюсы и минусы, и возможное применение.

Мини-курс “Advanced Java – Generics” подробно рассматривает скрытые проблемы, возникающие при игнорировании женериков, объясняет особенности наследования при использовании классов с обобщенной типизацией, а также показывает, как повысить эффективность кода с применением метасимволов (wildcard) и расширителей обобщения (extends и super).

Мини-курс “Advanced Java – Annotations/Reflection” рассказывает о том, как создавать собственные аннотации, определять их свойства и обрабатывать их с помощью рефлексии (reflection). В дополнении к этому данный мини-курс знакомит с другими часто используемыми особенностями применения Java Reflection API.

Мини-курс “Advanced Java – Serialization” представляет различные популярные техники для сериализации объектов в Java. Рассматривается базовая сериализация с применением встроенных инструментов, объясняются тонкости ее настройки и использования. Кроме того, мини-курс знакомит со ставшей уже встроенной сериализацией в XML с применением JAXB, а также с сериализацей в формат JSON с помощью библиотеки от Google.

Read More...

Monday, November 5, 2012

Java Практика - Занятие 9

На девятом занятии мы практиковались собирать проект с помощью Apache Ant. Про Ant и про Maven я рассказывал на последнем 19 уроке из курса Java для Тестировщиков. В этот раз мы более подробно остановились на создании скрипта сборки, написали скрипт "с нуля" для очень простого Java проекта и рассмотрели основные цели Ant. Чтобы не объяснять все это "на пальцах" и не писать много текста на доске, я воспользовался Eclipse, где сразу в IDE и показывал, как что делать.

Ответ на вопрос, почему именно Ant, а не Maven, достаточно прост: Ant часто используется в проектах  в нашей компании и поэтому оказался востребованным для слушателей курса. Объяснять, что лучше, а что хуже, я не здесь не буду - решите каждый сам для себя, попробовав оба инструмента. Урок по использованию Maven мы, возможно, сделаем, однако пока в планах такого нету.

Скачать исходные файла примера, который был создан на видео, можно по этой ссылке.

Ну и, собственно, видео:


Read More...

Thursday, October 18, 2012

Java Практика - Занятие 8

На восьмом занятии мы рассмотрели работу с XML файлами в Java. Про то, что такое XML, я не рассказывал в курсе Java для тестировщиков и на этом занятии тоже не останавливался — подразумевается, что Вы это уже знаете. Мы рассмотрели три базовых способа взаимодействия со структурными файлами XML: чтение и поиск с помощью SAX, чтение и создание с помощью DOM, и маршалинг и демаршалинг с помощью JAXB. Мы рассматривали работу с очень простыми XML документами без схем или DTD описаний.

SAX-парсер — это самый простой способ чтения XML документа и поиска информации в нём. Однако, в силу своей простоты, обработка чуть более сложных документов (с множеством уровней иерархии элементов) становится очень трудоёмкой задачей. На практике применяется, скорее, для очень простых, либо очень больших по объёму документов. SAX-парсер встроен в саму Java, и никаких дополнительных библиотек для его использования не нужно. На этом ресурсе (англ.) есть простой пример по чтению документа этим парсером. Также, там внизу ссылка на то, как читать UTF-8 XML документ c помощью SAX.

Другой способ чтения XML документов — это использование объектной модели документа DOM. Данный способ позволяет также легко модифицировать и создавать документ. Так как структура XML файлов представлена в виде иерархии, то ее легко отобразить с помощью объектов в Java, где можно выделить родителя (Document) со списком потомков (Element), у которых могут быть свои потомки и т.д. DOM — это программный интерфейс, и существует различные его реализации. В самой Java есть классическая реализация, но большей популярностью пользуется библиотека JDOM. Попросту говоря, в ней больше полезных функций, и поэтому работать с ней легче. Собственно, на видео я приводил примеры функций как раз этой библиотеки. На том же англ. ресурсе есть простые и хорошие примеры как читать XML с помощью DOM и как создавать документ. Также там есть пример, как читать документ с помощью JDOM и создавать его.

Еще одним способом работы с XML документами, который уже можно отнести к классическим — это использование JAXB: отображения XML в Java классы. Раньше, эта технология была доступна при подключении дополнительной библиотеки, но сейчас она уже включена в ядро Java. Суть отображения можно вкратце описать так: приложение, которое обрабатывает информацию, представляет данные в виде иерархии и взаимосвязи различных объектов; определенные поля в этих объектах (которые описаны в соответствующих классах) помечаются мета-информацией (в нашем случае, аннотациями), которая используется JAXB для сохранения значений полей в XML документ, а также для чтения их из документа. Процесс сохранения данных называется маршалингом. Процесс чтения — демаршалингом. Использовать JAXB очень удобно, если цель Вашего приложения — это не работа с XML, а работа с информацией. А так как информацию надо где-то хранить и где-то брать, и если это «где-то» - это XML-файл, то процесс ввода/вывода можно сделать достаточно прозрачным и легко модифицируемым. И снова, тот же англ. ресурс содержит пример работы с JAXB.

Так как XML — это достаточно взрослый формат представления данных, то очень много написано документации по работе с ним на любом языке.

В качестве домашнего задания для данного урока, можно выполнить следующее:

  1. Создать XML документ.
  2. Найти какую-либо информацию в документе с помощью SAX-парсера.
  3. Прочитать весь документ с помощью DOM-парсера (или JDOM) и вывести его на экран. 
  4. Создать несколько взаимосвязанных классов с несколькими полями и отобразить их с помощью JAXB: сохранить XML документ и прочитать его. Для тех, кто выполнял задания из нескольких первых занятий, то можно добавить аннотации к классам Product и сохранить информацию о продуктах в XML.
Ну и, собственно, видео занятия:

Read More...

Monday, September 10, 2012

Java Практика - Занятие 7

Седьмое занятие мы посвятили работе с файлами в Java. Мы рассмотрели базовые операции, такие как создание, удаление, и получение доступа к файлам и каталогам. Немного остановились на потоках, как бинарных, так и символьных, и их использовании для чтения и записи файлов. В конце занятия, я рассказал про библиотеку Apache Commons IO, в которой реализованы полезные методы для работы с файлами и потоками ввода/вывода. И, конечно, домашнее задание для закрепления материала. Про работу с файлами и потоками я рассказывал на уроке 11 из курса Java для тестировщиков, так что начинать изучение темы следует оттуда.

Для доступа к файлам в Java используются классы из пакета java.io. Для реализации высокопроизводительных операций ввода/вывода существуют также классы из пакета java.nio. Однако, их рассмотрение выходит за рамки данного курса. К тому же, я считаю, что разобраться там не составит труда после освоения традиционных способов.

Работу с файлами можно условно разделить на две составляющие. Во-первых, это операции, связанные с доступом и местоположением файлов и каталогов, такие как создание, перемещение, удаление, получение списка (у директории). Во-вторых, это операции чтения и записи содержимого файлов. Для первого случая используется базовый класс java.io.File, а также другие системные классы. Во втором случае используются потоки ввода/вывода. Стандартных системных классов Java часто бывает недостаточно для выполнения необходимых операций с файлами (например, копирование файла), и в таком случае использование сторонних библиотек выручает разработчика, чтобы не "изобретать велосипед" заново. Для работы с потоками в Java есть все, что нужно, хоть часто и приходится писать много сопутствующего кода для корректной обработки всех ситуаций. В данном случае также помогают сторонние библиотеки, предоставляющие методы, которые либо полностью выполняют нужные действия, либо избавляют от необходимости писать блоки стандартных вызовов.

Все операции ввода/вывода, а также методы создания потоков в Java выбрасывают проверяемые исключения. В обязательном порядке их необходимо отлавливать и обрабатывать. Как именно — это зависит уже от приложения, можно просто завершить работу, а можно попытаться восстановить нормальное функционирование с уведомлением пользователя. В любом случае, программист должен решить, что будет делать программа в случае возникновения ошибок ввода/вывода. Для ознакомления с исключениями можно послушать мой урок 9 из курса Java для тестировщиков.

На следующем занятии мы рассмотрим работу с двумя распространёнными типами файлов — properties и XML.

Домашнее задание для этого занятия:

  1. Написать программу, которая читает текстовый файл, состоящий из нескольких строк, и записывает эти строки в отсортированном по длине порядке в другой текстовый файл.

    Например, файл aa.txt, содержит следующие строки:
    World!
    Hello
    And how do you do?
    Созданный файл bb.txt будет содержать эти же строки в отсортированном по длине виде:
    Hello
    World!
    And how do you do?
    Для небольшого усложнения этого задания можно сделать следующее:
    • добавить возможность указывать исходный файл, целевой файл и направление сортировки (восходящая или спадающая) в командной строке, например так:
      java SortFile aa.txt bb.txt asc
      , где SortFile — класс, который мы запускаем, aa.txt — исходный файл, bb.txt — целевой файл, asc или desc — направление сортировки.

  2. Написать программу, которая копирует все файлы из заданного каталога в целевой, при этом переименовывая их в случайном порядке, назначая имена файлам из числовой последовательности от 1 до N, где N — это количество файлов в каталоге. При этом имена файлов не могут повторяться.

    Например, есть каталог, в котором хранятся файлы: a.txt b.txt c.txt Программа копирует эти файлы в другой каталог, назначая им следующие имена: 1.txt 2.txt 3.txt При этом назначение имен происходит случайным образом, т. е. например, a.txt → 2.txt, b.txt → 1.txt, c.txt → 3.txt. Для выбора случайного числа, можно использовать Java класс Random.
Ну и, собственно, видео. Прошу прощения за качество видео - в последний момент сломался мой фотоаппарат и пришлось записывать на телефоны - сначала на один (пока там место не закончилось), потом на второй. Стол, на котором были установлены телефоны, шатался, поэтому видео я обработал стабилизатором от youtube.

Read More...

Sunday, September 9, 2012

Java Практика - Занятие 6

После длительного перерыва, вызванного жарким летом и моим двойным отпуском, мы наконец-то вернулись к занятиям. Так как многие слушатели тоже были в отпуске, и кто-то что-то подзабыл, мы решили немного восстановить знания, обобщить известную информацию и уточнить план дальнейших действий. По просьбе "трудящихся" мы еще раз более подробно остановились на использовании интерфейсов в Java. Я уже рассказывал про это на уроке 5 из курса Java для тестировщиков. Можно рассматривать данное занятие, как дополнительную информацию, либо как подачу информации другими словами. Занятие получилось скорее теоретическим, чем практическим. Домашнего задания по определенным причинам нету :)

Read More...

Thursday, July 12, 2012

Java Практика - Занятие 5

На пятом занятии я решил остановиться на использовании коллекций, как альтернативу применению массивов для хранения наборов данных. Интерфейсы коллекций в Java обеспечивают весь необходимый инструментарий для работы с различными наборами данных, поэтому их употребление, во-первых, повышает скорость разработки программ, а во-вторых, улучшает качество кода за счет повторного использования уже написанного и отлаженного кода. Про коллекции я рассказывал на уроке 10 в курсе Java для тестировщиков. Так как применение коллекций упрощает разбираемый пример, я немного усложнил логику приложения, чтобы сделать ее более интересной. В дополнению к работе над разбираемой задачей в конце занятия было поставлено одна интересная задача для самостоятельной работы.

На этом занятии мы рассмотрели не все интерфейсы коллекций и возможные варианты их использования. Это еще предстоит в будущем. Пока что мы остановились только на интерфейсах Collection, List, Map. Также рассмотрели использование итератора для прохождения коллекции и возможного удаления элементов.

Домашнее задание для этого занятия:
  1. Добавить Map продуктов в класс Deal 
  2. Изменить методы getCost() и getSum(), чтобы они работали, используя Map продуктов. 
  3. Добавить Map свойств в Party вместо массивов keys и value. 
  4. Исправить методы ввода/вывода для работы с Map 
  5. Добавить возможность выбирать ранее введенный продукт при добавлении его в сделку.
Дополнительная задача для развития навыков программирования:
Написать программу, которая заполняет матрицу (двумерный массив) нулями и единицами так, чтобы получился рисунок песочных часов. Матрица обязательно квадратная. Размер матрицы пользователь вводит с консоли.
Например, для матрицы, размером 5х5, должен получиться такой рисунок:
1 1 1 1 1
0 1 1 1 0
0 0 1 0 0
0 1 1 1 0
1 1 1 1 1
Я также написал возможное решение этой задачи, если вдруг кому-то будет очень сложно. Скачать исходные файлы можно тут: JavaPractice05.zip (5,9 KB)

Чтобы откомпилировать и запустить этот пример, выполните следующие команды:
cd <каталог_куда_распаковали_архив>
cd src
javac *.java
java Program5 - это для запуска программы о сделках
java Program5Additional - это для запуска песочных часов 
Также, если Вы уже умеете работать со средой разработки Eclipse, то можете импортировать этот проект в нее и запустить. 


Ну и, собственно, видео занятия:

Read More...

Wednesday, July 4, 2012

Java Практика - Занятие 4

На четвертом занятии мы продолжили разбирать пример из предыдущего урока, немного усложнив его. Основное внимание в этот раз было уделено наследованию: класс Product мы сделали абстрактным и создали два его потомка. Также я показал, как можно использовать переопределение метода для уточнения логики в классе FotoProduct. Также немного поговорили об использовании констант в Java.

Домашним заданием к этому занятию будет сделать все то, о чем мы говорили, а именно:

  • Написать классы FotoProduct и BotinkiProduct
  • Написать методы для расчета скидки
  • Написать метод для расчета стоимости продукта с учетом скидки
  • Добавить поля в классы Product и Party
Также, заданием является сделать программу рабочей после вышеуказанных изменений, а именно:
  • Добавить ввод отдельных продуктов
  • Добавить ввод информации о Party
  • Добавить вывод информации о Party
В качестве дополнительного задания можно сделать следующее:
  • Добавить вывод полей отдельных продуктов
  • Усовершенствовать ввод и вывод, чтобы был более приятным для глаз :)
Обновление: Я в очередной раз написал возможное решение этой задачи. Скачать исходные файлы можно тут: JavaPractice04.zip (4,8 KB). Запуск программы описан в предыдущем посте.

 Ну и собственно видео:


Read More...

Sunday, July 1, 2012

Java Практика - Занятие 3

На третьем занятии мы уже подошли к объектам и проектированию. Я рассмотрел создание программы с позиции объектно-ориентированного дизайна. Бегло прошелся по теме третьего урока из курса Java для тестировщиков, чтобы вспомнить, что такое объект и как с ним работать. Далее мы решали задачу, немного похожую на реальный пример: выделяли объекты, рисовали диаграммы и реализовывали методы. 

На этом занятии я также впервые упомянул про одну из очень полезных книг, а именно книгу по шаблонам проектирования: Приемы объектно-ориентированного проектирования. Паттерны проектирования ("Банда четырёх": Эрих Гамма, Ричард Хелм, Ральф Джонсон, Джон Влиссидс). Я считаю, что каждый программист просто обязан изучить эту книгу и по возможности использовать шаблоны в своих программах. Конечно, это не легко будет делать сразу - понимание, где и какой шаблон лучше применять, приходит с опытом. Также, не расстраивайтесь, если Вы сразу не поймете эту книгу. Продолжайте изучать программирование и больше практикуйтесь писать программы - со временем Вы поймете, насколько мощный инструмент у Вас в руках. Однако, есть небольшое предостережение по поводу шаблонов проектирования: фокусируйтесь на простых решениях проблем, прежде чем сразу браться за применение сложных "рецептов" шаблонов. Так что не забывайте: Keep It Simple :)

Задачу, которую мы решали на занятии следующая:
Необходимо реализовать программу, которая будет позволять вводить сделки купли-продажи товаров между двумя участниками. В каждой сделке может быть несколько товаров, сумма сделки рассчитывается из суммы всех товаров. Сумма каждого товара рассчитывается из его стоимости и количества. Программа должна позволить ввести информацию о сделках, сохранить ее в памяти и вывести на экран. Ввод информацию осуществляется с экрана (консоли). Количество дополнительной информацию о сделке, участнике, товаре придумать самому (больше одного поля для класса). 
Форматы данных для хранения информации, которые я предложил, конечно же, не самые оптимальные. Например, использование массивов вместо коллекций, а также использование double для представления денег. Но это не главное для данного примера. Также, вводить информацию с консоли - это долго и нудно, но это тоже не главное. Я не хотел углубляться в способы представления определенной информации, в способы работы с файлами или базой данных - это все темы следующих занятий. Цель этого занятия - это научится выделять объекты, строить между ними связи и попрактиковаться программировать несложную логику. Поэтому ввод с консоли тут идеально подходит, ведь надо будет подумать, как последовательно все ввести, да еще чтобы это было красиво :)

На видео я вспоминаю про метод keyboard, который позволяет вводить данные с консоли, и который я обещал выслать слушателям. Итак, вот он: 
private String keyboard(String message) {
     System.out.print(message + ": ");
     Scanner scan = new Scanner(System.in);
     String rez = scan.next();
     scan.close();
     return rez;
}
Я также написал возможное решение этой задачи, если вдруг кому-то будет очень сложно. Скачать исходные файлы можно тут: JavaPractice03.zip (3,4 KB)
Чтобы откомпилировать и запустить этот пример, выполните следующие команды: 
cd <каталог_куда_распаковали_архив>
cd src 
javac *.java
java Program
Также, если Вы уже умеете работать со средой разработки Eclipse, то можете импортировать этот проект в нее и запустить. 

В качестве дополнительного задания, можно написать отдельные класс Keyboard, который будет содержать статические методы для ввода строки (String), целого числа (Integer) и дробного числа (Double). Методы по вводу чисел будет проверять, а число ли введено вообще, и выдавать сообщение об ошибке или требовать правильный ввод.

Ну и собственно видео:


Read More...

Saturday, June 16, 2012

Java Практика - Занятие 2

Второе занятие из курса Java Практика я посвятил такому важному для каждого программиста явлению, как выделение части кода в отдельные подпрограммы (функции) с целью их многократного использования и устранения дублирования кода. Само собой разумеется, что эти две причины - далеко не единственные, ради которых используют функции. Однако, наверное, они основные, если не вдаваться в сложные механизмы взаимодействия объектов в Java программе. Дополнительно, я остановился на способах передачи данных в функции. Конечно, пришлось немного забегать наперед, рассказывая про объекты в Java, ведь функции не могут существовать сами по себе (даже статические функции принадлежат классу), но много на объектах я не останавливался. Все-таки, основное, что надо вынести из этого урока - это то, что в программе необходимо выделять логически связанные блоки в отдельные подпрограммы, чтобы повторно их использовать, устранить дублирование кода и сделать программу более понятной и обозримой.

Перед просмотром этого занятия можно посмотреть Урок 4 из курса Java для тестировщиков, где я как раз рассказываю про объявление функций (методов класса), аргументы функций и возврат значений из них. Там, конечно, еще и много чего другого, так что Урок 3 тоже посмотрите, если не совсем понятно, что такое объекты и "с чем их едят".

Из, собственно, практики в этом занятии я немного остановился на заданиях из первого занятия. Также мы рассмотрели, что можно вынести в отдельные подпрограммы в алгоритмах сортировки массива. А также рассмотрели алгоритм бинарного поиска в массиве, реализация которого и есть следующим заданием.

Итак, задания для самостоятельной работы:
  • реализовать еще один алгоритм сортировки массива (отличный от того, что был реализован для предыдущего занятия)
  • реализовать алгоритм бинарного поиска элемента в отсортированном массиве.

Ну и собственно видео второго занятия, которое, кстати, было записано в FullHD :)

Read More...

Saturday, June 9, 2012

Занятия по Java

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

Так как предыдущий курс Java для тестировщиков был в основном теоретическим и ознакомительным, то в этот раз занятия будут проходить следующим образом. Слушатели сначала самостоятельно смотрят уроки на youtube (не все сразу, а по одной или две), потом на занятии я некоторое время резюмирую теоретический материал, на чем-то, возможно, останавливаюсь подробнее или что-то добавляю, отвечаю на вопросы. Далее, я разбираю какую-нибудь практическую задачку, решение которой основывается на полученных теоретических знаниях. Ну и в конце я задаю небольшое задание для самостоятельной работы.

Как и в прошлый раз, видео я буду записывать и выкладывать на youtube, объединяя их в отдельный плейлист. Надеюсь, что наличие практической составляющей поможет многим быстрее и лучше разобраться с Java, тем более, что многие просили о различных задачах в многочисленных комментариях.

Итак, первое занятие из курса Java практика можно посмотреть ниже. Перед просмотром этого видео, рекомендуется ознакомиться с уроком 1 и уроком 2 из курса Java для тестировщиков. Обратите также внимание на комментарии ко второму уроку, где многие поправляли ошибки, которые я допускал. Вообще, некоторые комментарии очень даже хорошие и полезные, особенно от пользователя hazartilirot .

Задания для самостоятельной работы после первого занятия:
  1. Написать программу, которая выдает заданное число из последовательности Фибоначчи. 
  2. Написать программу, которая сортирует массив чисел.
Естественно, при написании программ не желательно использовать встроенные механизмы Java для сортировки или поиска числа Фибоначчи :)

Read More...

Monday, October 24, 2011

javax.net.ssl.SSLException: bad_record_mac

While writing a java net application I've encountered an interesting problem, which solution was not very trivial. The task was to connect to one website, parse the output, and write extracted information to a file. At first glance the task is "a piece of cake", but the problem appeared at the stage of connecting to the web site. The site uses the https protocol, and I had to use something more complex than basic java's HttpURLConnection. I've tried to use java's HttpsURLConnection, but while connecting to the site I received the following exception, which got me stuck me for a while: javax.net.ssl.SSLException: bad_record_mac. Eventually the problem was solved and the solution is described below.

Firstly, I will describe classes that were used to perform the connection. I've decided not to use internal java api directly and to look for some 3-rd party library, because besides connecting to the site, I had to execute some post and get queries to get required information and I wanted to do that with less pain. I chose to use the HttpClient library from Apache commons project. Here is the basic connection example that uses that library:

HttpClient httpclient = new DefaultHttpClient();
try {
    HttpGet httpget = new HttpGet("http://www.google.com/");
    ResponseHandler<String> responseHandler = new BasicResponseHandler();
    String responseBody = httpclient.execute(httpget, responseHandler);
} finally {
    httpclient.getConnectionManager().shutdown();
}

However, it won't work with some https websites. It does work with many of them, but some of them fail with different ssl exceptions. The site I was connecting to firstly failed with the following exception:

javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated

That means that the certificates were not verified correctly. Therefore, I had to implement more complex solution to handle different SSL cases. Here you might look for some other 3-rd party library that will handle secure socket connections by itself, however you might not get the full control. You can use this advice from the HttpClient manual and implement everything on your own. Eventually, everything can work fine OR you might get the exception mentioned at the beginning. If you're lucky one - my congratulations. If not - keep reading :)

In order to get the better understanding I decided to implement everything based on HttpClient and then debug it to see where it fails. I didn't care about checking the certificates and trusting the connection and just wanted to get the page contents. I've used examples from this blog post that I found pretty interesting. Therefore, I've created MyConnectionFactory that extends SSLSocketFactory. It initialized the SSL context with my own TrustManager and then uses it to create secure sockets.

public static class MySSLSocketFactory extends SSLSocketFactory {
    private SSLContext sslContext = SSLContext.getInstance("SSLv3");
    public MySSLSocketFactory() throws Exception {
        super((TrustStrategy) null, new AllowAllHostnameVerifier());
        sslContext.init(null, new TrustManager[] { myTrustManager }, null);
    }
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose) 
            throws IOException, UnknownHostException {
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }
}

I created the implementation of TrustManager that basically does nothing in its methods - so it skipped any security check. In other circumstances its probably not a wise thing to do, but for my task that was enough, so I didn't want to complicate things.

TrustManager myTrustManager = new X509TrustManager() {
    public void checkClientTrusted(X509Certificate[] chain, String authType) 
        throws CertificateException {    }
    public void checkServerTrusted(X509Certificate[] chain, String authType) 
        throws CertificateException {    }
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }
}

Then I put everything together by registering my socket factory for the port 443 connections and then creating the HttpClient with my connection manager. The code to setup HttpClient looks like this:

private static HttpClient setupHttpClient() throws Exception {
    SSLSocketFactory sf = new MySSLSocketFactory();
    SchemeRegistry registry = new SchemeRegistry();
    registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
    registry.register(new Scheme("https", sf, 443));
    ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);
    return new DefaultHttpClient(ccm);
}

With this code I was able to connect to my https website, but I started to get the exception javax.net.ssl.SSLException: bad_record_mac. And that's where all the fun started - looking into Internet and debugging to get the solution.

First of all, I've downloaded source code for HttpClient and started to debug to see where exactly the problem occurs. It was interesting to find out that the problem occurs when the getSession() method is called on SSLSocket. Java performs the SSL handshake and it fails. So, I went to the Internet to find the solution, because very likely the problem was solved before.

Quite interesting looks the following stackoverflow answer to similar question, which says that the problem could be due to the load balancing, when the MAC address changes during negotiation. It could be the reason that the problem occurs sometimes. However, in my case the exception appeared every time, so I continued to search.

Eventually, I found two different sources that pointed out for the reason and how to overcome it: one is the knowledge base article for JIRA client connecting to server, and another is last coderanch answer. The problem appears because Java tries all kinds of secure socket protocols (TLS, SSLv2, SSLv3, etc.) even if only one is supported by the server. This results in the aborted connection. Trapping this error can be hard if you don't have access to the server. But if not the load balancing, then the reason could be either unsupported protocol, or unsupported cipher algorithm.

The solution is to configure Java in such a way that it will use only one secure socket protocol for communication. Therefore, in both createSocket methods of MySSLSocketFactory I've added the following code after creating sockets:

((SSLSocket) socket).setEnabledProtocols(new String[] { "SSLv3" });
((SSLSocket) socket).setUseClientMode(true);

And it worked! That solved my problem. The handshake went fine, the connection went fine, and I was able to do my task. In conclusion, I can say, that while writing this blog post, I could not reproduce the problem. :) So, maybe, it really has something to do with load balancing - I didn't dig into it. In any case, debugging of SSL problems can be tough, so enabling Java net log by calling System.setProperty("javax.net.debug", "all"); can be very helpful.

The testing program with working example with SSL connection can be downloaded here: http://goo.gl/JFdw5

Read More...