Sunday, October 28, 2012

Красивый file upload с jQuery

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

jQuery File Upload 

Проект лежит здесь: https://github.com/blueimp/jQuery-File-Upload
Примерчики здесь: http://blueimp.github.com/jQuery-File-Upload

Пример. Ниже реализована загрузка файла с прогресом. Будет одна кнопка Upload, которая позволит выбрать файл и сразу загрузить его на сервер.

1. Скачиваем.

Скачиваю отсюда https://github.com/blueimp/jQuery-File-Upload/downloads, распаковываю архивчик.

2. Копируем javascript и css файлы в свой проект.

Я буду пользоваться минимальной установкой, поэтому в свой проект копирую только некоторые файлы. Ресурсы моего проекта находятся в папке webapp/resources, в нее копирую следующие javascript файлики из архивчика:
- js/vendor/jquery.ui.widget.js
- js/jquery.iframe-transport.js
- js/jquery.fileupload.js
- css/jquery.fileupload-ui.css

Подробнее о минимальной установке здесь: https://github.com/blueimp/jQuery-File-Upload/wiki/Basic-plugin

3. Добавляем Bootstrap и jQuery

3.1. Файлик с jQuery берем здесь http://jquery.com/download/ и добавляем в проект.
3.2. Bootstrap берем здесь http://twitter.github.com/bootstrap/index.html. Добавляем файлы:
- css/bootstrap.css
- img/glyphicons-halflings.png
- img/glyphicons-halflings-white.png

4. Создаем страничку

Красиво отобразить JSP страничку в блоге не получилось, поэтому даю ссылку на файл jsp.
Полный текст JSP странички можно посмотреть здесь.

5. Пишем сервлет загрузки

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

Wednesday, October 24, 2012

Unit тесты с embedded Jetty

Частенько хочется проверить обращение к внешнему HTTP серверу. Раньше я пользовался встроенным в JDK http сервером (см пакет com.sun.net.httpserver). В этом случае тест работает быстрее, но вытаскивать параметры из http запроса приходилось писать самому.

Я попробовал запустить embedded Jetty сервер в тесте, в котором создать сервлетик, который запоминает приходящие параметры реквеста. Вот что получилось.

Сам тест
Реализация фейкового сервера

Зависимости

Полностью проект можно скачать тут

Интересно
Если будет использоваться асинхронная отсылка http запроса из теста, то синхронизировать сам тест с обработкой запроса можно с помощью метода FakeServer.waitForResponse.
Вот интересная статья про семафоры http://www.baptiste-wicht.com/2010/09/java-concurrency-part-5-monitors-locks-and-conditions/

Friday, October 05, 2012

Динамическая конфигурация Java Security Policy в Jetty

Задача

В рамках моего веб приложения надо умудриться задеплоить еще один war, на котором будет работать какой-то сервлет. Поскольку этот war - это стороннее веб приложение, то надо запретить ему доступ к файловой системе, открытие сокетов и тем более вызывать System.exit.
Подобная задача легко решается в OSGi контейнере (пример на OSGi тут). Но у меня Jetty и необходимо очень тупое простое решение.

Предположим в этом "левом" веб-приложении какой-нибудь умник решил проверить систему на прочность и написал такой код:

Естественно, что при вызове сервлета  System.exit сделает свое дело и погасит мой сервер.

Деплоим стороннее веб приложение

Прежде всего надо убедиться, что модули jetty-webapp и jetty-server подключены к проекту. У меня версия Jetty 8.1.3.v20120416



Дальше пишем код деплоймента веб архива в Jetty

Если задеплоить этот код в любой web container, то как только мы дернем страничку из браузера, то все...

Настраиваем Java security manager

Самый тупой способ, который я нашел - это подставить свою реализацию java.security.policy:
Надо обратить внимание на, что Policy надо устанавливать ДО того, как переопределить SecurityManager, иначе не хватит прав для установки новой Policy :)

