barbitoff programmer`s blog

Здесь я публикую заметки из программерской жизни: грабли, на которые мне случилось наступить, проблемы, для которых было найдено элегантное (или не очень) решение, а также все, с чем мне пришлось столкнуться и чем хотелось бы поделиться =)
PS Если хотите меня поблагодарить - на странице есть 3 места, чтобы это сделать =)

суббота, 28 апреля 2012 г.

Java: генерация MD5-хэша

Есть не одна библиотека, обладающая таким функционалом, но если проект использует Spring Security, можно воспользоваться md5-кодировщиком Md5PasswordEncoder оттуда:
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.security.authentication.encoding.PasswordEncoder;

PasswordEncoder encoder = new Md5PasswordEncoder();
String hash= encoder.encodePassword(str, null); 
Вторым параметром encodePassword можно задать salt.

Java: Генерация случайных строк (например, паролей)

Функционал по генерированию случайных строк есть в Apache Commons Lang (http://commons.apache.org/lang/) в классе RandomStringUtils. Он умеет генерировать алфавитные строки заданной длины, буквенно-цифровые и ASCII-строки. Также можно самостоятельно задать набор символов для генерации строки. Полученные строки можно использовать в качестве, например, паролей (не знаю правда, насколько это безопасно).

PostgreSQL: поля serial и "ERROR: duplicate key value" при вставке

Проблема:

При вставке строки в таблицу (пусть она называется "mytable"), использующую поле типа "serial" (пусть оно называется "id", а соответствующий ему ключ - "id_pkey") в качестве первичного ключа, появляется ошибка:
ERROR:  duplicate key value violates unique constraint "id_pkey"
, хотя в запросе явно это поле не задается и вроде бы должно быть автоматически взято из соответствующей последовательности (пусть она называется "id_sequence").

Причина:

Последовательность, используемая для генерации поля "id_pkey", почему-то выдала значение, которое уже есть в таблице. Такое может случиться, например, если в какой-то строке таблице значение "id_pkey" задавалось / редактировалось вручную, в обход последовательности. 

Решение:

Можно просто попробовать повторить вставку на случай, если следующее значение последовательности не приведет к ошибке. Или же восстановить последовательность:
select setval(' id_sequence', (select max( id ) + 1 from  mytable));
Другой вариант - выполнить:
REINDEX INDEX  id_pkey; 
Спасибо http://vasilec.blogspot.com/2010/04/duplicate-key-value-violates-unique.html за подсказку. 

пятница, 27 апреля 2012 г.

Spring Security за AJP proxy

Проблема:

Приложение, использующее Spring Security, находится за AJP-прокси (Apache2 mod_proxy_ajp), которое меняет контекст приложения:
ProxyPass / ajp://localhost:8009/Context/
ProxyPassReverse / ajp://localhost:8009/Context/
Редиректы, генерируемые Spring Security, привязаны к контексту веб-приложения, что вроде бы должно исправляться директивой ProxyPassReverse, однако не работает для  AJP-проксирования (если использовать http, то Apache2 корректно модифицирует контекст при перенаправлениях).

Решение:

Вариантов, в принципе, 3:
  1. Отказаться от AJP-проксирования в пользу HTTP
  2. Разворачивать веб-приложение в корне backend-сервера
  3. Использовать mod_rewrite для корректировки контекста на стороне прокси-сервера:
RewriteEngine on
RewriteRule ^/Context/(.*)$ /$1 [R=301]
Спасибо http://stackoverflow.com/questions/6063339/spring-security-and-ajp-proxy

java.net.URLEncoder.encode и пробелы

java.net.URLEncoder.encode кодирует строку в соответствии со стандартом HTML 4.01, который предписывает заменять символ пробела на "+", а не на "%20", как предписывает RFC3986

среда, 25 апреля 2012 г.

PostgreSQL: просмотр значений пользовательского ENUM-типа

Выполняется запросом:
select enum_range(null::my_enum_type)
, где my_enum_type - имя типа, созданного ранее запросом вроде:
CREATE TYPE  my_enum_type  AS ENUM ('sad', 'ok', 'happy');

Использование карт в конфигурации Spring Security

Задача:

Одному из бинов, используемых в xml-файле конфигурации Spring Security, необходимо установить свойство, передав качестве значения карту (Map).

Решение:

Инициализация карты и её установка в качестве свойства бина делается так:

<beans:bean id="myBeanId" class="my.bean.Class" >
<beans:property name="myMapProperty">
 <beans:map>
<beans:entry key="key1" value="val1"/>
<beans:entry key="key2" value="val2"/>
 </beans:map>
</beans:property>
</beans:bean>
(здесь xmlns:beans="http://www.springframework.org/schema/beans)