05 декабря 2008

Java FX 1.0 релиз состоялся

Вчера, 04.12.2008, состоялся релиз Java FX 1.0. Посмотреть примеры работы, изучить туториалы и скачать SDK можно с сайта http://www.javafx.com/

Sun's JavaFX 1.0 platform opens a vast global market for developers and content authors who want to deploy their content, services and experiences across all the screens of their customers' lives. Worldwide industry estimates show that Java technology is already on more than 90 percent of desktops and laptops, 85 percent of mobile devices and is a technology leader in next-generation televisions, Blu-ray disc players and TV set-top boxes.

Множественные уязвимости в Sun Java JDK и JRE

Обнаруженные уязвимости позволяют удаленному пользователю обойти некоторые ограничения безопасности, получить доступ к важным данным, вызвать отказ в обслуживании и скомпрометировать целевую систему.
Всего 23 уязвимости(SecurityLab)

Решение: Установите исправление

JDK and JRE 6 Update 11:
http://java.sun.com/javase/downloads/index.jsp
JDK and JRE 5.0 Update 17:
http://java.sun.com/javase/downloads/index_jdk5.jsp
SDK and JRE 1.4.2_19:
http://java.sun.com/j2se/1.4.2/download.html
SDK and JRE 1.3.1_24:
http://java.sun.com/j2se/1.3/download.html

Источники:

Sun News Radio

Узнать новости Sun Microsystems можно из первых уст http://www.blogtalkradio.com/stations/sunradio/SunNews

28 ноября 2008

Работа со строками в oracle

Наиболее частая операция, которую необходимо выполнять - это выбор подстроки из строки. Для этого в oracle присутствует специальная встроенная функция substr
например : substr('test string #1', 5, 11 ) , где 1й параметр - это задана строка, 2й - позиция с которой начинается подстрока, 3й(не обязательный) - длинна подстроки.
Если точна позиция начала подстроки не известна , можно воспользоваться функцией instr
Например instr('test string #1', ' ' ) - будет найдено первое вхождение пробела в строку. В функции instr есть ещё третий параметр, который задаёт начало поиска, причём если указать -1 начало будет производится с конца строки.

Другие полезные функции:

ascii('S') - ascii код символа
upper / lower / initcap - преобразования регистра букв в большие / маленькие / первая большая все остальные маленькие.
chr(168) - получения символа по заданному ascii коду
concat('s1','s2') - соединение строк
trim / rtrim / ltrim - отбрасывание пробелов
reverse('12345') - получение строки с символами в обратном порядке
length - длинна строки

23 ноября 2008

Паттерн поведения Observer (наблюдатель)

Наблюдатель (Observer) - паттерн поведения объектов, устанавливающий систему оповещения объектами своих соседей в процессе их деятельности.
Известен также под именами: Dependents (подчиненные), Publish-Subscribe (издатель-подписчик).

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

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

Реализация паттерна поведения Наблюдатель (Observer).

/** Observer design pattern sample
*/

import java.util.ArrayList;
import java.util.List;

public class Child {
// --
List list = new ArrayList();
void addObserver(Observer o){
list.add(o);
}
void removeObserver(Observer o){
list.remove(o);
}
void notifyObservers(){
for (Observer o:list){
o.update();
}
}
// --
void childGrow(int newAge){
System.out.println("Age of child changed to " + newAge);
notifyObservers();
}
public static void main(String []s){
Child ot = new Child();
ot.childGrow(1);
ot.addObserver(new Food());
ot.addObserver(new Toys());
ot.addObserver(new Clothes());
ot.childGrow(3);
ot.removeObserver(new Food());
ot.childGrow(10);
ot.removeObserver(new Toys());
ot.childGrow(15);
ot.addObserver(new Food());
ot.childGrow(20);
ot.removeObserver(new Food());
ot.removeObserver(new Clothes());
ot.childGrow(25);
}
}

interface Observer {
void update();
}

abstract class BaseObserver implements Observer {
public boolean equals(Object obj) {
return this.getClass().equals(obj.getClass());
}
}

class Clothes extends BaseObserver {
public void update() {
System.out.println("Change childs' clothes");
}
}

class Toys extends BaseObserver {
public void update() {
System.out.println("Change childs' toys");
}
}

class Food extends BaseObserver {
public void update() {
System.out.println("Change childs' food");
}
}


Итак, у нас есть класс Child , который описывает модель ребёнка, основное действие - ребёнок растёт : childGrow, и в зависимости от возвраста ребёнка необходимо менять одежду, еду, игрушки - эти сущности описываются классами Clothes, Food, Toys соответственно. Эти три сущности реалиузют интерфейс Observer через класс BaseObserver.
После создания экземпляра класса ребёнка мы можем добавить или удалить специфических наблюдателей, и при достижении ребёнком какого то возраста (вызов childGrow) автоматически произойдёт обновление зарегистрированных в это время слушателей.


Источники:
Ппаттерн наблюдатель
Observer pattern
Speaking on the Observer pattern

22 ноября 2008

Перенаправление системного вывода в файл

Для того что бы выводить информацию из Java программы в файл не обязательно использовать навороченные системы логгирования.
Можно просто перенаправить стандартный поток вывода и стандартный поток для ошибок в файл.
Сделать это можно с помощью следующего фрагмента кода:


PrintStream st = new PrintStream(new FileOutputStream("output.txt"));
System.setErr(st);
System.setOut(st);

20 ноября 2008

Java EE справочник по русски

Java 2 Enterprise Eddition (J2EE)

Обзор J2EE:
Учебник по J2EE (PDF):
Разработчикам:

17 ноября 2008

JScience : Java научная библиотека

JSscience - всеобъемлющая Java библиотека предоставляющая API для научных вычислений. API включает функции для выполнения различных задач из таких областей науки, как : физика, биология, социология, астрономия, экономика, география и др.

Описание некоторых возможностей:
  • Модуль coordinates совместимый с OGC/ISO спецификацией для разработке географических
  • linear algebra - модуль включающий параметризированный класс матрица , позволяющий решать линейные уравнения различной сложности.
  • measurements - модуль для произведения измерений различной точности
  • models - модуль поддерживающий различные физические системы.
  • monetary- модуль для проведения валютных операций из заданой точностью.

Документация(версия 4.3.1)
Скачать библиотеку(версия 4.3.1)

SwisSQL - Oracle to Java Migration Tool

SwisSQL- утилита для преобразования Oracle PL/SQL кода в Java. SwisSQL на вход получает код пакетов, функций, процедур, тригеров и преобразует в Jdbc код.

Туториал построения Spring MVC приложения в Netbeans

http://www.developinjava.com/articles.php?article_id=3

Springmodules

Spring. Модули, дополнения и тулзы интеграции для Spring.

Документация

Последний релиз 0.8 содержит :

15 ноября 2008

Психологический барьер предодолён 100 уникальных посетителей в день.

14 ноября 2008 года Google Analytics показал, что сайт посетило ровно 100 уникальных посетителей. На данный момент это рекорд.
В среднем, за последних 2 месяца количество уникальных посетителей колеблется от 70 до 80 , постоянно увеличиваясь.
Так что продолжу добавлять востребованный контент, для достижения новых рекордов.