Thursday, September 20, 2012

Git: Как пофиксить detached HEAD

Если git при комите ругается, что у вас detached HEAD, то пофиксить можно 4-мя командами:

git branch temp
git checkout temp
git branch -f master temp
git checkout master

И, опционально,
git branch -d temp

Что при этом происходит
1. создаем временную ветку с текущего положения HEAD
2. переключаемся на временную ветку
3. сбросить master до позиции в temp
4. переключиться на мастер
5. удалить временную ветку

Tuesday, September 18, 2012

Tetris coding dojo. Включаем мозг. Включение #0.

О чем это

Сейчас трудно найти программиста, который не знал бы, что такое ТДД или рефакторинг. Трудно найти такого, который еще и применял бы эти практики в жизни. Мне, например, повезло и я ощутил полезность всего спектра так называемых "инженерных практик" в реальной разработке. Многие ребята не могут похвастаться таким везением. Естественно, что не попробовав применить, например, ТДД на практике, сложно сделать какой-нибудь вывод о его полезности.
Конечно же есть масса тренингов по инженерным практикам. Но проблема в том, что практические задания на  подобных мероприятиях довольно простые. На них мы можем только отработать базовые навыки. К тому же приходится давать довольно много теории, рассматривать различныые варианты решения задачи и подводить слушателей к правильным теоретическим выводам. Не хватает практического подтверждения (или опровержения :)) правильности сделанных выводов.
Решение этой проблемы пришло само собой:

Tetris Coding dojo

Вообще Coding dojo - отличное и веселое мероприятие. Мы (я и Саша Баглай) подумали, что это подходящий формат для того, чтобы попрактиковаться в применении своих мозгов навыков в инженерных практиках. Мы одолжили идею coding dojo и сделали свой фреймворк.
За основу взяли известную всем игру - тетрис. Будем учить компьютер играть в тетрис! Мало того, мы еще будем соревноваться в том, кто круче это сделает :)

Думаю, что лучше один раз увидеть, чем написать 100500 слов описания.

Пробное включение

Недавно мы с Сашей попробовали сами написать код управления фигурками. Это мероприятие выбило нас из жизни часа на 4 :). В результате пофиксили несколько багов во фреймворке. Я же научился расставлять "палочки" и "квадратики", сделал несколько небольших рефакторингов и окончательно убедился, что я тестозависим :).

Код тетриса лежит на гитхабе, написан на java. Запускается одной командой (mvn jetty:run). Чуть позже напишу подробную инструкцию (если не поленюсь:)). Велкам с коментами, пожеланиями и участием.

Saturday, September 01, 2012

Вспомнил детство : ZX Spectrum, деревянные игрушки...

Говорят, что нереализованные детские мечты нужно осуществлять, ибо они как-то там мешают во взрослой жизни. Так вот, когда деревья были больше, трава зеленее, а самая навороченная компьютерная игра требовала 48Кб памяти и 0.8 Мгц частоты ЦПУ, у меня была идея фикс - победить злостных инопланетянских роботов-захватчиков в стратегической реал-тайм (!) игрушке "Nether Earth". Я бился в нее сутками, но эти гады все равно беспощадно уничтожали мою базу. Естественно, что это сказывалось на моем эмоциональном состоянии, успеваемости в школе и вообще надо было утереть нос моему товарищу, который эту игру якобы прошел.

Настало время реванша. 

Первым делом нужен эмулятор ZX Spectrum. Их как оказалось довольно много, вот хотя бы список эмуляторов под Видновс.
Но мне не нужны легкие пути, я взял эмулятор под Java  - JSpeccy :). Не беда, что сайт разработчика на испанском, зато он регулярно выпускает обновления (последнее было в июне 2012 года!) в отличие от остальных. 

Найти саму игру тоже оказалось несложно. На сайте Bit 16 я быстро нашел Nether Eath.

