<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2russianfull.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Andrey Yasinetskiy@Software Development</title>
	
	<link>http://yasinetskiy.com</link>
	<description />
	<lastBuildDate>Mon, 29 Mar 2010 09:36:41 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/AndreyYasinetskiysoftwareDevelopment" /><feedburner:info uri="andreyyasinetskiysoftwaredevelopment" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:emailServiceId>AndreyYasinetskiysoftwareDevelopment</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><feedburner:feedFlare href="http://add.my.yahoo.com/rss?url=http%3A%2F%2Ffeeds.feedburner.com%2FAndreyYasinetskiysoftwareDevelopment" src="http://us.i1.yimg.com/us.yimg.com/i/us/my/addtomyyahoo4.gif">Subscribe with My Yahoo!</feedburner:feedFlare><feedburner:feedFlare href="http://www.newsgator.com/ngs/subscriber/subext.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FAndreyYasinetskiysoftwareDevelopment" src="http://www.newsgator.com/images/ngsub1.gif">Subscribe with NewsGator</feedburner:feedFlare><feedburner:feedFlare href="http://feeds.my.aol.com/add.jsp?url=http%3A%2F%2Ffeeds.feedburner.com%2FAndreyYasinetskiysoftwareDevelopment" src="http://o.aolcdn.com/favorites.my.aol.com/webmaster/ffclient/webroot/locale/en-US/images/myAOLButtonSmall.gif">Subscribe with My AOL</feedburner:feedFlare><feedburner:feedFlare href="http://www.bloglines.com/sub/http://feeds.feedburner.com/AndreyYasinetskiysoftwareDevelopment" src="http://www.bloglines.com/images/sub_modern11.gif">Subscribe with Bloglines</feedburner:feedFlare><feedburner:feedFlare href="http://www.netvibes.com/subscribe.php?url=http%3A%2F%2Ffeeds.feedburner.com%2FAndreyYasinetskiysoftwareDevelopment" src="http://www.netvibes.com/img/add2netvibes.gif">Subscribe with Netvibes</feedburner:feedFlare><feedburner:feedFlare href="http://fusion.google.com/add?feedurl=http%3A%2F%2Ffeeds.feedburner.com%2FAndreyYasinetskiysoftwareDevelopment" src="http://buttons.googlesyndication.com/fusion/add.gif">Subscribe with Google</feedburner:feedFlare><feedburner:feedFlare href="http://www.pageflakes.com/subscribe.aspx?url=http%3A%2F%2Ffeeds.feedburner.com%2FAndreyYasinetskiysoftwareDevelopment" src="http://www.pageflakes.com/ImageFile.ashx?instanceId=Static_4&amp;fileName=ATP_blu_91x17.gif">Subscribe with Pageflakes</feedburner:feedFlare><feedburner:feedFlare href="http://www.live.com/?add=http%3A%2F%2Ffeeds.feedburner.com%2FAndreyYasinetskiysoftwareDevelopment" src="http://tkfiles.storage.msn.com/x1piYkpqHC_35nIp1gLE68-wvzLZO8iXl_JMledmJQXP-XTBOLfmQv4zhj4MhcWEJh_GtoBIiAl1Mjh-ndp9k47If7hTaFno0mxW9_i3p_5qQw">Subscribe with Live.com</feedburner:feedFlare><feedburner:feedFlare href="http://lenta.yandex.ru/settings.xml?name=feed&amp;url=http%3A%2F%2Ffeeds.feedburner.com%2FAndreyYasinetskiysoftwareDevelopment" src="http://lenta.yandex.ru/i/addfeed.gif">?????? ? ??????.?????</feedburner:feedFlare><feedburner:feedFlare href="http://www.addtoany.com/?linkname=Andrey%20Yasinetskiy%40Software%20Development&amp;linkurl=http%3A%2F%2Ffeeds.feedburner.com%2FAndreyYasinetskiysoftwareDevelopment&amp;type=feed" src="http://www.addtoany.com/addfr-b.gif">Add to Any Feed Reader</feedburner:feedFlare><item>
		<title>Идеальный финансовый менеджер</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/_YQBebjykX8/</link>
		<comments>http://yasinetskiy.com/2010/03/ideal-finance-manager/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 09:31:37 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[Онлайн-сервисы]]></category>
		<category><![CDATA[Разное]]></category>
		<category><![CDATA[finance]]></category>
		<category><![CDATA[management tool]]></category>
		<category><![CDATA[online service]]></category>

		<guid isPermaLink="false">http://yasinetskiy.com/?p=159</guid>
		<description><![CDATA[После длительного испытательного срока, проб и ошибок, матюков и слов благодарности, пришел к мнению, что меня совершенно не устраивает положение, которое сложилось в области финансовых менеджеров. 
Большинство из них делятся на: тупые, совсем тупые, не для людей, с невероятно странной логикой, слишком сложные и запутанные.
Поработав в течении года с системой 4konverta, ничего кроме раздражения не [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://yasinetskiy.com/files/personal-budgeting.jpg" align="left" hspace="10">После длительного испытательного срока, проб и ошибок, матюков и слов благодарности, пришел к мнению, что меня совершенно не устраивает положение, которое сложилось в области финансовых менеджеров. </p>
<p>Большинство из них делятся на: тупые, совсем тупые, не для людей, с невероятно странной логикой, слишком сложные и запутанные.</p>
<p>Поработав в течении года с системой <a href="4konverta.com">4konverta</a>, ничего кроме раздражения не испытывал. Вроде и сделано толково, интерфейс приятный и задум не плохой, но блин, зачем нужно было делить месяц на 4 недели и соответственно 4 конверта, и подвязывать под это всю остальную логику работы с личными финансами?!</p>
<p>Приведу пример, пусть ваш месячный доход (допустим зарплата) составляет 10 000 грн. Как правило, между получением этого дохода проходит месяц, что в системе можно легко настроить. Однако после внесения этой суммы в качестве регулярного дохода она будет поделена на 4 недели, что само по себе меньше! В итоге, в остатке у вас будет написана сумма ≈ 9333 исходя из которой будут рассчитаны все 4 конверта на месяц в перёд.</p>
<p>Лично меня такой подход в корне не устраивает. Я хочу видеть всю сумму, текущий остаток (хотя в последней версии это таки было интегрировано) и оперировать финансами не привязываясь к &#8220;конвертам&#8221;, а исходя из расчета финансов на месяц вперёд.</p>
<p>Вот несколько критериев:</p>
<ul>
<li>Мой расчетный период ровно месяц, а не неделя</li>
<li>Даже если поступает доход в середине месяца он всё равно попадает на общий месячный баланс</li>
<li>Если я формирую финансовую цель, значит я изначально знаю какую сумму откладывать ежемесячно. Я не откладывю &#8220;понедельно&#8221; по 478 грн. 66 коп.</li>
<li>У меня есть регулярные траты (например оплата коммунальных услуг, интернет и т.д.), которые не привязаны конкретно к первой или второй неделе месяца. Эти траты просто существуют и сумма на них перманентно выделяется в самом начале (тут даже планировать нечего, эту сумму нужно просто вычесть!).</li>
</ul>
<p>Исходя из всего этого, сформирую список требований к системе, которой бы я хотел пользоваться:</p>
<ul>
<li>Хочу заносить дневные траты автоматически. Например, просто сканируя чек своим мобильным телефоном.</li>
<li>Подстройка логики учета финансов под отдельно взятую ситуацию.</li>
<li>Возможность отклаывать на финансовые цели не привязываясь к дате. Захотел в начале месяца всю сумму, захотел 4 раза по разу в неделю &#8211; пожалуйста.</li>
<li>Интеграция с платежными системами и с моей платежной карточкой.</li>
<li>Работа параллельно с несколькими счетами.</li>
<li>Настройка финансовых инструментов. Например есть у вас депозит приносящий определенный процент в месяц или акции или недвижимость. Было бы здорово подстроить под это отдельный счет, который будет автоматически пополняться.</li>
<li>Различные виды отчетов. Детализация по категориями трат.</li>
<li>Умный планировщик/помощник, помогающий оптимизировать траты.</li>
</ul>
<p>И завернуть всё это в интуитивно понятный и удобный интерфейс.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=_YQBebjykX8:h3j-jUuV2p0:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=_YQBebjykX8:h3j-jUuV2p0:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=_YQBebjykX8:h3j-jUuV2p0:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=_YQBebjykX8:h3j-jUuV2p0:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=_YQBebjykX8:h3j-jUuV2p0:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/_YQBebjykX8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2010/03/ideal-finance-manager/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2010/03/ideal-finance-manager/</feedburner:origLink></item>
		<item>
		<title>Настройка связки Glassfish / MySQL / Spring</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/jdMLaDR18_E/</link>
		<comments>http://yasinetskiy.com/2010/03/setting-up-glassfish-mysql-spring/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 11:30:45 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Базы данных]]></category>
		<category><![CDATA[Фреймворки]]></category>
		<category><![CDATA[glassfish]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://yasinetskiy.com/?p=149</guid>
		<description><![CDATA[Намедни понадобилось перевести свой старый проект на Glassfish. Проект построен на SpringMVC, и как не сложно догадаться в качестве главного хранилища данных использует гадкий MySQL.
По умолчанию, как и предполагалось, ничего не заработало, не найдя вразумительных ответов по теме в гуглах, пришлось часок поковыряться самостоятельно, и решение было найдено.
В старой версии проекта использовался пресловутый JdbcTemplate и [...]]]></description>
			<content:encoded><![CDATA[<p>Намедни понадобилось перевести свой старый проект на <a href="http://www.sun.com/software/products/appsrvr/http://www.sun.com/software/products/appsrvr/index.jsp">Glassfish</a>. Проект построен на SpringMVC, и как не сложно догадаться в качестве главного хранилища данных использует гадкий MySQL.</p>
<p>По умолчанию, как и предполагалось, ничего не заработало, не найдя вразумительных ответов по теме в гуглах, пришлось часок поковыряться самостоятельно, и решение было найдено.</p>
<p>В старой версии проекта использовался пресловутый JdbcTemplate и URL коннекта прописывался непосредство в XML конфиге Spring&#8217;а.</p>
<p>Однако, какой смысл использовать это неповоротливое, в плане масштабируемости решение, если мы переводим весь проект на могучий Glassfish, где есть удобная в настройке поддержка JNDI ресурсов и пулов, и даже контроль транзакционности &#8220;из коробки&#8221;.</p>
<p>Первое, что понадобится сделать — это правильно сконфигурировать наше веб приложение. Для этого понадобиться внести правки в конфигурацию контекста Spring, web.xml, а также создать специальный sun-web.xml декскриптор.</p>
<p><span id="more-149"></span></p>
<p><strong><em>applicationContext.xml:</em></strong></p>
<div class="codecolorer-container xml mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;bean</span> <span style="color: #000066;">id</span>=<span style="color: #ff0000;">&quot;jndiDataSource&quot;</span> <span style="color: #000066;">class</span>=<span style="color: #ff0000;">&quot;org.springframework.jndi.JndiObjectFactoryBean&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;property</span> <span style="color: #000066;">name</span>=<span style="color: #ff0000;">&quot;jndiName&quot;</span><span style="color: #000000; font-weight: bold;">&gt;</span><span style="color: #000000; font-weight: bold;">&lt;value<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>java:comp/env/jndiSourceName<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/value<span style="color: #000000; font-weight: bold;">&gt;</span></span><span style="color: #000000; font-weight: bold;">&lt;/property<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/bean<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
...</div></div>
<p>Далее, необходимо объявить ссылку на указанный выше ресурс в веб дескрипторе, если мы хотим использовать пространство java:comp/env.</p>
<p><strong><em>web.xml:</em></strong></p>
<div class="codecolorer-container xml mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">...<br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;resource-ref<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;res-ref-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jndiSourceName<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/res-ref-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;res-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>javax.sql.DataSource<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/res-type<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;res-auth<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>Container<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/res-auth<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/resource-ref<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
...</div></div>
<p>Последнее на уровне конфигурации, что прийдется сделать — это создать специальный дескриптор для Glassfish в папке WEB-INF.</p>
<p><strong><em>sun-web.xml:</em></strong></p>
<div class="codecolorer-container xml mac-classic" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><div class="xml codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;sun-web-app<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;resource-ref<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;res-ref-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>jndiSourceName<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/res-ref-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;jndi-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span>realJNDINameInGlassfish<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/jndi-name<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
&nbsp; &nbsp; <span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/resource-ref<span style="color: #000000; font-weight: bold;">&gt;</span></span></span><br />
<span style="color: #009900;"><span style="color: #000000; font-weight: bold;">&lt;/sun-web-app<span style="color: #000000; font-weight: bold;">&gt;</span></span></span></div></div>
<p>Далее конфигурируем Glassfish. Для этого понадобиться сделать 2 вещи.</p>
<p>Скачиваем <a href="http://www.mysql.com/downloads/connector/j/">MySQL Connector/J</a>, распаковываем и копируем mysql-connector-java-x.x.x-bin.jar в папку домена Glassfish ./domain1/lib/ext.</p>
<p>Перезапускаем сервер.</p>
<p>Далее идём в консоль Glassfish по пути Resources-&gt;JDBC-&gt; Connection Pools и создаём новый пул, при этом Resource Type выбираем <strong>javax.sql.DataSource</strong>, Database Vendor: <strong>MySQL</strong> соответственно. Жмём <strong>Next</strong> и на следующей страничке выбираем Datasource Classname: <strong>com.mysql.jdbc.jdbc2.optional.MysqlDataSource</strong>.</p>
<p>В параметрах указываем, User, Password, ServerName, Port. Это то, что необходимо указать обязательно и о чем пишется в любом QuickStart Guide.</p>
<p>Однако, о чем умалчивает документация — это о том, что также нужно руками прописать URL и Url, что представляет собой стандартную запись урлы коннекшены. По крайней мере, у меня всё заработало только после того, как я прописал эти параметры.</p>
<p>Последним шагом заходим в JDBC Resources и создаём новый ресурс с именем, которое соответствует указанному в конфиге sun-web.xml.</p>
<p>Рестартуем приложение из админ-консоли Glassfish, и вуа-ля, всё работает.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=jdMLaDR18_E:e_rfB89IiEk:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=jdMLaDR18_E:e_rfB89IiEk:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=jdMLaDR18_E:e_rfB89IiEk:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=jdMLaDR18_E:e_rfB89IiEk:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=jdMLaDR18_E:e_rfB89IiEk:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/jdMLaDR18_E" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2010/03/setting-up-glassfish-mysql-spring/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2010/03/setting-up-glassfish-mysql-spring/</feedburner:origLink></item>
		<item>
		<title>Принципы написания User Stories</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/rL4PBndRn-U/</link>
		<comments>http://yasinetskiy.com/2010/03/user-story-principles/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 15:19:02 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[Agile методологии]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[management]]></category>
		<category><![CDATA[user-stories]]></category>

		<guid isPermaLink="false">http://yasinetskiy.com/?p=140</guid>
		<description><![CDATA[Пару слов о критериях, которым стоит следовать при создании новых User Story.
Существует такой термин — I.N.V.E.S.T.
Данная аббревиатура состоит из первых букв шести принципов, которым стоит придерживаться при создании новой User Story:

Independent (Независимая)
Каждая новая User Story должна быть максимально независима от других (на сколько это возможно). Зависимости между историями делают их планирование, приоритизацию и оценку более [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-145" style="margin-left: 5px; margin-right: 5px;" title="User Stories" src="http://yasinetskiy.com/wp-content/uploads/2010/03/just_enough.gif" alt="User Stories" width="150" height="249" />Пару слов о критериях, которым стоит следовать при создании новых <a href="http://en.wikipedia.org/wiki/User_story">User Story</a>.</p>
<p>Существует такой термин — <strong>I.N.V.E.S.T.</strong></p>
<p>Данная аббревиатура состоит из первых букв шести принципов, которым стоит придерживаться при создании новой User Story:</p>
<ul>
<li><strong>Independent (Независимая)<br />
</strong>Каждая новая User Story должна быть максимально независима от других (на сколько это возможно). Зависимости между историями делают их планирование, приоритизацию и оценку более сложными. Чаще всего, зависимостей между User Story можно избежать засчет объединения историй в одну или же разбиения на более мелкие.</li>
<li><strong>Negotiable (Подверженная изменениям/обсуждению)<br />
</strong>Истории нужно обсуждать и изменять если это необходимо. &#8220;Карточка&#8221; с User Story — это всего лишь краткое описание истории, которое не содержит деталей. Детали, как правило, прорабатываются на стадии обсуждения. Однако, не стоит забывать, что избыточное количество деталей может ограничивать общение с заказчиком в процессе разработки.</li>
<li><strong>Valuable (Полезная)<br />
</strong>Каждая, отдельно взятая история, должна приносить определенную пользу (будь-то пользователь или заказчик). Самый надежный способ сделать историю полезной — это заставить заказчика написать её. Как только заказчик осознает, что User Story это не окончательный документ на подпись, и что User Story можно обсуждать и менять, он будет чувствовать себя комфортнее при её написании.</li>
<li><strong>Estimable (Поддающаяся временной оценке)<br />
</strong>Разработчики должны иметь возможность оценивать истории, тем самым позволяя расставить приоритеты на итерацию. Проблемы, которые могут помешать разработчикам выполнить оценку истории: отсутствие понимания бизнес процессов (в этом случае необходимо выделять больше времени на обсуждение историй); или же история слишком большая (в этом случае требуется разбиение на более мелкие истории).</li>
<li><strong>Small (Небольшая)<br />
</strong>Хорошая User Story должна быть проста в реализации, обычно представляющая не более 1-й человеко/недели реализации. История, для реализации которой требуется больше времени может содержать больше ошибок связанных с масштабированием и оценкой.</li>
<li><strong>Testable (Тестируемая)<br />
</strong>User Story должна поддаваться тестированию. Главное помнить, мы не разрабатываем ничего что нельзя протестировать. Если вы не можете протестировать историю, вы никогда не сможете сказать готова ли она.Пример истории не поддающейся тестированию: &#8220;Программа должны быть простая в использовании&#8221;.</li>
</ul>
<p><em>Источник: <a href="http://agilesoftwaredevelopment.com">http://agilesoftwaredevelopment.com</a></em></p>
<p><em> </em></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=rL4PBndRn-U:0CXGZ_eNTgM:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=rL4PBndRn-U:0CXGZ_eNTgM:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=rL4PBndRn-U:0CXGZ_eNTgM:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=rL4PBndRn-U:0CXGZ_eNTgM:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=rL4PBndRn-U:0CXGZ_eNTgM:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/rL4PBndRn-U" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2010/03/user-story-principles/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2010/03/user-story-principles/</feedburner:origLink></item>
		<item>
		<title>Chromicious 2.0 – Релиз новой версии плагина</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/zZDKeEeoQLw/</link>
		<comments>http://yasinetskiy.com/2010/01/chromicious-2-release/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 13:07:42 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[Chromium]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[chromicious]]></category>
		<category><![CDATA[delicious]]></category>
		<category><![CDATA[google chrome]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://yasinetskiy.com/?p=132</guid>
		<description><![CDATA[
Не так давно я выложил первую версию своего плагина для работы с закладками Delicious.com для браузера Google Chrome. Неожиданно для меня плагин получил довольно большое одобрение со стороны пользователей Chrome, не смотря на то что первая версия была ни на что не похожа.
За три месяца плагин приобрел собственный логотип, который представляет собой смесь концепции логотипа [...]]]></description>
			<content:encoded><![CDATA[<p><img class="  alignleft" style="margin-left: 5px; margin-right: 5px;" title="Chromelicious Bookmarks Extension" src="http://thedeliciouschrome.com/chromicious_bookmarks_logo.png" alt="Chromicious Bookmarks Extension" width="300" height="72" /></p>
<p>Не так давно я выложил первую версию своего <a title="Chromelicious Bookmarks Extension" href="https://chrome.google.com/extensions/detail/animchmhhndbcfahoigdpelodbhnhepg">плагина</a> для работы с закладками Delicious.com для браузера <a href="http://google.com/chrome">Google Chrome</a>. Неожиданно для меня плагин получил довольно большое одобрение со стороны пользователей Chrome, не смотря на то что первая версия была ни на что не похожа.</p>
<p>За три месяца плагин приобрел собственный логотип, который представляет собой смесь концепции логотипа <a href="http://delicious.com">Delicious.com</a> и цветов логотипа Google Chrome, достаточно подходящее название, которое было предложено одним из пользователей, а также оброс более богатой функциональностью.<br />
<span id="more-132"></span><br />
Сегодня представляю вам второую версию плагина, которая была значительно улучшена и переработана. Самое пристальное внимание было уделено удобству использования и стабильности.</p>
<p>И так, что же нового:</p>
<ul>
<li>Поиск закладок теперь не case-sensitive</li>
<li>Поиск закладок стал значительно быстрее и продвинутей</li>
<li>Добавилась возможность фильтровать закладки по тэгам</li>
<li>Исправлен дефект связанный ошибочным срабатыванием горячих клавиш</li>
<li>Значительно улучшен интерфейс</li>
</ul>
<p>Что одидается в следующей версии:</p>
<ul>
<li>Поддержка эккаунтов Yahoo ID!</li>
<li>Выделенный текст на странице будет подставляться в описание закладки</li>
<li>Просмотр тэгов отдельно для каждой закладки</li>
<li>Будут добавлены favicon в списке отображения закладок</li>
</ul>
<p>Официальный сайт: <a title="Chromelicious Bookmarks Extension Official Site" href="http://thedeliciouschrome.com/">http://thedeliciouschrome.com</a></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=zZDKeEeoQLw:wMUBQ683TNY:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=zZDKeEeoQLw:wMUBQ683TNY:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=zZDKeEeoQLw:wMUBQ683TNY:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=zZDKeEeoQLw:wMUBQ683TNY:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=zZDKeEeoQLw:wMUBQ683TNY:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/zZDKeEeoQLw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2010/01/chromicious-2-release/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2010/01/chromicious-2-release/</feedburner:origLink></item>
		<item>
		<title>Краткое резюму об Agile методологиях</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/cnHWNVkvYyU/</link>
		<comments>http://yasinetskiy.com/2010/01/short-resume-about-agile-practice/#comments</comments>
		<pubDate>Fri, 22 Jan 2010 11:24:13 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[Agile методологии]]></category>
		<category><![CDATA[agile]]></category>
		<category><![CDATA[business process]]></category>
		<category><![CDATA[management]]></category>

		<guid isPermaLink="false">http://yasinetskiy.com/?p=122</guid>
		<description><![CDATA[В свете грядущей конференции AgileBaseCamp, которая состоится уже завтра хотелось бы резюмировать некоторые мысли и опыт, накопившиеся за последнее время.]]></description>
			<content:encoded><![CDATA[<p>В свете грядущей конференции <a href="http://agilebasecamp.org">AgileBaseCamp</a>, которая состоится уже завтра хотелось бы резюмировать некоторые мысли и опыт, накопившиеся за последнее время.</p>
<p><span id="more-122"></span></p>
<p>В доказательстве новых теорем и законов существует как правило три стадии. Первая стадия заключается в осознании и необходимости поиска новых подходов и решений в той или иной области и соответственно нахождении такого решения. Что как правило приводит к пониманию или осознанию нового явления, но еще не доказуемого или имеющего слабую теоретическую базу.</p>
<p>Вторая стадия &#8211; испытаний и опытов. С целью подтвердить явление проводится ряд экспериментов, в ходе которых накапливаются знания и необходимые научные обоснования для построения полной доказательной базы с целью объяснить явления с научной точки зрения.</p>
<p>Третья стадия &#8211; доказательство. В ходе второй стадии опытов и экспериментов был установлен ряд неопровержимых фактов достаточных для доказательства явления с научной точки зрения.</p>
<p>А теперь давайте посмотрим на современные методологии разработки программного обеспечения с научной точки зрения. Становится очевидно, что Agile методологии находятся на второй стадии научного обоснования. Существует множество экспериментов, причем достаточно успешных, множество практик и теорий, однако не существует полного научного обоснования доказывающего эффективность этих подходов.</p>
<p>И конечной формулы нет. В сумме мы имеем набор гибких практик об эффективном взаимодействии людей в команде, но не процессов, в связи с чем доказать это не возможно. Agile &#8211; это больше о психологии, а не о практике разработки ПО.</p>
<p>В связи с чем нельзя точно сказать, что один и тот же набор практик будет одинаково эффективен во всех командах. Однако данное утверждение не мешает некоторым проект-менеджерам впасть в паранойю, навязывая все подряд.</p>
<p><strong>А теперь о неприятном</strong></p>
<p>Цель любой методологии (а в данном случае Agile), чем бы она не была обоснована &#8211; сократить риски и затраты на выполнение задачи с целью оптимизации производства любыми доступными средствами. И вот тут кроется большой подводный камень для разработчиков.</p>
<p>Понятие минимизации рисков достаточно обширное, однако давайте рассмотрим его с точки зрения обычного разработчика.</p>
<p>Понятие минимизации рисков для конечного(низшего) уровня в большой бизнес-иерархии, уровня разработки, сводится к &#8220;дроблению&#8221; технических задач до настолько мелких, что в конечном счете от одного взятого разработчика как единици рабочей сили в целом для процесса ничего не зависит.</p>
<p>Чем это грозит отдельно взятому разработчику? По сути ничем. Вы такой же исполнительный элемент в иерархии как и раньше. Только в случае Agile быть таким элементов немного веселее (что кстати по мнению автора также является частью &#8220;большого плана&#8221;). Если вы это понимаете &#8211; это уже часть прогресса и значит вы найдете достаточно сил для дальнейшего профессионального развития.</p>
<p>Если от прочтения предыдущего абзаца вам стало страшно (вы осознали свое место и вам стало не по себе) &#8211; расслабьтесь, сейчас будет еще неприятнее.</p>
<p>Фокус заключается в том, что будь вы менеджером (вас повысили?), вы будете точно также применять различные методологии для минимизации рисков и оптимизации расходов как это делали до вас, заботясь о конечном business value.</p>
<p>Agile &#8211; отличный налаженный инструмент для успешного ведения бизнеса, но в тоже время отличный убийца для многих разработчиков в профессиональном смысле.</p>
<p>Данная методология создана исключительно с целью увеличение прибыльности бизнеса и организации полного контроля над процессом разработки, где талант и способности отдельно взятого разработчика редко что значат.</p>
<p>Не согласны? И правильно! Читайте далее.</p>
<p><strong>Но не все так плохо</strong></p>
<p>Все выше изложенные негативные стороны, для вас как для разработчика, применимы как правило к крупным компаниям и к крупным распределенным командам, где действительно крайней сложно следить за всем ходом процесса разработки. И как писалось выше, Agile для конечного разработчика призван служить лишь способом сделать этот процесс более приятным и подконтрольным (помните рассуждения о религии в фильме &#8220;Дух времени&#8221;?).</p>
<p>Но если у вас небольшая команда, вы создаете свой проект и ищите эффективные способы для его реализации, хотите оптимизировать свои бизнес процессы в уже существующей команде.</p>
<p>Тогда Agile &#8211; это то, что вам нужно. В данном случае, таланты каждого игрока команды превозносятся в ранг необходимых составляющих успеха и делают процесс разработки действительно увлекательным и эффективном.</p>
<p><!-- Technorati Tags Start --></p>
<p>Technorati Tags:<br />
<a rel="tag" href="http://technorati.com/tag/agile">agile</a>, <a rel="tag" href="http://technorati.com/tag/business%20process">business process</a>, <a rel="tag" href="http://technorati.com/tag/management">management</a></p>
<p><!-- Technorati Tags End --></p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=cnHWNVkvYyU:7mOavbPOzy8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=cnHWNVkvYyU:7mOavbPOzy8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=cnHWNVkvYyU:7mOavbPOzy8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=cnHWNVkvYyU:7mOavbPOzy8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=cnHWNVkvYyU:7mOavbPOzy8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/cnHWNVkvYyU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2010/01/short-resume-about-agile-practice/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2010/01/short-resume-about-agile-practice/</feedburner:origLink></item>
		<item>
		<title>Delicious Bookmarks Extension для Google Chrome</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/7Xnq-YSctP4/</link>
		<comments>http://yasinetskiy.com/2009/09/delicious-bookdelicious-bookmarks-extension-dlya-google-chrome/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 08:00:27 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[Онлайн-сервисы]]></category>
		<category><![CDATA[delicious]]></category>
		<category><![CDATA[extensions]]></category>
		<category><![CDATA[google chtome]]></category>
		<category><![CDATA[plugins]]></category>

		<guid isPermaLink="false">http://beta.yasinetskiy.com/?p=80</guid>
		<description><![CDATA[Выложил свой первый extension для браузера Google Chrome, который позволяет сохранять закладки на Delcious.com. На данный момент функциональность довольно простая, собственно, как и номер версии 0.1.2, однако планируется существенное усовершенствование в скором времени.
Скачать можно здесь.
]]></description>
			<content:encoded><![CDATA[<p>Выложил свой первый extension для браузера Google Chrome, который позволяет сохранять закладки на Delcious.com. На данный момент функциональность довольно простая, собственно, как и номер версии 0.1.2, однако планируется существенное усовершенствование в скором времени.</p>
<p>Скачать можно <a href="http://www.chromeextensions.org/social-communications/delicious-bookmarks/">здесь</a>.</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=7Xnq-YSctP4:Xva0UfHz4R8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=7Xnq-YSctP4:Xva0UfHz4R8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=7Xnq-YSctP4:Xva0UfHz4R8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=7Xnq-YSctP4:Xva0UfHz4R8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=7Xnq-YSctP4:Xva0UfHz4R8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/7Xnq-YSctP4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2009/09/delicious-bookdelicious-bookmarks-extension-dlya-google-chrome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2009/09/delicious-bookdelicious-bookmarks-extension-dlya-google-chrome/</feedburner:origLink></item>
		<item>
		<title>Создаем MultiActionController для обработки множества форм</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/4KbksQZPeRY/</link>
		<comments>http://yasinetskiy.com/2009/02/sozdaem-multiactioncontroller-dlya-obrabotki-mnozhestva-form/#comments</comments>
		<pubDate>Wed, 04 Feb 2009 09:00:18 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://beta.yasinetskiy.com/?p=77</guid>
		<description><![CDATA[Часто, при разработке веб-приложений на Spring возникает ситуация, когда приходится объеденять сразу несколько действий в один контроллер. Для этого Бог и создал MultiActionController. Однако, Бог не предусмотрел прямой возможности обрабатывать одним таким контроллером сразу несколько форм. Вот как раз о вмешательстве простого человека в дела Божьи и пойдет речь в этой статье.Итак, братья и сестры, [...]]]></description>
			<content:encoded><![CDATA[<p>Часто, при разработке веб-приложений на Spring возникает ситуация, когда приходится объеденять сразу несколько действий в один контроллер. Для этого Бог и создал MultiActionController. Однако, Бог не предусмотрел прямой возможности обрабатывать одним таким контроллером сразу несколько форм. Вот как раз о вмешательстве простого человека в дела Божьи и пойдет речь в этой статье.<span id="more-77"></span>Итак, братья и сестры, нам понадобятся:</p>
<ul>
<li>SimpleFormController</li>
<li>MethodNameResovler</li>
</ul>
<p>Первое, что нужно сделать &#8211; это реализовать собственный GodMethodNameResovler, который будет имплементировать стандартный интерфейс MethodNameResolver и поместить туда примерно такой код:</p>
<pre>
<div class="codecolorer-container text mac-classic java" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class GodMethodNameResolver implements MethodNameResolver { &nbsp; &nbsp;private Properties mapping; &nbsp; &nbsp;private String defaultMethodName; &nbsp; &nbsp;public void setMappings(Properties mappings) { &nbsp; &nbsp; &nbsp; &nbsp;this.mappings = mappings; &nbsp; &nbsp;} &nbsp; &nbsp;public void setDefaultMethodName(String defaultMethodName) { &nbsp; &nbsp; &nbsp; &nbsp;this.defaultMethodName = defaultMethodName; &nbsp; &nbsp;} &nbsp; &nbsp;public void afterPropertiesSet() { &nbsp; &nbsp; &nbsp; &nbsp;if (mapping == null) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw new IllegalArgumentException(&quot;Methods mapping property required.&quot;); &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;} &nbsp; &nbsp;public String getHandlerMethodName(HttpServletRequest request) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throws NoSuchRequestHandlingMethodException { &nbsp; &nbsp; &nbsp; &nbsp;for (Iterator it = this.mappings.keySet().iterator(); it.hasNext();) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;String submitParamter = (String)it.next(); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (WebUtils.hasSubmitParameter(request, submitParamter)) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return (String)mapping.get(submitParamter); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp; &nbsp;return defaultMethodName; &nbsp; &nbsp;}}</div></td></tr></tbody></table></div>
</pre>
<p>Когда с этим покончено, создадим абстрактный контроллер, который в последствии будут наследовать все остальные MultiActionController&#8217;ы:</p>
<pre>
<div class="codecolorer-container text mac-classic java" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public abstract class AbstractMultiActionFormController extends SimpleFormController { &nbsp; &nbsp;private MethodNameResolver methodNameResolver; &nbsp; &nbsp;protected ModelAndView processFormSubmission(HttpServletRequest request,&nbsp; &nbsp; &nbsp; &nbsp; HttpServletResponse response, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Object command, BindException errors) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throws Exception { &nbsp; &nbsp; &nbsp; &nbsp;if (errors.hasErrors() || isFormChangeRequest(request)) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return showForm(request, response, errors); &nbsp; &nbsp; &nbsp; &nbsp;} else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;String methodName = getMethodNameResolver().getHandlerMethodName(request); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Method m = (Method)this.getClass().getMethod(methodName, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;new Class[] {HttpServletRequest.class, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Object.class, BindException.class}); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (m == null) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;throw new NoSuchRequestHandlingMethodException(methodName, getClass()); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;List params = new ArrayList(3); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;params.add(request); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;params.add(command); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;params.add(errors); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return (ModelAndView) m.invoke(this,&nbsp; &nbsp; &nbsp; params.toArray(new Object[params.size()])); &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;} &nbsp; &nbsp;public void setMethodNameResolver(MethodNameResolver methodNameResolver) { &nbsp; &nbsp; &nbsp; &nbsp;methodNameResolver = methodNameResolver; &nbsp; &nbsp;} &nbsp; &nbsp;public MethodNameResolver getMethodNameResolver() { &nbsp; &nbsp; &nbsp; &nbsp;return methodNameResolver; &nbsp; &nbsp;}}</div></td></tr></tbody></table></div>
</pre>
<p>Также, потребуется описать все это в конфиге спринга:</p>
<pre>
<div class="codecolorer-container text mac-classic xml" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&amp;lt;bean id=&quot;godMethodNameResolver&quot; class=&quot;com.myapp.GodMethodNameResolver&quot;&amp;gt; &nbsp; &nbsp;&amp;lt;property name=&quot;mappings&quot;&amp;gt; &nbsp; &nbsp; &nbsp; &nbsp;&amp;lt;props&amp;gt; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&amp;lt;prop key=&quot;testAction&quot;&amp;gt;testAction&amp;lt;/prop&amp;gt; &nbsp; &nbsp; &nbsp; &nbsp;&amp;lt;/props&amp;gt; &nbsp; &nbsp;&amp;lt;/property&amp;gt; &nbsp; &nbsp;&amp;lt;property name=&quot;defaultMethodName&quot;&amp;gt;&amp;lt;value&amp;gt;testAction&amp;lt;/value&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/bean&amp;gt;&amp;lt;bean id=&quot;blessMultiFormController&quot; class=&quot;com.myapp.BlessMultiFormController&quot;&amp;gt; &nbsp; &nbsp;&amp;lt;property name=&quot;methodNameResolver&quot;&amp;gt;&amp;lt;ref bean=&quot;godMethodNameResolver&quot;/&amp;gt;&amp;lt;/property&amp;gt; &nbsp; &nbsp;&amp;lt;property name=&quot;sessionForm&quot;&amp;gt;&amp;lt;value&amp;gt;true&amp;lt;/value&amp;gt;&amp;lt;/property&amp;gt; &nbsp; &nbsp;&amp;lt;property name=&quot;successView&quot;&amp;gt;&amp;lt;value&amp;gt;someformview&amp;lt;/value&amp;gt;&amp;lt;/property&amp;gt; &nbsp; &nbsp;&amp;lt;property name=&quot;commandName&quot;&amp;gt;&amp;lt;value&amp;gt;somecommand&amp;lt;/value&amp;gt;&amp;lt;/property&amp;gt; &nbsp; &nbsp;&amp;lt;property name=&quot;formView&quot;&amp;gt;&amp;lt;value&amp;gt;someformview&amp;lt;/value&amp;gt;&amp;lt;/property&amp;gt;&amp;lt;/bean&amp;gt;</div></td></tr></tbody></table></div>
</pre>
<p>И последний шаг &#8211; создание контроллера:</p>
<pre>
<div class="codecolorer-container text mac-classic java" style="overflow:auto;white-space:nowrap;border: 1px solid #9F9F9F;width:550px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class BlessMultiFormController extends AbstractMultiActionFormController { &nbsp; &nbsp;public ModelAndView testAction(HttpServletRequest request, Object command, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;BindException errors) throws Exception { &nbsp; &nbsp; &nbsp; &nbsp;// do something with form &nbsp; &nbsp; &nbsp; &nbsp;return showForm(request, errors, getFormView()); &nbsp; &nbsp;}}</div></td></tr></tbody></table></div>
</pre>
<p>Алилуя!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=4KbksQZPeRY:1iClnDynosE:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=4KbksQZPeRY:1iClnDynosE:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=4KbksQZPeRY:1iClnDynosE:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=4KbksQZPeRY:1iClnDynosE:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=4KbksQZPeRY:1iClnDynosE:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/4KbksQZPeRY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2009/02/sozdaem-multiactioncontroller-dlya-obrabotki-mnozhestva-form/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2009/02/sozdaem-multiactioncontroller-dlya-obrabotki-mnozhestva-form/</feedburner:origLink></item>
		<item>
		<title>Google API или что скрывается за кулисами</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/MOi7JCOV8YU/</link>
		<comments>http://yasinetskiy.com/2008/08/google-api-ili-chto-skryvaetsya-za-kulisami/#comments</comments>
		<pubDate>Fri, 29 Aug 2008 11:39:36 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[google api]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[youtube]]></category>

		<guid isPermaLink="false">http://beta.yasinetskiy.com/?p=73</guid>
		<description><![CDATA[ Недавно, работая над одним своим проектом мне пришлось решать задачу по удаленному взаимодействию с различными популярными веб-ресурсами. Из их числа были такие сайты как Youtube, Gmail, GoogleReader, Flickr и другие не менее известные. Первая проблема, с которой мне пришлось столкнуться это то, что все ресурсы поддерживают разные протоколы, из их числа стандартная тройка: REST, [...]]]></description>
			<content:encoded><![CDATA[<p><img style="margin-top: 0px; margin-right: 5px; margin-bottom: 0px; margin-left: 0px" src="http://yasinetskiy.com/wp-content/uploads/2008/08/google-api.jpg" alt="google-api" width="238" height="240" align="left" /> Недавно, работая над одним своим проектом мне пришлось решать задачу по удаленному взаимодействию с различными популярными веб-ресурсами. Из их числа были такие сайты как <a title="Youtube" href="http://youtube.com">Youtube</a>, <a title="Gmail" href="http://gmail.com">Gmail</a>, <a title="GoogleReader" href="http://google.com/reader">GoogleReader</a>, <a title="Flickr" href="http://flickr.com">Flickr</a> и другие не менее известные. Первая проблема, с которой мне пришлось столкнуться это то, что все ресурсы поддерживают разные протоколы, из их числа стандартная тройка: <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">REST</a>, <a href="http://en.wikipedia.org/wiki/XML-RPC">XML-RPC</a>, <a href="http://en.wikipedia.org/wiki/SOAP">SOAP</a>. Вторая проблема, а скорее просто настоящее занудство &#8211; это написание клиентов к каждому из этих сайтов. Удручающее мероприятие, не правда ли? И если на архитектурном уровне первая проблема решается парой паттернов типа Adapter и Factory, то со второй все обстоит гораздо менее приятно.В данном случае, нелегкую судьбину девелопера поможет спасти замечательный Google API. Честно сказать, до этого момента у меня было достаточно скептическое и поверхностное мнение о Google API. В большей степени потому, что попросту не сталкивался с подобными задачи, ну и не проявлял лишний интерес.<span id="more-73"></span>Переходя от лирики к сути заметки хочется прояснить в перую очередь, что же поддерживает GoogleAPI, с какими сервисами позволяет работать и что в себя включает.Прежде всего список поддерживаемых сервисов:</p>
<ul>
<li><a title="Blogger.com data API" href="http://code.google.com/apis/blogger/">Blogger</a></li>
<li><a title="YouTube API details" href="http://code.google.com/apis/youtube/overview.html">YouTube</a></li>
<li><a title="FeedBurner data API" href="http://code.google.com/apis/feedburner/">FeedBurner</a></li>
<li><a title="Picasa Web Albumes API" href="http://code.google.com/apis/picasaweb/overview.html">Picasa Web Albumes</a></li>
<li><a title="Google Data APIs full list" href="http://code.google.com/more/#products-dataapis-gdata">&#8230;and all Google Apps</a></li>
</ul>
<p>И значете что? Доступ ко всем этим прелестям вы можете получить уже прямо сейчас, <a title="Google Data APIs Client Libraries" href="http://code.google.com/apis/gdata/clientlibs.html">скачав</a> всего лишь одну библиотеку. Библиотека, представляющая из себя в полном смысле слова КЛИЕНТ, доступна для таких платформ:</p>
<ul>
<li>Java</li>
<li>.NET</li>
<li>PHP</li>
<li>Python</li>
<li>Objective-C</li>
<li>JavaScript</li>
</ul>
<p>Работать с ней очень просто. Ниже приведу пример работы с YouTube:</p>
<p class="csharpcode">
<pre class="csharpcode"><span class="kwrd">public</span> <span class="kwrd">class</span> YouTubeServiceDelegate {    <span class="kwrd">private</span> <span class="kwrd">static</span> final String CLIENT_ID = <span class="str">"<em>Your client ID here</em>"</span>;    <span class="kwrd">private</span> <span class="kwrd">static</span> final String DEVELOPER_KEY = <span class="str">"<em>Your developer key here</em>"</span>;    <span class="kwrd">private</span> <span class="kwrd">static</span> final String USER_SPECIFIC_URL        = <span class="str">"http://gdata.youtube.com/feeds/api/users/{userId}/uploads"</span>;    <span class="kwrd">public</span> VideoFeed getVideosByUserId(String userId)        throws <em>YourException</em> {        YouTubeService service =</pre>
<pre class="csharpcode">            <span class="kwrd">new</span> YouTubeService(CLIENT_ID, DEVELOPER_KEY);        VideoFeed videoFeed = <span class="kwrd">null</span>;        <span class="kwrd">try</span> {            videoFeed = service.getFeed(<span class="kwrd">new</span> URL(                USER_SPECIFIC_URL.replace(<span class="str">"{userId}"</span>, userId)),                VideoFeed.<span class="kwrd">class</span>);        } <span class="kwrd">catch</span> (IOException e) {            <span class="kwrd">throw</span> <span class="kwrd">new</span> <em>YourException(<span class="str">"Say something"</span>)</em>;        } <span class="kwrd">catch</span> (ServiceException e) {            <span class="kwrd">throw</span> <span class="kwrd">new</span> <em>YourException(<span class="str">"Say something"</span>)</em>;        }        <span class="kwrd">return</span> videoFeed;        }}</pre>
<p><!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } --><!-- .csharpcode, .csharpcode pre { 	font-size: small; 	color: black; 	font-family: consolas, "Courier New", courier, monospace; 	background-color: #ffffff; 	/*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt  { 	background-color: #f4f4f4; 	width: 100%; 	margin: 0em; } .csharpcode .lnum { color: #606060; } -->Приведенный выше простейший класс демонстрирует как легко и просто получить список загруженного видео с YouTube для определенного пользователя.Удачного вам использования!</p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=MOi7JCOV8YU:hRUcjGpAG_Y:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=MOi7JCOV8YU:hRUcjGpAG_Y:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=MOi7JCOV8YU:hRUcjGpAG_Y:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=MOi7JCOV8YU:hRUcjGpAG_Y:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=MOi7JCOV8YU:hRUcjGpAG_Y:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/MOi7JCOV8YU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2008/08/google-api-ili-chto-skryvaetsya-za-kulisami/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2008/08/google-api-ili-chto-skryvaetsya-za-kulisami/</feedburner:origLink></item>
		<item>
		<title>Разработка веб-приложений на Spring. Часть 3 (Реализация)</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/YHOaOgRkmKQ/</link>
		<comments>http://yasinetskiy.com/2008/02/spring-web-applications-development-part3/#comments</comments>
		<pubDate>Wed, 27 Feb 2008 09:50:37 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Фреймворки]]></category>

		<guid isPermaLink="false">http://yasinetskiy.com/2008/02/27/spring-web-applications-development-part3/</guid>
		<description><![CDATA[Разобравшись со всеми навалившимися делами и задачами, спешу опубликовать 3-ю завершающую статью из серии &#8220;Разработка веб-приложений на Spring&#8221;, которая полностью посвящается непосредственно реализации поставленной задачи в предыдущих статьях: Разработка веб-приложений на Spring. Часть 1 (Проектирование), Разработка веб-приложений на Spring. Часть 1 (Конфигурирование).
В этой статье нам предстоит сделать:

Сервис и DAO для работы с данными
Контроллер обработки формы
Валидатор [...]]]></description>
			<content:encoded><![CDATA[<p>Разобравшись со всеми навалившимися делами и задачами, спешу опубликовать 3-ю завершающую статью из серии &#8220;Разработка веб-приложений на Spring&#8221;, которая полностью посвящается непосредственно реализации поставленной задачи в предыдущих статьях: <a href="http://yasinetskiy.com/2008/01/21/spring-web-applications-development-part1/" title="Разработка веб-приложений на Spring. Часть 1 (Проектирование)">Разработка веб-приложений на Spring. Часть 1 (Проектирование)</a>, <a href="http://yasinetskiy.com/2008/02/06/spring-web-applications-development-part2/" title="Разработка веб-приложений на Spring. Часть 2 (Конфигурация)">Разработка веб-приложений на Spring. Часть 1 (Конфигурирование)</a>.</p>
<p>В этой статье нам предстоит сделать:</p>
<ul>
<li>Сервис и DAO для работы с данными</li>
<li>Контроллер обработки формы</li>
<li>Валидатор формы</li>
<li>JSP страницу</li>
</ul>
<p>Одним словом &#8211; ерунда осталась <img src='http://yasinetskiy.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><span id="more-43"></span></p>
<p><font size="4"><strong>Сервисы и DAO<br />
</strong></font></p>
<p>Для начала разберёмся, для чего нужно и то и другое, ведь можно обойтись без сервисов и работать просто с DAO. Да, можно. Однако, прежде всего это более правильный подход или архитектура, называйте как угодно. Уровень сервисов включает в себя не только выполнение таких простых действий как сохранить и получить объект, но и содержит в себе часть логики, необходимую для выполнения действий над данными перед сохранением или получением из БД. Тобишь, говоря более наглядно, метод отвечающий, например, за сохранение нового пользователя в БД на уровне DAO будет скорее всего называться <em>save</em>, а на уровне сервиса <em>register</em>. Улавливаете разницу? Во вторых, на уровне сервисов в нашем приложении будет происходить управление транзакциями.</p>
<p>Переходя от нудной теории к практике создадим сервис, обеспечивающий добавление нового подписчика в БД.</p>
<p><strong><em>InviteSubscribersService.java</em></strong></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">@Transactional(readOnly = true)<br />
public class InviteSubscribersService {</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">private InviteSubscribersDAO dao;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)<br />
public void create(InviteSubscriber subscriber) throws DataAccessException, ServiceException {<br />
if (subscriber == null) {<br />
throw new </font><font face="courier new,courier" size="2">ServiceException(&#8221;Subscriber cannot be null or empty&#8221;);</font><br />
<font face="courier new,courier" size="2">}</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">getInviteSubscribersDAO()</font><font face="courier new,courier" size="2">.save(subscriber);<br />
}</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public void setInviteSubscribersDAO(InviteSubscribersDAO dao) {<br />
this.dao = dao;<br />
}</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public InviteSubscribersDAO getInviteSubscribersDAO() {<br />
return dao;<br />
}<br />
}</font></p>
<p>Разберём по порядку, что тут к чему.</p>
<p>Аннотация  <font face="courier new,courier" size="2">@Transactional(readOnly = true)</font>перед объявлением класса говорит о том, что все методы содержащиеся в классе расcчитаны по умолчанию на чтение данных из БД. Далее сследует объявление DAO, с которым будет работать сервис и непосредственно сам метод, выполняющий создание нового подписчика в БД.</p>
<p>Аннотация <font face="courier new,courier" size="2">@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)</font>говорит о том, что этот метод транзакционный. Фокус в том, что вам не нужно вручную делать commit и rollback, как это приходилось делать нашим  предкам. Об этом позаботится менеджер транзакций встроенный в Spring, который мы успешно сконфигурировали в предыдущей статье. В случае, если произойдёт exception, менеджер автоматически выполнит rollback, в противном случае commit. При желании, можно указать на какие конкретно типы Exception должен срабатывать rollback. Об этом более детально смотрите документацию Spring.</p>
<p>Далее, как вы уже догадались, следует создать DAO.</p>
<p><strong><em>InviteSubscribersDAO.java</em></strong></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public class InviteSubscribersDAO extends HibernateDaoSupport {</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public void save(InviteSubscriber subscriber) throws DataAccessException {<br />
getHibernateTemplate().save(subscriber);<br />
}<br />
}</font></p>
<p>Здесь всё просто. Работа с Hibernate происходит через специальный слой  HibernateDaoSupport встроенный в Spring. Зачем использовать какой-то слой, если можно работать с Hibernate на прямую? Очень просто &#8211; этот слой автоматически следит за созданием и закрытием сессий, как следствие &#8211; у вас меньше головной боли.</p>
<p><font size="4"><strong>Контроллер обработки формы</strong></font></p>
<p>Создадим контроллер, который будет обрабатывать нашу форму подписки.</p>
<p><strong><em>InviteActionController.java</em></strong></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public class InviteActionController extends SimpleFormController {</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">private InviteSubscribersService subscribersService;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">protected ModelAndView onSubmit(HttpServletRequest request,<br />
HttpServletResponse response,<br />
Object command,<br />
BindException errors) throws Exception {</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">InviteFormBean form = (InviteFormBean)command;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">InviteSubscriber subscriber = new InviteSubscriber();<br />
subscriber.setEmail(form.getEmail());</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">getSubscribersService()</font><font face="courier new,courier" size="2">.create(subscriber);</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">request.setAttribute(&#8221;afterprocess_message&#8221;, &#8220;Thank you! You have joined to the AllOfRSS users.&#8221;);<br />
return super.onSubmit(request, response, form, errors);<br />
}</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public InviteSubscribersService getSubscribersService() {<br />
return subscribersService;<br />
}</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public void setSubscribersService(InviteSubscribersService subscribersService) {<br />
this.subscribersService = subscribersService;<br />
}<br />
}</font></p>
<p>Здесь вообще всё проще пареной репы. Метод <font face="courier new,courier" size="2">onSubmit</font> срабатывает при сабмите формы. Command &#8211; это объект формы, преобразуем его в соответсвующий бин и создаём объект для сохранения в БД. Объект errors содержит ошибки, возвращаемые валидатором. Создаём валидатор и не забываем, что он уже <a href="http://yasinetskiy.com/source/example/allofrss/part2/allofrss-context.xml">прописан</a> у нас в конфиге, а значит больше ни о чём думать не надо, всё будет работать автоматически.</p>
<p><font size="4"><strong>Валидатор</strong></font></p>
<p><strong><em>InviteFormValidator.java</em></strong></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public class InviteFormValidator implements Validator {</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public boolean supports(Class candidate) {<br />
return InviteFormBean.class.isAssignableFrom(candidate);<br />
}</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">public void validate(Object obj, Errors errors) {<br />
ValidationUtils.rejectIfEmptyOrWhitespace(errors, &#8220;email&#8221;, &#8220;required&#8221;, &#8220;To proccess this action you need to fill your e-mail!&#8221;);</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">InviteFormBean form = (InviteFormBean)obj;<br />
Pattern pattern = Pattern.compile(&#8221;.+@.+\\.[a-z]+&#8221;);<br />
Matcher matcher = pattern.matcher(form.getEmail());<br />
if (!matcher.matches()) {<br />
errors.rejectValue(&#8221;email&#8221;, &#8220;required&#8221;, &#8220;Ivalid e-mail address!&#8221;);<br />
}<br />
}<br />
}</font></p>
<p>Осталось создать JSP страничку с формой.</p>
<p><font size="4"><strong>JSP страница</strong></font></p>
<p><strong><em>invite.jsp</em></strong></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;%@ page language=&#8221;java&#8221; contentType=&#8221;text/html; charset=utf-8&#8243; pageEncoding=&#8221;utf-8&#8243;%&gt;<br />
&lt;%@ taglib prefix=&#8221;c&#8221; uri=&#8221;http://java.sun.com/jsp/jstl/core&#8221; %&gt;<br />
&lt;%@ taglib prefix=&#8221;form&#8221; uri=&#8221;http://www.springframework.org/tags/form&#8221; %&gt;<br />
&lt;%@ taglib prefix=&#8221;spring&#8221; uri=&#8221;http://www.springframework.org/tags&#8221; %&gt;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;c:set var=&#8221;successmessage&#8221; value=&#8221;&lt;%= request.getAttribute(&#8221;afterprocess_message&#8221;)%&gt;&#8221;/&gt;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;form:form commandName=&#8221;invite&#8221;&gt;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;form:input path=&#8221;email&#8221; id=&#8221;email&#8221; cssClass=&#8221;text&#8221;/&gt;<br />
&lt;input type=&#8221;submit&#8221; value=&#8221;?&#8221;/&gt;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">${successmessage}</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;spring:hasBindErrors name=&#8221;invite&#8221;&gt;<br />
&lt;form:errors path=&#8221;email&#8221; /&gt;<br />
&lt;/spring:hasBindErrors&gt;<br />
</font></p>
<p><font style="background-color: #eeeee3" face="courier new,courier" size="2">&lt;/form:form&gt; </font></p>
<p>Я даже не буду здесть ничего объяснять. Просто внимательно посмотрите на форму, а затем на конфигы, созданные в<a href="http://yasinetskiy.com/2008/02/06/spring-web-applications-development-part2/" title="Разработка веб-приложений на Spring. Часть 2 (Конфигурация)"> предыдущей статье</a> и у вас не останется ни одного вопроса.</p>
<p>Надеюсь у вас не возникнет проблем с реализацией, а вопросовы пишите в комментарии. С удовольствием отвечу.</p>
<p>Развлекайтесь и больше бывайте на свежем воздухе&#8230; <img src='http://yasinetskiy.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> </p>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=YHOaOgRkmKQ:0avGOLOdKN8:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=YHOaOgRkmKQ:0avGOLOdKN8:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=YHOaOgRkmKQ:0avGOLOdKN8:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=YHOaOgRkmKQ:0avGOLOdKN8:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=YHOaOgRkmKQ:0avGOLOdKN8:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/YHOaOgRkmKQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2008/02/spring-web-applications-development-part3/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2008/02/spring-web-applications-development-part3/</feedburner:origLink></item>
		<item>
		<title>Разработка веб-приложений на Spring. Часть 2 (Конфигурация)</title>
		<link>http://feedproxy.google.com/~r/AndreyYasinetskiysoftwareDevelopment/~3/AwTk8hjILt8/</link>
		<comments>http://yasinetskiy.com/2008/02/spring-web-applications-development-part2/#comments</comments>
		<pubDate>Tue, 05 Feb 2008 22:14:06 +0000</pubDate>
		<dc:creator>Andrey Yasinetskiy</dc:creator>
				<category><![CDATA[J2EE]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Spring]]></category>
		<category><![CDATA[Фреймворки]]></category>
		<category><![CDATA[allofrss]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[фреймворк]]></category>

		<guid isPermaLink="false">http://yasinetskiy.com/2008/02/06/spring-web-applications-development-part2/</guid>
		<description><![CDATA[В предыдущей статье мы занимались проектированием будущего приложения на Spring. Определили его цели, структуру, а также рассмотрели основные компоненты. В качестве примера используем всё тот же AllOfRss.com.
В данной статье я рассмотрю конфигурацию нашего приложения. В процессе будут созданы все необходимые конфигурационные файлы для его полноценного функционирования.
Для начала откроем Eclipse и создадим новый проект (File-&#62;New-&#62;Web Project), [...]]]></description>
			<content:encoded><![CDATA[<p>В <a href="http://yasinetskiy.com/2008/01/21/spring-web-applications-development-part1/" title="Разработка веб-приложений на Spring. Часть 1 (Проектирование)">предыдущей</a> статье мы занимались проектированием будущего приложения на Spring. Определили его цели, структуру, а также рассмотрели основные компоненты. В качестве примера используем всё тот же <a href="http://allofrss.com" title="AllOfRss.com">AllOfRss.com</a>.</p>
<p>В данной статье я рассмотрю конфигурацию нашего приложения. В процессе будут созданы все необходимые конфигурационные файлы для его полноценного функционирования.<br />
Для начала откроем Eclipse и создадим новый проект (File-&gt;New-&gt;Web Project), также рекомендую установить плагин для более комфортной работы с фреймворком Spring &#8211; <a href="http://springide.org" title="Spring IDE Plugin">Spring IDE Plugin</a>. В процессе создания проекта, Eclipse попросит указать название вашей &#8220;Web root folder&#8221; (по умолчанию стоит &#8211; WebRoot), я обычно указываю &#8211; web, а также J2EE Specification Level, отметьте &#8211; Java EE 5.0 (если, конечно, вы используете Java 5). Остальное пусть будет без изменений.</p>
<p><font size="4"><strong>Веб дескриптор</strong></font></p>
<p>Как и в любом другом веб-приложении на Java всё начинается с конфигурации web.xml (web(WebRoot)/WEB-INF/web.xml).</p>
<p>Для начала установим путь к осноному конфигу Spring.</p>
<p><strong><em>web.xml</em></strong></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;context-param&gt;<br />
&lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;<br />
&lt;param-value&gt;/WEB-INF/allofrss-servlet.xml&lt;/param-value&gt;<br />
&lt;/context-param&gt;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;listener&gt;<br />
&lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;<br />
&lt;/listener&gt;</font></p>
<p>Сравнительно с другими веб-приложениям на Java, приложение на Spring не отличается особой оригинальностью поскольку здесь тоже всё работает через сервлеты, правда сервлет здесь будет всего один. DispatcherServlet главный сервлет в приложении на Spring. Он выполняет роль &#8220;гейтвея&#8221; входящих запросов, перенаправляя вызовы &#8220;внутрь&#8221; системы (в науке это называется паттерном <a href="http://java.sun.com/blueprints/corej2eepatterns/Patterns/FrontController.html" title="Core J2EE Patterns - Front Controller">Front Controller</a>).</p>
<p><span id="more-40"></span></p>
<p><em><strong>web.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;servlet&gt;<br />
&lt;servlet-name&gt;allofrss&lt;/servlet-name&gt;<br />
&lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;<br />
&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;<br />
&lt;/servlet&gt;</font></p>
<p>Следует, также, установить маппинг на DispatcherServlet. Конструкция, приведенная ниже, означает, что все запросы, которые начинаются с &#8220;/c&#8221; будут направлены на  DispatcherServlet.</p>
<p><strong><em>web.xml</em></strong></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;servlet-mapping&gt;<br />
&lt;servlet-name&gt;allofrss&lt;/servlet-name&gt;<br />
&lt;url-pattern&gt;/c/*&lt;/url-pattern&gt;<br />
&lt;/servlet-mapping&gt;</font></p>
<p>И последенее, что следует внести в наш web.xml:</p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;welcome-file-list&gt;<br />
&lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;<br />
&lt;/welcome-file-list&gt;</font></p>
<p>Закончив с конфигурацией web.xml, можно перейти к настройке Spring приложения. Я предлагаю разделить конфигурацию на 3 конфигурационных файла:</p>
<ul>
<li>/WEB-INF/context/common.xml &#8211; основной конфиг, содержащий информацию о маппингах и слое отображения</li>
<li>/WEB-INF/context/allofrss-context.xml &#8211; конфиг, содержащий информацию о контроллерах приложения</li>
<li>/WEB-INF/context/allofrss-data.xml &#8211; содержит информацию о классах доступа к БД</li>
</ul>
<p><strong><font size="4">Настройка маппинга и слоя отображения</font></strong></p>
<p>Создайте файл /WEB-INF/context/common.xml следующего содержания.</p>
<p><em><strong>common.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;beans xmlns=&#8221;http://www.springframework.org/schema/beans&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xmlns:aop=&#8221;http://www.springframework.org/schema/aop&#8221;<br />
xsi:schemaLocation=&#8221;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&#8221;&gt;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;!&#8211; This config contains main info about application mappings and view resolvers&#8211;&gt; </font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;/beans&gt;</font></p>
<p>Далее, следует добавить информацию о классе, который будет заниматься маппингом реквестов в приложении. Как я упоминал в <a href="http://yasinetskiy.com/2008/01/21/spring-web-applications-development-part1/" title="Разработка веб-приложений на Spring. Часть 1 (Проектирование)">предыдущей</a> статье, для этих целей будем использовать <font face="courier new,courier" size="2">SimpleUrlHandlerMapping.</font></p>
<p><em><strong>common.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;bean id=&#8221;simpleUrlMapping&#8221; class=&#8221;org.springframework.web.servlet.handler.SimpleUrlHandlerMapping&#8221;&gt;<br />
</font><font face="courier new,courier" size="2">&#8230;</font><br />
<font face="courier new,courier" size="2">&lt;/bean&gt;</font></p>
<p>В терминах Spring любой класс, конфигурируемый с его помощью называется бином(&lt;bean&#8230;), не путать с JavaBeans. В связи с этим, поначалу вас может одолевать вопрос, типа, причём тут бин если я подключаю обычный класс. Извините, не ко мне вопрос, просто смиритесь <img src='http://yasinetskiy.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Запись id=&#8221;simpleUrlMapping&#8221; определяет уникальный идентификатор для подключаемого класса для возможности ссылаться на этот класс в пределах конфигов по короткому имени.</p>
<p>Определив класс, добавим ему параметры маппинга.</p>
<p><em><strong>common.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;bean id=&#8221;simpleUrlMapping&#8221; class=&#8221;org.springframework.web.servlet.handler.SimpleUrlHandlerMapping&#8221;&gt;<br />
&lt;property name=&#8221;order&#8221;&gt;&lt;value&gt;0&lt;/value&gt;&lt;/property&gt;<br />
&lt;property name=&#8221;mappings&#8221;&gt;<br />
&lt;props&gt;<br />
&lt;prop key=&#8221;/welcome&#8221;&gt;inviteController&lt;/prop&gt;<br />
&lt;prop key=&#8221;/about&#8221;&gt;aboutController&lt;/prop&gt;<br />
&lt;/props&gt;<br />
&lt;/property&gt;<br />
&lt;/bean&gt;</font></p>
<p>Записи  &lt;prop key=&#8221;/welcome&#8221;&gt;inviteController&lt;/prop&gt;, &lt;prop key=&#8221;/about&#8221;&gt;aboutController&lt;/prop&gt; означают, что запросы /welcome и /about должны обработать классы с id inviteController и aboutController соотвественно.</p>
<p>Осталось подключить класс, который будет заниматься отображением.</p>
<p><em><strong>common.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;bean id=&#8221;viewResolver&#8221; class=&#8221;org.springframework.web.servlet.view.InternalResourceViewResolver&#8221;&gt;<br />
&lt;property name=&#8221;cache&#8221; value=&#8221;false&#8221;/&gt; &lt;!&#8211; Запрещаем кэширование &#8211;&gt;<br />
&lt;property name=&#8221;viewClass&#8221;&gt;&lt;value&gt;org.springframework.web.servlet.view.JstlView&lt;/value&gt;&lt;/property&gt; &lt;!&#8211; Используем JSTL &#8211;&gt;<br />
&lt;property name=&#8221;prefix&#8221;&gt;&lt;value&gt;/WEB-INF/templates/jsp/&lt;/value&gt;&lt;/property&gt; &lt;!&#8211; Путь, где будут храниться JSP &#8211;&gt;<br />
&lt;property name=&#8221;suffix&#8221;&gt;&lt;value&gt;.jsp&lt;/value&gt;&lt;/property&gt; &lt;!&#8211; Расширение для файлов шаблонов &#8211;&gt;<br />
&lt;/bean&gt;</font></p>
<p><font size="4"><strong>Конфигурация контроллеров</strong></font></p>
<p>Создайте файлик /WEB-INF/context/allofrss-context.xml с базовым содержанием, аналогичным предыдущему common.xml.</p>
<p>Добавим информацию о классах контроллерах.</p>
<p><em><strong>allofrss-context.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;bean id=&#8221;inviteController&#8221; class=&#8221;com.allofrss.controllers.action.InviteActionController&#8221;&gt;<br />
&lt;property name=&#8221;commandName&#8221; value=&#8221;invite&#8221;/&gt; &lt;!&#8211; Название формы&#8211;&gt;<br />
&lt;property name=&#8221;commandClass&#8221; value=&#8221;com.allofrss.beans.form.InviteFormBean&#8221;/&gt; &lt;!&#8211; Бин формы &#8211;&gt;<br />
&lt;property name=&#8221;formView&#8221; value=&#8221;invite&#8221;/&gt; &lt;!&#8211; Название JSP с формой &#8211;&gt;<br />
&lt;property name=&#8221;successView&#8221; value=&#8221;invite&#8221;/&gt; &lt;!&#8211; Название JSP, которая будет показана после успешной обработки формы &#8211;&gt;<br />
&lt;property name=&#8221;validator&#8221;&gt; &lt;!&#8211; Класс валидатора формы &#8211;&gt;<br />
&lt;bean class=&#8221;com.allofrss.validators.InviteFormValidator&#8221;/&gt;<br />
&lt;/property&gt;<br />
&lt;/bean&gt; </font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2"> &lt;bean id=&#8221;aboutController&#8221; class=&#8221;com.allofrss.controllers.lookup.AboutController&#8221;/&gt;</font></p>
<p><font size="4"><strong>Конфигурация доступа к БД</strong></font></p>
<p>Аналогично, создаём файл /WEB-INF/context/allofrss-data.xml следующего содержания.</p>
<p><em><strong>allofrss-data.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;beans xmlns=&#8221;http://www.springframework.org/schema/beans&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xmlns:aop=&#8221;http://www.springframework.org/schema/aop&#8221;<br />
xmlns:tx=&#8221;http://www.springframework.org/schema/tx&#8221;<br />
xsi:schemaLocation=&#8221;<br />
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd<br />
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd<br />
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd&#8221;&gt;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;/beans&gt;</font></p>
<p>Для начала следует определить источник данных, в качестве параметров класса передать данные о драйвере базы данных, логине и пароле.</p>
<p><em><strong>allofrss-data.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;bean id=&#8221;dataSource&#8221; class=&#8221;org.apache.commons.dbcp.BasicDataSource&#8221; destroy-method=&#8221;close&#8221;&gt;<br />
&lt;property name=&#8221;driverClassName&#8221; value=&#8221;com.mysql.jdbc.Driver&#8221;/&gt;<br />
&lt;property name=&#8221;url&#8221; value=&#8221;jdbc:mysql://localhost:3306/database_name?useUnicode=true&#8221;/&gt;<br />
&lt;property name=&#8221;username&#8221; value=&#8221;username&#8221;/&gt;<br />
&lt;property name=&#8221;password&#8221; value=&#8221;password&#8221;/&gt;<br />
&lt;/bean&gt; </font></p>
<p>Как я упоминал в предыдущей статье, в качестве ORM будет использоваться фреймворк Hibernate. В Spring присутствуют классы, облегчающие процесс интеграции Hibernate в ваше приложение. Прежде всего следует определить класс поддержки сессий БД.</p>
<p><em><strong>allofrss-data.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;bean id=&#8221;sessionFactory&#8221; class=&#8221;org.springframework.orm.hibernate3.LocalSessionFactoryBean&#8221;&gt;<br />
&lt;property name=&#8221;dataSource&#8221; ref=&#8221;dataSource&#8221;/&gt; &lt;!&#8211; В качестве параметра передается ссылка на определенный выше класс источника данных &#8211;&gt;<br />
&lt;property name=&#8221;mappingResources&#8221;/&gt;<br />
&lt;property name=&#8221;hibernateProperties&#8221;&gt; &lt;!&#8211; Некоторые параметры Hibernate &#8211;&gt;<br />
&lt;value&gt;<br />
hibernate.dialect=org.hibernate.dialect.MySQLDialect<br />
hibernate.show_sql=true<br />
hibernate.format_sql=false<br />
hibernate.use_sql_comments=true<br />
hibernate.connection.charSet=utf8<br />
&lt;/value&gt;<br />
&lt;/property&gt;<br />
&lt;/bean&gt; </font></p>
<p>На данном этапе можно сказать, что конфигурация доступа к БД закончена, однако мы на этом не остановимся и добавим ещё один очень важный компонент &#8211; поддержку транзакций.</p>
<p>Воспользуемся встроенным в Spring менеджером транзакций  <font face="courier new,courier" size="2">DataSourceTransactionManager</font>, а также поддержкой AOP. Для этого добавим несколько простых строчек.</p>
<p><em><strong>allofrss-data.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">    &lt;tx:annotation-driven transaction-manager=&#8221;txManager&#8221;/&gt;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;bean id=&#8221;txManager&#8221; class=&#8221;org.springframework.jdbc.datasource.DataSourceTransactionManager&#8221;&gt;<br />
&lt;property name=&#8221;dataSource&#8221; ref=&#8221;dataSource&#8221;/&gt; &lt;!&#8211; В качестве параметра всё тот же источник данных &#8211;&gt;<br />
&lt;/bean&gt; </font></p>
<p>Ну и на последок, объединим все созданные конфигурационные файлы, создав файл /WEB-INF/allofrss-servlet.xml с таким содержанием.</p>
<p><em><strong>allofrss-servlet.xml</strong></em></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;?xml version=&#8221;1.0&#8243; encoding=&#8221;UTF-8&#8243;?&gt;<br />
&lt;beans xmlns=&#8221;http://www.springframework.org/schema/beans&#8221;<br />
xmlns:xsi=&#8221;http://www.w3.org/2001/XMLSchema-instance&#8221;<br />
xmlns:aop=&#8221;http://www.springframework.org/schema/aop&#8221;<br />
xsi:schemaLocation=&#8221;http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd&#8221;&gt;</font></p>
<p style="background-color: #eeeee3"><font face="courier new,courier" size="2">&lt;import resource=&#8221;context/<a href="http://yasinetskiy.com/source/example/allofrss/part2/allofrss-data.xml">allofrss-data.xml</a>&#8221; /&gt;<br />
&lt;import resource=&#8221;context/<a href="http://yasinetskiy.com/source/example/allofrss/part2/allofrss-context.xml">allofrss-context.xml</a>&#8221; /&gt;<br />
&lt;import resource=&#8221;context/<a href="http://yasinetskiy.com/source/example/allofrss/part2/common.xml">common.xml</a>&#8221; /&gt;<br />
&lt;/beans&gt; </font></p>
<p>Вот теперь действительно всё. В этой статье я планировал перейти уже непосредственно к реализации нашего приложения, однако в процессе написания всё же решил разделить статью на две части. Ожидайте следующую завершающую часть уже совсем скоро.</p>
<p><strong>Читайте также</strong>:</p>
<ul>
<li><a href="http://yasinetskiy.com/2008/01/21/spring-web-applications-development-part1/" title="Разработка веб-приложений на Spring. Часть 1 (Проектирование)">Разработка веб-приложений на Spring. Часть 1 (Проектирование)</a></li>
<li><a href="http://yasinetskiy.com/2008/01/11/webdev-obzor-frejmvorka-spring/" title="Webdev: Обзор фреймворка Spring">Webdev: Обзор фреймворка Spring</a></li>
</ul>
<div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=AwTk8hjILt8:5kkNopASMKI:7Q72WNTAKBA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=7Q72WNTAKBA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=AwTk8hjILt8:5kkNopASMKI:V_sGLiPBpWU"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?i=AwTk8hjILt8:5kkNopASMKI:V_sGLiPBpWU" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=AwTk8hjILt8:5kkNopASMKI:yIl2AUoC8zA"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=yIl2AUoC8zA" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?a=AwTk8hjILt8:5kkNopASMKI:qj6IDK7rITs"><img src="http://feeds.feedburner.com/~ff/AndreyYasinetskiysoftwareDevelopment?d=qj6IDK7rITs" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/AndreyYasinetskiysoftwareDevelopment/~4/AwTk8hjILt8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://yasinetskiy.com/2008/02/spring-web-applications-development-part2/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://yasinetskiy.com/2008/02/spring-web-applications-development-part2/</feedburner:origLink></item>
	</channel>
</rss>