12 ноября 2008

Добавление элементов в Java масив

Написал 2 простые функции по добавлению одного или нескольких элементов в конец масива.

public static String[] addToArray(String[] array, String s) {
String[] ans = new String[array.length+1];
System.arraycopy(array, 0, ans, 0, array.length);
ans[ans.length - 1] = s;
return ans;
}

public static String[] addToArray(String[] array, String[] s) {
String[] ans = new String[array.length + s.length];
System.arraycopy(array, 0, ans, 0, array.length);
System.arraycopy(s, 0, ans, array.length, s.length);
return ans;
}

У кого есть более эффективный метод прошу поделиться.

SpringSource покупает G2One

11 ноября, 2008, SpringSource объявили, что он приобрели G2One - компанию которая поддерживает Groovy и Grails технологии.
источник 1(en)
источник 2(ru)

11 ноября 2008

Создание представления в PL/SQL c помощью execute immediate

Вот пытаюсь выполнить PL/SQL код, который должен создать представление в базе данных:
declare
begin
execute immediate 'create or replace force view test_view1 ("f1","F2") as select 0, sysdate from dual;';
end;
/
И получаю совершенно неожиданный результат, а именно исключение:
ORA-00911: invalid character
ORA-06512: at line 3
00911. 00000 - "invalid character"
*Cause: identifiers may not start with any ASCII character other than ...

И это при том, что SQL команда по созданию этого представления успешно протестированна и выполняется без ошибок.
В заблуждение вводит текст исключения, потому что хочется сразу проверить введённое имя представления, хоть оно и правильное. Методом проб и ошибок (точенее одной пробы) удалось установить что вызвало это исключение.
Причина - это точка с запятой указанная после ключевого слова dual ... всё логично, но при такой обработке исключение довольно сложно обнаружить такую ошибку.

И ещё одна заметка на эту тему : названия полей для представлений должны быть написаны большыми буквами!!! Такую ошибку также довольно сложно обнаружить, и притом не на этапе создания представления, а лишь на этапе тестирования, выполняя запросы к представлению.
Например в моём случае , запрос:
seleсt f2 from test_view1 успешно выполниться , в то время как
seleсt f1 from test_view1 сообщит мне что колонки f1 в таблице нету ...

Будьте бдительны).


JavaFX 1.0 релиз в декабре

По сообщению The Planetarium официальный релиз JavaFX намечен на 2 декабря 2008 года.
Напомню, что в начале этого года Sun создал JavaFX Preview SDK для программирования на JavaFX.

о JavaFx

08 ноября 2008

Новые функции в Java Math

Если в проекте много "математики" , то код получается не красивый и сложно понимаемый, приходиться писать множество комментариев , что бы было понятно что к чему.
Но SUN идёт на встречу разработчикам, и в каждой новой версии добавляет всё новые функции в основной математический класс - java.lang.Math

Новое в Java 1.5 :

log10(double a) - логарифм с основанием 10
cbrt(double a) - корень кубический
ulp(double d) - на сколько я понял это модуль разницы между параметром d преобразованным в float и ближайшим по возрастанию double значением. поправьте если я не прав!
signum(double d) - возвращает знак числа: 0, если d=0; -1.0 если d<0;>0;
sinh(double x) - \
cosh(double x) - - гиперболические синус, косинус и тангес
tanh(double x)- /
hypot(double x, double y) - гипотенуза
expm1(double x) - = exp(x) - 1
log1p(double x) - = ln(x+1)

Новое в 1.6
copySign(double magnitude, double sign)
getExponent(double d)
nextAfter(double start, double direction)
nextUp(double d)
scalb(double d, int scaleFactor)

Всё красиво, всё удобно - чего только стоит функция гипотенузы. Но всё имеет свои минусы, тут они также есть.
Если сравнить производительность, например той же функции hypot(x,y)
c более привычным способом получения значения гипотенузы Math.sqrt(x*x + y*y), то получим достаточно интересные результаты, а именно - разница в скорости выполнении различается почти в 100 раз!!! причём как это не удивительно , но не в пользу нововведённой функции.
Итак , мой тестовый класс:

public class RealType {
public static void main(String[] s) throws Exception{
long start1;
int counter = 0;
double temp = 0;
for (int k=0; k<5;>
start1 = System.currentTimeMillis();
for (int i=0; i<1000;>
for (int j=0; j<5000;>
temp = Math.sqrt(i*i + j*j);
counter++;
}
}
System.out.println("Spent time to run sqrt " + counter + " times : " + (System.currentTimeMillis() - start1));
counter = 0;
start1 = System.currentTimeMillis();
for (int i=0; i<1000;>
for (int j=0; j<5000;>
temp = Math.hypot(i, j);
counter++;
}
}
System.out.println("Spent time to run hypot " + counter + " times : " + (System.currentTimeMillis() - start1));
}
}
}

После выполнения я получил приблизительно следующие результаты:

Spent time to run sqrt 5000000 times : 63
Spent time to run hypot 5000000 times : 4109
Spent time to run sqrt 5000000 times : 47
Spent time to run hypot 5000000 times : 4172
Spent time to run sqrt 5000000 times : 47
Spent time to run hypot 5000000 times : 4140
Spent time to run sqrt 5000000 times : 47
Spent time to run hypot 5000000 times : 4157
Spent time to run sqrt 5000000 times : 46
Spent time to run hypot 5000000 times : 4172

Тоесть, скорость выполнения одного вызова функции на моём компьютере занимает 800 наносекунд для hypot и 9 наносекунд для sqrt.
Для того что бы понять откуда такая разница, пришлось порытся в исходниках и посмотреть что собой представляет нативная hypot . Поиски привели меня к hypot_e.c и выглядит он следующим образом:

/*----------------------*/


#include "fdlibm.h"

#ifdef __STDC__
double __ieee754_hypot(double x, double y)
#else
double __ieee754_hypot(x,y)
double x, y;
#endif
{
double a=x,b=y,t1,t2,y1,y2,w;
int j,k,ha,hb;

ha = __HI(x)&0x7fffffff; /* high word of x */
hb = __HI(y)&0x7fffffff; /* high word of y */
if(hb > ha) {a=y;b=x;j=ha; ha=hb;hb=j;} else {a=x;b=y;}
__HI(a) = ha; /* a <- |a| */
__HI(b) = hb; /* b <- |b| */
if((ha-hb)>0x3c00000) {return a+b;} /* x/y > 2**60 */
k=0;
if(ha > 0x5f300000) { /* a>2**500 */
if(ha >= 0x7ff00000) { /* Inf or NaN */
w = a+b; /* for sNaN */
if(((ha&0xfffff)|__LO(a))==0) w = a;
if(((hb^0x7ff00000)|__LO(b))==0) w = b;
return w;
}
/* scale a and b by 2**-600 */
ha -= 0x25800000; hb -= 0x25800000; k += 600;
__HI(a) = ha;
__HI(b) = hb;
}
if(hb <>
if(hb <= 0x000fffff) { /* subnormal b or 0 */
if((hb|(__LO(b)))==0) return a;
t1=0;
__HI(t1) = 0x7fd00000; /* t1=2^1022 */
b *= t1;
a *= t1;
k -= 1022;
} else { /* scale a and b by 2^600 */
ha += 0x25800000; /* a *= 2^600 */
hb += 0x25800000; /* b *= 2^600 */
k -= 600;
__HI(a) = ha;
__HI(b) = hb;
}
}
/* medium size a and b */
w = a-b;
if (w>b) {
t1 = 0;
__HI(t1) = ha;
t2 = a-t1;
w = sqrt(t1*t1-(b*(-b)-t2*(a+t1)));
} else {
a = a+a;
y1 = 0;
__HI(y1) = hb;
y2 = b - y1;
t1 = 0;
__HI(t1) = ha+0x00100000;
t2 = a - t1;
w = sqrt(t1*y1-(w*(-w)-(t1*y2+t2*b)));
}
if(k!=0) {
t1 = 1.0;
__HI(t1) += (k<<20);
return t1*w;
} else return w;
}