Запустил как обычно из командной строки
java -jar JSpeccy.jar 

Круто - появилась строка ввода! Правда в ZX Spectrum она замаскирована под название компании - разработчика ;)

Дальше в меню File->Load... выбираю файл образа игры

Ожидал, что игрушка сразу запустится, но этого, естественно, не произошло :). В Синклере игры считывались с магнитофона, для чего нужно ввести команду LOAD "". Магическое нажатие на клавишу J выдало команду LOAD, а <Ctrl> + P вывел двойную кавычку.

Нажал на <ENTER> и пошла загрузка. Жаль, что звук с магнитофона не сэмулировали :)

Чудесная заставка, офигительный звук :). Без всяких звуковых карт и музыкальных сопроцессоров! Частота колебаний динамика программируется ручками :).


Запрограммировал клавиши, жму старт. Вот она - сила 3D графики! Никаких графических сопроцессоров и видеокарт. Почти "реал 3d" :).

На экране
1. Контрольный модуль, может летать и садиться на базу
2. База

На базе можно создавать роботов из имеющихся деталей. Количество деталей ограничено и поставляется заводами.

Создал первого супер робота

И выпустил его из завода

Роботом можно управлять непосредственно или запрограммировать его поведение.


Варианты поведения
- Пройти вперед / назад
- Найти и уничтожить вражеского робота / фабрику / вражескую базу
- Найти и захватить нейтральную  фабрику / вражескую фабрику / вражескую базу

Я задал команду захватить завод. После того, как робот постоит на заводе 10 сек, завод считается захваченным, о чем свидетельствует появившийсе вверху слева американский флаг :).

Что особенно меня убивало в этой игре - так это управление во время боя. Для того, чтобы повернуться нужно выбрать "Move robot", а дойдя до огневой позиции успеть остановить робота, выбрать оружие для стрельбы и стрельнуть. Жутко неудобно, особенно когда по тебе стреляют несколько вражеских машин.

Вот такая нехитрая игрушка. Для середины 80х это была мега крутая игра. А сейчас даже не верится, что на 48кб можно разместить саму игру с "3д" графикой и звуком.

Кстати, вчера играл 3 часа подряд, но мою базу опять захватили подлые инопланетские роботы :(

Monday, August 20, 2012

Coding dojo. Установка сервера на PHP.

Ниже инструкции для установки локального сервера coding-dojo для Apache (рекомендуемая) и для расширения sockets.

Настройка локального сервера на Apache + php.

Для того, чтобы воспользоваться этой конфигурацией необходим настроенный Apache + php. Как я настраивал можно почитать здесь. 

1. Скачиваем шаблон php скрипта отсюда и подкладываем его в любое место, доступное apache. В моем случае это Z:\home\calculator\www\solver.php 

2. Проверка локального сервера.
Теоретически все готово. Проверить можно, запустив скрипт с примером запроса. Например: http://www.calculator/solver.php?q=what+is+the+sum+of+8+and+27

Должны увидеть тело запроса в браузере. Примерно так:

Рядом с solver.php должен создасться файлик requests.txtс содержимым запроса:

Дальше регистрируем нового игрока. В качестве URL надо ввести адрес, по которому доджо сервер запустит скрипт solver.php. В моем случае это  http://www.calculator/solver.php.
Идем  сюда.

Установка локального сервера, работающего на расширении sockets 

1. Установка локального сервера.
Скачиваем архивчик отсюда. Это содержимое репозитория со старт-поинтами взятый отсюда
https://github.com/bodil/extreme_startup_servers.
Распаковываем (у меня в папку C:\workspace\projects\dojo-startup\extreme_startup_servers).

В папке php/sockets находится 2 файлика : server.php и solver.php

Важно!
Сервер требует расширения php_sockets. Для этого строка extension=php_sockets.dll в файле php.ini должна быть раскоментирована.

2. Запуск локального сервера.
Запускаем server.php из командной строки:
php server.php

Если при запуске не подключается расширение php_sockets, то см. ниже "что делать..."

3. Проверка локального сервера.
Наш локальный сервер запущен. Не мешает проверить как он работает. Для этого в браузере вводим такой линк http://localhost:9000/?q=what+is+the+sum+of+8+and+22.

По идее в консоли должно появится сообщение с запросом и ответом на него:

Если посмотреть содержимое файла solver.php, то понятно почему ответ такой же как и запрос :)