Теперь всё становится ясным, такое количество дополнительных проверок не могут обойтись дёшево. Совсем другой вопрос всегда ли нужны они! Решать вам...

Список наиболее часто используемых системных таблиц Oracle

Если быть точнее, то это не таблицы, а представления (view) .

Итак, поехали в алфавитном порядке:


ALL_ARGUMENTS - список всех аргументов по объектам
ALL_CATALOG - список всех table, view, synonym, sequence доступных пользователю*
ALL_COL_COMMENTS - список всех коментариев к колонкам для доступных таблиц и представлений
ALL_CONSTRAINTS - список всех внешних связей
ALL_DB_LINKS - дб линки достпные пользователю
ALL_ERRORS - недавние ошибки возникшие при создании хранимого объекта
ALL_INDEXES - индексы
ALL_IND_COLUMNS - колонки по индексам
ALL_LOBS - колоник по таблицам которые имеют тип LOB
ALL_OBJECTS - все доступные объекты
ALL_OBJECT_TABLES - все доступные таблицы
ALL_SEQUENCES - очереди
ALL_SNAPSHOTS - snapshot
ALL_SOURCE - код хранимых объектов
ALL_SYNONYMS - synonyms
ALL_TABLES - таблицы
ALL_TAB_COLUMNS - колонки для таблиц и представлений
ALL_TAB_COL_STATISTICS - статистика по обращениям к таблицам, представлениям
ALL_TAB_COMMENTS - коментарии к таблицам, представлениям
ALL_TRIGGERS - тригеры
ALL_TRIGGER_COLS - колонки таблиц используемые в тригерах
ALL_TYPES - типы
ALL_USERS - информация о пользователях
ALL_VIEWS - список представлений

DATABASE_COMPATIBLE_LEVEL - параметр совместимости бд, устанавливается в init.ora

DBA_DB_LINKS - все дб линки *
DBA_ERRORS - текущие ошибки при создании хранимых объектов
DBA_OBJECTS - все объекты в бд
DBA_ROLES- все существующие роли в бд
DBA_ROLE_PRIVS - все привилегии
DBA_SOURCE - исходные коды всех хранимых объектов
DBA_TABLESPACES - все пространства таблиц
DBA_TAB_PRIVS - все права доступа к таблицам
DBA_TRIGGERS - все тригеры
DBA_TS_QUOTAS - quotas
DBA_USERS - все пользователи
DBA_VIEWS- все представления

DICTIONARY - коментарии к таблицам и представлениям
DICT_COLUMNS - коментарии к колонкам таблиц и представлений

GLOBAL_NAME - глобальное имя бд

NLS_DATABASE_PARAMETERS - NLS параметры бд
NLS_INSTANCE_PARAMETERS - NLS параметры инстанса
NLS_SESSION_PARAMETERS - NLS параметры сессии

PRODUCT_COMPONENT_VERSION - версии компонентов продукта

ROLE_TAB_PRIVS - таблица привилегий по ролям
SESSION_PRIVS - доступные привилегии текущему пользователю
SESSION_ROLES - роли текущего пользователя
TABLE_PRIVILEGES - привилегии по таблицам

* Вероятно вы заметили что некоторые таблицы (точнее представления) имеют одинаковые названия, но разный префикс - DBA_ и ALL_

В чём же их отличия.

В представлении с префиксом ALL_ содержатся записи, которые доступны только текущему пользователю.

В представлении с префиксом DBA_ такого ограничения нет - тут содержатся абсолютно все записи, но зато к этому представлению имеют доступ только немногие привелигированные пользователи - с ролью SELECT_CATALOG_ROLE.

Полезные запросы к системным таблицам

В системных таблицах оракл так много интересного и полезного. Поделюсь тем чем сам регулярно пользуюсь.
- Список всех оракловых объектов :
select * from all_objects /* where upper(object_name) like '%[NAME]%' and object_type in ('TABLE','VIEW') */;
- Список активных сессий и параметры подключённых пользователей к базе данных:
select sid, username, schemaname, osuser, machine, program,type from sys.V_$SESSION where status = 'ACTIVE';
- Список сессий находящихся в режиме ожидания :
select s.sid, s.username, s.schemaname, s.osuser, s.machine, s.program, s.type,
sw.event, sw.p1text, sw.seconds_in_wait, sw.wait_class,sw.state
from sys.V_$SESSION s, sys.V_$SESSION_WAIT sw
where s.sid = sw.sid
and s.status = 'ACTIVE';
- Последние выполненные запросы в базе:
select sql_text, sql_full_text from SYS.V_$SQL order by first_load_time desc; (первая колонка содержит только первую строку запроса, а вот во второй запрос представлен полностью.)
- SQL&PL/SQL код текущего пользователя в базе : скрипты создание всех таблиц, тригеров, процедур, пакетов и т.д. :
select * from sys.USER_SOURCE order by name , line
(форма представления конечно не слишком читабельная, но немного изменив вышеуказанный запрос можно легко найти где по всему коду встречается то или иное ключевое слово).

01 ноября 2008

Форма обратной связи

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


Ваш вопрос/предложение/замечание:
Имя
Содержание*


Внимание, после отправки сообщения, вы будете переправлены на домашнюю страницу блога!!

31 октября 2008

Лучший Java Web фреймворк


В комментариях можно писать свой вариант.

DarkStar: разарботка MMORG ( онлайн игр ) на Java

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

Так, расскажу немного о внутренностях. В целом это стандартный клиент сервер, который берёт на себя задачу управления. Основное понятие используемое в Darkstar проекте - это задача - Task. Любое действие можно описать с помощью задачи. Пример:
Атака (один игрок атакует - наносит удар другому игроку).
Итак происходит обращение к Task менеджеру с вызовом соотвующей задачи с указанными параметрами. TaskManager в свою очередь лезет в базу данных достаёт необходимые параметры (количество жизни у врага, мощность брони; мощность, ти оружия и т.д.) - за работу с базой данных отвечает PersistanceManager. На основе извлечённых данных производиться рассчёт силы удара и результат - нанесённое повреждение: опять обращение к PersistanceManager и сохранение в БД. Осталось разослать эту информацию игрокам участвующим в схватке - не проблема - TaskManager обращается к ChanelManagerу и обновлённые данные получают все игроки. Итак три слона держащие мир Darkstar это TaskManager , PersistanceManager и ChanelManagerу , можно и свой написать, но это только в очень искушённых проектах.
Подробности на сайте сообщества. Там много примеров, хорошая документация и всё что нужно для разработки.

Try it now.

Links:
About
Project Darkstar community

25 октября 2008

Java презентации

Обнаружил тучу Java презентаций на сайте parleys.com . В презентациях охватывается большинство тем связанных с javа : от fundamentals до java ee фреймворков.
Взяты презентации из популярнейших Java конференций : JavaPolis, BeJUG, SpringOne, JaZoon, JavaZone and EclipseCon

У сайта есть также свой подкаст : parleys.libsyn.com где можно прослушать доклады по презентациям в mp3 формате.

Наслаждайтесь.

P.S. Всё оформлено очень красиво и по взрослому: в одном окне слайды презентации , во втором видно докладчика...как будто сам присутствуешь на конференции. Особенно удобное их десктоп приложение, которое скачивается на этом же сайте.

JAD : Java декомпилятор

Jad - java декомпилятор, программа которая читает один или больше Javaклассов и преобразует их в исходный код(по личной практике сообщу, чтокод получается почти такой же как и до компиляции), который можно будетповторно скомпилировать.
Jad написан на чистом С++, поэтому работает в несколько раз быстрее чем декомпиляторы написаны на Java.
Использовать просто:

jad example1.class

Но , jad по умолчанию выдает декомпилированным файлам расширение jad, что бы избежать этого , можно использовать опцию -s :

jad -sjava example1.class


Если надо декомпилировать набор классов, можно воспользоваться командой:

jad -o -r -sjava -dsrc tree/**/*.class


(**) - значит что декомпиляция будет производиться во всех поддиректориях папки tree.

JAD

20 октября 2008

Spring Security : хранение пользователей в БД. часть 2

Предварительно прочитать:
SS: хранение пользователей в БД. часть 1
В этой части мы рассмотрим возможность объеденения ORM фреймворка (например hibernate) вместе со Spring Security. При этом будут использоваться аннотации.
Итак, lets go.
Если вы желаете хранить пользователей в своих таблицах, а не предлагаемых SS-ом и желаете обращатся к ним с помощью hibernate? тогда вам надо:

1) Реализовать интерфейс UserDetailsService, в котором аж одна функция loadUserByUsername. У меня этот интерфейс обращается к моим dao классам , с помощью которых и извлекает информацию о пользователях, например:
@Component
@Transactional
public class UserServiceImpl implements UserDetailsService {
    @Autowired
    UserDao userDao;
    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException, DataAccessException {         
        return userDao.get(username);
    }
}


Особенность, обратите внимание , что функция loadUserByUsername возвращает не абы-шо , а некий объект UserDetails. Это между прочим тоже интерфейс.

2) Реализовать интерфейс UserDetails. SS рекомендует воспользоватся стандартным классом org.springframework.security.userdetails.User , в котором уже реализован этот интерфейс, но этот вариант далеко не всем подойдёт.
Если таки не подойдёт, надо реализовать несколько простых стандартных функций не представляющих большой интерес, аля: getUsername, getPassword, isEnabled, isCredentialsNonExpired, isCredentialsNonExpired, isAccountNonExpired. Причём последние 4 возвращают ложь или правду. Гораздо интересней функция getAuthorities(), а точнее то что она возвращает, а возвращает она массив GrantedAuthority... это между прочим тоже интерфейс, который нам придётся реализовывать :).

3) Реализовать интерфейс GrantedAuthority. Что это за интерфейс , и что это за единственная функция getAuthority() , которую надо реализовать? GrantedAuthority - это привилегия, роль, полномочие, ограничение которое получает пользователь на выполнение того или иного действия. Как задавать набор действий для каждой определённой роли в общем рассматривалось в первой заметке по SS , и более подробно будет рассматриватся в дальнейшем.
Основные используемые роли :
ROLE_ADMINISTRATOR, ROLE_USER, ROLE_SUPERVISOR, ROLE_WE_DONT_HAVE, ROLE_TELLER, ROLE_ANONYMOUS
Каждый пользователь может обладать не менее чем одной ролью. Поэтому в бд лучше всего иметь одну таблицу для данных пользователя и вторую для ролей. Первая таблица связана со второй в отношении один ко многим.

4) Последний штрих. Все классы написаны, осталось только настроить конфигурацию, для того, что-бы использовался нужный сервис получения пользователей. Это можно сделать в applicationContext-security.xml сделующим образом:
Регистрируем бин с классом реализующем UserDetailsService интерфейс:

    <beans:bean id="myUserDetailsService" class="path.to.UserServiceImpl" />   

В authentication-provider указываем какой сервис использовать для получения данных о пользователях:

    <authentication-provider user-service-ref='myUserDetailsService'/>

  Это всё.

Spring Security : хранение пользователей в БД. часть 1

В предыдущей заметке по Spring Security (SS) я рассмотрел пример использования SS. Пример был примитивный, ориентированный исключительно на знакомство с SS.
Теперь более подробно рассмотрим вопрос хранения данных о пользователях. В первом примере эти данные были забиты раз и навсегда в xml файл и как либо оперировать ними было невероятно трудно. Более привычный способ хранения пользователей - это база данных.
В SS реализован UserDetailsService, который позволяет получать информацию о пользователях посредством jdbc подключения к базе данных, для этого достаточно в конфигурации зарегистировать бин:
<bean id="userDetailsService" class="org.springframework.security.userdetails.jdbc.JdbcDaoImpl">
  <property name="dataSource" ref="dataSource"/>
</bean> 
 

Где в качестве dataSource используется бин настроек подключения к бд, например:
   <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
  <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>
  <property name="url" value="jdbc:hsqldb:hsql://localhost:9001"/>
  <property name="username" value="sa"/>
  <property name="password" value=""/>
</bean>


При это в базе данных должна существовать следующая схема: таблицы users и authorities, а также внешний ключ.
  CREATE TABLE users (
  username VARCHAR(50) NOT NULL PRIMARY KEY,
  password VARCHAR(50) NOT NULL,
  enabled BIT NOT NULL
  );
 
  CREATE TABLE authorities (
  username VARCHAR(50) NOT NULL,
  authority VARCHAR(50) NOT NULL
  );
 
  ALTER TABLE authorities ADD CONSTRAINT fk_authorities_users foreign key (username) REFERENCES users(username);

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

18 октября 2008

Опрос. Какие технологии вас интересуют больше всего?



Пример использования Spring Security в Web приложениях


Вступление


Не так давно Spring анонсировала свою новую разработку Spring Security. Это модуль для услуг безопасности, который должен заменить Acegi Security для всех Spring приложений.
Acegi очень популярный фреймворк для безопасности, обладающий обширной функциональностью:
- аутентификация и авторизация пользователей
- контроль доступа
Spring Security унаследовало всё лучшее от Acegi, а также обзавелось новыми фичами(features) :
- совместимость с OpenID, NTLM, LDAP аутентификация;
- поддержка аннотаций согласно стандарту JSR-250;
- упрощения в использовании;
- поддержка дополнительных языков;
и многие другие.