3.1. Немного модифицированный файл solver.php находится здесь. Он записывает все входящие запросы в файлик, что очень удобно во время соревнования.

Дальше  регистрируем наш сервер в системе. Описано здесь.

Регистрация нового пользователя на доджо сервере.

Теперь можем регистрировать наш сервер. Переходим на страничку хоста (http://localhost:3000 или в случае другого компа – IP адрес этой машины), нажимаем I want to play и вводим имя (латинскими буквами!) и URL вашего сервера. 



Если хост смог достучаться до сервера, то увидим примерно такую обнадеживающую надпись

Можем посмотреть результат работы нашей программы. Поскольку мы еще ничего не запрограммировали, то ожидаем примерно такую картинку:
В консоли локального сервера будет примерно такое (в случае с сервером на sockets extension)

В лог request.txt файле будет примерно такое:

В принципе можно уже начинать программировать solver.php так, чтобы он давал адекватные ответы :)

Что делать, если...

Что делать, если не запускается php_sockets?
Если при запуске server.php выдается подобная ошибка, то нужно скачать соовместимую версию библиотеки php_sockets.dll.

Эта ошибка у меня полечилась скачиванием и установкой расширений денвера (http://www.denwer.ru/packages/php5.html).
Второй вариант лечения - скачать zip с пакетом пхп отсюда и скопировать php_sockets.dll в папку расширений php.

Saturday, July 28, 2012

PHP для бабушек. Ставим Symfony.


Что такое Symfony? 
Клевый ответ на этот вопрос на сайте разработчиков: "Symfony - это PHP Web Development framework. Что тут неясно? А если неясно, то проще считай, что это религия!" (framework + philosophy+comunity)
Не веришь? Можешь сам перевести отсюда http://symfony.com/what-is-symfony :)

Попробую пройти "обряд крещения". Как обычно расписано по шагам для старичков с хреновой памятью типа меня :)
Вот инструкция по установке и использованию. Я просто следовал ей.

Я проделывал это на двух компах, у которых путь установки проекта отличается именем замапленного диска. Отсюда и разные пути в тексте и скриншотах.

1. Установка

Модный способ - через композер. Как поставить композер, описано здесь.
В рутовой папке проекта (у меня это w:\home\calculator\www) запустить такое  (я запускал из гитового баша как обычно):

php composer.phar create-project symfony/framework-standard-edition Symfony/

Нифига не заработало на домашнем компе, но заработало на рабочем. Поэтому следующий вариант такой:

Скачиваю отсюда http://symfony.com/download Symfony Standart и распаковываю в рутовую папку. В руте у меня появится папка Symfony
w\
|-calculator
  |-www
    |-Symfony



Запускаю в папочке w:\calculator\www\Symfony (с баш строки как обычно)
php bin/vendors install

далее идет непериводимая игра слов выдаваемых скриптом и гитом.
Появилась папочка vendor. Сюда Symfony понапихивало массу полезностей.
Все эти полезности описаны в файлике Symfony\deps. На 11м слайде презенташки можно увидеть как он выглядит.

Проверяю. Открываю в браузере * http://www.calculator/Symfony/web/config.php. Вижу страничку конфига.
* www.calculator я добавил в файл Windows\System32\drivers\etc\hosts. Подробнее здесь.


Тут он мне предлагает поделать всякие усовершенствования типа поставить акселератор, что-то поменять в php.ini. Естественно забиваю на эти сообщения - они мне жить пока не мешают.



2. Создаю свое приложение.

Тут я перепрыгнул на слайд 32. Сначала хочу создать приложение, а потом залить его в git.

Создаю бандл
в папке Symfony запускаю php app/console generate:bundle

Ввожу имя нейпспейса (Tdd/CalculatorBundle) и имя бандла (Calculator).

Дальше куча вопросов, на которые просто жимаю <Enter>

Бандл - это директория со всем, что нужно для фичи. Вот такое мне сгенерилось:


3. Смотрим на тесты

Генератор бандлов также создал папку с тестами

В ней находится один тест на контроллер

Запустить этот тест вместе со сьютом можно из корневой папки Symfony. Запускаю команду
phpunit -c app/
 параметр -c указывает конфигурационный файл для phpunit.

Почему надо запускать тесты с опцией -c?
Тест на контроллер создает и запускает симфонийский кернел со всеми зависимостями. В файле app/phpunit.xml.dist есть ссылка на bootstrap, который делает предварительную инициализацию окружения. 


Настройки Netbeans для запуска тестов
Чтобы мои тесты запускались прямо в Netbeans я сделал следующее:
- Указал где лежат тесты (окно Project properties, пункт Sources)

- Выбрал phpunit.xml.dist в качестеве XML Configuration для тестов (окно Project properties, пункт PHPUnit)

Теперь мои тесты запускаются также из ИДЕ:


Tuesday, July 24, 2012

Composer - это Maven для PHP?

Вот обнаружил, что на ПХП не так уж все и печально с менеджментом зависимостей. В PHP мире, оказывается существует замечательная штука - Composer.
Вот, например, список пакетов, доступных для скачивания композером  http://packagist.org/packages/. И это только репозиторий композера по умолчанию! Кстати, то что джависты называют репозиторием мавена, в композере называется Packagist.
Composer также позволяет скачивать зависимости из VCS (естественно, что git/github чаще всех встречается в качестве репозиториев PHPшных модулей).

Короче, просмотрев "по диагонали" доку (http://getcomposer.org/doc/) у меня начало развиваться чувство неполноценности мавена, как основного средства менеджмента зависимостей на моих Java проектах :). Вариантов хранения зависимостей - тьма! Можно хранить в VCS, можно в зип архиве на http server'e, также поддерживаются репозитории глобального менеджера зависимостей (PEAR). А хочешь - ставь свой репозиторий и работай с ним. Код packagist'a доступен для всеобщего доступа https://github.com/composer/packagist .

"Хочу купить!" - так сказала бы моя жена, увидев красивую вещь, которая ей очень нужна. И я повторю ее фразу в отношении composer'a.

Итак, приступил к покупке Composer'a :)
Доку как обычно читать буду потом, сразу ставлю:

1. В гитовом баш окне перехожу в Z:\usr\local\php5 (эта папка должна быть доступна по путям)


2. Запускаю такую следующую команду. Как поставить curl можно нагуглить если что.
curl -s http://getcomposer.org/installer | php

3. Для того, чтобы композер запускался из командной строки windows создаю батник composer.bat в z:\usr\local\bin с таким содержимым
php z:\usr\local\php5\composer.phar %*


4. composer.phar уже есть исполняемый файл для баша. Если в баш окне попробовать выполнить composer.phar help, то должно выдаться окно с хелпом


5. Такое же самое окошко с хелпом должно вывестись, если запускать из командной строки windows команду  composer help

Ну поставил, и че теперь?
Теперь я хочу добавить фреймворк Symfony2 в свой проект. Сам этот фреймворк лежит на  http://packagist.org/. Его зависимости разбросаны по всей сети.

1. Создаю новый проект в папке w:\home. Использую свою любимую ИДЕ для этого.

2. В корне проекта создаю файлик composer.json с вот таким содержимым:

То есть я указал, что хочу версию php не ниже 5.3.0 и версию symfony 2.0.16.

3. Инсталлирую зависимости в свой проект. В гитовом окне запускаю
composer.phar install
В моем проекте появилась папка vendor. В нее композер аккуратненько сложил все необходимые зависимости и что самое интересное - сгенерировал скрипт autoload.php.

4. Как использовать зависимости?
В папочке с пхп скриптами (у меня это w:\home\calculator\www) создаю файлик index.php с таким содержимым:
Request - это абстракция реквеста в Symfony. Что-то подобное классу HttpServletReqest из мира джавы.

5. Открываю браузер на страничке http://www.calculator/index.php
Работает. Могу дальше колбасить код :)