Пример

Что бы показать на сколько просто использовать Spring Security рассмотрим простой пример.
Для начала вам понадобиться любое простое Spring MVC веб приложение. В одном из более ранних постов я приводил примеры туториалов. Хотя, идеальной подойдёт пример petclinic , который поставляется в zip архиве spring-framework with dependencies.
Также нам понадобиться zip архив Spring Security 2.0.X , а точнее библиотеки из него.
Из которого надо в WEB-INF\lib скопировать следующие библиотеки:
spring-security-core-2.0.4.jar
spring-security-core-tiger-2.0.4.jar
spring-security-acl-2.0.4.jar
spring-security-taglibs-2.0.4.jar

И ещё одна библиотека от apache:
commons-codec-1.3.jar

Ещё необходимо создать конфигурационный файл для Spring Security в папке WEB-INF :
<!-- applicationContext-security.xml -->
<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.1.xsd">
<!-- alot of config will be here -->
</beans:beans>


Шаг следующий - настройка web.xml , где мы должны подключить конфиг для Spring Security:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/applicationContext-security.xml
</param-value>
</context-param>

Здесь же в web.xml сразу после закрытия тега /context-param добавляем фильтр:

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

И последний шаг - настраиваем доступ к страницам, указываем для SpringSecurity на какие странице можно заходить анонимно, а на которые доступ получат только авторизированные пользователи. Добавляем в aplicationContext-security.xml следующий код:
<http auto-config="true">
<intercept-url pattern="/*.do" access="ROLE_USER" />
<intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
</http>

В этом же файле создадим парочку пользователей:
<authentication-provider>
<password-encoder hash="md5"/>
<user-service>
<user name="rod" password="a564de63c2d0da68cf47586ee05984d7" authorities="ROLE_SUPERVISOR, ROLE_USER, ROLE_TELLER" />
<user name="dianne" password="65d15fe9156f9c4bbffd98085992a44e" authorities="ROLE_USER,ROLE_TELLER" />
</user-service>
</authentication-provider>

Можно тестировать. Запускаем сервер и пытаемся открыть домашнюю страницу, ваш запрос должен быть перехвачен и вместо данных вывестись форма с предложением ввести свои данные. Вы можете попробовать ввести
логин: rod , пароль: koala
либо
логин: dianne , пароль: emu
и увидеть ожидаемую страницу.
Ещё не помешает добавить кнопку для выхода из аккаунта, лучше всего в шаблон, например в header :
<table class="header">
<tr>
<td><a href="<c:url value="/welcome.do"/>">Home</a></td>
<td align="right"><a href="<c:url value="/j_spring_security_logout"/>">Logout</a></td>
</tr>
</table>

Оригинал: статья 1 , статья 2.

17 октября 2008

Open Source - сборники народных сказок

Решил поискать в истории некоторые аналоги для "open source" и os сообщества. И такой аналог нашёлся - народный фольклор: песни, танцы, музыка, притчи, истории, баллады и многое другое то что народ копил многие годы, передавая от родителей к детям. И творили люди свои шедевры не за деньги, а потому что им по настоящему нравилось то что они делают. Гениальные произведения мало вероятно, что удастся найти среди народных, но много хорошего, приятного для души очень много. Хорошо что кроме творящих ещё находятся люди, которые собирают эти произведения воедино, только благодаря ним к нам доходят сборники сказок, притч, песен ... творчества народа.

В опен сорсе наблюдается кое что аналогичное, только вот слово народ заменили более модным "комьюнити". А сборники народного творчества в опен сорсе пользуются особой популярностью. И что-бы некоторым пост не показался абсолютно бесполезным, размещу ка я ссылки на такие народные опен-сорс сборники:

http://sourceforge.net/
http://koders.com/
http://code.google.com/
http://java2s.com/
http://java-source.net/
http://www.exampledepot.com/
http://www.planet-source-code.com/
http://www.codebeach.com/
http://www.osalt.com/

Ну, думаю достаточно.

P.S. Жаль только что в список не попал не один славянский сайт, хоть люди у нас далеко не последние творят , а получается как и с народным фольклором - за-рубежом считается что русская народная музыка - это хор Красной армии.

16 октября 2008

15 октября 2008

Динамический HTML список c использованием jQuery библиотеки


Допустим есть у вас html список (или таблица) с несколькими элементами , например:

<ul id="list_cheloveg">

<li id="174">
    <a class="link_cheloveg" href="read.html?id=174">Andrej Vanjiradjan1</a>
    <a class="dialog_edit" href="edit.html?id=174">Edit</a>
    <a class="delete" href="delete.html?id=174">Del</a>
</li>

<li id="175">
    <a class="link_cheloveg" href="read.html?id=175">Andrej Vanjiradjan2</a>
    <a class="dialog_edit" href="edit.html?id=175">Edit</a>
    <a class="delete" href="delete.html?id=175">Del</a>
</li>

<li id="176">
    <a class="link_cheloveg" href="read.html?id=176">Andrej Vanjiradjan3</a>
    <a class="dialog_edit" href="edit.html?id=176">Edit</a>
    <a class="delete" href="delete.html?id=176">Del</a>
</li>
</ul>


И вам надо добавить в конец ещё один элемент , либо отредактировать какой то из существующих. Найболее часто такая задача встречается при отправке запросов через Ajax, и ответ как раз и должен обновить таблицу.

Из 10 статей найденых в гугл, 9 предлагают использувать функцию getElementById, и с помощью неё установить HTML код конкретного элемента, например:

document.getElementById("176").innerHTML = '<li id=177> <a class . и т.д. копи пастим весь html c новыми атрибутоами.. </a></li>';

способ достаточно простой, но очень не красивый, тем более если это не список, а таблица в которой больше 10 столбиков.
Библиотека jQuery, позволяет эту задачу выполнить гораздо элегантней.

Шаг 1. скачиваем библиотеку и подключаем к странице:

<script type="text/javascript" src="jquery.js"></script>

Шаг 2.пишем javascript функцию, которая будет получать новые аттрибуты, обрабатывать их и обновлять таблицу.
Например, в моём случае список - это люди: уникальный id, имя и фамилия:

<script type="text/javascript">
function updateList(id,firstName,lastName) {
    var oldId   = $('#list_cheloveg li').attr('id');
    var oldText = $('#list_cheloveg li:last .link_cheloveg').text();
    var oldHtml = $('#list_cheloveg li:last').html();
    for (i=0;i<3;i++) { // id used 3 times in row    
        oldHtml = oldHtml.replace(''+oldId,''+id);
    }
    oldHtml = oldHtml.replace(oldText,firstName + ' ' + lastName);
    var newHtml = '<li id=' + id + '>' + oldHtml + '</li>';    
     if ( document.getElementById(id) == null ) {         
        $('#list_cheloveg').append(newHtml);
    } else {
        document.getElementById(id).innerHTML=newHtml;
    }
}
</script>

Что же делает эта функция? Она выбирает последнюю строку(последниц элемент списка) из таблицы,
создаёт 3 переменных, в которых сохраняет уникальный id, имя+фамилию , и старый html код который мы будем редактировать.
Панализировав список, можно увидеть, что нам надо заменить 3 раза уникальный id и один раз имя+фамилия. Это мы и сделали с помощью стандартной функции replace. Далле мы проверяем весь документ и исчем запись с новым id , если не находим, значит добавляем элемент в конец списка, как новую строку, если находим значит заменяем его.

Протестировать єтот пример можно с помощью двух ссылок:

<a href=# onclick="updateList(194,'textA','textB');">add</a>
<a href=# onclick="updateList(174,'textAA','textBB');">update</a>

P.s. Если скопируете весь html код из этого сообщения в один файл , и сохраните его в какую то  папку, и в эту же папку добавите jQuery библиотеку jquery.js , то сможете успешно протестировать то что я описал в посте.

Получение в Java коде номер строки и имя выполняемого файла

Во время отладки приложения наиболее часто используется вывод с помощью System.out.println(). Иногда, приходиться добавлять достаточно большое количество таких выводов, что бы понять процесс выполнения приложения и для каждого из выводов надо придумывать свой уникальный текст, что бы потом по тексту найти нужное место в коде.
А что если выводить на экран имя файла, метода и номер строки который в данный момент выполняется. Это автоматически обеспечит уникальные сообщения для каждого вывода System.out ,  а также позволит легко и быстро размножать такие выводы в коде. Вывод будет выглядеть приблизительно так:

System.out.println(getCodePoint());

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

public static String getCodePoint() {
    StackTraceElement ste = Thread.currentThread().getStackTrace()[2];
    return ste.getFileName() + ":" +
           ste.getClassName() + ":" +
           ste.getMethodName() + ":" + 
           ste.getLineNumber();
}


Магия и ничего более :).

14 октября 2008

Как получить состояние любого локального / удалённого java процесса

Данная задача является особенно актуальной для серверной части, где у вас на одной машине может в фоновом режиме выполнятся несколько Java процессов.
Для того что бы определить как выполняется определённый процесс надо знать его pid (process Id). Вы можете получить его из диспечера задач (в windows) , команд ps или top в линуксе, но поиски этим методом могут занять не мало времени.
Существует специальная команда, получающая список всех работающих процессов на определённой JVM :
$JAVA_HOME/bin/jps

Первая колонка - это и есть pid запущенных Java процессов.
C помощью следующей команды мы сможем получить stacktrace (характеристику текущего состояния) всех запущенных процессов, либо определённого процеса :

$JAVA_HOME/bin/jstack
[pid]

GWT & Spring MVC & Hibernate(JPA). Web приложения из 3х частей

Нашёл интересный пример (аля туториал) как собирать веб приложение в связке : GWT + Spring + Hibernate c JPA .
Пример достаточно прост , но довольно подробный. Разработка приложения разбита на 3 части.
Первая часть. Создаём в нашей IDE GWT проект. Создаём нужные конфиг файлы, пишем GWT код , и компилируем в две JavaScript библиотеки.
Вторая часть. Создаём Spring MVC + Hibernate проект. MVC приложение - создаём нужные конфиг файлы, контроллеры, представления. Интегрируем библиотеки из части 1 в проект.
Часть 3. Создаём классы по работе с БД. Используем Hibernate проект с JPA аннотациями.

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

туториал смотреть тут (язык англ.)

13 октября 2008

Интернационализация и локализация в Spring MVC

Интерфейс ApplicationContext расширяет интерфейс называемый MessageSource , который предоставляет функциональность по интернационализации приложений. (Подробней)
Существует две реализации описанного интерфейса : StaticMessageSource и
ResourceBundleMessageSource . Если быть точнее они реализуют не сам MessageSource, а его дочерний класс HierarchicalMessageSource, который кроме прочего позволяет иерархически обрабатывать сообщения.
StaticMessageSource - тяжёлый в использовании, но позволяющий програмно добавлять сообщения в список заготовленных сообщений, что далеко не всегда нужно.
ResourceBundleMessageSource рассмотрим болле подробно с помощью примера:
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames">
<list>
<value>format</value>
<value>exceptions</value>
</list>
</property>
</bean>

Тут мы зарегистрировали бин, который будет искать messages в двух файлах:

format.properties
errors.properties

Это файлы используемые по умолчанию, но если в вашем броузере установлена какая то специфическая локализация ,

то сначала будут искатся файлы характерные для этой локализации ,
например для украинского языка:
format_uk.properties
errors_uk.properties

для немецкого
format_de.properties
errors_de.properties

и так далее ..

Все выше перечисленные файлы необходимо разместить в CLASSPATH.
В каждом из файлов в столбик записаны код сообщения и их значения для определённого языка.
Например
# в файле 'format.properties'
message=Hello world message!

Или пример по сложнее:
# в файле 'errors_uk.properties'
argument.required=Поле '{0}' є обов`язковим для заповнення

Для того что бы вывести эти сообщения на jsp странице используется тег spring:message .


В результате получаем вполне понятное сообщение об ошибке для украинской локализации:
Пример из файла error_uk :
Поле Address є обов`язковим для заповнення

10 октября 2008

UKраина или UnitedKingdom. Правильная локализация

Каждый современный браузер предоставляет возможность выбрать язык по умолчанию или даже несколько языков, и проставить среди них приоритеты.
В FF это можно сделать с помощью меню Инструменты - Настройка - Содержимое - Языки - Выбрать.
В Опере - Инструменты - Настройки - Языки - Настройки
В ИЕ : Свойства обозревателя - Общие - Языки

В общем то ничего необычного, удобно и практично. Но это предистория, фишка в другом. Доменные имена для страны Украина заканчиваются на .UA, на номерах присутствуют буквы UA.
Так почему же в настройках локализации, сокращение для украинской локализации UK ? Мне не понятно. Видимо в разработке этого стандарта из Украины никто не участвовал , да из Великобритании тоже.

P.S. Возможно некоторым этот пост показался глупостью, не имеющим значения. Но это не так, почему это не так, я опишу в одном из следующих сообщений где буду рассказывать как происходит локализациия приложений в современных веб фрэймворках, в частности в Spring Framework.

09 октября 2008

Spring MVC. Преобразование данных

Spring MVC: Failed to convert property value of type [java.lang.String] to required type ...

Вот такую ошибку вы получите если захотите создать html форму с текстовым полем , а пожелаете сохранить этот текст, в класс Date (например).

Сделать это можно с помощью следующего кода
Контроллер:

//...
setupFormWithDate(ModelMap model){
java.util.Date nowDate = new Date(System.currentTimeMillis());
model.addAttribute("someDate",nowDate);
return "form";
}
//...

Представление:

<!-- ... -->
<form:input path="${someDate}" />
<!-- ... -->


Решается такая проблема довольно просто. При инициализации необходимо рассказать спрингу как реагировать на поля в которых мы вводим данные типа дата.

@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}

В SpringFramework существует специальный класс CustomDateEditor , в котором
реализована логика преобразования нашего объекта типа Date в строку и наоборот. Первый параметр в конструкторе CustomDateEditor формат представления даты как строки, в нешем случае год-месяц-день. Этот класс позаботиться что-бы nowDate из первого примера, преобразовался в
указанный формат и вывелся на форму, при отправке формі на сервер, текстовое значение поля someDate будет также обрабатывать класс CustomDateEditor и преобразует его в правильную дату.
Второй параметр определяет допускаются ли пустые значения в этом поле.

Более сложный вариант, когда мы хотим вывести в текстовое (либо другое) поле значение, которое не принадлежит к классу созданному нами.

Например у нас есть класс Address:
class Address {
int zip;
String country;
String region;
String city;
String street;
String house;
int floor;
int flat;

public String toString(){
return ""+zip+":"+country+":"+region // + ...
}
}
и есть класс User у которого есть домашний и рабочий адреса. Предположим, что
выделять 16 полей на форме под адресса мы не хотим, потому что они будут занимать слишком много места.
Не проблема, создадим 2 поля, назовём их workAddress и homeAddress.
Теперь нам нужен некий Custom Editor, который будет знать как преобразовывать из тектового значения в класс Address и наоборот.
Так как стандартного такого для нашего класса нет и не будет, то создадим свой. Этот класс должен расширять java.beans.PropertyEditorSupport и перегрузить один из его методов , а именно : setAsText. Назовём наш редактор : AddressPropertyEditor.
P.s. обратите внимание, в классе Address я уже создал стандартный метод (toString) , который преобразует объект Address в строку, где все члены разделены двоеточием. Но это же можно было сделать и в классе AddressPropertyEditor, с помощью перегрузки метода getAsText.

Наш редактор свойств будет выглядеть приблизительно так:
class AddressPropertyEditor extends PropertyEditorSupport {

@Override
public void setAsText(String text) {
Address address;
// начало логики преобразования из строки в Address
// TODO text.split(':')
// check if text is correct , throw exceptions if it's not
// TODO address set properies
// конец логики преобразования из строки в Address
setValue(address); // устнавливаем значения типа Address
}

Остался последний штрих. По аналогии с регистрацией CustomDateEditor, надо
зарегистировать редактор для преобразования нашего адресса:

@InitBinder
//...
binder.registerCustomEditor(Address.class, new AddressPropertyEditor());

P.s. Пример с адресом я выбрал конечно яркий, но не реальный.
Другой хороший пример(который я только что придумал).
В одно текстовое поле добавляется List<String> - список текстовых значений. Например список тегов к сообщению в блоге вводиться именно таким образом.

08 октября 2008

File Uploading with Spring Framework

Наверное ни один веб портал не может обойтись без такой операции как загрузка файлов на сервер.
Особенно актуальная єта задача для больших веб приложений, которые разрабатываются в основном на java ee.
В  этой заметке я рассмотрю как осуществляется аплоад файлов при использовании Spring фрэймоврка 2.5 (с использованием аннотаций).

Сначала нам необходимо зарегистрировать специальный бин - MultipartResolver, который будет сканировать все запросы к серверу и искать формы с типом multipart (т.е. с файлом для загрузки на сервер). Если такая форма найдётся этот бин передаст её для дальнейшей специальной обработки в сервлет MultipartHttpServletRequest, который и закачает наш файл.
<!-- MultipartResolver for parsing file uploads, implementation for Commons FileUpload -->
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
Всё это Spring сам делать не умеет, но хорошо это умеет делать Apache Commons FileUpload,
функциональность которого и вызывается через Spring Framework. Так что необходимо подключить commons-fileupload.jar и commons-io.jar библиотеки.

Настройка завершена, теперь код.
Создаём jsp страничку с multipart формой и единственным параметром file типа file. Назовём её например uploadFile.jsp:
<form action="uploadFile.html" method="post" encType="multipart/form-data">
  <tr>
      <td>Content</td>
     <td><input type="file" name="file"><br></td>
  </tr>
  <tr>
      <td colspan="2"><input type="submit" value="Upload file"></td>
  </tr>
</form>
 
Создаём класс контроллера.
Нам необходимо обрабатывать минимум 2 запроса. Первый - для отображения формы, через которую будет производиться загрузка файла, второй для обработки непосредственной загрузки файла (submit формы).
Например:
@Controller
class UploadController {

    @RequestMapping(value = "/file.html", method = RequestMethod.GET)
    public String setupUploadFile(){
        return "uploadFile";
    }
   
    @RequestMapping(value = "/uploadFile.html")   
    public String processUploadPreview(
            @RequestParam("file") MultipartFile file
            ){
      // Сохраняем файл на диск...
      // Содержание загруженного файла можно получить с помощь:
      // file.getInputStream()
      // имя и расширения файла можно извлечь из свойств
      // file.getName() , file.getContentType()
        return "redirect:index.html";
    } 
}


Это всё. Можно переходить к тестированию.

Аспектно ориентированное программирование: Основы

В своём блоге Антон Наумов подробно рассказывает о основах АОП и принципах его применения вместе со Spring Framework. link

Если этого вам оказалось мало, более развёрнутый взгляд на AOP  можно услышать в интервью с исследователями из Siemens (Christa Schwanninger & Iris Groher ) : link2
We discuss the fundamentals of AOP, define many of the relevant terms
and also look at how and where AOP is used in practice, as well as at
some current research trends.

P.s. если вы не поняли что написано выше, на ссылку2 нет смысла нажимать, интервью на англ. языке.

06 октября 2008

Java подкасты

Теперь скучать во время поездок в транспорте любителям Java не придётся. Вашему вниманию предоставляется список подкастов, которые могут быть интересны Java программисту.
The Art of programming - подкаст о программировании на русском языке, много внимание уделяется Java и сопутствующим технологиям.

Java Posse - известнейший Java подкаст на англ. языке, уже более 200 выпусков.

ZDot podcast - ещё один подкаст на англ. языке посвящённый в основном Java EE технологиям (есть несколько интересных выпусков по JSF и hibernate).

JavaOne podcast - подкаст на англ. языке посвящённый конференции JavaOne

Радио-Т
- подкаст на русском языке об ИТ в целом, тут можно услышать достаточно проффесиональный взгляд на новинки технического мира.

05 октября 2008

Поиск обновлён

Строка поиска размещённая на этом сайте в колонке справа теперь ищет только по ресурсам имеющим непосредственное отношение к Java и сопутствующим технологиям. Список сайтов постоянно обновляется.

P.s. Если хотите что-бы и ваш сайт/блог попал в избранный список, пишите об этом в комментариях.

01 октября 2008

Разместить баннер бесплатно!

Если вы владелец информационного ресурса, каким либо образом связанного с ИТ в целом и с программированием (java) в частности, я готов разместить ссылку или красивый баннер на ваш сайт в своём блоге, причём совершенно безвозмездно, тоесть даром. Пишите.

22 сентября 2008

Программировать весело. Утилиты для знакомства с Java

В этой заметке расскажу о двух утилитах, которые помогут начинающим программистам познакомиться с Объектно ориентированным программированием в целом и с Java в частности.
Первая утилитка - Greenfoot. Предназначена для школьников средних и старших классов. Программа делает программирование весёлой забавой. В ней вы можете создать простенькое 2D приложение с помощью красивого и удобного графического интерфейса. С большой вероятностью она породит интерес к программированию даже у тех детей, которые раньше им не увлекались.
Более подробный Greenfoot туториал на английском языке.
BlueJ - интегрированная Java среда разработки для студентов ВУЗов, которые только начали изучать Java. Основной упор в утилите сделан на построение ООП приложения. C помощью BlueJ вы познакомитись с понятиями объекта, метода, поля. BlueJ предоставляет простой графический интерфейс для построение диаграммы классов. Также в приложение встроен редактор кода, компилятор, дебаггер и даже виртуальная машина для тестирования вашего приложения.
Подробный туториал на русском языке по BlueJ


Рис.1 BlueJ

Перед запуском перечисленных программ не забудьте скачать и установить J2SE 5 либо 6 версию.

Десктоп приложение со встроенной БД

Patrick Keegan подробно рассказывает как создать своё приложение со встроенной базой данных, в качестве среды разработки выбран NetBeans, в качестве базы данных Derby.

продолжение на английском...

19 сентября 2008

Анализатор Java объектов

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

Objectreferenceanalyser (ORA) графическая утилита позволяющая :
- Рассмотреть архитектуру анализируемого приложения;
- Обнаружить ошибки или недочёты в архитектуре приложения;
- Обнаружить и предотвратить утечки памяти тем самім повісив производительность приложения;
- Увидеть зависимость между объектами/модулями в приложении.




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

Если же вы захотите протестировать свой код с помощью ORA, вам придётся найти ключевое место в своей программе - точка входа , где все объекты уже проинициализированны и созданы. Найти корневой класс/объект опираясь на который вы желаете произвести анализ и добавить три строчки в свой код:

//1. You have to instantiate a Analyser: AnalyserInterface ref = new ObjectReferencesCore("SomeIdentifier"); //2. You have to pass the to be analysed root object to the analyzer (mostly you pass some main components which hold important data): ref.addAndAnalyseRootObject(MyRootObject); //3. You have to start the visualizer to be able to see something new Visualizer(ref).start();


Более подробное описание и способы применения на страничке программы:
http://refanalyse.sourceforge.net/

18 сентября 2008

Sametime Risk. Java стратегия

Sametime Risk

Жанр: стратегия
Мультиплеер: присутствует
Лицензия: бесплатно
Графика: 4/10
Играбельность: 9/10

Стратегия с простенькой графикой написанная полностью на Java. Целью игры является захват мира.
Изначально Земля пропорционально разделяется между всеми игроками. А дальше начинается самое интересное.
Каждый игрок поочерёдно ходит и пытается захватить территории соперника. Захват может осуществляться если на вашей территории больше 1 единицы войск. Как и в реальной войне, так и в этой игре имеет место случай. Но больше рассказывать не буду. Скачивайте бесплатно игрушку с SourceForge и наслаждайтесь замечательным гэймплеем.





22 августа 2008

Tips! События в Java FX

Рассмотрим следующий кусочек кода :
Ellipse
{

centerX: 10, centerY: 10
radiusX: 150, radiusY: 50

stroke: Color.GREEN
onMouseClicked: function( e: MouseEvent ):Void {
// (1)do smth ... }
Если добавить этот код во Frame, будет нарисован эллипс с зелёным ободком, а при нажатии на него клавишей мыши выполниться некоторое действие (1). Но есть существенное НО : нажимать надо не в эллипс , а исключительно на зелёный ободок , что - бы что то произошло. Понятно, что это очень не удобно. Исправить данную "фичу" можно довольно просто:

Ellipse {
centerX: 10, centerY: 10
radiusX: 150, radiusY: 50
stroke: Color.GREEN
fill: Color.WHITE
onMouseClicked: function( e: MouseEvent ):Void { // (1)do smth ... }

Как видите я просто заполнил эллипс белой краской , визуально ничего не изменилось, но все собітия onMouseXxxx будут теперь отрабатывать не только для оботка, но и для всего эллипса.

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

import javafx.application.*;
import javafx.scene.geometry.*;
import javafx.scene.paint.*;
import javafx.input.*;
var Rad:Integer = 10;
Frame {
title: "Test onMouseXx application"
width: 200 height: 200
closeAction: function() {
java.lang.System.exit( 0 );
}
visible: true
stage: Stage
{

content: [
Circle
{

centerX: 100, centerY: 100

radius: bind Rad stroke: Color.GREEN //fill: Color.WHITE onMouseClicked:
function( e: MouseEvent ):Void {
if (Rad == 50)
{
Rad = 10; }
else
{
Rad = 50; }
}

}
]
}

}

15 августа 2008

JavaScript библиотека jQuery

Ни одно юзабельное веб приложение не сможет обойтись без богатого веб интерфейса, который легко реализовать с помощью JavaScript и, например библиотеки jQuery:
jQeury: плавающий dialog box,
jQuery и Ajax,
jQuery: drag-and-drop сортируемый список,
таблица с помощью jQuery,
colorPicker: выбор цвета,
jQuey Treeview - древовидное меню,
jQuery Ajax форма,
Валидация данных в Ajax форме
и много других интересных статей по jQuery тут.

30 июля 2008

JavaFX - первое приложение

Для начала необходимо скачать и настроить компилятор.
Скачать последню версию компилятора можно по ссылке : archive.zip(12Мб)

- распакуйте архив в удобную для вас папку
- добавьте полный путь к папке openjfx-compiler\dist\bin\ в перменную PATH

Откройте текстовый редактор и создайте в нём файл HelloWorld.fx

import javafx.application.Frame;
import javafx.application.Stage;
import javafx.scene.text.Text;

Frame {

title: "Hello JavaFX Script"
width: 300
height: 100

stage:Stage {
content: [
Text {
x: 100, y: 30
content: "Hello world"
}
]
}

visible: true
}

Сохраните файл, скомпилируйте и выполните его с помощью следующих команд:

>javafxc HelloWorld.fx
>javafx HelloWorld

Внимание, на вашем компьютере должно быть установлено JDK версии не менее 1.6 для успешного работы Java FX.

Итак, приложение создало окно (Frame) указанных размров c заголовком Hello JavaFX Script и текстом Hello world посреди окна.

Другие римеры на Java FX
Tesla Demo
SVG to Java FX Translator Demo
(примеры загружаются через Java Web Start)

Source:
Open Java FX
JavaFX по русски

23 июня 2008

Spring MVC

Spring MVC - это реализация шаблона MVC (модель - представление - контроллер) в Spring Framework.
Используется для создания Web приложений.
Для создания приложения первого приложения вам не помешает скачать
необходимые библиотеки из оффициального сайта Spring.
Во время написания заметки самой новой версией была 2.5.4 ею и предлагаю воспользоваться.
Также вам на первых порах не помешают следующие библиотеки:
commons-logging-1.1.jar
jstl.jar, standard.jar
Свой "hello world" я создавать не буду, таких достаточно в интернете, напрмер
можно воспользоваться одним из следующих туториалов:
http://mhimu.wordpress.com/2007/11/27/spring-mvc-tutorial/ (англ.)
http://artamonov.ru/2006/03/15/prostoe-prilozhenie-na-spring/ (рус.)