Composer позволяет не только устанавливать зависимые модули, но и создавать свои проекты и выкладывать их куда душа захочет (об этом подробнее позже). С помощью него можно так же добавить зависимость на любой проект, который изначально не использовал Composer.
Вот еще классная статья на хабре http://habrahabr.ru/post/145946/

Friday, July 20, 2012

Ставим Pear руками


Хотел поставить Pear по своей инструкции, но в последнем расширении Денвера почему-то нет go-phear.bat. Поэтому пришлось искать альтернативные варианты поиска

1. Скачал go-pear.phar в папку W:\usr\local\php5\PEAR
curl http://pear.php.net/go-pear.phar > go-pear.phar


2. В папке W:\usr\local\php5\PEAR запускаю командуphp -d phar.require_hash=0 go-pear.phar


3. Дальше жму везде ENTER. Много сообщений о том, что что-то инсталлится

4. Потом спросило не хочу ли я проапдейтить php.ini <Y>

5. Установщик подготовил файлик PEARPEAR_ENV.reg, который я внес в реестр

6. Но путь к PEAR все равно пришлось прописать в переменной окружения Path

PhpStorm. Настраиваем IDE и Debug


Недавно нас с Сашей попросили провести тренинг по ТДД на PHP. Следовательно, возникла необходимость срочно ознакомиться с PHP, попробовать разные фреймворки для юнит тестов, моки и т.д. В общем, поделать что-то. Netbeans – классная ИДЕ для ПХП, но я уверен, что PHPStorm лучше и я разберусь с пхп быстрее в нем, хоть он и платный. А evaluation периода мне хватит, т.к. тренинг через 3 недели J

С установкой проблем никаких. Идем сюда https://www.jetbrains.com/phpstorm/download/, скачиваем и ставим.

Чтобы не париться я поставил Денвер. Как это делается, я уже описывал в этом посте.

Не помню откуда я взял это, но здесь https://github.com/DragonBe/zftest  чувак выложил тестовое приложение на пхп с примерами юнит тестов. То, что надо. Клонирую репозиторий git отсюда git://github.com/DragonBe/zftest.git в папочку D:\workspace\projects\php\zftest.

В PhpStorm создаю новый проект

Дальше нужно сказать IDE где установлен PHP. В окне настроек PHP (File->Settings->PHP) ввожу такой путь к PHP : W:\usr\local\php5. W - диск, на который замаунтил денвер.

Немного паники вызвала ошибка "PHP Startup: Unable to load dynamic library", которая вываливалась несколько раз. Но пофиксилось просто:

Открываем файлик php.ini в W:\usr\local\php5 и находим строчку, где указывается extension_dir. У меня она выглядела вот так:

Поменял на нормальный виндовый путь:

И нажал кнопочку "Reload" в настройках PHP.

Дальше попробовал запустить юнит тесты

И получил такой результат:

О том, как поставить PHPUnit я уже писал здесь

А проблему с дебагом пофиксил таким же способом, как и проблему загрузки dll-ек при конфигурации проекта. Т.е. открыл файлик php.ini, нашел настройки xdebug:

и изменил путь на вменяемый: